use ndarray::Array1;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Individual {
pub variables: Array1<f64>,
pub fitness: f64,
}
impl Individual {
pub fn new(variables: Array1<f64>, fitness: f64) -> Self {
Self { variables, fitness }
}
}
pub trait Problem: Send + Sync {
fn objective(&self, variables: &Array1<f64>) -> f64;
fn penalty(&self, _variables: &Array1<f64>) -> f64 {
0.0
}
fn fitness(&self, variables: &Array1<f64>) -> f64 {
self.objective(variables) + self.penalty(variables)
}
fn dim(&self) -> usize;
fn bounds(&self) -> (Array1<f64>, Array1<f64>);
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MultiObjectiveIndividual {
pub variables: Array1<f64>,
pub fitness: Vec<f64>,
pub rank: usize,
pub crowding_distance: f64,
}
impl MultiObjectiveIndividual {
pub fn new(variables: Array1<f64>, fitness: Vec<f64>) -> Self {
Self {
variables,
fitness,
rank: 0,
crowding_distance: 0.0
}
}
}
pub trait MultiObjectiveProblem: Send + Sync {
fn objectives(&self, variables: &Array1<f64>) -> Vec<f64>;
fn penalties(&self, _variables: &Array1<f64>) -> Vec<f64> {
vec![]
}
fn dim(&self) -> usize;
fn bounds(&self) -> (Array1<f64>, Array1<f64>);
fn num_objectives(&self) -> usize;
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MultiObjectiveResult {
pub pareto_front: Vec<MultiObjectiveIndividual>,
pub history: Vec<f64>, }
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SolverConfig {
pub population_size: usize,
pub max_iterations: usize,
}
impl Default for SolverConfig {
fn default() -> Self {
Self {
population_size: 50,
max_iterations: 100,
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct OptimizationResult {
pub best_variables: Array1<f64>,
pub best_fitness: f64,
pub history: Vec<f64>,
}
pub struct SimpleProblem<F>
where F: Fn(&Array1<f64>) -> f64 + Send + Sync
{
pub objective_func: F,
pub dim: usize,
pub lower: Array1<f64>,
pub upper: Array1<f64>,
}
impl<F> Problem for SimpleProblem<F>
where F: Fn(&Array1<f64>) -> f64 + Send + Sync
{
fn objective(&self, variables: &Array1<f64>) -> f64 {
(self.objective_func)(variables)
}
fn dim(&self) -> usize { self.dim }
fn bounds(&self) -> (Array1<f64>, Array1<f64>) {
(self.lower.clone(), self.upper.clone())
}
}