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}