use rand::Rng;
use serde::{Deserialize, Serialize};
pub trait Genome: Clone + Send + Sync + Sized {
type Phenotype;
fn random<R: Rng>(rng: &mut R) -> Self;
fn mutate<R: Rng>(&mut self, rng: &mut R, rate: f64);
fn crossover<R: Rng>(&self, other: &Self, rng: &mut R) -> Self;
fn to_phenotype(&self) -> Self::Phenotype;
fn distance(&self, _other: &Self) -> f64 {
0.0
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BehaviorDescriptor {
pub values: Vec<f64>,
}
impl BehaviorDescriptor {
pub fn new(values: Vec<f64>) -> Self {
Self { values }
}
pub fn distance(&self, other: &Self) -> f64 {
self.values
.iter()
.zip(other.values.iter())
.map(|(a, b)| (a - b).powi(2))
.sum::<f64>()
.sqrt()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_behavior_distance() {
let a = BehaviorDescriptor::new(vec![0.0, 0.0]);
let b = BehaviorDescriptor::new(vec![3.0, 4.0]);
assert!((a.distance(&b) - 5.0).abs() < 1e-10);
}
#[test]
fn test_behavior_distance_same_point() {
let a = BehaviorDescriptor::new(vec![1.0, 2.0, 3.0]);
let b = BehaviorDescriptor::new(vec![1.0, 2.0, 3.0]);
assert!((a.distance(&b)).abs() < 1e-10);
}
#[test]
fn test_behavior_distance_single_dimension() {
let a = BehaviorDescriptor::new(vec![0.0]);
let b = BehaviorDescriptor::new(vec![5.0]);
assert!((a.distance(&b) - 5.0).abs() < 1e-10);
}
#[test]
fn test_behavior_descriptor_new() {
let desc = BehaviorDescriptor::new(vec![1.0, 2.0, 3.0]);
assert_eq!(desc.values, vec![1.0, 2.0, 3.0]);
}
}