Skip to content

Commit

Permalink
Cross random elements instead of always even ones in uniform crossover.
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin1887 committed Feb 28, 2021
1 parent 8ee497c commit aeaca01
Showing 1 changed file with 41 additions and 39 deletions.
80 changes: 41 additions & 39 deletions oxigen/src/crossover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,52 +125,54 @@ impl<T, G: Genotype<T>> Crossover<T, G> for CrossoverFunctions {
)
}
UniformCross => {
let mut child1: G = ind1
.clone()
.into_iter()
.zip(ind2.clone().into_iter())
.enumerate()
.map(|(i, (gen1, gen2))| if i % 2 == 0 { gen1 } else { gen2 })
.collect();
let mut child2: G = ind1
.clone()
.into_iter()
.zip(ind2.clone().into_iter())
.enumerate()
.map(|(i, (gen1, gen2))| if i % 2 != 0 { gen1 } else { gen2 })
.collect();

// If one individual is shorter than other the zipped iterator ends in the smallest
// one, so the rest of the original individual should be appended to the child
let len1 = ind1.iter().len();
let len2 = ind2.iter().len();
if len1 > len2 {
child1 = child1
// Elements that change (only until the shortest individual)
// As nth consumes the iterator, besides the global index the
// difference with the previous (+ 1 for the taken value) change is used
let ind_size = min(ind1.iter().len(), ind2.iter().len());
let mut change: Vec<(usize, usize)> = Vec::with_capacity(ind_size);
let mut rng = rand::thread_rng();
let mut previous = 0;
for i in 0..ind_size {
if rng.gen() {
change.push((i, i - previous));
previous = i + 1;
}
}
if !change.is_empty() {
let mut other = ind2.clone().into_iter();
// change must be cloned to use it with the second child without removed items
let mut change1 = change.clone();
let child1: G = ind1
.clone()
.into_iter()
.chain(
ind1.clone()
.into_iter()
.enumerate()
.filter(|(i, _el)| *i >= len2)
.map(|(_i, el)| el),
)
.enumerate()
.map(|(i, gen)| {
if !change1.is_empty() && change1[0].0 == i {
other.nth(change1.remove(0).1).unwrap()
} else {
gen
}
})
.collect();
} else if len1 < len2 {
child2 = child2
let mut other = ind1.clone().into_iter();
let child2: G = ind2
.clone()
.into_iter()
.chain(
ind2.clone()
.into_iter()
.enumerate()
.filter(|(i, _el)| *i >= len1)
.map(|(_i, el)| el),
)
.enumerate()
.map(|(i, gen)| {
if !change.is_empty() && change[0].0 == i {
other.nth(change.remove(0).1).unwrap()
} else {
gen
}
})
.collect();
}

(child1, child2)
(child1, child2)
} else {
// No changes
(ind1.clone(), ind2.clone())
}
}
}
}
Expand Down

0 comments on commit aeaca01

Please sign in to comment.