1use fugue::{addr, ChoiceValue, Trace};
7use rand::seq::SliceRandom;
8use rand::Rng;
9use serde::{Deserialize, Serialize};
10
11use crate::error::GenomeError;
12use crate::genome::bounds::MultiBounds;
13use crate::genome::traits::{EvolutionaryGenome, PermutationGenome};
14
15#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
23pub struct Permutation {
24 perm: Vec<usize>,
26}
27
28impl Permutation {
29 pub fn new(perm: Vec<usize>) -> Self {
34 let result = Self { perm };
35 assert!(
36 result.is_valid_permutation(),
37 "Input must be a valid permutation of 0..n"
38 );
39 result
40 }
41
42 pub fn new_unchecked(perm: Vec<usize>) -> Self {
47 Self { perm }
48 }
49
50 pub fn try_new(perm: Vec<usize>) -> Result<Self, GenomeError> {
52 let result = Self { perm };
53 if result.is_valid_permutation() {
54 Ok(result)
55 } else {
56 Err(GenomeError::InvalidStructure(
57 "Input is not a valid permutation of 0..n".to_string(),
58 ))
59 }
60 }
61
62 pub fn identity(n: usize) -> Self {
64 Self {
65 perm: (0..n).collect(),
66 }
67 }
68
69 pub fn random<R: Rng>(n: usize, rng: &mut R) -> Self {
71 let mut perm: Vec<usize> = (0..n).collect();
72 perm.shuffle(rng);
73 Self { perm }
74 }
75
76 pub fn len(&self) -> usize {
78 self.perm.len()
79 }
80
81 pub fn is_empty(&self) -> bool {
83 self.perm.is_empty()
84 }
85
86 pub fn get(&self, i: usize) -> Option<usize> {
88 self.perm.get(i).copied()
89 }
90
91 pub fn inverse(&self) -> Self {
95 let n = self.perm.len();
96 let mut inv = vec![0; n];
97 for (i, &j) in self.perm.iter().enumerate() {
98 inv[j] = i;
99 }
100 Self { perm: inv }
101 }
102
103 pub fn compose(&self, other: &Self) -> Result<Self, GenomeError> {
107 if self.perm.len() != other.perm.len() {
108 return Err(GenomeError::DimensionMismatch {
109 expected: self.perm.len(),
110 actual: other.perm.len(),
111 });
112 }
113 let composed: Vec<usize> = self.perm.iter().map(|&i| other.perm[i]).collect();
114 Ok(Self { perm: composed })
115 }
116
117 pub fn swap(&mut self, i: usize, j: usize) {
119 self.perm.swap(i, j);
120 }
121
122 pub fn reverse_segment(&mut self, start: usize, end: usize) {
124 if start < end && end < self.perm.len() {
125 self.perm[start..=end].reverse();
126 }
127 }
128
129 pub fn insert(&mut self, from: usize, to: usize) {
131 if from == to || from >= self.perm.len() || to >= self.perm.len() {
132 return;
133 }
134 let elem = self.perm.remove(from);
135 self.perm.insert(to, elem);
136 }
137
138 pub fn inversions(&self) -> usize {
143 let n = self.perm.len();
144 let mut count = 0;
145 for i in 0..n {
146 for j in (i + 1)..n {
147 if self.perm[i] > self.perm[j] {
148 count += 1;
149 }
150 }
151 }
152 count
153 }
154
155 pub fn kendall_tau_distance(&self, other: &Self) -> Result<usize, GenomeError> {
160 if self.perm.len() != other.perm.len() {
161 return Err(GenomeError::DimensionMismatch {
162 expected: self.perm.len(),
163 actual: other.perm.len(),
164 });
165 }
166
167 let other_inv = other.inverse();
169 let composed = self.compose(&other_inv)?;
170
171 Ok(composed.inversions())
173 }
174
175 pub fn is_cyclic(&self) -> bool {
177 if self.perm.is_empty() {
178 return true;
179 }
180
181 let n = self.perm.len();
182 let mut visited = vec![false; n];
183 let mut current = 0;
184 let mut cycle_len = 0;
185
186 while !visited[current] {
187 visited[current] = true;
188 current = self.perm[current];
189 cycle_len += 1;
190 }
191
192 cycle_len == n && current == 0
193 }
194
195 pub fn into_inner(self) -> Vec<usize> {
197 self.perm
198 }
199
200 pub fn as_slice(&self) -> &[usize] {
202 &self.perm
203 }
204}
205
206impl EvolutionaryGenome for Permutation {
207 type Allele = usize;
208 type Phenotype = Vec<usize>;
209
210 fn to_trace(&self) -> Trace {
214 let mut trace = Trace::default();
215 for (i, &val) in self.perm.iter().enumerate() {
216 trace.insert_choice(addr!("perm", i), ChoiceValue::Usize(val), 0.0);
217 }
218 trace
219 }
220
221 fn from_trace(trace: &Trace) -> Result<Self, GenomeError> {
225 let mut perm = Vec::new();
226 let mut i = 0;
227 while let Some(val) = trace.get_usize(&addr!("perm", i)) {
228 perm.push(val);
229 i += 1;
230 }
231 if perm.is_empty() {
232 return Err(GenomeError::InvalidStructure(
233 "No permutation found in trace".to_string(),
234 ));
235 }
236 Self::try_new(perm)
237 }
238
239 fn decode(&self) -> Self::Phenotype {
240 self.perm.clone()
241 }
242
243 fn dimension(&self) -> usize {
244 self.perm.len()
245 }
246
247 fn generate<R: Rng>(rng: &mut R, bounds: &MultiBounds) -> Self {
248 let n = bounds.dimension();
249 Self::random(n, rng)
250 }
251
252 fn distance(&self, other: &Self) -> f64 {
253 self.kendall_tau_distance(other).unwrap_or(0) as f64
254 }
255
256 fn trace_prefix() -> &'static str {
257 "perm"
258 }
259}
260
261impl PermutationGenome for Permutation {
262 fn permutation(&self) -> &[usize] {
263 &self.perm
264 }
265
266 fn permutation_mut(&mut self) -> &mut [usize] {
267 &mut self.perm
268 }
269
270 fn from_permutation(perm: Vec<usize>) -> Result<Self, GenomeError> {
271 Self::try_new(perm)
272 }
273}
274
275impl std::ops::Index<usize> for Permutation {
276 type Output = usize;
277
278 fn index(&self, index: usize) -> &Self::Output {
279 &self.perm[index]
280 }
281}
282
283impl From<Vec<usize>> for Permutation {
284 fn from(perm: Vec<usize>) -> Self {
285 Self::new(perm)
286 }
287}
288
289impl From<Permutation> for Vec<usize> {
290 fn from(p: Permutation) -> Self {
291 p.perm
292 }
293}
294
295impl IntoIterator for Permutation {
296 type Item = usize;
297 type IntoIter = std::vec::IntoIter<usize>;
298
299 fn into_iter(self) -> Self::IntoIter {
300 self.perm.into_iter()
301 }
302}
303
304impl<'a> IntoIterator for &'a Permutation {
305 type Item = &'a usize;
306 type IntoIter = std::slice::Iter<'a, usize>;
307
308 fn into_iter(self) -> Self::IntoIter {
309 self.perm.iter()
310 }
311}
312
313#[cfg(test)]
314mod tests {
315 use super::*;
316 use crate::genome::traits::PermutationGenome;
317
318 #[test]
319 fn test_permutation_new() {
320 let p = Permutation::new(vec![2, 0, 1, 3]);
321 assert_eq!(p.len(), 4);
322 assert_eq!(p[0], 2);
323 assert_eq!(p[1], 0);
324 }
325
326 #[test]
327 #[should_panic(expected = "valid permutation")]
328 fn test_permutation_new_invalid_duplicate() {
329 Permutation::new(vec![0, 1, 1, 3]);
330 }
331
332 #[test]
333 #[should_panic(expected = "valid permutation")]
334 fn test_permutation_new_invalid_out_of_range() {
335 Permutation::new(vec![0, 1, 5, 3]);
336 }
337
338 #[test]
339 fn test_permutation_try_new() {
340 assert!(Permutation::try_new(vec![2, 0, 1, 3]).is_ok());
341 assert!(Permutation::try_new(vec![0, 1, 1, 3]).is_err());
342 }
343
344 #[test]
345 fn test_permutation_identity() {
346 let p = Permutation::identity(5);
347 assert_eq!(p.as_slice(), &[0, 1, 2, 3, 4]);
348 }
349
350 #[test]
351 fn test_permutation_random() {
352 let mut rng = rand::thread_rng();
353 let p = Permutation::random(10, &mut rng);
354 assert!(p.is_valid_permutation());
355 assert_eq!(p.len(), 10);
356 }
357
358 #[test]
359 fn test_permutation_inverse() {
360 let p = Permutation::new(vec![2, 0, 3, 1]);
361 let inv = p.inverse();
362 assert_eq!(inv.as_slice(), &[1, 3, 0, 2]);
365
366 let composed = p.compose(&inv).unwrap();
368 assert_eq!(composed.as_slice(), &[0, 1, 2, 3]);
369 }
370
371 #[test]
372 fn test_permutation_compose() {
373 let p1 = Permutation::new(vec![1, 2, 0]);
374 let p2 = Permutation::new(vec![2, 0, 1]);
375 let composed = p1.compose(&p2).unwrap();
376 assert_eq!(composed.as_slice(), &[0, 1, 2]);
379 }
380
381 #[test]
382 fn test_permutation_swap() {
383 let mut p = Permutation::new(vec![0, 1, 2, 3]);
384 p.swap(0, 3);
385 assert_eq!(p.as_slice(), &[3, 1, 2, 0]);
386 }
387
388 #[test]
389 fn test_permutation_reverse_segment() {
390 let mut p = Permutation::new(vec![0, 1, 2, 3, 4]);
391 p.reverse_segment(1, 3);
392 assert_eq!(p.as_slice(), &[0, 3, 2, 1, 4]);
393 }
394
395 #[test]
396 fn test_permutation_insert() {
397 let mut p = Permutation::new(vec![0, 1, 2, 3, 4]);
398 p.insert(1, 4);
399 assert_eq!(p.as_slice(), &[0, 2, 3, 4, 1]);
400 }
401
402 #[test]
403 fn test_permutation_inversions() {
404 let p1 = Permutation::identity(5);
406 assert_eq!(p1.inversions(), 0);
407
408 let p2 = Permutation::new(vec![4, 3, 2, 1, 0]);
410 assert_eq!(p2.inversions(), 10); let p3 = Permutation::new(vec![1, 0, 2, 3, 4]);
414 assert_eq!(p3.inversions(), 1);
415 }
416
417 #[test]
418 fn test_permutation_kendall_tau() {
419 let p1 = Permutation::new(vec![0, 1, 2, 3]);
420 let p2 = Permutation::new(vec![0, 1, 2, 3]);
421 assert_eq!(p1.kendall_tau_distance(&p2).unwrap(), 0);
422
423 let p3 = Permutation::new(vec![0, 1, 3, 2]);
424 assert_eq!(p1.kendall_tau_distance(&p3).unwrap(), 1);
425
426 let p4 = Permutation::new(vec![3, 2, 1, 0]);
427 assert_eq!(p1.kendall_tau_distance(&p4).unwrap(), 6);
428 }
429
430 #[test]
431 fn test_permutation_is_cyclic() {
432 let cyclic = Permutation::new(vec![3, 2, 0, 1]);
434 assert!(cyclic.is_cyclic());
436
437 let identity = Permutation::identity(4);
439 assert!(!identity.is_cyclic()); let empty = Permutation::identity(0);
443 assert!(empty.is_cyclic());
444 }
445
446 #[test]
447 fn test_permutation_decode() {
448 let p = Permutation::new(vec![2, 0, 1]);
449 assert_eq!(p.decode(), vec![2, 0, 1]);
450 }
451
452 #[test]
453 fn test_permutation_dimension() {
454 let p = Permutation::new(vec![2, 0, 1, 3, 4]);
455 assert_eq!(p.dimension(), 5);
456 }
457
458 #[test]
459 fn test_permutation_generate() {
460 let mut rng = rand::thread_rng();
461 let bounds = MultiBounds::symmetric(1.0, 10);
462 let p = Permutation::generate(&mut rng, &bounds);
463 assert_eq!(p.dimension(), 10);
464 assert!(p.is_valid_permutation());
465 }
466
467 #[test]
468 fn test_permutation_distance() {
469 let p1 = Permutation::new(vec![0, 1, 2, 3]);
470 let p2 = Permutation::new(vec![3, 2, 1, 0]);
471 assert_eq!(p1.distance(&p2), 6.0);
472 }
473
474 #[test]
475 fn test_permutation_to_trace() {
476 let p = Permutation::new(vec![2, 0, 1]);
477 let trace = p.to_trace();
478
479 assert_eq!(trace.get_usize(&addr!("perm", 0)), Some(2));
480 assert_eq!(trace.get_usize(&addr!("perm", 1)), Some(0));
481 assert_eq!(trace.get_usize(&addr!("perm", 2)), Some(1));
482 assert_eq!(trace.get_usize(&addr!("perm", 3)), None);
483 }
484
485 #[test]
486 fn test_permutation_from_trace() {
487 let mut trace = Trace::default();
488 trace.insert_choice(addr!("perm", 0), ChoiceValue::Usize(1), 0.0);
489 trace.insert_choice(addr!("perm", 1), ChoiceValue::Usize(2), 0.0);
490 trace.insert_choice(addr!("perm", 2), ChoiceValue::Usize(0), 0.0);
491
492 let p = Permutation::from_trace(&trace).unwrap();
493 assert_eq!(p.as_slice(), &[1, 2, 0]);
494 }
495
496 #[test]
497 fn test_permutation_trace_roundtrip() {
498 let original = Permutation::new(vec![4, 2, 0, 3, 1]);
499 let trace = original.to_trace();
500 let recovered = Permutation::from_trace(&trace).unwrap();
501 assert_eq!(original, recovered);
502 }
503
504 #[test]
505 fn test_permutation_from_trace_invalid() {
506 let mut trace = Trace::default();
507 trace.insert_choice(addr!("perm", 0), ChoiceValue::Usize(0), 0.0);
508 trace.insert_choice(addr!("perm", 1), ChoiceValue::Usize(0), 0.0); let result = Permutation::from_trace(&trace);
511 assert!(result.is_err());
512 }
513
514 #[test]
515 fn test_permutation_from_trace_empty() {
516 let trace = Trace::default();
517 let result = Permutation::from_trace(&trace);
518 assert!(result.is_err());
519 }
520
521 #[test]
522 fn test_permutation_serialization() {
523 let p = Permutation::new(vec![2, 0, 1, 3]);
524 let serialized = serde_json::to_string(&p).unwrap();
525 let deserialized: Permutation = serde_json::from_str(&serialized).unwrap();
526 assert_eq!(p, deserialized);
527 }
528
529 #[test]
530 fn test_permutation_iteration() {
531 let p = Permutation::new(vec![2, 0, 1]);
532 let collected: Vec<usize> = p.into_iter().collect();
533 assert_eq!(collected, vec![2, 0, 1]);
534 }
535
536 #[test]
537 fn test_permutation_ref_iteration() {
538 let p = Permutation::new(vec![2, 0, 1]);
539 let sum: usize = p.into_iter().sum();
540 assert_eq!(sum, 3);
541 }
542
543 #[test]
544 fn test_permutation_into_inner() {
545 let p = Permutation::new(vec![2, 0, 1]);
546 let v: Vec<usize> = p.into_inner();
547 assert_eq!(v, vec![2, 0, 1]);
548 }
549
550 #[test]
551 fn test_permutation_from_vec() {
552 let p: Permutation = vec![1, 0, 2].into();
553 assert_eq!(p.as_slice(), &[1, 0, 2]);
554 }
555}