use super::{
Chromosome,
gene::{ArithmeticGene, BoundedGene, Gene, Valid},
};
use crate::random_provider;
use radiate_utils::Float;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::{
fmt::{Debug, Display},
ops::{Add, Div, Mul, Range, Sub},
};
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct FloatGene<F: Float> {
allele: F,
value_range: Range<F>,
bounds: Range<F>,
}
impl<F: Float> FloatGene<F> {
pub fn new(allele: F, value_range: Range<F>, bounds: Range<F>) -> Self {
FloatGene {
allele,
value_range: value_range.start.max(F::MIN)..value_range.end.min(F::MAX),
bounds: bounds.start.max(F::MIN)..bounds.end.min(F::MAX),
}
}
}
impl<F: Float> Valid for FloatGene<F> {
fn is_valid(&self) -> bool {
self.allele >= self.bounds.start && self.allele <= self.bounds.end
}
}
impl<F: Float> Gene for FloatGene<F> {
type Allele = F;
fn allele(&self) -> &F {
&self.allele
}
fn allele_mut(&mut self) -> &mut F {
&mut self.allele
}
fn new_instance(&self) -> FloatGene<F> {
FloatGene {
allele: random_provider::range(self.value_range.clone()),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
fn with_allele(&self, allele: &F) -> FloatGene<F> {
FloatGene {
allele: *allele,
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<F: Float> BoundedGene for FloatGene<F> {
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<F: Float> ArithmeticGene for FloatGene<F> {
fn mean(&self, other: &FloatGene<F>) -> FloatGene<F> {
FloatGene {
allele: F::safe_mul(F::safe_add(*self.allele(), *other.allele()), F::HALF)
.safe_clamp(self.bounds.start, self.bounds.end),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<F: Float> Add for FloatGene<F> {
type Output = FloatGene<F>;
fn add(self, other: FloatGene<F>) -> FloatGene<F> {
FloatGene {
allele: F::safe_add(self.allele, other.allele)
.safe_clamp(self.bounds.start, self.bounds.end),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<F: Float> Sub for FloatGene<F> {
type Output = FloatGene<F>;
fn sub(self, other: FloatGene<F>) -> FloatGene<F> {
FloatGene {
allele: F::safe_sub(self.allele, other.allele)
.safe_clamp(self.bounds.start, self.bounds.end),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<F: Float> Mul for FloatGene<F> {
type Output = FloatGene<F>;
fn mul(self, other: FloatGene<F>) -> FloatGene<F> {
FloatGene {
allele: F::safe_mul(self.allele, other.allele)
.safe_clamp(self.bounds.start, self.bounds.end),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<F: Float> Div for FloatGene<F> {
type Output = FloatGene<F>;
fn div(self, other: FloatGene<F>) -> FloatGene<F> {
FloatGene {
allele: F::safe_div(self.allele, other.allele)
.safe_clamp(self.bounds.start, self.bounds.end),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
impl<F: Float> Default for FloatGene<F> {
fn default() -> Self {
FloatGene {
allele: F::ZERO,
value_range: F::MIN..F::MAX,
bounds: F::MIN..F::MAX,
}
}
}
impl<F: Float> From<F> for FloatGene<F> {
fn from(allele: F) -> Self {
FloatGene {
allele,
value_range: F::MIN..F::MAX,
bounds: F::MIN..F::MAX,
}
}
}
impl<F: Float> From<Range<F>> for FloatGene<F> {
fn from(range: Range<F>) -> Self {
let (min, max) = (range.start.max(F::MIN), range.end.min(F::MAX));
FloatGene {
allele: random_provider::range(range),
value_range: min..max,
bounds: min..max,
}
}
}
impl<F: Float> From<(Range<F>, Range<F>)> for FloatGene<F> {
fn from((value_range, bounds): (Range<F>, Range<F>)) -> Self {
let value_range = value_range.start.max(F::MIN)..value_range.end.min(F::MAX);
let bounds = bounds.start.max(F::MIN)..bounds.end.min(F::MAX);
let allele = random_provider::range(value_range.clone());
FloatGene {
allele,
value_range,
bounds,
}
}
}
impl<F: Float> Display for FloatGene<F> {
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 FloatChromosome<F: Float> {
genes: Vec<FloatGene<F>>,
}
impl<F: Float> FloatChromosome<F> {
pub fn new(genes: Vec<FloatGene<F>>) -> Self {
FloatChromosome { genes }
}
}
impl<F: Float> Chromosome for FloatChromosome<F> {
type Gene = FloatGene<F>;
fn as_slice(&self) -> &[Self::Gene] {
&self.genes
}
fn as_mut_slice(&mut self) -> &mut [Self::Gene] {
&mut self.genes
}
}
impl<F: Float> Valid for FloatChromosome<F> {
fn is_valid(&self) -> bool {
self.genes.iter().all(|gene| gene.is_valid())
}
}
impl<F: Float> From<FloatGene<F>> for FloatChromosome<F> {
fn from(gene: FloatGene<F>) -> Self {
FloatChromosome { genes: vec![gene] }
}
}
impl<F: Float> From<Vec<FloatGene<F>>> for FloatChromosome<F> {
fn from(genes: Vec<FloatGene<F>>) -> Self {
FloatChromosome { genes }
}
}
impl<F: Float> From<Vec<F>> for FloatChromosome<F> {
fn from(alleles: Vec<F>) -> Self {
FloatChromosome {
genes: alleles.into_iter().map(FloatGene::from).collect(),
}
}
}
impl<F: Float> From<(usize, Range<F>)> for FloatChromosome<F> {
fn from((size, range): (usize, Range<F>)) -> Self {
FloatChromosome {
genes: (0..size).map(|_| FloatGene::from(range.clone())).collect(),
}
}
}
impl<F: Float> From<(usize, Range<F>, Range<F>)> for FloatChromosome<F> {
fn from((size, range, bounds): (usize, Range<F>, Range<F>)) -> Self {
FloatChromosome {
genes: (0..size)
.map(|_| FloatGene::from((range.clone(), bounds.clone())))
.collect(),
}
}
}
impl<F: Float> FromIterator<FloatGene<F>> for FloatChromosome<F> {
fn from_iter<I: IntoIterator<Item = FloatGene<F>>>(iter: I) -> Self {
FloatChromosome {
genes: iter.into_iter().collect(),
}
}
}
impl<F: Float> IntoIterator for FloatChromosome<F> {
type Item = FloatGene<F>;
type IntoIter = std::vec::IntoIter<FloatGene<F>>;
fn into_iter(self) -> Self::IntoIter {
self.genes.into_iter()
}
}
impl<F: Float> Debug for FloatChromosome<F> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.genes)
}
}
#[cfg(test)]
mod tests {
use super::*;
const MIN: f32 = -1e18;
const MAX: f32 = 1e18;
#[test]
fn test_new() {
let gene_one = FloatGene::from(0_f32..1_f32);
let gene_two = FloatGene::from((-1.0..1.0, -100.0..100.0));
let gene_three = FloatGene::new(10.0, (MIN * 10.0)..(MAX * 10.0), -1000.0..1000.0);
assert_eq!(*gene_one.max(), 1_f32);
assert_eq!(gene_one.bounds().0, &0_f32);
assert_eq!(gene_one.bounds().1, &1_f32);
assert!(gene_one.is_valid());
assert_eq!(*gene_two.max(), 1.0);
assert_eq!(gene_two.bounds().0, &-100.0);
assert_eq!(gene_two.bounds().1, &100.0);
assert!(gene_two.is_valid());
assert_eq!(*gene_three.allele(), 10.0);
assert_eq!(*gene_three.max(), MAX * 10.0);
assert_eq!(gene_three.bounds().0, &-1000.0);
assert_eq!(gene_three.bounds().1, &1000.0);
}
#[test]
fn test_from() {
let gene = FloatGene::from(0_f32..1_f32);
let copy = gene.clone();
assert_eq!(gene, copy);
}
#[test]
fn test_is_valid() {
let gene = FloatGene::from(0_f32..1_f32);
assert!(gene.is_valid());
assert!(gene.allele >= 0_f32 && gene.allele <= 1_f32);
}
#[test]
fn test_gene_clamping() {
let one = FloatGene::new(5.0, 0.0..10.0, 0.0..10.0);
let two = FloatGene::new(5.0, 0.0..10.0, 0.0..10.0);
let really_big = FloatGene::new(100000.0, 0.0..10.0, 0.0..10.0);
let add = one.clone() + two.clone();
let sub = one.clone() - two.clone();
let mul = one.clone() * two.clone();
let div = one.clone() / two.clone();
assert_eq!(add.allele, 10.0);
assert_eq!(sub.allele, 0.0);
assert_eq!(mul.allele, 10.0);
assert_eq!(div.allele, 1.0);
let big_add = one.clone() + really_big.clone();
let big_sub = one.clone() - really_big.clone();
let big_mul = one.clone() * really_big.clone();
let big_div = really_big.clone() / one.clone();
assert_eq!(big_add.allele, 10.0);
assert_eq!(big_sub.allele, 0.0);
assert_eq!(big_mul.allele, 10.0);
assert_eq!(big_div.allele, 10.0);
}
#[test]
fn test_chromosome() {
let chromosome = FloatChromosome::from((10, -1.0..1.0));
assert_eq!(chromosome.len(), 10);
assert!(chromosome.is_valid());
for gene in chromosome.iter() {
assert!(gene.is_valid());
assert!(gene.allele >= -1.0 && gene.allele <= 1.0);
}
}
#[test]
fn test_chromosome_from_vec() {
let chromosome = FloatChromosome::from(vec![0.0, 1.0, 2.0]);
assert_eq!(chromosome.len(), 3);
assert!(chromosome.is_valid());
for (gene, allele) in chromosome.iter().zip(vec![0.0, 1.0, 2.0]) {
assert!(gene.is_valid());
assert_eq!(gene.allele, allele);
}
}
#[test]
fn test_chromosome_from_range_with_bounds() {
let chromosome = FloatChromosome::from((3, 0.0..10.0, -10.0..10.0));
assert_eq!(chromosome.len(), 3);
assert!(chromosome.is_valid());
for gene in chromosome.iter() {
assert!(gene.is_valid());
assert!(gene.allele >= 0.0 && gene.allele <= 10.0);
assert!(gene.bounds.start >= -10.0 && gene.bounds.end <= 10.0);
}
}
#[test]
fn test_gene_arithmetic() {
let gene_one = FloatGene::from(5_f32);
let gene_two = FloatGene::from(10_f32);
let zero_gene = FloatGene::from(0_f32);
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 mean = gene_one.clone().mean(&gene_two.clone());
let div_zero = gene_one.clone() / zero_gene.clone();
assert_eq!(add.allele, 15_f32);
assert_eq!(sub.allele, -5_f32);
assert_eq!(mul.allele, 50_f32);
assert_eq!(div.allele, 0.5_f32);
assert_eq!(mean.allele, 7.5_f32);
assert_eq!(div_zero.allele, 5_f32);
}
#[test]
#[cfg(feature = "serde")]
fn test_float_gene_serialization() {
let gene = FloatGene::from(0.5_f32..1.5_f32);
assert!(gene.is_valid());
let serialized = serde_json::to_string(&gene).expect("Failed to serialize FloatGene");
let deserialized: FloatGene<f32> =
serde_json::from_str(&serialized).expect("Failed to deserialize FloatGene");
let chromosome = FloatChromosome::from((10, 0.0..1.0, -1.0..1.0));
let serialized_chromosome =
serde_json::to_string(&chromosome).expect("Failed to serialize FloatChromosome");
let deserialized_chromosome: FloatChromosome<f32> =
serde_json::from_str(&serialized_chromosome)
.expect("Failed to deserialize FloatChromosome");
assert_eq!(gene, deserialized);
assert_eq!(chromosome, deserialized_chromosome);
}
}