use crate::utils::*; use nalgebra::{base::*, matrix, vector}; use std::marker::PhantomData; pub trait Settings {} pub trait Model { /// Returns f(x) fn f(&self, x: Vect) -> Vect; /// Returns df(x)/dx fn df(&self, x: Vect) -> Mat; fn get_settings(&self) -> &S; fn get_settings_mut(&mut self) -> &mut S; } pub trait Coloring { fn prepare>>(iter: I) -> Option

; fn color(pre: &P, val: Vect) -> C; } pub struct MinMaxColoringInfo { pub min: [T; D], pub max: [T; D], } pub trait Constraint { fn constrain_mut(&self, val: &mut Vect); fn constrain(&self, mut val: Vect) -> Vect { self.constrain_mut(&mut val); val } } pub struct MinMaxConstraint { pub min: [T; D], pub max: [T; D], } impl Constraint for MinMaxConstraint { fn constrain_mut(&self, val: &mut Vect) { for ((comp, min), max) in val.iter_mut().zip(self.min.iter()).zip(self.max.iter()) { *comp = num_traits::clamp(*comp, *min, *max) } } } // Models pub mod constrained { use super::*; #[derive(Clone, Debug)] pub struct ConstrainedSettings { pub constraint: O, pub model: M, pub _p: PhantomData<(T, S)>, } impl Settings for ConstrainedSettings {} #[derive(Clone)] pub struct Constrained { pub s: ConstrainedSettings, } impl, M: Model, S: Settings, const D: usize> Model, D> for Constrained { fn f(&self, x: Vect) -> Vect { self.s.constraint.constrain(self.s.model.f(x)) } fn df(&self, x: Vect) -> Mat { self.s.model.df(x) } fn get_settings(&self) -> &ConstrainedSettings { &self.s } fn get_settings_mut(&mut self) -> &mut ConstrainedSettings { &mut self.s } } impl, S, P, C, const D: usize> Coloring for Constrained { fn prepare>>(iter: I) -> Option

{ M::prepare(iter) } fn color(pre: &P, val: Vect) -> C { M::color(pre, val) } } } /// SIR model without vital dynamics pub mod sir { use super::*; #[derive(Clone, Debug)] pub struct SirSettings { /// Transmission probability pub beta: T, /// Removal probability pub gamma: T, pub pop: T, } impl Settings for SirSettings {} #[derive(Clone)] pub struct Sir { pub s: SirSettings, } impl Model, 2> for Sir { fn f(&self, x: Vector2) -> Vector2 { vector![ -self.s.beta * x[0] * x[1] / self.s.pop, self.s.beta * x[0] * x[1] / self.s.pop - self.s.gamma * x[1] ] } fn df(&self, x: Vector2) -> Matrix2 { matrix![ -self.s.beta*x[1]/self.s.pop, -self.s.beta*x[0]/self.s.pop; self.s.beta*x[1]/self.s.pop, self.s.beta*x[0]/self.s.pop-self.s.gamma ] } fn get_settings(&self) -> &SirSettings { &self.s } fn get_settings_mut(&mut self) -> &mut SirSettings { &mut self.s } } impl From> for Vect { fn from(s: SirSettings) -> Self { vector![s.beta, s.gamma, s.pop] } } impl From> for SirSettings { fn from(v: Vect) -> Self { Self { beta: v[0], gamma: v[1], pop: v[2], } } } } /// SIR model with vital dynamics, constant population pub mod sirv { use super::*; #[derive(Clone, Debug)] pub struct SirvSettings { /// Transmission probability pub beta: T, /// Removal probability pub gamma: T, /// Birth rate pub lambda: T, /// Death rate pub mu: T, pub pop: T, } impl Settings for SirvSettings {} #[derive(Clone)] pub struct Sirv { pub s: SirvSettings, } impl Model, 2> for Sirv { fn f(&self, x: Vector2) -> Vector2 { vector![ self.s.lambda - self.s.beta * x[0] * x[1] / self.s.pop - self.s.mu * x[0], self.s.beta * x[0] * x[1] / self.s.pop - self.s.gamma * x[1] - self.s.mu * x[1] ] } fn df(&self, x: Vector2) -> Matrix2 { matrix![ -self.s.beta*x[1]/self.s.pop - self.s.mu, -self.s.beta*x[0]/self.s.pop; self.s.beta*x[1]/self.s.pop, self.s.beta*x[0]/self.s.pop-self.s.gamma - self.s.mu ] } fn get_settings(&self) -> &SirvSettings { &self.s } fn get_settings_mut(&mut self) -> &mut SirvSettings { &mut self.s } } impl From> for Vect { fn from(s: SirvSettings) -> Self { vector![s.beta, s.gamma, s.lambda, s.mu, s.pop] } } impl From> for SirvSettings { fn from(v: Vect) -> Self { Self { beta: v[0], gamma: v[1], lambda: v[2], mu: v[3], pop: v[4], } } } } /// Giraffe pub mod giraffe { use super::*; #[derive(Clone, Debug)] pub struct GiraffeSettings { pub a_a: T, pub a_b: T, pub b_a: T, pub b_b: T, } impl Settings for GiraffeSettings {} #[derive(Clone)] pub struct Giraffe { pub s: GiraffeSettings, } impl Model, 2> for Giraffe { fn f(&self, x: Vector2) -> Vector2 { vector![ self.s.a_a * x[0] + self.s.b_a * x[1], self.s.a_b * x[0] + self.s.b_b * x[1] ] } fn df(&self, _x: Vector2) -> Matrix2 { matrix![ self.s.a_a, self.s.b_a; self.s.a_b, self.s.b_b ] } fn get_settings(&self) -> &GiraffeSettings { &self.s } fn get_settings_mut(&mut self) -> &mut GiraffeSettings { &mut self.s } } impl From> for Vect { fn from(s: GiraffeSettings) -> Self { vector![s.a_a, s.a_b, s.b_a, s.b_b] } } impl From> for GiraffeSettings { fn from(v: Vect) -> Self { Self { a_a: v[0], a_b: v[1], b_a: v[2], b_b: v[3], } } } /*impl Coloring, [u8; 3], 2> for Giraffe { fn prepare>>( iter: I, ) -> Option> { let mut r = MinMaxColoringInfo { min: [1.0, 1.0], max: [0.0, 0.0], }; for val in iter { if val[0] < r.min[0] { r.min[0] = val[0]; } if val[0] > r.max[0] { r.max[0] = val[0]; } if val[1] < r.min[1] { r.min[1] = val[1]; } if val[1] > r.max[1] { r.max[1] = val[1]; } } if r.min[0] == r.max[0] || r.min[1] == r.max[1] { None } else { Some(r) } } fn color(pre: &MinMaxColoringInfo, val: Vect) -> [u8; 3] { [ ((val[1] - pre.min[1]).abs() / (pre.max[1] - pre.min[1]).abs() * 255.0) as u8, 0, ((val[0] - pre.min[0]).abs() / (pre.max[0] - pre.min[0]).abs() * 255.0) as u8, ] }*/ impl Coloring for Giraffe { fn prepare>>(_iter: I) -> Option<()> { Some(()) } fn color(_pre: &(), val: Vect) -> [u8; 3] { [ (val[0] * 255.0) as u8, ((val[0] + val[1]) * 127.5) as u8, 255 - (val[1] * 255.0) as u8, ] } } } /// https://arxiv.org/abs/2210.05227 pub mod lyfe { use super::*; #[derive(Clone, Debug)] pub struct LyfeSettings { pub da: T, pub db: T, pub f: T, pub r: T, } impl Settings for LyfeSettings {} #[derive(Clone)] pub struct Lyfe { pub s: LyfeSettings, } impl Model, 2> for Lyfe { fn f(&self, x: Vector2) -> Vector2 { vector![ x[0] * x[1].powi(2) + self.s.f * (1.0 - x[0]), x[0] * x[1].powi(2) - (self.s.f + self.s.r) * x[1] ] } fn df(&self, x: Vector2) -> Matrix2 { matrix![ x[1].powi(2)-self.s.f, 2.0*x[0]*x[1]; x[1].powi(2), 2.0*x[0]*x[1] - (self.s.f+self.s.r) ] } fn get_settings(&self) -> &LyfeSettings { &self.s } fn get_settings_mut(&mut self) -> &mut LyfeSettings { &mut self.s } } impl From> for Vect { fn from(s: LyfeSettings) -> Self { vector![s.da, s.db, s.f, s.r] } } impl From> for LyfeSettings { fn from(v: Vect) -> Self { Self { da: v[0], db: v[1], f: v[2], r: v[3], } } } /*impl Coloring, [u8; 3], 2> for Lyfe { fn prepare>>( iter: I, ) -> Option> { let mut r = MinMaxColoringInfo { min: [1.0, 1.0], max: [0.0, 0.0], }; for val in iter { if val[0] < r.min[0] { r.min[0] = val[0]; } if val[0] > r.max[0] { r.max[0] = val[0]; } if val[1] < r.min[1] { r.min[1] = val[1]; } if val[1] > r.max[1] { r.max[1] = val[1]; } } if r.min[0] == r.max[0] || r.min[1] == r.max[1] { None } else { Some(r) } } fn color(pre: &MinMaxColoringInfo, val: Vect) -> [u8; 3] { [ ((val[1] - pre.min[1]).abs() / (pre.max[1] - pre.min[1]).abs() * 255.0) as u8, 0, ((val[0] - pre.min[0]).abs() / (pre.max[0] - pre.min[0]).abs() * 255.0) as u8, ] }*/ impl Coloring for Lyfe { fn prepare>>(_iter: I) -> Option<()> { Some(()) } fn color(_pre: &(), val: Vect) -> [u8; 3] { [ (val[0] * 255.0) as u8, ((val[0] + val[1]) * 127.5) as u8, 255 - (val[1] * 255.0) as u8, ] } } } pub mod bike { use super::*; #[derive(Clone, Debug)] pub struct BikeSettings { /// Pénétration dans l'air pub cx: T, /// Gravité pub g: T, /// Masse pub m: T, /// Pente pub th: T, } impl Settings for BikeSettings {} fn b(x: f64, v: f64) -> f64 { 80. } fn db(x: f64, v: f64) -> Vector2 { vector![0., 0.] } #[derive(Clone)] pub struct Bike { pub s: BikeSettings, } impl Model, 2> for Bike { fn f(&self, x: Vector2) -> Vector2 { vector![ x[1], self.s.g * self.s.th.sin() - (self.s.cx * x[1].powi(2) + b(x[0], x[1])) / self.s.m ] } fn df(&self, x: Vector2) -> Matrix2 { let dbx = db(x[0], x[1]); matrix![ 0., 1.; -dbx[0]/self.s.m, -(2.*self.s.cx*x[1]+dbx[1])/self.s.m ] } fn get_settings(&self) -> &BikeSettings { &self.s } fn get_settings_mut(&mut self) -> &mut BikeSettings { &mut self.s } } impl From> for Vect { fn from(s: BikeSettings) -> Self { vector![s.cx, s.g, s.m, s.th] } } impl From> for BikeSettings { fn from(v: Vect) -> Self { Self { cx: v[0], g: v[1], m: v[2], th: v[3], } } } /*impl Coloring, [u8; 3], 2> for Lyfe { fn prepare>>( iter: I, ) -> Option> { let mut r = MinMaxColoringInfo { min: [1.0, 1.0], max: [0.0, 0.0], }; for val in iter { if val[0] < r.min[0] { r.min[0] = val[0]; } if val[0] > r.max[0] { r.max[0] = val[0]; } if val[1] < r.min[1] { r.min[1] = val[1]; } if val[1] > r.max[1] { r.max[1] = val[1]; } } if r.min[0] == r.max[0] || r.min[1] == r.max[1] { None } else { Some(r) } } fn color(pre: &MinMaxColoringInfo, val: Vect) -> [u8; 3] { [ ((val[1] - pre.min[1]).abs() / (pre.max[1] - pre.min[1]).abs() * 255.0) as u8, 0, ((val[0] - pre.min[0]).abs() / (pre.max[0] - pre.min[0]).abs() * 255.0) as u8, ] }*/ impl Coloring for Bike { fn prepare>>(_iter: I) -> Option<()> { Some(()) } fn color(_pre: &(), val: Vect) -> [u8; 3] { [ (val[0] * 255.0) as u8, ((val[0] + val[1]) * 127.5) as u8, 255 - (val[1] * 255.0) as u8, ] } } } pub mod bike2 { use super::*; #[derive(Clone, Debug)] pub struct BikeSettings { /// Pénétration dans l'air pub cx: T, /// Gravité pub g: T, /// Masse pub m: T, /// Pente pub th: T, /// (x, v, settings) -> ((b1, b2), (b1', b2')) pub b: fn(T, T, &BikeSettings) -> ((T, T), (T, T)), } impl Settings for BikeSettings {} #[derive(Clone)] pub struct Bike { pub s: BikeSettings, } impl Model, 2> for Bike { fn f(&self, x: Vector2) -> Vector2 { let ((b1, b2), (_db1, _db2)) = (self.s.b)(x[0], x[1], &self.s); vector![ x[1], self.s.g * self.s.th.sin() - (self.s.cx * x[1].powi(2) + b1 + b2) / self.s.m ] } fn df(&self, x: Vector2) -> Matrix2 { let ((_b1, _b2), (db1, db2)) = (self.s.b)(x[0], x[1], &self.s); matrix![ 0., 1.; 0., -(2.*self.s.cx*x[1]+db1+db2)/self.s.m ] } fn get_settings(&self) -> &BikeSettings { &self.s } fn get_settings_mut(&mut self) -> &mut BikeSettings { &mut self.s } } }