use super::{
Chromosome,
gene::{ArithmeticGene, Gene, Valid},
};
use crate::{chromosomes::BoundedGene, random_provider};
use radiate_utils::Integer;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::{
fmt::Debug,
ops::{Add, Div, Mul, Range, Sub},
};
#[derive(Clone, PartialEq, Default, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct IntGene<T: Integer> {
allele: T,
value_range: Range<T>,
bounds: Range<T>,
}
impl<T: Integer> IntGene<T> {
pub fn new(allele: T, value_range: Range<T>, bounds: Range<T>) -> Self {
IntGene {
allele,
value_range,
bounds,
}
}
}
impl<T: Integer> Gene for IntGene<T> {
type Allele = T;
fn allele(&self) -> &T {
&self.allele
}
fn allele_mut(&mut self) -> &mut T {
&mut self.allele
}
fn new_instance(&self) -> IntGene<T> {
IntGene {
allele: random_provider::range(self.value_range.clone()),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
fn with_allele(&self, allele: &T) -> IntGene<T> {
IntGene {
allele: *allele,
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<T: Integer> Valid for IntGene<T> {
fn is_valid(&self) -> bool {
self.allele >= self.bounds.start && self.allele <= self.bounds.end
}
}
impl<T: Integer> BoundedGene for IntGene<T> {
fn min(&self) -> &Self::Allele {
&self.value_range.start
}
fn max(&self) -> &Self::Allele {
&self.value_range.end
}
fn bounds(&self) -> (&Self::Allele, &Self::Allele) {
(&self.bounds.start, &self.bounds.end)
}
}
impl<T: Integer> ArithmeticGene for IntGene<T> {
fn mean(&self, other: &IntGene<T>) -> IntGene<T> {
IntGene {
allele: (self.allele.safe_add(other.allele)).safe_div(T::TWO),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<T: Integer> Add for IntGene<T> {
type Output = IntGene<T>;
fn add(self, other: IntGene<T>) -> IntGene<T> {
IntGene {
allele: self
.allele
.safe_add(other.allele)
.safe_clamp(self.bounds.start, self.bounds.end),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<T: Integer> Sub for IntGene<T> {
type Output = IntGene<T>;
fn sub(self, other: IntGene<T>) -> IntGene<T> {
IntGene {
allele: self
.allele
.safe_sub(other.allele)
.safe_clamp(self.bounds.start, self.bounds.end),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<T: Integer> Mul for IntGene<T> {
type Output = IntGene<T>;
fn mul(self, other: IntGene<T>) -> IntGene<T> {
IntGene {
allele: self
.allele
.safe_mul(other.allele)
.safe_clamp(self.bounds.start, self.bounds.end),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<T: Integer> Div for IntGene<T> {
type Output = IntGene<T>;
fn div(self, other: IntGene<T>) -> IntGene<T> {
IntGene {
allele: self
.allele
.safe_div(other.allele)
.safe_clamp(self.bounds.start, self.bounds.end),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<T: Integer> From<T> for IntGene<T> {
fn from(allele: T) -> Self {
IntGene {
allele,
value_range: T::MIN..T::MAX,
bounds: T::MIN..T::MAX,
}
}
}
impl<T: Integer> From<Range<T>> for IntGene<T> {
fn from(range: Range<T>) -> Self {
let (min, max) = (range.start, range.end);
IntGene {
allele: random_provider::range(range),
value_range: min..max,
bounds: min..max,
}
}
}
impl<T: Integer> From<(Range<T>, Range<T>)> for IntGene<T> {
fn from((range, bounds): (Range<T>, Range<T>)) -> Self {
IntGene {
allele: random_provider::range(range.clone()),
value_range: range,
bounds,
}
}
}
impl<T: Integer> std::fmt::Display for IntGene<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.allele)
}
}
#[derive(Clone, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct IntChromosome<I: Integer> {
genes: Vec<IntGene<I>>,
}
impl<I: Integer> IntChromosome<I> {
pub fn new(genes: Vec<IntGene<I>>) -> Self {
IntChromosome { genes }
}
}
impl<I: Integer> Chromosome for IntChromosome<I> {
type Gene = IntGene<I>;
fn as_slice(&self) -> &[Self::Gene] {
&self.genes
}
fn as_mut_slice(&mut self) -> &mut [Self::Gene] {
&mut self.genes
}
}
impl<T: Integer> Valid for IntChromosome<T> {
fn is_valid(&self) -> bool {
self.genes.iter().all(|gene| gene.is_valid())
}
}
impl<T: Integer> From<IntGene<T>> for IntChromosome<T> {
fn from(gene: IntGene<T>) -> Self {
IntChromosome { genes: vec![gene] }
}
}
impl<T: Integer> From<Vec<IntGene<T>>> for IntChromosome<T> {
fn from(genes: Vec<IntGene<T>>) -> Self {
IntChromosome { genes }
}
}
impl<T: Integer> From<(usize, Range<T>)> for IntChromosome<T> {
fn from((size, range): (usize, Range<T>)) -> Self {
IntChromosome {
genes: (0..size).map(|_| IntGene::from(range.clone())).collect(),
}
}
}
impl<T: Integer> From<(usize, Range<T>, Range<T>)> for IntChromosome<T> {
fn from((size, range, bounds): (usize, Range<T>, Range<T>)) -> Self {
IntChromosome {
genes: (0..size)
.map(|_| IntGene::from((range.clone(), bounds.clone())))
.collect(),
}
}
}
impl<T: Integer> From<Vec<T>> for IntChromosome<T> {
fn from(alleles: Vec<T>) -> Self {
IntChromosome {
genes: alleles.into_iter().map(IntGene::from).collect(),
}
}
}
impl<T: Integer> FromIterator<IntGene<T>> for IntChromosome<T> {
fn from_iter<I: IntoIterator<Item = IntGene<T>>>(iter: I) -> Self {
IntChromosome {
genes: iter.into_iter().collect(),
}
}
}
impl<T: Integer> IntoIterator for IntChromosome<T> {
type Item = IntGene<T>;
type IntoIter = std::vec::IntoIter<IntGene<T>>;
fn into_iter(self) -> Self::IntoIter {
self.genes.into_iter()
}
}
impl<T: Integer> Debug for IntChromosome<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.genes)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let gene = IntGene::from(0..10);
assert!(gene.allele >= 0 && gene.allele <= 10);
}
#[test]
fn test_new_instance() {
let gene = IntGene::from(0..10);
let new_gene = gene.new_instance();
assert!(new_gene.allele >= 0 && new_gene.allele <= 10);
}
#[test]
fn test_from_allele() {
let gene = IntGene::from(5);
let new_gene = gene.with_allele(&5);
assert_eq!(new_gene.allele, 5);
}
#[test]
fn test_is_valid() {
let gene = IntGene::from(0..10);
assert!(gene.is_valid());
}
#[test]
fn test_bounds() {
let gene_one = IntGene::from((0..10, 0..10));
let gene_two = IntGene::from((0..10, -100..100));
let (one_min, one_max) = gene_one.bounds();
let (two_min, two_max) = gene_two.bounds();
assert_eq!(*one_min, 0);
assert_eq!(*one_max, 10);
assert_eq!(*two_min, -100);
assert_eq!(*two_max, 100);
assert_eq!(gene_one.min(), &0);
assert_eq!(gene_one.max(), &10);
assert_eq!(gene_two.min(), &0);
assert_eq!(gene_two.max(), &10);
assert!(gene_one.is_valid());
assert!(gene_two.is_valid());
}
#[test]
fn test_mean() {
let gene = IntGene::from(5);
let other = IntGene::from(5);
let new_gene = gene.mean(&other);
assert_eq!(new_gene.allele, 5);
}
#[test]
fn test_int_arithmetic_doesnt_overflow() {
let gene = IntGene::<u8>::from(8_u8);
let other = IntGene::<u8>::from(8_u8);
let sixteen = IntGene::<u8>::from(16_u8);
assert_eq!((gene.clone() + other.clone()).allele, 16);
assert_eq!((gene.clone() - sixteen.clone()).allele, 0);
assert_eq!((gene.clone() * other.clone()).allele, 64);
let zero = IntGene::<u8>::from(0_u8);
assert_eq!((gene.clone() / zero.clone()).allele, 8);
assert_eq!((gene.clone() / other.clone()).allele, 1);
let max = IntGene::<u8>::from(u8::MAX);
assert_eq!((max.clone() + other.clone()).allele, u8::MAX);
assert_eq!((zero.clone() - other.clone()).allele, 0);
let i_eight = IntGene::<i8>::from(8_i8);
let i_other = IntGene::<i8>::from(8_i8);
let i_sixteen = IntGene::<i8>::from(16_i8);
assert_eq!((i_eight.clone() + i_other.clone()).allele, 16);
assert_eq!((i_eight.clone() - i_sixteen.clone()).allele, -8);
assert_eq!((i_eight.clone() * i_other.clone()).allele, 64);
}
#[test]
fn test_int_clamp_arithmetic_clamping() {
let gene = IntGene::new(5, 5..10, 0..10);
let other = IntGene::new(5, 8..10, 0..10);
let really_big = IntGene::new(100000, 0..10, 0..10);
let add = gene.clone() + other.clone();
let sub = gene.clone() - other.clone();
let mul = gene.clone() * other.clone();
let div = gene.clone() / other.clone();
let really_big_add = gene.clone() + really_big.clone();
let really_big_sub = gene.clone() - really_big.clone();
let really_big_mul = gene.clone() * really_big.clone();
let really_big_div = gene.clone() / really_big.clone();
assert_eq!(add.allele, 10);
assert_eq!(sub.allele, 0);
assert_eq!(mul.allele, 10);
assert_eq!(div.allele, 1);
assert_eq!(really_big_add.allele, 10);
assert_eq!(really_big_sub.allele, 0);
assert_eq!(really_big_mul.allele, 10);
assert_eq!(really_big_div.allele, 0);
}
#[test]
fn test_into() {
let gene: IntGene<i32> = 5.into();
assert_eq!(gene.allele, 5);
}
#[test]
fn test_chromosome_from_range() {
let chromosome = IntChromosome::from((10, 0..10));
assert_eq!(chromosome.genes.len(), 10);
for gene in &chromosome.genes {
assert!(gene.allele >= 0 && gene.allele <= 10);
}
}
#[test]
fn test_chromosome_from_range_with_bounds() {
let chromosome = IntChromosome::from((10, 0..10, -10..10));
assert_eq!(chromosome.genes.len(), 10);
for gene in &chromosome.genes {
assert!(gene.allele >= 0 && gene.allele <= 10);
assert_eq!(*gene.bounds().0, -10);
assert_eq!(*gene.bounds().1, 10);
}
}
#[test]
fn test_chromosome_from_alleles() {
let alleles = vec![1, 2, 3, 4, 5];
let chromosome = IntChromosome::from(alleles.clone());
assert_eq!(chromosome.genes.len(), 5);
for (i, gene) in chromosome.genes.iter().enumerate() {
assert_eq!(gene.allele, alleles[i]);
}
}
#[test]
fn test_gene_arithmetic() {
let gene_one = IntGene::from(5);
let gene_two = IntGene::from(5);
let zero_gene = IntGene::from(0);
let add = gene_one.clone() + gene_two.clone();
let sub = gene_one.clone() - gene_two.clone();
let mul = gene_one.clone() * gene_two.clone();
let div = gene_one.clone() / gene_two.clone();
let div_zero = gene_one.clone() / zero_gene.clone();
let mean = gene_one.mean(&gene_two);
assert_eq!(add.allele, 10);
assert_eq!(sub.allele, 0);
assert_eq!(mul.allele, 25);
assert_eq!(div.allele, 1);
assert_eq!(div_zero.allele, 5);
assert_eq!(mean.allele, 5);
}
#[test]
#[cfg(feature = "serde")]
fn test_int_gene_serialization() {
let gene = IntGene::from(-5_i32..5_i32);
assert!(gene.is_valid());
let serialized = serde_json::to_string(&gene).expect("Failed to serialize IntGene");
let deserialized: IntGene<i32> =
serde_json::from_str(&serialized).expect("Failed to deserialize IntGene");
let chromosome = IntChromosome::from((10, 0..10, -10..10));
let serialized_chromosome =
serde_json::to_string(&chromosome).expect("Failed to serialize IntChromosome");
let deserialized_chromosome: IntChromosome<i32> =
serde_json::from_str(&serialized_chromosome)
.expect("Failed to deserialize IntChromosome");
assert_eq!(gene, deserialized);
assert_eq!(chromosome, deserialized_chromosome);
}
}