use crate::nsga2::configuration::ObjectiveDirection;
use crate::traits::ChromosomeT;
#[derive(Debug, Clone)]
pub struct ParetoIndividual<U>
where
U: ChromosomeT,
{
pub chromosome: U,
pub objectives: Vec<f64>,
pub rank: usize,
pub crowding_distance: f64,
pub constraint_violation: f64,
}
impl<U> ParetoIndividual<U>
where
U: ChromosomeT,
{
pub fn new(chromosome: U, objectives: Vec<f64>) -> Self {
ParetoIndividual {
chromosome,
objectives,
rank: 0,
crowding_distance: 0.0,
constraint_violation: 0.0,
}
}
pub fn is_feasible(&self) -> bool {
self.constraint_violation <= 0.0
}
}
#[derive(Debug, Clone)]
pub struct ParetoFront<U>
where
U: ChromosomeT,
{
pub individuals: Vec<ParetoIndividual<U>>,
}
impl<U> ParetoFront<U>
where
U: ChromosomeT,
{
pub fn new(individuals: Vec<ParetoIndividual<U>>) -> Self {
ParetoFront { individuals }
}
pub fn len(&self) -> usize {
self.individuals.len()
}
pub fn is_empty(&self) -> bool {
self.individuals.is_empty()
}
}
pub fn dominates(a: &[f64], b: &[f64]) -> bool {
let mut at_least_one_better = false;
for (ai, bi) in a.iter().zip(b.iter()) {
if ai > bi {
return false;
}
if ai < bi {
at_least_one_better = true;
}
}
at_least_one_better
}
pub fn dominates_with_directions(a: &[f64], b: &[f64], directions: &[ObjectiveDirection]) -> bool {
let mut at_least_one_better = false;
for (idx, (ai, bi)) in a.iter().zip(b.iter()).enumerate() {
let dir = directions
.get(idx)
.copied()
.unwrap_or(ObjectiveDirection::Minimize);
let (better, worse) = match dir {
ObjectiveDirection::Minimize => (ai < bi, ai > bi),
ObjectiveDirection::Maximize => (ai > bi, ai < bi),
};
if worse {
return false;
}
if better {
at_least_one_better = true;
}
}
at_least_one_better
}
pub fn constrained_dominates(
a_obj: &[f64],
b_obj: &[f64],
a_violation: f64,
b_violation: f64,
directions: &[ObjectiveDirection],
) -> bool {
let a_feasible = a_violation <= 0.0;
let b_feasible = b_violation <= 0.0;
match (a_feasible, b_feasible) {
(true, true) => dominates_with_directions(a_obj, b_obj, directions),
(true, false) => true,
(false, true) => false,
(false, false) => a_violation < b_violation,
}
}