meiosis 0.1.0

An evolutionary algorithm library with as many compile time checks as possible.
Documentation
use core::num::NonZeroUsize;

use rand::seq::IteratorRandom;
use rand::Rng;

use crate::neighbour::Neighbour;
use crate::random::Random;

use super::Gene;

// unsigned

impl Gene for u8 {}
impl Random for u8 {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for u8 {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the maximum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MAX);

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(distance).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the minimum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MIN);

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(distance).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}

impl Gene for u16 {}
impl Random for u16 {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for u16 {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the maximum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MAX);

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(distance).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the minimum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MIN);

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(distance).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}

impl Gene for u32 {}
impl Random for u32 {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for u32 {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the maximum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MAX);

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(distance).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the minimum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MIN);

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(distance).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}

impl Gene for u64 {}
impl Random for u64 {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for u64 {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the maximum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MAX);

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(distance).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the minimum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MIN);

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(distance).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}

impl Gene for u128 {}
impl Random for u128 {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for u128 {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the maximum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MAX);

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(distance).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the minimum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MIN);

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(distance).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}

impl Gene for usize {}
impl Random for usize {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for usize {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(maximal_distance.get()).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(maximal_distance.get()).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}

// signed

impl Gene for i8 {}
impl Random for i8 {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for i8 {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the maximum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MAX);

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(distance).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the minimum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MIN);

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(distance).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}

impl Gene for i16 {}
impl Random for i16 {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for i16 {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the maximum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MAX);

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(distance).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the minimum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MIN);

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(distance).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}

impl Gene for i32 {}
impl Random for i32 {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for i32 {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the maximum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MAX);

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(distance).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the minimum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MIN);

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(distance).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}

impl Gene for i64 {}
impl Random for i64 {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for i64 {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the maximum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MAX);

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(distance).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the minimum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MIN);

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(distance).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}

impl Gene for i128 {}
impl Random for i128 {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for i128 {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the maximum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MAX);

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(distance).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the minimum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MIN);

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(distance).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}

impl Gene for isize {}
impl Random for isize {
    fn random<RNG>(rng: &mut RNG) -> Self
    where
        RNG: Rng,
    {
        rng.gen()
    }
}
impl Neighbour for isize {
    fn random_forward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.successor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the maximum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MAX);

        let min = self.checked_add(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the maximum value
        let max = self.checked_add(distance).unwrap_or(Self::MAX);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn random_backward_neighbour<RNG>(&self, rng: &mut RNG, maximal_distance: NonZeroUsize) -> Option<Self>
    where
        RNG: Rng,
    {
        if maximal_distance.get() == 1 {
            return self.predecessor(rng);
        }

        // try to convert the maximal distance to a value that fits in `Self`, and if it doesn't
        // we assume the minimum
        let distance = Self::try_from(maximal_distance.get()).unwrap_or(Self::MIN);

        let max = self.checked_sub(1)?;
        // we don't want to overflow, but also not abort if we do, so we clamp to the minimum value
        let min = self.checked_sub(distance).unwrap_or(Self::MIN);

        // should we have an empty range `choose` automatically gives us `None`
        (min..=max).choose(rng)
    }

    fn successor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_add(1)
    }

    fn predecessor<RNG>(&self, _rng: &mut RNG) -> Option<Self>
    where
        RNG: Rng,
    {
        self.checked_sub(1)
    }
}