diff --git a/oxigen/src/crossover.rs b/oxigen/src/crossover.rs index 96daab5..c92e655 100644 --- a/oxigen/src/crossover.rs +++ b/oxigen/src/crossover.rs @@ -4,6 +4,8 @@ use genotype::Genotype; use rand::distributions::Uniform; use rand::prelude::*; use std::cmp::{min, PartialEq}; +use std::mem::replace; + use CrossoverFunctions::*; /// This trait defines the cross function. @@ -21,6 +23,8 @@ pub enum CrossoverFunctions { MultiCrossPoint, /// Uniform Crossover. UniformCross, + /// Uniform Partially Matched + UniformPartiallyMatched(f32) } impl> Crossover for CrossoverFunctions { @@ -128,6 +132,58 @@ impl> Crossover for CrossoverFunctions { .map(|(i, (gen1, gen2))| if i % 2 != 0 { gen1 } else { gen2 }), ); + (child1, child2) + } + UniformPartiallyMatched(indpb) => { + let size = min(ind1.iter().len(), ind2.iter().len()); + + let mut ind1_temp : Vec> = ind1.clone().into_iter().map(|e| Some(e)).collect(); + let mut ind2_temp : Vec> = ind2.clone().into_iter().map(|e| Some(e)).collect(); + + let mut i1 : Vec = (0..ind1_temp.len()).collect(); + let mut i2 : Vec = (0..ind2_temp.len()).collect(); + + let mut p1 = vec![0; size]; + let mut p2 = vec![0; size]; + + for i in 0..size { + p1[i1[i]] = i; + p2[i2[i]] = i; + } + + for i in 0..size { + let p : f32 = SmallRng::from_entropy().gen(); + if p < *indpb { + let temp1 = i1[i]; + let temp2 = i2[i]; + + i1[i] = temp2; + i1[p1[temp2]] = temp1; + + i2[i] = temp1; + i2[p2[temp1]] = temp2; + + p1[temp1] = p1[temp2]; + p1[temp2] = p1[temp1]; + p2[temp1] = p2[temp2]; + p2[temp2] = p2[temp1]; + } + } + + let mut child1 = ind1.clone(); + child1.from_iter( + i1.iter().map(|loc| { + replace(&mut ind1_temp[*loc], None).unwrap() + }) + ); + + let mut child2 = ind2.clone(); + child2.from_iter( + i2.iter().map(|loc| { + replace(&mut ind2_temp[*loc], None).unwrap() + }) + ); + (child1, child2) } }