permu_rs/permutation.rs
1use std::convert::TryFrom;
2use std::convert::TryInto;
3
4use std::fmt;
5use fmt::{Debug, Display};
6
7use rand::Rng;
8
9use crate::{Population, Distribution, errors::Error };
10
11/// Contains a permutation vector and methods to generate permutations.
12#[derive(Debug)]
13#[derive(Clone)]
14#[derive(PartialEq)]
15pub struct Permutation<T> {
16 pub permu : Vec<T>,
17}
18
19impl<T> Permutation<T> where
20 T : Copy +
21 From<u8> +
22 TryFrom<usize> +
23 TryInto<usize> +
24 Eq +
25 rand::distributions::range::SampleRange +
26 std::cmp::PartialOrd +
27 std::ops::Sub +
28 Display +
29 Debug,
30{
31
32 /// Returns the length of the inner permutation vector.
33 pub fn len(&self) -> usize {
34 self.permu.len()
35 }
36
37 /// Initializes a Permutation with the given vector.
38 ///
39 /// # Errors
40 /// If the given vector is not a permutation the function will return
41 /// a `NotPermutation` error.
42 ///
43 /// # Example
44 /// ```
45 /// use permu_rs::permutation::Permutation;
46 ///
47 /// let permu_ok = Permutation::<u8>::from_vec(vec![0,4,2,1,3]).unwrap();
48 ///
49 /// // Returns an error as the given vector is not a permutation
50 /// let permu_err = Permutation::<u8>::from_vec(vec![5,4,2,1,3]);
51 /// assert!(permu_err.is_err());
52 /// ```
53 pub fn from_vec(vec: Vec<T>) -> Result<Permutation<T>, Error> {
54 let permu = Permutation {permu : vec};
55
56 match permu.is_permu() {
57 true => Ok(permu),
58 false => Err(Error::NotPermutation),
59 }
60 }
61
62 /// Initializes a Permutation with the given vector.
63 /// No checking is done to the given vector, the
64 /// permutation can be initialized with a vector that
65 /// is not a permutation.
66 ///
67 /// # Example
68 /// ```
69 /// use permu_rs::permutation::Permutation;
70 /// let vec : Vec<u16> = vec![0,1,2,3,4];
71 /// let permu : Permutation<u16> = Permutation::from_vec_unsec(vec);
72 /// ```
73 pub fn from_vec_unsec(vec: Vec<T>) -> Permutation<T> {
74 Permutation { permu : vec }
75 }
76
77 /// Generates a random permutation of the length given.
78 ///
79 /// # Panics
80 /// If the length given is grater than the maximum value that `T` can hold,
81 /// the method will panic.
82 ///
83 /// # Example
84 /// ```
85 /// use permu_rs::permutation::Permutation;
86 /// let rand_permu : Permutation<u16> = Permutation::random(8);
87 /// assert!(rand_permu.is_permu());
88 /// assert_eq!(8, rand_permu.permu.len());
89 /// ```
90 pub fn random(length: usize) -> Permutation<T> {
91 let mut permu: Vec<T> = Vec::with_capacity(length);
92
93 let zero = T::from(0u8);
94
95 let max = match T::try_from(length) {
96 Ok(v) => v,
97 Err(_) => panic!("Can not create a permutation longer than the max size of the its type"),
98 };
99
100 while permu.len() < length {
101 // Generate random number. n : [0, length)
102 let n = rand::thread_rng().gen_range(zero, max);
103
104 if !Self::contains(&permu, n) {
105 permu.push(n);
106 }
107 }
108 Permutation{ permu : permu }
109 }
110
111 /// Returns an identity permutation of the length given.
112 ///
113 /// # Panics
114 /// If the length given is grater than the maximum value that `T` can hold,
115 /// the method will panic.
116 ///
117 /// # Example
118 /// ```
119 /// use permu_rs::permutation::Permutation;
120 /// let identity : Permutation<u8> = Permutation::identity(5);
121 /// assert_eq!(vec![0,1,2,3,4], identity.permu);
122 /// ```
123 pub fn identity(length: usize) -> Permutation<T> {
124 let mut identity: Vec<T> = Vec::new();
125
126 (0..length).for_each(|i| {
127 identity.push(match T::try_from(i) {
128 Ok(v) => v,
129 Err(_) => panic!("Can not create a permutation longer than the max size of the its type"),
130 });
131 });
132
133 Permutation { permu : identity }
134 }
135
136 /// Checks if the give `Permutation` contains an element inside.
137 /// If the element is inside `Permutation` returns true.
138 fn contains(permu: &Vec<T>, item: T) -> bool {
139 permu.iter().any(|&x| x == item)
140 }
141
142 /// Checks if the vector inside `Permutation` is really a permutation.
143 ///
144 /// # Example
145 /// ```
146 /// use permu_rs::permutation::Permutation;
147 /// let permu1 : Permutation<u8> = Permutation::from_vec_unsec(vec![0,1,2,3]);
148 /// let permu2 : Permutation<u8> = Permutation::from_vec_unsec(vec![1,2,3]);
149 /// let permu3 : Permutation<u8> = Permutation::from_vec_unsec(vec![0,1,4,3]);
150 /// let permu4 : Permutation<u8> = Permutation::from_vec_unsec(vec![0,1,1,3]);
151 ///
152 /// assert!(permu1.is_permu());
153 /// assert!(!permu2.is_permu()); // Not permutation
154 /// assert!(!permu3.is_permu()); // Not permutation
155 /// assert!(!permu4.is_permu()); // Not permutation
156 /// ```
157 pub fn is_permu(&self) -> bool {
158 (0..self.permu.len()).all(|i| {
159 // NOTE:
160 // This will never panic as the boundaries of the
161 // type T will always be respected here.
162 // i : [0, permu.len] <= T.max_value()
163 let elem = match T::try_from(i) {
164 Ok(v) => v,
165 Err(_) => panic!("Length conversion failed"),
166 };
167 Self::contains(&self.permu, elem)
168 })
169 }
170
171 /// Fills a given output `Permutation` with the inverted permutation of the current
172 /// permutation. inverted(permutation) = permutation^(-1).
173 ///
174 /// # Errors
175 /// Returns a `LengthError` if the both permutations are not of the same length.
176 ///
177 /// # Example
178 /// ```
179 /// use permu_rs::permutation::Permutation;
180 /// // Init permutations
181 /// let permu = Permutation::<u8>::from_vec(vec![0,2,3,1]).unwrap();
182 /// let target = Permutation::<u8>::from_vec(vec![0,3,1,2]).unwrap();
183 /// // Target permutation, filled with zeros
184 /// let mut output = Permutation::from_vec_unsec(vec![0u8; permu.len()]);
185 ///
186 /// // Calculate the inverted permutation of `permu`
187 /// permu.invert(&mut output).unwrap();
188 ///
189 /// println!("permu: {:?}", permu);
190 /// println!("invert: {:?}", output);
191 /// assert_eq!(target, output);
192 /// ```
193 pub fn invert(&self, output: &mut Permutation<T>) -> Result<(), Error> {
194 // Lengths of both permutations must match
195 if self.len() != output.len() {
196 return Err(Error::LengthError);
197 }
198 // Calculate the inverted permutation and store it in output permu
199 (0..self.len()).for_each(|e| {
200 // Whats the index of e in the permutation
201 let index = self.permu.iter()
202 .position(|&x| x == match e.try_into() {
203 Ok(v) => v,
204 Err(_) => unreachable!(),
205 });
206
207 // Convert index (usize) to T type, this should not fail
208 if let Some(index) = index {
209 let index = match T::try_from(index) {
210 Ok(i) => i,
211 Err(_) => unreachable!(),
212 };
213
214 output.permu[e] = index;
215 } else {
216 unreachable!();
217 }
218 });
219 Ok(())
220 }
221
222 /// Composes the current `Permutation` with a given permutation with the given one.
223 /// In other words: `result = permu[other]`.
224 ///
225 // # Error
226 // # TODO
227 ///
228 /// # Example
229 /// ```
230 /// use permu_rs::permutation::Permutation;
231 ///
232 /// let mut permu = Permutation::<u8>::random(4);
233 /// let identity = Permutation::<u8>::identity(4);
234 /// let mut result = Permutation::<u8>::random(4);
235 /// let other = Permutation::<u8>::random(4);
236 ///
237 /// permu.compose_with(&identity, &mut result).unwrap();
238 /// assert_eq!(permu, result);
239 ///
240 /// permu.compose_with(&other, &mut result).unwrap();
241 /// let mut aux = other.clone();
242 /// other.invert(&mut aux);
243 ///
244 /// let mut result2 = result.clone();
245 /// result.compose_with(&aux, &mut result2).unwrap();
246 /// assert_eq!(permu, result2);
247 /// ```
248 pub fn compose_with(&self, other: &Permutation<T>,
249 result: &mut Permutation<T>) -> Result<(), Error> {
250 // Check lengths
251 if self.len() != other.len() && other.len() == result.len() {
252 return Err(Error::LengthError);
253 }
254
255 self.permu.iter()
256 .zip(other.permu.iter())
257 .for_each(|(elem, index)| {
258 let i = match T::try_into(*index) {
259 Ok(v) => v,
260 Err(_) => unreachable!(),
261 };
262 result.permu[i] = *elem;
263 });
264 Ok(())
265 }
266}
267
268/// Population of `Permutations`.
269#[derive(PartialEq)]
270#[derive(Debug)]
271#[derive(Clone)]
272pub struct PermuPopulation<T> {
273 pub population : Vec<Permutation<T>>,
274 pub size : usize,
275}
276
277impl<T> PermuPopulation<T> where
278 T : Copy +
279 From<u8> +
280 TryFrom<usize> +
281 TryInto<usize> +
282 // PartialEq<T> +
283 Eq +
284 rand::distributions::range::SampleRange +
285 std::cmp::PartialOrd +
286 std::ops::Sub +
287 Display +
288 Debug,
289{
290 /// Returns a `PermuPopulation` created from a vector of `Permutation`.
291 ///
292 /// # Example
293 /// ```
294 /// use permu_rs::permutation::{Permutation, PermuPopulation};
295 /// let vec = vec![Permutation::identity(5),
296 /// Permutation::random(5)];
297 /// let pop = PermuPopulation::<u8>::from_vec(vec);
298 /// assert_eq!(2, pop.size);
299 /// ```
300 pub fn from_vec(vec: Vec<Permutation<T>>) -> PermuPopulation<T> {
301 let size = vec.len();
302 PermuPopulation {population : vec, size : size}
303 }
304
305 /// Returns a `PermuPopulation` of the size given with `Permutations` filled with zeros .
306 /// The permutation's length must be specified.
307 ///
308 /// # Example
309 /// ```
310 /// use permu_rs::permutation::PermuPopulation;
311 ///
312 /// // Creates a population of 10 permutations with length 20
313 /// let pop : PermuPopulation<u8> = PermuPopulation::zeros(10, 20);
314 ///
315 /// println!("Zeros population:\n{}", pop);
316 /// ```
317 pub fn zeros(size: usize, length: usize) -> PermuPopulation<T> {
318 let zero = T::from(0u8);
319 let zeros = vec![zero;length];
320
321 let mut pop : Vec<Permutation<T>> = Vec::new();
322
323 (0..size).for_each(|_| pop.push(Permutation::from_vec_unsec(zeros.clone())));
324
325 PermuPopulation {population: pop, size : size}
326 }
327 /// Creates a `PermuPopulation` of identity `Permutation`s.
328 /// The number of `Permutation`s in the returned `PermuPopulation` is given by
329 /// `size` parameter and the length of `Permutation`s is `length`.
330 ///
331 /// # Example
332 /// ```
333 /// use permu_rs::permutation as permu;
334 ///
335 /// let population = permu::PermuPopulation::<u8>::identity(10, 5);
336 /// population.population.iter()
337 /// .for_each(|p| assert_eq!(*p, permu::Permutation::<u8>::identity(5)));
338 ///
339 /// println!("Identity population:\n{}", population);
340 /// ```
341 pub fn identity(size: usize, length: usize) -> PermuPopulation<T> {
342 let mut pop : Vec<Permutation<T>> = Vec::new();
343 (0..size).for_each(|_| pop.push(Permutation::identity(length)));
344
345 PermuPopulation { population : pop, size : size}
346
347 }
348
349 /// Initializes a `PermuPopulation` of random `Permutations` of the size and length given.
350 ///
351 /// # Example
352 /// ```
353 /// use permu_rs::permutation::PermuPopulation;
354 ///
355 /// let pop : PermuPopulation<u8> = PermuPopulation::random(10, 5);
356 /// pop.population.iter().for_each(|p| assert!(p.is_permu())); // All permutations
357 ///
358 /// assert_eq!(pop.size, pop.population.len()); // PermuPopulation size check
359 /// ```
360 pub fn random(size: usize, length: usize) -> PermuPopulation<T> {
361 let mut pop : Vec<Permutation<T>> = Vec::with_capacity(size); // Initialize
362 (0..size).for_each(|_| pop.push(Permutation::random(length)) ); // Generate
363 PermuPopulation { population : pop, size : size}
364 }
365
366 /*
367 /// Fills a given `InversionPopulation` with `inversion` representations from the
368 /// `PermuPopulation`.
369 ///
370 /// # Errors
371 /// Returns a `LengthError` if the size of both populations are not equal.
372 ///
373 /// # Panics
374 /// If the length of `inversion` are not the length of `Permutation`s - 1.
375 ///
376 /// # Example
377 /// ```
378 /// use permu_rs::permutation::PermuPopulation;
379 /// use permu_rs::inversion::InversionPopulation;
380 ///
381 /// let (size, length) = (20,10);
382 /// let permus = PermuPopulation::<u8>::random(size, length);
383 /// let mut inv = InversionPopulation::zeros(size, length-1); // Init inv vector population
384 ///
385 /// permus.to_inversion(&mut inv).unwrap();
386 ///
387 /// println!("{}", permus);
388 /// println!("{}\n", inv);
389 /// ```
390 pub fn to_inversion(&self, inv_pop: &mut InversionPopulation<T>) -> Result<(), Error> {
391 InversionPopulation::from_permus(&self, inv_pop)?;
392 Ok(())
393 }
394 */
395
396 /// Replaces all individuals from the `PermuPopulation` with its respective inverted
397 /// `PermuPopulation`. For more info, check `Permutation`'s `invert` method.
398 ///
399 /// # Panics
400 ///
401 /// The function panics if an error occurs when running `invert` method to any `Permutation`of
402 /// the `PermuPopulation`.
403 ///
404 /// # Example
405 ///
406 /// ```
407 /// use permu_rs::permutation::*;
408 ///
409 /// // Init populations
410 /// let permu = Permutation::<u8>::from_vec(vec![0,2,3,1]).unwrap();
411 /// let mut pop = PermuPopulation::from_vec(vec![permu]);
412 /// println!("initial pop: {:?}", pop);
413 ///
414 /// let target = Permutation::<u8>::from_vec(vec![0,3,1,2]).unwrap();
415 /// let target_pop = PermuPopulation::from_vec(vec![target]);
416 ///
417 /// // Calculate the inverted permutation of `permu`
418 /// pop.invert();
419 ///
420 /// println!("inverted pop: {:?}", pop);
421 /// assert_eq!(target_pop, pop);
422 /// ```
423 pub fn invert(&mut self) {
424 self.population.iter_mut()
425 .enumerate()
426 .for_each(|(_index, mut permu)| {
427 permu.clone().invert(&mut permu).unwrap();
428 });
429 }
430
431 #[doc(hidden)]
432 fn argsort(vec: &[usize], output: &mut Vec<usize>) {
433 let mut sorted: Vec<(usize, &usize)> = vec.iter().enumerate().collect();
434 sorted.sort_by(|(_i1, e1), (_i2, e2)| e1.cmp(e2) );
435
436 for i in 0..output.len() {
437 let (index, _elem) = sorted[i];
438 output[i] = index;
439 }
440 }
441
442 /// Returns the central perutation of the current `PermuPopulation`. The central permutation is
443 /// calculated with the Borda algorithm.
444 ///
445 /// # Example
446 ///
447 /// ```
448 /// use permu_rs::permutation::*;
449 ///
450 /// let pop = PermuPopulation::<u8>::from_vec(vec![
451 /// Permutation::from_vec(vec![0, 1, 2]).unwrap(),
452 /// Permutation::from_vec(vec![0, 2, 1]).unwrap(),
453 /// Permutation::from_vec(vec![1, 0, 2]).unwrap(),
454 /// Permutation::from_vec(vec![1, 2, 0]).unwrap(),
455 /// Permutation::from_vec(vec![2, 0, 1]).unwrap(),
456 /// Permutation::from_vec(vec![2, 1, 0]).unwrap(),
457 /// ]);
458 ///
459 /// let target = Permutation::<u8>::from_vec(vec![0, 1, 2]).unwrap();
460 ///
461 /// let central = pop.central_permu();
462 /// assert_eq!(target, central);
463 /// ```
464 pub fn central_permu(&self) -> Permutation<T> {
465 let size = self.population[0].len();
466 let mut sum: Vec<usize> = vec![0; size];
467 // Sum by columns and store result in sum vector
468 self.population.iter()
469 .for_each(|permu|
470 permu.permu.iter()
471 .enumerate()
472 .for_each(|(index, val)|
473 sum[index] += match T::try_into(*val) {
474 Ok(v) => v,
475 Err(_) => unreachable!(),
476 }));
477
478 // Argsort the sum vector to get the central permutation
479 let mut argsorted = vec![0; size];
480 Self::argsort(&sum, &mut argsorted);
481
482 // Convert to T and create the permutation
483 let mut inner = Vec::<T>::with_capacity(size);
484
485 argsorted.iter().
486 for_each(|x| inner.push(match T::try_from(*x) {
487 Ok(v) => v,
488 Err(_) => unreachable!(),
489 }));
490
491 Permutation { permu: inner }
492 }
493}
494
495impl<T> Population<T> for PermuPopulation<T> where
496 T : Copy +
497 From<u8> +
498 TryFrom<usize> +
499 TryInto<usize> +
500 Eq +
501 rand::distributions::range::SampleRange +
502 std::cmp::PartialOrd +
503 std::ops::Sub +
504 Display +
505 Debug,
506{
507
508 /// Implementation of `learn` method for `PermuPopulation`.
509 ///
510 /// # Example
511 /// ```
512 /// use permu_rs::{Population, Distribution};
513 /// use permu_rs::permutation::{PermuPopulation, Permutation};
514 ///
515 /// let v = vec![Permutation::<u8>::from_vec_unsec(vec![0,1,2,3]),
516 /// Permutation::<u8>::from_vec_unsec(vec![1,2,0,3])];
517 /// let pop = PermuPopulation::from_vec(v);
518 /// let distr = pop.learn();
519 ///
520 /// let target = vec![vec![1,1,0,0],
521 /// vec![0,1,1,0],
522 /// vec![1,0,1,0],
523 /// vec![0,0,0,2]];
524 ///
525 /// let target = Distribution::PermuDistribution(target, false);
526 /// assert_eq!(target, distr);
527 /// ```
528 ///
529 // NOTE: (i : positions, j : values)
530 fn learn(&self) -> Distribution {
531 let m = self.population[0].permu.len(); // Number of positions
532
533 let mut distr: Vec<Vec<usize>> = vec![vec![0; m]; m]; // Init distribution matrix
534
535 (0..self.size).for_each(|i| {
536 (0..self.population[0].permu.len()).for_each(|j| {
537 let e : usize = match self.population[i].permu[j].try_into() {
538 Ok(v) => v,
539 Err(_) => panic!(),
540 };
541 distr[j][e] += 1;
542 })
543 });
544
545 Distribution::PermuDistribution(distr, false)
546 }
547
548 /// Implementation of `sample` method for `PermuPopulation`.
549 ///
550 /// # Errors
551 /// Returns a `LengthError` if the length of the output population's `Permutation`s length
552 /// is not equal to its population `Permutation`'s. Returns an `IncorrectDistrType` error if
553 /// the given distribution is not `PermuDistribution`.
554 ///
555 /// # Example
556 ///
557 /// ```
558 /// use permu_rs::permutation::PermuPopulation;
559 /// use permu_rs::{Population, Distribution};
560 ///
561 /// let pop = PermuPopulation::<u8>::random(1, 5); // Population to learn from
562 /// let mut samples = PermuPopulation::<u8>::zeros(10, 5); // Population to fill with samples
563 ///
564 /// let mut distr = pop.learn();
565 ///
566 /// samples.sample(&mut distr).unwrap();
567 ///
568 /// println!("{}", samples);
569 /// ```
570 fn sample(&mut self, distr: &mut Distribution) -> Result<(), Error> {
571
572 // Check if the given Distribution is correct
573 let (distr, soften) = match distr {
574 Distribution::PermuDistribution(d, s) => (d, s),
575 _ => return Err(Error::IncorrectDistrType),
576 };
577
578 // Check distribution and population's permus' sizes
579 let length = match distr.len() == self.population[0].permu.len() {
580 true => distr.len(),
581 false => return Err(Error::LengthError),
582 };
583
584 // Check if the distribution is soften
585 if !*soften {
586 // If not, soften the distribution by adding one to every element of the matrix
587 *distr = distr.iter()
588 .map(|row| row.iter().map(|x| x+1).collect())
589 .collect();
590 *soften = true;
591 }
592
593 // let mut used_indx = Vec::<usize>::with_capacity(length);
594
595 (0..self.size).for_each(|out_i| {
596
597 // used_indx.clear();
598 let mut used_indx = Vec::<usize>::with_capacity(length);
599
600 // let ref_permu = Permutation::<usize>::identity(length);
601 let order = Permutation::<usize>::random(length);
602
603 order.permu.iter().for_each(|ord| {
604 let (index_f, val_f) : (Vec<usize>, Vec<usize>) = distr[*ord].iter()
605 .enumerate()
606 .filter(|(index, _)| // Skip the values already existing in the permutation
607 used_indx.iter()
608 .find( |&x| *x == *index )
609 .is_none())
610 .unzip();
611
612 let max: usize = val_f.iter().sum();
613 let rand: f64 = rand::thread_rng().gen_range(0.0, max as f64);
614
615 let mut i = 0;
616 let mut s = val_f[i];
617 while (s as f64) < rand {
618 i += 1;
619 s += val_f[i];
620 }
621 let v = index_f[i];
622 // Never panics, as the boundaries of T are always respected here
623 self.population[out_i].permu[*ord] = match T::try_from(v) {
624 Ok(v) => v,
625 Err(_) => panic!("Conversion error when sampling"),
626 };
627 used_indx.push(index_f[i]);
628 });
629 });
630 Ok(())
631 }
632
633 // NOTE: This is only a temporary solution, the clone should be avoided
634 fn to_permus(&self, permus: &mut PermuPopulation<T>) -> Result<(), Error> {
635 // Check if both populations have yhe same size and length
636 if self.size != permus.size ||
637 self.population[0].len() != permus.population[0].len() {
638 return Err(Error::LengthError);
639 }
640 // Clone self to output permutation population
641 for i in 0..self.size {
642 permus.population[i] = self.population[i].clone();
643 }
644 Ok(())
645 }
646
647 // NOTE: This is only a temporary solution, the clone should be avoided
648 fn from_permus(&mut self, permus: &PermuPopulation<T>) -> Result<(), Error> {
649 // Check if both populations have yhe same size and length
650 if self.size != permus.size ||
651 self.population[0].len() != permus.population[0].len() {
652 return Err(Error::LengthError);
653 }
654 // Clone self to output permutation population
655 for i in 0..self.size {
656 self.population[i] = permus.population[i].clone();
657 }
658 Err(Error::IncorrectDistrType)
659 }
660
661}
662
663impl<T> fmt::Display for PermuPopulation<T> where
664 T : Debug
665{
666 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
667
668 // For empty distibutions
669 if self.size == 0 {
670 return write!(f, "[]\nPermuPopulation, shape: 0,0\n");
671 }
672
673 let mut formatted = String::from("[");
674
675 self.population.iter()
676 .take(self.size -1) // Do not take the last item
677 .for_each(|permu| {
678 formatted.push_str(format!("{:?},\n", permu.permu).as_str());
679 });
680
681 // Now, take the last item
682 formatted.push_str(format!("{:?}]",
683 self.population[self.size-1].permu).as_str());
684
685 write!(f, "{}\nPermuPopulation, shape: {},{}\n",
686 formatted, self.size, self.population[0].permu.len())
687 }
688}