use super::Codec;
use crate::genome::genotype::Genotype;
use crate::{Chromosome, FloatChromosome};
use crate::{chromosomes::ContiguousChromosome, genome::Gene};
use radiate_utils::Float;
use std::ops::Range;
#[derive(Clone)]
pub struct FloatCodec<F: Float, T = F> {
chrome_sizes: Vec<usize>,
value_range: Range<F>,
bounds: Range<F>,
shapes: Option<Vec<(usize, usize)>>,
_marker: std::marker::PhantomData<T>,
}
impl<F: Float, T> FloatCodec<F, T> {
pub fn with_bounds(mut self, range: Range<F>) -> Self {
self.bounds = range;
self
}
#[inline]
fn common_encode(&self) -> Genotype<FloatChromosome<F>> {
if let Some(shapes) = &self.shapes {
Genotype::from(
shapes
.iter()
.map(|(rows, cols)| {
FloatChromosome::from((
rows * cols,
self.value_range.clone(),
self.bounds.clone(),
))
})
.collect::<Vec<FloatChromosome<F>>>(),
)
} else {
Genotype::from(
self.chrome_sizes
.iter()
.map(|&size| {
FloatChromosome::from((size, self.value_range.clone(), self.bounds.clone()))
})
.collect::<Vec<FloatChromosome<F>>>(),
)
}
}
}
impl<F: Float> FloatCodec<F, Vec<Vec<Vec<F>>>> {
pub fn tensor(shapes: Vec<(usize, usize)>, range: Range<F>) -> Self {
FloatCodec {
chrome_sizes: shapes.iter().map(|(rows, cols)| rows * cols).collect(),
value_range: range.clone(),
bounds: range,
shapes: Some(shapes),
_marker: std::marker::PhantomData,
}
}
}
impl<F: Float> FloatCodec<F, Vec<Vec<F>>> {
pub fn matrix(shapes: Vec<usize>, range: Range<F>) -> Self {
FloatCodec {
chrome_sizes: shapes,
value_range: range.clone(),
bounds: range,
shapes: None,
_marker: std::marker::PhantomData,
}
}
}
impl<F: Float> FloatCodec<F, Vec<F>> {
pub fn vector(count: usize, range: Range<F>) -> Self {
FloatCodec {
chrome_sizes: vec![count],
value_range: range.clone(),
bounds: range,
shapes: None,
_marker: std::marker::PhantomData,
}
}
}
impl FloatCodec<f32> {
pub fn scalar(range: Range<f32>) -> Self {
FloatCodec {
chrome_sizes: vec![1],
value_range: range.clone(),
bounds: range,
shapes: None,
_marker: std::marker::PhantomData,
}
}
}
impl<F: Float, const N: usize> From<[usize; N]> for FloatCodec<F, Vec<Vec<F>>> {
fn from(chrome_sizes: [usize; N]) -> Self {
FloatCodec {
chrome_sizes: chrome_sizes.to_vec(),
value_range: F::default()..F::default(),
bounds: F::default()..F::default(),
shapes: None,
_marker: std::marker::PhantomData,
}
}
}
impl<F: Float, const N: usize> From<([usize; N], Range<F>)> for FloatCodec<F, Vec<Vec<F>>> {
fn from((chrome_sizes, range): ([usize; N], Range<F>)) -> Self {
FloatCodec {
chrome_sizes: chrome_sizes.to_vec(),
value_range: range.clone(),
bounds: range,
shapes: None,
_marker: std::marker::PhantomData,
}
}
}
impl<F: Float> Codec<FloatChromosome<F>, Vec<Vec<Vec<F>>>> for FloatCodec<F, Vec<Vec<Vec<F>>>> {
#[inline]
fn encode(&self) -> Genotype<FloatChromosome<F>> {
self.common_encode()
}
#[inline]
fn decode(&self, genotype: &Genotype<FloatChromosome<F>>) -> Vec<Vec<Vec<F>>> {
if let Some(shapes) = &self.shapes {
let mut layers = Vec::new();
for (i, chromosome) in genotype.iter().enumerate() {
layers.push(
chromosome
.as_slice()
.chunks(shapes[i].1)
.map(|chunk| chunk.iter().map(|gene| *gene.allele()).collect::<Vec<F>>())
.collect::<Vec<Vec<F>>>(),
);
}
layers
} else {
vec![
genotype
.iter()
.map(|chromosome| {
chromosome
.iter()
.map(|gene| *gene.allele())
.collect::<Vec<F>>()
})
.collect::<Vec<Vec<F>>>(),
]
}
}
}
impl<F: Float> Codec<FloatChromosome<F>, Vec<Vec<F>>> for FloatCodec<F, Vec<Vec<F>>> {
#[inline]
fn encode(&self) -> Genotype<FloatChromosome<F>> {
self.common_encode()
}
#[inline]
fn decode(&self, genotype: &Genotype<FloatChromosome<F>>) -> Vec<Vec<F>> {
genotype
.iter()
.map(|chromosome| {
chromosome
.iter()
.map(|gene| *gene.allele())
.collect::<Vec<F>>()
})
.collect::<Vec<Vec<F>>>()
}
}
impl<F: Float> Codec<FloatChromosome<F>, Vec<F>> for FloatCodec<F, Vec<F>> {
#[inline]
fn encode(&self) -> Genotype<FloatChromosome<F>> {
self.common_encode()
}
#[inline]
fn decode(&self, genotype: &Genotype<FloatChromosome<F>>) -> Vec<F> {
genotype
.iter()
.flat_map(|chromosome| {
chromosome
.iter()
.map(|gene| *gene.allele())
.collect::<Vec<F>>()
})
.collect::<Vec<F>>()
}
}
impl<F: Float> Codec<FloatChromosome<F>, F> for FloatCodec<F, F> {
#[inline]
fn encode(&self) -> Genotype<FloatChromosome<F>> {
self.common_encode()
}
#[inline]
fn decode(&self, genotype: &Genotype<FloatChromosome<F>>) -> F {
genotype
.iter()
.flat_map(|chromosome| {
chromosome
.iter()
.map(|gene| *gene.allele())
.collect::<Vec<F>>()
})
.next()
.unwrap_or_default()
}
}
impl<F: Float> Codec<FloatChromosome<F>, Vec<Vec<F>>> for Vec<FloatChromosome<F>> {
#[inline]
fn encode(&self) -> Genotype<FloatChromosome<F>> {
Genotype::from(
self.iter()
.map(|chromosome| {
chromosome
.iter()
.map(|gene| gene.new_instance())
.collect::<FloatChromosome<F>>()
})
.collect::<Vec<FloatChromosome<F>>>(),
)
}
#[inline]
fn decode(&self, genotype: &Genotype<FloatChromosome<F>>) -> Vec<Vec<F>> {
genotype
.iter()
.map(|chromosome| {
chromosome
.iter()
.map(|gene| *gene.allele())
.collect::<Vec<F>>()
})
.collect::<Vec<Vec<F>>>()
}
}
impl<F: Float> Codec<FloatChromosome<F>, Vec<F>> for FloatChromosome<F> {
#[inline]
fn encode(&self) -> Genotype<FloatChromosome<F>> {
Genotype::from(
self.iter()
.map(|gene| gene.new_instance())
.collect::<FloatChromosome<F>>(),
)
}
#[inline]
fn decode(&self, genotype: &Genotype<FloatChromosome<F>>) -> Vec<F> {
genotype
.iter()
.flat_map(|chromosome| {
chromosome
.iter()
.map(|gene| *gene.allele())
.collect::<Vec<F>>()
})
.collect::<Vec<F>>()
}
}