genx 0.4.0

An easy to use and modular genetic algorithms library.
Documentation
use super::{check_continuous, check_length};
use rand::{prelude::IteratorRandom, rngs::StdRng, SeedableRng};

pub fn order_crossover(
    parent1: &Vec<usize>,
    parent2: &Vec<usize>,
    seed: Option<u64>,
) -> (Vec<usize>, Vec<usize>) {
    check_length(parent1, parent2);
    if !check_continuous(parent1) || !check_continuous(parent2) {
        panic!("Vectors must contain continuous unique values");
    }

    let n = parent1.len();
    let mut prng = match seed {
        Some(seed) => StdRng::seed_from_u64(seed),
        None => StdRng::from_entropy(),
    };

    let mut selected = (0..n).map(|x| x).choose_multiple(&mut prng, 2);
    selected.sort();

    let (mut child1, mut child2) = (parent1.clone(), parent2.clone());
    let (mut holes1, mut holes2) = (
        (0..n).map(|_| false).collect::<Vec<bool>>(),
        (0..n).map(|_| false).collect::<Vec<bool>>(),
    );

    for i in selected[0]..=selected[1] {
        holes1[parent2[i]] = true;
        holes2[parent1[i]] = true;

        child1[i] = parent2[i];
        child2[i] = parent1[i];
    }

    let (mut pos1, mut pos2) = (selected[1] + 1, selected[1] + 1);
    for i in 0..n {
        if !holes1.get(parent1[(i + selected[1] + 1) % n]).unwrap() {
            child1[pos1 % n] = parent1[(i + selected[1] + 1) % n];
            pos1 += 1;
        }
        if !holes2.get(parent2[(i + selected[1] + 1) % n]).unwrap() {
            child2[pos2 % n] = parent2[(i + selected[1] + 1) % n];
            pos2 += 1;
        }
    }

    (child1, child2)
}