diff --git a/README.md b/README.md index 6554775..5df47f6 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Oxigen provides the following features: * Customizable mutation and selection rates with constant, linear and Quadratic functions according to generations built-in (you can implement your own functions via the `MutationRate` and `SelectionRate` traits). * Customizable age unfitness of individuals, with no unfitness, linear and Quadratic unfitness with threshold according to generations of the individual built-in (you can implement your own age functions via the `Age` trait). * Accumulated `Roulette`, `Tournaments` and `Cup` built-in selection functions (you can implement your own selection functions via the `Selection` trait). -* `SingleCrossPoint`, `MultiCrossPoint` and `UniformCross` built-in crossover functions (you can implement your own crossover function via the `Crossover` trait). +* `SingleCrossPoint`, `MultiCrossPoint`, `UniformCross`, and `UniformPartiallyMatched` built-in crossover functions (you can implement your own crossover function via the `Crossover` trait). * Many built-in survival pressure functions. You can implement your own survival pressure functions via the `SurvivalPressure` trait. * `Niches` built-in `PopulationRefitness` function. You can implement your own population refitness functions via the `PopulationRefitness` trait. * `SolutionFound`, `Generation` and `Progress` and more built-in stop criteria (you can implement your own stop criteria via the `StopCriterion` trait). 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) } }