use super::{
Chromosome,
gene::{BoundedGene, Gene, Valid},
};
use crate::{
chromosomes::{ContiguousChromosome, NumericGene},
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> 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(),
}
}
fn set_allele(&mut self, allele: F) {
let (bound_min, bound_max) = self.bound_range();
self.allele = allele.safe_clamp(*bound_min, *bound_max);
}
}
impl<F: Float> BoundedGene for FloatGene<F> {
fn init_min(&self) -> &Self::Allele {
&self.value_range.start
}
fn init_max(&self) -> &Self::Allele {
&self.value_range.end
}
fn init_range(&self) -> (Self::Allele, Self::Allele) {
(self.value_range.start, self.value_range.end)
}
fn bound_min(&self) -> &Self::Allele {
&self.bounds.start
}
fn bound_max(&self) -> &Self::Allele {
&self.bounds.end
}
fn bound_range(&self) -> (&Self::Allele, &Self::Allele) {
(&self.bounds.start, &self.bounds.end)
}
}
impl<F: Float> NumericGene for FloatGene<F> {
fn safe_add(&self, other: &Self) -> Self {
add_gene(self, *other.allele())
}
fn safe_sub(&self, other: &Self) -> Self {
sub_gene(self, *other.allele())
}
fn safe_mul(&self, other: &Self) -> Self {
mul_gene(self, *other.allele())
}
fn safe_div(&self, other: &Self) -> Self {
div_gene(self, *other.allele())
}
fn mean(&self, other: &Self) -> Self {
FloatGene {
allele: self
.allele
.safe_mean(other.allele)
.safe_clamp(self.bounds.start, self.bounds.end),
value_range: self.value_range.clone(),
bounds: self.bounds.clone(),
}
}
}
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> Add for FloatGene<F> {
type Output = FloatGene<F>;
fn add(self, other: FloatGene<F>) -> FloatGene<F> {
add_gene(&self, *other.allele())
}
}
impl<F: Float> Sub for FloatGene<F> {
type Output = FloatGene<F>;
fn sub(self, other: FloatGene<F>) -> FloatGene<F> {
sub_gene(&self, *other.allele())
}
}
impl<F: Float> Mul for FloatGene<F> {
type Output = FloatGene<F>;
fn mul(self, other: FloatGene<F>) -> FloatGene<F> {
mul_gene(&self, *other.allele())
}
}
impl<F: Float> Div for FloatGene<F> {
type Output = FloatGene<F>;
fn div(self, other: FloatGene<F>) -> FloatGene<F> {
div_gene(&self, *other.allele())
}
}
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)
}
}
fn add_gene<F: Float>(gene: &FloatGene<F>, value: F) -> FloatGene<F> {
FloatGene {
allele: F::safe_add(*gene.allele(), value).safe_clamp(gene.bounds.start, gene.bounds.end),
value_range: gene.value_range.clone(),
bounds: gene.bounds.clone(),
}
}
fn sub_gene<F: Float>(gene: &FloatGene<F>, value: F) -> FloatGene<F> {
FloatGene {
allele: F::safe_sub(*gene.allele(), value).safe_clamp(gene.bounds.start, gene.bounds.end),
value_range: gene.value_range.clone(),
bounds: gene.bounds.clone(),
}
}
fn mul_gene<F: Float>(gene: &FloatGene<F>, value: F) -> FloatGene<F> {
FloatGene {
allele: F::safe_mul(*gene.allele(), value).safe_clamp(gene.bounds.start, gene.bounds.end),
value_range: gene.value_range.clone(),
bounds: gene.bounds.clone(),
}
}
fn div_gene<F: Float>(gene: &FloatGene<F>, value: F) -> FloatGene<F> {
FloatGene {
allele: F::safe_div(*gene.allele(), value).safe_clamp(gene.bounds.start, gene.bounds.end),
value_range: gene.value_range.clone(),
bounds: gene.bounds.clone(),
}
}
#[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 iter(&self) -> impl Iterator<Item = &Self::Gene> {
self.genes.iter()
}
fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Gene> {
self.genes.iter_mut()
}
fn get(&self, index: usize) -> Option<&Self::Gene> {
self.genes.get(index)
}
fn get_mut(&mut self, index: usize) -> Option<&mut Self::Gene> {
self.genes.get_mut(index)
}
fn set(&mut self, index: usize, gene: Self::Gene) {
if let Some(slot) = self.genes.get_mut(index) {
*slot = gene;
}
}
fn len(&self) -> usize {
self.genes.len()
}
}
impl<F: Float> ContiguousChromosome for FloatChromosome<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.init_max(), 1_f32);
assert_eq!(gene_one.bound_range().0, &0_f32);
assert_eq!(gene_one.bound_range().1, &1_f32);
assert!(gene_one.is_valid());
assert_eq!(*gene_two.init_max(), 1.0);
assert_eq!(gene_two.bound_range().0, &-100.0);
assert_eq!(gene_two.bound_range().1, &100.0);
assert!(gene_two.is_valid());
assert_eq!(*gene_three.allele(), 10.0);
assert_eq!(*gene_three.init_max(), MAX * 10.0);
assert_eq!(gene_three.bound_range().0, &-1000.0);
assert_eq!(gene_three.bound_range().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);
}
}