use radiate_utils::Float;
use super::Codec;
use crate::genome::Gene;
use crate::genome::genotype::Genotype;
use crate::{Chromosome, FloatChromosome};
use std::ops::Range;
#[derive(Clone)]
pub struct FloatCodec<F: Float, T = F> {
num_chromosomes: usize,
num_genes: 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(
(0..self.num_chromosomes)
.map(|_| {
FloatChromosome::from((
self.num_genes,
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 {
num_chromosomes: shapes.len(),
num_genes: 0,
value_range: range.clone(),
bounds: range,
shapes: Some(shapes),
_marker: std::marker::PhantomData,
}
}
}
impl<F: Float> FloatCodec<F, Vec<Vec<F>>> {
pub fn matrix(rows: usize, cols: usize, range: Range<F>) -> Self {
FloatCodec {
num_chromosomes: rows,
num_genes: cols,
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 {
num_chromosomes: 1,
num_genes: count,
value_range: range.clone(),
bounds: range,
shapes: None,
_marker: std::marker::PhantomData,
}
}
}
impl FloatCodec<f32> {
pub fn scalar(range: Range<f32>) -> Self {
FloatCodec {
num_chromosomes: 1,
num_genes: 1,
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>>()
}
}