From 6141d4a9b2d391e03973253dedd417cac2c84750 Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Thu, 29 Aug 2024 07:50:26 +0100 Subject: [PATCH 01/14] Added Python API to generate reference points with DasDarren1998 --- optirustic-py/README.md | 32 ++++++++++ optirustic-py/optirustic.pyi | 59 ++++++++++++++++-- optirustic-py/src/constraint.rs | 2 +- optirustic-py/src/lib.rs | 14 +---- optirustic-py/src/reference_points.rs | 80 ++++++++++++++++++++++++ optirustic-py/tests/test_api.py | 87 ++++++++++++++++++++++----- 6 files changed, 243 insertions(+), 31 deletions(-) create mode 100644 optirustic-py/src/reference_points.rs diff --git a/optirustic-py/README.md b/optirustic-py/README.md index b6040ce..87a12f8 100644 --- a/optirustic-py/README.md +++ b/optirustic-py/README.md @@ -100,3 +100,35 @@ NSGA2.plot_convergence( ) plt.show() ``` + +## Generate reference points +To generate, plot and inspect the reference points for the `NSGA3` algorithm you can us: + +### One layer + +```python +import matplotlib.pyplot as plt +from optirustic import DasDarren1998 + +ds = DasDarren1998(number_of_objectives=3, number_of_partitions=5) +points = ds.calculate() +ds.plot(points) +plt.show() + +``` +### Two layers + +```python +import matplotlib.pyplot as plt +from optirustic import DasDarren1998 + +two_layers = dict( + boundary_layer=3, + inner_layer=4, + scaling=None, +) +ds = DasDarren1998(number_of_objectives=3, number_of_partitions=two_layers) +points = ds.calculate() +ds.plot(points) +plt.show() +``` \ No newline at end of file diff --git a/optirustic-py/optirustic.pyi b/optirustic-py/optirustic.pyi index 48406ae..b61897b 100644 --- a/optirustic-py/optirustic.pyi +++ b/optirustic-py/optirustic.pyi @@ -1,5 +1,6 @@ from datetime import timedelta, datetime from enum import Enum +from typing import TypedDict import matplotlib.pyplot as plt @@ -288,10 +289,58 @@ class NSGA3(AlgorithmData): :return: The figure object. """ -def plot_reference_points(reference_points: list[list[float]]) -> plt.Figure: +class TwoLayerPartitions(TypedDict): + boundary_layer: int + """ This is the number of partitions to use in the boundary layer. """ + inner_layer: int + """ This is the number of partitions to use in the inner layer. """ + scaling: float | None + """ Control the size of the inner layer. This defaults to 0.5 which means that the + maximum points on each objectives axis will be located at 0.5 instead of 1 (as in + the boundary layer). """ + +class DasDarren1998: """ - Generate a chart showing the reference point locations (for example using the Das - & Darren (2019) method). - :param reference_points: The reference points. - :return: The figure object. + Derive the reference points or weights using the methodology suggested in Section 5.2 in the + Das & Dennis (1998) paper (https://doi.org/10.1137/S1052623496307510) """ + + def __init__( + self, number_of_objectives: int, number_of_partitions: int | TwoLayerPartitions + ): + """ + Derive the reference points or weights using the methodology suggested by + Das & Dennis (1998). + :param number_of_objectives: The number of problem objectives. + :param number_of_partitions: The number of uniform gaps between two consecutive + points along all objective axis on the hyperplane. With this option you can + create one or two layer of points with different spacing: To create: + - 1 layer or set of points with a constant uniform gaps use a 'int'. + - 2 layers of points with each layer having a different gap use a + dictionary with the following keys: inner_layer (the number of partitions + to use in the inner layer), boundary_layer (the number of partitions to + use in the boundary layer) and scaling (to control the size of the inner) + layer. This defaults to 0.5 which means that the maximum points on each + objectives axis will be located at 0.5 instead of 1 (as in the boundary layer + Use the 2nd approach if you are trying to solve a problem with many objectives + (4 or more) and want to reduce the number of reference points to use. Using two + layers allows (1) setting a smaller number of reference points, (2) controlling + the point density in the inner area and (3) ensure a well-spaced point distribution. + """ + + def calculate(self) -> list[list[float]]: + """ + Generate the vector of weights of reference points. + :return: The vector of weights of size `number_of_points`. Each nested list, + of size equal to `number_of_objectives`, contains the relative coordinates + (between 0 and 1) of the points for each objective. + """ + + @staticmethod + def plot(reference_points: list[list[float]]) -> plt.Figure: + """ + Generate a chart showing the reference point locations (for example using the Das + & Darren (2019) method). + :param reference_points: The reference points. + :return: The figure object. + """ diff --git a/optirustic-py/src/constraint.rs b/optirustic-py/src/constraint.rs index 071f7db..8e5c3a2 100644 --- a/optirustic-py/src/constraint.rs +++ b/optirustic-py/src/constraint.rs @@ -5,7 +5,7 @@ use pyo3::prelude::*; use optirustic::core::{Constraint, RelationalOperator}; /// Constraint -#[pyclass(name = "PyRelationalOperator", eq, eq_int)] +#[pyclass(name = "RelationalOperator", eq, eq_int)] #[derive(PartialEq)] pub enum PyRelationalOperator { EqualTo, diff --git a/optirustic-py/src/lib.rs b/optirustic-py/src/lib.rs index 81adf0b..9a8931c 100644 --- a/optirustic-py/src/lib.rs +++ b/optirustic-py/src/lib.rs @@ -18,11 +18,13 @@ use crate::constraint::PyRelationalOperator; use crate::individual::{PyData, PyIndividual}; use crate::objective::PyObjectiveDirection; use crate::problem::PyProblem; +use crate::reference_points::PyDasDarren1998; mod constraint; mod individual; mod objective; mod problem; +mod reference_points; mod variable; /// Get the python function from the utils.plot module @@ -252,23 +254,13 @@ impl NSGA3 { } } -#[pyfunction] -/// Reference point plot from vector -pub fn plot_reference_points(ref_points: Vec>) -> PyResult { - Python::with_gil(|py| { - let fun: Py = get_plot_fun("plot_reference_points", py)?; - fun.call1(py, (ref_points,)) - }) -} - #[pymodule(name = "optirustic")] fn optirustic_py(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; - - m.add_function(wrap_pyfunction!(plot_reference_points, m)?)?; + m.add_class::()?; Ok(()) } diff --git a/optirustic-py/src/reference_points.rs b/optirustic-py/src/reference_points.rs new file mode 100644 index 0000000..7e7b470 --- /dev/null +++ b/optirustic-py/src/reference_points.rs @@ -0,0 +1,80 @@ +use pyo3::exceptions::PyValueError; +use pyo3::prelude::*; + +use optirustic::utils::{DasDarren1998, NumberOfPartitions, TwoLayerPartitions}; + +use crate::get_plot_fun; + +#[derive(Clone, Debug, FromPyObject)] +#[pyo3(from_item_all)] +pub struct PyTwoLayerPartitions { + pub boundary_layer: usize, + pub inner_layer: usize, + pub scaling: Option, +} + +#[derive(Clone, Debug, FromPyObject)] +pub enum PyNumberOfPartitions { + #[pyo3(transparent, annotation = "int")] + OneLayer(usize), + #[pyo3(transparent, annotation = "dict")] + TwoLayers(PyTwoLayerPartitions), +} + +#[pyclass(name = "DasDarren1998")] +#[derive(Clone)] +pub struct PyDasDarren1998 { + number_of_objectives: usize, + number_of_partitions: PyNumberOfPartitions, +} + +// TODO number_of_partitions number or dict +#[pymethods] +impl PyDasDarren1998 { + #[new] + /// Initialise the class + pub fn new( + number_of_objectives: usize, + number_of_partitions: PyNumberOfPartitions, + ) -> PyResult { + Ok(Self { + number_of_objectives, + number_of_partitions, + }) + } + + pub fn calculate(&self) -> PyResult>> { + let number_of_partitions = match &self.number_of_partitions { + PyNumberOfPartitions::OneLayer(n) => NumberOfPartitions::OneLayer(*n), + PyNumberOfPartitions::TwoLayers(data) => { + NumberOfPartitions::TwoLayers(TwoLayerPartitions { + boundary_layer: data.boundary_layer, + inner_layer: data.inner_layer, + scaling: data.scaling, + }) + } + }; + let ds = DasDarren1998::new(self.number_of_objectives, &number_of_partitions) + .map_err(|e| PyValueError::new_err(e.to_string()))?; + Ok(ds.get_weights()) + } + + /// Reference point plot from vector + pub fn plot(&self, ref_points: Vec>) -> PyResult { + Python::with_gil(|py| { + let fun: Py = get_plot_fun("plot_reference_points", py)?; + fun.call1(py, (ref_points,)) + }) + } + + pub fn __repr__(&self) -> PyResult { + Ok(format!( + "DasDarren1998(number_of_objectives={}, number_of_partitions={:?})", + self.number_of_objectives, self.number_of_partitions + )) + } + + pub fn __str__(&self) -> String { + self.__repr__().unwrap() + } +} diff --git a/optirustic-py/tests/test_api.py b/optirustic-py/tests/test_api.py index 4d104ca..7707d0c 100644 --- a/optirustic-py/tests/test_api.py +++ b/optirustic-py/tests/test_api.py @@ -2,14 +2,21 @@ from pathlib import Path import matplotlib.pyplot as plt -from optirustic import NSGA3, ObjectiveDirection, NSGA2 +from optirustic import ( + NSGA3, + ObjectiveDirection, + NSGA2, + DasDarren1998, +) class PythonTest(unittest.TestCase): root_folder = Path(__file__).parent.parent.parent def test_reader(self): - file = self.root_folder / "examples" / "results" / "DTLZ1_3obj_NSGA3_gen400.json" + file = ( + self.root_folder / "examples" / "results" / "DTLZ1_3obj_NSGA3_gen400.json" + ) data = NSGA3(file.as_posix()) p = data.problem @@ -33,21 +40,73 @@ def test_reader(self): self.assertAlmostEqual(data.hyper_volume([100, 100, 100]), 999999.97, 2) def test_plot(self): - self.assertTrue(isinstance(NSGA2( - (self.root_folder / "examples" / "results" / "SCH_2obj_NSGA2_gen250.json").as_posix() - ).plot(), plt.Figure)) + self.assertTrue( + isinstance( + NSGA2( + ( + self.root_folder + / "examples" + / "results" + / "SCH_2obj_NSGA2_gen250.json" + ).as_posix() + ).plot(), + plt.Figure, + ) + ) - self.assertTrue(isinstance(NSGA3( - (self.root_folder / "examples" / "results" / "DTLZ1_3obj_NSGA3_gen400.json").as_posix() - ).plot(), plt.Figure)) + self.assertTrue( + isinstance( + NSGA3( + ( + self.root_folder + / "examples" + / "results" + / "DTLZ1_3obj_NSGA3_gen400.json" + ).as_posix() + ).plot(), + plt.Figure, + ) + ) - self.assertTrue(isinstance(NSGA3( - (self.root_folder / "examples" / "results" / "DTLZ1_8obj_NSGA3_gen750.json").as_posix() - ).plot(), plt.Figure)) + self.assertTrue( + isinstance( + NSGA3( + ( + self.root_folder + / "examples" + / "results" + / "DTLZ1_8obj_NSGA3_gen750.json" + ).as_posix() + ).plot(), + plt.Figure, + ) + ) - self.assertTrue(isinstance(NSGA2.plot_convergence( - (self.root_folder / "examples" / "results" / "convergence").as_posix(), [10000, 10000] - ), plt.Figure)) + self.assertTrue( + isinstance( + NSGA2.plot_convergence( + ( + self.root_folder / "examples" / "results" / "convergence" + ).as_posix(), + [10000, 10000], + ), + plt.Figure, + ) + ) + + def test_reference_points(self): + ds = DasDarren1998(3, 5) + points = ds.calculate() + self.assertEqual(len(points), 21) + self.assertTrue(isinstance(ds.plot(points), plt.Figure)) + + two_layers = dict( + boundary_layer=3, + inner_layer=4, + scaling=None, + ) + ds = DasDarren1998(3, two_layers) + self.assertEqual(len(ds.calculate()), 25) if __name__ == "__main__": From 0c0dcf0c796adfc3350d8f46833d8c861f592875 Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 06:44:31 +0100 Subject: [PATCH 02/14] Added AdaptiveReferencePoints and AdaptiveNSGA3 that implement the adaptive NSGA3 with dynamic reference points --- README.md | 17 +- src/algorithms/a_nsga3.rs | 15 + src/algorithms/mod.rs | 2 + src/algorithms/nsga3/adaptive_ref_points.rs | 379 ++++++++++++++++++++ src/algorithms/nsga3/mod.rs | 50 ++- src/utils/reference_points.rs | 1 - 6 files changed, 456 insertions(+), 8 deletions(-) create mode 100644 src/algorithms/a_nsga3.rs create mode 100644 src/algorithms/nsga3/adaptive_ref_points.rs diff --git a/README.md b/README.md index 8d21b38..ecbfc31 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,10 @@ evolutionary algorithms (MOEAs). It allows you to: - export the population history as JSON and resume its evolution from file - generate charts with the dedicated [Python package](https://pypi.org/project/optirustic/) -At the moment, it comes with the `NSGA2` and `NSGA3` algorithms. +The library comes with the following +algorithms: [`NSGA2`](https://docs.rs/optirustic/latest/optirustic/algorithms/struct.NSGA2.html), +[`NSGA3`](https://docs.rs/optirustic/latest/optirustic/algorithms/struct.NSGA3.html) and +[`AdaptiveNSGA3`](https://docs.rs/optirustic/latest/optirustic/algorithms/struct.AdaptiveNSGA3.html). The API documentation is available on [docs.rs](https://docs.rs/optirustic/). Examples showcasing this library's features are available in @@ -160,6 +163,18 @@ and these are the plotted solutions:

(back to top)

+### Plotting and inspecting data + +With the library, you can set +the [`export_history`](https://docs.rs/optirustic/latest/optirustic/algorithms/struct.NSGA2Arg.html#structfield.export_history) +option, to export serialised results as JSON files as the algorithm evolves, or +call [`save_to_json`](https://docs.rs/optirustic/latest/optirustic/algorithms/trait.Algorithm.html#method.save_to_json) +to export the results at the last population evolution. + +This crate comes with a companion [Python package](./optirustic-py) to inspect the results +and easily plot the Pareto front or the algorithm convergence. This is how all the charts within +this README file were generated. Have a look at the `py` file in the [example folder](./examples). + # License This project is licensed under the terms of the MIT license. \ No newline at end of file diff --git a/src/algorithms/a_nsga3.rs b/src/algorithms/a_nsga3.rs new file mode 100644 index 0000000..25f4eb3 --- /dev/null +++ b/src/algorithms/a_nsga3.rs @@ -0,0 +1,15 @@ +use crate::algorithms::{NSGA3Arg, NSGA3}; +use crate::core::{OError, Problem}; + +/// Adaptive `NSGA3` algorithm. This is an alias for [`NSGA3`] when the `adaptive` option is set to +/// `true`. +pub struct AdaptiveNSGA3; + +impl AdaptiveNSGA3 { + /// Initialise the [`NSGA3`] algorithm with `adaptive` option set to `true`. + /// + /// returns: `NSGA3` + pub fn new(problem: Problem, options: NSGA3Arg) -> Result { + NSGA3::new(problem, options, true) + } +} diff --git a/src/algorithms/mod.rs b/src/algorithms/mod.rs index 7beb300..703780c 100644 --- a/src/algorithms/mod.rs +++ b/src/algorithms/mod.rs @@ -1,3 +1,4 @@ +pub use a_nsga3::AdaptiveNSGA3; pub use algorithm::{Algorithm, AlgorithmExport, AlgorithmSerialisedExport, ExportHistory}; pub use nsga2::{NSGA2Arg, NSGA2}; pub use nsga3::{NSGA3Arg, Nsga3NumberOfIndividuals, NSGA3}; @@ -5,6 +6,7 @@ pub use stopping_condition::{ MaxDuration, MaxGeneration, StoppingCondition, StoppingConditionType, }; +mod a_nsga3; mod algorithm; mod nsga2; mod nsga3; diff --git a/src/algorithms/nsga3/adaptive_ref_points.rs b/src/algorithms/nsga3/adaptive_ref_points.rs new file mode 100644 index 0000000..cb0d1a4 --- /dev/null +++ b/src/algorithms/nsga3/adaptive_ref_points.rs @@ -0,0 +1,379 @@ +use std::collections::HashMap; + +use log::debug; + +use crate::core::OError; +use crate::utils::{vector_min, DasDarren1998, NumberOfPartitions}; + +/// This implements the adaptive reference point procedure Jain and Deb (2013) in Section VII. This +/// will identify non-useful points and re-position them to try to allocate one point for each +/// Pareto-optimal solution. This archived in two steps: +/// +/// 1) **Addition of new reference points:** for each crowded point, where the niche counter rho_j +/// is larger or equal to 2, three new points are added around the reference point. The points +/// are centred around the original point with the same gap. +/// The new points are accepted if they lie in the 1st quadrant (i.e. all their coordinates are +/// between 0 and 1) and they do not overlap with any existing reference point. +/// 2) **Deletion of existing reference points:** if all reference point have a niche counter equal +/// to 1 (ideal case), all new included points with rho_j=0 are deleted. Original points with +/// no association and new points with rho_j=1 are preserved. +/// +/// > Jain, Himanshu & Deb, Kalyanmoy. (2014). An Evolutionary Many-Objective Optimization +/// > Algorithm Using Reference-Point Based Non dominated Sorting Approach, Part II: Handling +/// > Constraints and Extending to an Adaptive Approach. Evolutionary Computation, IEEE +/// > Transactions on. 18. 602-622. . +pub(crate) struct AdaptiveReferencePoints<'a> { + /// The vector of reference points. Their position will change and new points will be added or + /// deleted depending on the Pareto front evolution. + reference_points: &'a mut Vec>, + /// The map mapping the reference point index to the number of associated individuals. + rho_j: &'a mut HashMap, + /// The number of original reference points. This is used to identify whether a point in + /// `reference_points` and `rho_j` is an original one, created when the evolution started. + number_of_or_reference_points: usize, + /// The three points to add around an original reference point. They lie on the plane through + /// the origin + new_points_set: Vec>, +} + +impl<'a> AdaptiveReferencePoints<'a> { + /// Initialise the adaptive algorithm. + /// + /// # Arguments + /// + /// * `reference_points`: The vector of reference points. + /// * `rho_j`: The map mapping the reference point index to the number of associated + /// individuals. + /// * `number_of_or_reference_points`: The number of original reference points. + /// + /// returns: `Result` + pub fn new( + reference_points: &'a mut Vec>, + rho_j: &'a mut HashMap, + number_of_or_reference_points: usize, + ) -> Result { + let number_of_objectives = reference_points.first().unwrap().len(); + + // measure the minimum gap between the points. This equal to 1 divided by the number of + // partitions for one layer. With two layer, this gives the minimum gap of the two layers. + let gap = (0..reference_points.len() - 1) + .flat_map(|p_id| { + (0..3) + .filter_map(|c_id| { + let d = f64::abs( + reference_points[p_id][c_id] - reference_points[p_id + 1][c_id], + ); + if d > 0.0 { + Some(d) + } else { + None + } + }) + .collect::>() + }) + .collect::>(); + let gap = vector_min(&gap)?; + + // create the 3 new points with the gap. These can be shifted with respect to the original + // reference point later + let ds = DasDarren1998::new(number_of_objectives, &NumberOfPartitions::OneLayer(1))?; + + // scale them to have the same original gap + let mut new_points_set = ds.get_weights(); + new_points_set = new_points_set + .iter() + .map(|new_p| new_p.iter().map(|new_c| new_c * gap).collect()) + .collect(); + + // shift them with respect to the plane centroid so that the plane they lie on pass through + // the origin + let centroid: Vec = (0..number_of_objectives) + .map(|c_idx| { + new_points_set.iter().map(|v| v[c_idx]).sum::() / new_points_set.len() as f64 + }) + .collect(); + new_points_set = new_points_set + .iter() + .map(|new_p| { + new_p + .iter() + .zip(¢roid) + .map(|(coord, ci)| coord - ci) + .collect() + }) + .collect(); + + Ok(AdaptiveReferencePoints { + reference_points, + rho_j, + number_of_or_reference_points, + new_points_set, + }) + } + + /// Add and remove new reference points. + pub fn calculate(&mut self) -> Result<(), OError> { + self.add()?; + self.delete(); + + Ok(()) + } + + /// Add new reference points if needed. + fn add(&mut self) -> Result<(), OError> { + // addition is performed on original reference points only. + let mut all_new_points = vec![]; + for (ref_point_index, counter) in self.rho_j.iter() { + if self.is_original_ref_point(*ref_point_index) && *counter >= 2 { + // shift the simplex with the three points to be centred around the original + // reference point + let new_points: Vec> = self + .new_points_set + .iter() + .map(|new_p| { + // coordinates + new_p + .iter() + .zip(&self.reference_points[*ref_point_index]) + .map(|(new_c, old_c)| new_c + old_c) + .collect() + }) + .collect(); + + debug!( + "Selected new ref points {:?} for #{ref_point_index} = {:?}", + new_points, &self.reference_points[*ref_point_index] + ); + all_new_points.push(new_points); + } + } + + // add the points to the ref point list and niche counter + for new_points in all_new_points { + for point in new_points { + // skip if the point already exists or is outside the 1st quadrant + if self.has_point(&point, None) { + debug!("Disregarded already existing ref point {:?}", point); + continue; + } + if point.iter().any(|c| *c < 0.0 || *c > 1.0) { + debug!("Disregarded outside-range ref point {:?}", point); + continue; + } + + debug!("Added new ref points {:?}", point); + self.reference_points.push(point); + let new_index = self.reference_points.len(); + self.rho_j.insert(new_index, 0); + } + } + + Ok(()) + } + + /// Delete the additional reference points. + fn delete(&mut self) { + // Count number of points with a perfect association to an individual (niche counter is 1) + let perfect_assoc_counter: usize = self + .rho_j + .iter() + .map(|(_, counter)| if *counter == 1 { 1 } else { 0 }) + .sum(); + + println!("perfect_assoc_counter={perfect_assoc_counter}"); + // delete new points without association + if perfect_assoc_counter == self.number_of_or_reference_points { + let mut points_to_delete = vec![]; + for (ref_point_idx, point) in self.reference_points.iter().enumerate() { + // ignore original reference points + if self.is_original_ref_point(ref_point_idx) { + continue; + } + // delete new point from map + if self.rho_j[&ref_point_idx] == 0 { + points_to_delete.push(point.clone()); + self.rho_j.remove(&ref_point_idx); + } + } + + println!("points_to_delete={:?}", points_to_delete); + self.reference_points + .retain(|v| !points_to_delete.contains(&v)); + } + } + + /// Check whether the reference point index identifies a original point created when the + /// evolution started. + /// + /// # Arguments + /// * `ref_point_index`: The reference point index. + /// + /// return: `bool` + fn is_original_ref_point(&self, ref_point_index: usize) -> bool { + ref_point_index < self.number_of_or_reference_points + } + + /// Check if the reference point set has already the new `point`. This returns `true` if all + /// `point`'s coordinates are close to a reference point within the `tolerance`. This is done + /// due to rounding errors when the new reference points are scaled and translated. + /// + /// # Arguments + /// + /// * `point`: The new point to check. + /// * `tolerance`: The tolerance. Defaults to `10^-6`. + /// + /// returns: `bool` + pub fn has_point(&self, point: &[f64], tolerance: Option) -> bool { + let tolerance = tolerance.unwrap_or(0.000001); + for ref_point in self.reference_points.iter() { + if ref_point + .iter() + .zip(point) + .all(|(r, p)| (r - p).abs() < tolerance) + { + return true; + } + } + return false; + } +} + +#[cfg(test)] +mod test { + use std::collections::HashMap; + use std::panic; + + use crate::algorithms::nsga3::adaptive_ref_points::AdaptiveReferencePoints; + use crate::core::test_utils::assert_approx_array_eq; + use crate::utils::{DasDarren1998, NumberOfPartitions}; + + #[test] + /// Add new points around the reference points + fn test_ref_point_addition() { + let ds = DasDarren1998::new(3, &NumberOfPartitions::OneLayer(5)).unwrap(); + + let test_data = HashMap::from([ + // 2 points have negative coordinates + ( + 3_usize, + (1_usize, vec![vec![0.13333333, 0.53333333, 0.33333333]]), + ), + // all 3 points are added + ( + 12, + ( + 3, + vec![ + vec![0.33333333, 0.13333333, 0.53333333], + vec![0.33333333, 0.33333333, 0.33333333], + vec![0.53333333, 0.13333333, 0.33333333], + ], + ), + ), + ]); + + for (sc_id, (ref_point_index, results)) in test_data.iter().enumerate() { + let mut ref_points = ds.get_weights(); + let mut rho_j = HashMap::new(); + for point_idx in 0..ref_points.len() { + rho_j.insert(point_idx, 0); + } + *rho_j.get_mut(&ref_point_index).unwrap() = 2_usize; + let counter = ref_points.len(); + + let mut a = AdaptiveReferencePoints::new(&mut ref_points, &mut rho_j, counter).unwrap(); + a.calculate().unwrap(); + + // check point counter + assert_eq!(ref_points.len(), counter + results.0); + assert_eq!(rho_j.len(), ref_points.len()); + + // check expected points + for (pos, expected) in results.1.iter().enumerate() { + let result = panic::catch_unwind(|| { + assert_approx_array_eq( + &ref_points[ref_points.len() - (results.1.len()) + pos], + &expected, + None, + ); + }); + match result { + Ok(_) => {} + Err(e) => match e.downcast::() { + Ok(v) => panic!( + "Scenario {} failed because:\n {:?}.\n Reference points were: {:?}", + sc_id + 1, + v, + ref_points + ), + _ => {} + }, + } + } + } + } + + #[test] + /// Create more points, but some overlaps and are not added twice + fn test_ref_point_addition_overlap() { + let ds = DasDarren1998::new(3, &NumberOfPartitions::OneLayer(5)).unwrap(); + let mut ref_points = ds.get_weights(); + let mut rho_j = HashMap::new(); + for point_idx in 0..ref_points.len() { + rho_j.insert(point_idx, 0); + } + assert_approx_array_eq(&ref_points[7], &[0.2, 0.2, 0.6], Some(0.0)); + *rho_j.get_mut(&7).unwrap() = 2_usize; + + assert_approx_array_eq(&ref_points[12], &[0.4, 0.2, 0.4], Some(0.0)); + *rho_j.get_mut(&12).unwrap() = 2_usize; + + let counter = ref_points.len(); + + let mut a = AdaptiveReferencePoints::new(&mut ref_points, &mut rho_j, counter).unwrap(); + a.calculate().unwrap(); + + // one point ([0.33333333 0.13333333 0.53333333]) is in common + assert_eq!(ref_points.len(), counter + 5); + assert_eq!(rho_j.len(), ref_points.len()); + } + + #[test] + fn test_ref_point_deletion() { + let ds = DasDarren1998::new(3, &NumberOfPartitions::OneLayer(5)).unwrap(); + let mut ref_points = ds.get_weights(); + let or_counter = ref_points.len(); + + let mut rho_j = HashMap::new(); + // all original points have one association except one + for point_idx in 0..ref_points.len() { + rho_j.insert(point_idx, 1); + } + rho_j.insert(11, 0); + + // add new points + ref_points.push(vec![0.33, 0.13, 0.53]); // 21 + ref_points.push(vec![0.33, 0.33, 0.33]); // 22 + rho_j.insert(21, 0); + rho_j.insert(22, 1); + + println!("rho_j={:?}", rho_j); + // TODO point 21 will be deleted + let counter = ref_points.len(); + println!("{:?}", counter); + let mut a = AdaptiveReferencePoints::new(&mut ref_points, &mut rho_j, or_counter).unwrap(); + a.calculate().unwrap(); + + // one additional point is preserved + assert_eq!(a.reference_points.len(), or_counter + 1); + + // point 21 is deleted + assert_eq!(ref_points.contains(&vec![0.33, 0.13, 0.53]), false); + assert_eq!(rho_j.contains_key(&21), false); + + // point 22 still present along with all original ref points + assert_eq!(ref_points.contains(&vec![0.33, 0.33, 0.33]), true); + assert_eq!(rho_j.contains_key(&22), true); + assert_eq!(rho_j.contains_key(&11), true); + } +} diff --git a/src/algorithms/nsga3/mod.rs b/src/algorithms/nsga3/mod.rs index 3edbb88..1ee5b29 100644 --- a/src/algorithms/nsga3/mod.rs +++ b/src/algorithms/nsga3/mod.rs @@ -7,6 +7,7 @@ use rand::RngCore; use optirustic_macros::{as_algorithm, as_algorithm_args, impl_algorithm_trait_items}; +use crate::algorithms::nsga3::adaptive_ref_points::AdaptiveReferencePoints; use crate::algorithms::nsga3::associate::AssociateToRefPoint; use crate::algorithms::nsga3::niching::Niching; use crate::algorithms::nsga3::normalise::Normalise; @@ -19,6 +20,7 @@ use crate::operators::{ }; use crate::utils::{fast_non_dominated_sort, DasDarren1998, NumberOfPartitions}; +mod adaptive_ref_points; mod associate; mod niching; mod normalise; @@ -91,6 +93,9 @@ pub struct NSGA3Arg { pub struct NSGA3 { /// The vector of reference points reference_points: Vec>, + /// The number of original reference points. This equals the size of `reference_points` if + /// the `adaptive` option is set to `false`. + number_of_or_reference_points: usize, /// The ideal point coordinates when the algorithm starts up to the current evolution ideal_point: Vec, /// The operator to use to select the individuals for reproduction. This is a binary tournament @@ -103,6 +108,9 @@ pub struct NSGA3 { mutation_operator: PolynomialMutation, /// The seed to use. rng: Box, + /// Whether to use the reference point adaptive approach and convert the algorithm from `NSGA3` + /// to `A-NSGA3`. + adaptive: bool, } impl NSGA3 { @@ -111,11 +119,27 @@ impl NSGA3 { /// # Arguments /// /// * `problem`: The problem being solved. - /// * `args`: The [`NSGA3Arg`] arguments to customise the algorithm behaviour. + /// * `options`: The [`NSGA3Arg`] arguments to customise the algorithm behaviour. + /// * `adaptive`: Whether to use the adaptive approach to handle the reference points. Normally + /// reference points are fixed and never change position, and `NSGA3` will try to associate one + /// individual to each reference point. However, there are some problems where the reference lines + /// never intersects the Pareto front and no Pareto-optimal solutions are associated to those + /// reference points. The reference points intersecting the front may have too many points + /// associated and create crowded solutions. + /// To improve the solutions for these kind of problems, when this option is set to `true`, new + /// reference points will adaptively be added around the provided points to reduce crowding and + /// force one solution to be associated to preferably only on reference direction. + /// This option converts `NSGA3` to [`crate::algorithms::AdaptiveNSGA3`] (where `A` stands for + /// adaptive) and it is explained in Section VII of Jain and Deb (2013). For a detailed + /// explanation about the implementation see `AdaptiveReferencePoints`. /// /// returns: `NSGA3`. - pub fn new(problem: Problem, options: NSGA3Arg) -> Result { - let name = "NSGA3".to_string(); + pub fn new(problem: Problem, options: NSGA3Arg, adaptive: bool) -> Result { + let name = if !adaptive { + "NSGA3".to_string() + } else { + "AdaptiveNSGA3".to_string() + }; let nsga3_args = options.clone(); let das_darren = DasDarren1998::new( @@ -123,9 +147,11 @@ impl NSGA3 { &options.number_of_partitions, )?; let reference_points = das_darren.get_weights(); + let number_of_or_reference_points = reference_points.len(); + info!( "Created {} reference directions", - das_darren.number_of_points() + number_of_or_reference_points ); // create the population @@ -189,6 +215,7 @@ impl NSGA3 { Ok(Self { number_of_individuals, reference_points, + number_of_or_reference_points, ideal_point: vec![f64::INFINITY; problem.number_of_objectives()], population, problem, @@ -202,6 +229,7 @@ impl NSGA3 { export_history: options.export_history, rng: get_rng(options.seed), args: nsga3_args, + adaptive, }) } @@ -398,6 +426,16 @@ impl Algorithm for NSGA3 { // update the population self.population = selected_individuals; + + // add new refernece points + if self.adaptive { + let mut a = AdaptiveReferencePoints::new( + &mut self.reference_points, + &mut rho_j, + self.number_of_or_reference_points, + )?; + a.calculate()?; + } } else { // update the population self.population = new_population; @@ -502,7 +540,7 @@ mod test_problems { seed: Some(1), }; - let mut algo = NSGA3::new(problem, args).unwrap(); + let mut algo = NSGA3::new(problem, args, false).unwrap(); assert_eq!(algo.reference_points().len(), expected_ref_points); algo.run().unwrap(); @@ -601,7 +639,7 @@ mod test_problems { seed: Some(1), }; - let mut algo = NSGA3::new(problem, args).unwrap(); + let mut algo = NSGA3::new(problem, args, false).unwrap(); assert_eq!(algo.reference_points().len(), 91); algo.run().unwrap(); diff --git a/src/utils/reference_points.rs b/src/utils/reference_points.rs index 49eedea..f2891ae 100644 --- a/src/utils/reference_points.rs +++ b/src/utils/reference_points.rs @@ -259,7 +259,6 @@ impl DasDarren1998 { /// * `file`: The path and file where to save the serialised data. /// /// returns: `Result<(), OError>` - /// ``` pub fn serialise(ref_points: &[Vec], file: &PathBuf) -> Result<(), OError> { #[derive(Serialize)] pub struct Points<'a>(pub &'a [Vec]); From cd24948f47fdcf883b51901392b203906be74ada Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 06:52:09 +0100 Subject: [PATCH 03/14] Improved docstrings for adaptive NSGA3 --- src/algorithms/a_nsga3.rs | 11 +++++++++++ src/algorithms/nsga3/adaptive_ref_points.rs | 1 + 2 files changed, 12 insertions(+) diff --git a/src/algorithms/a_nsga3.rs b/src/algorithms/a_nsga3.rs index 25f4eb3..451a0f6 100644 --- a/src/algorithms/a_nsga3.rs +++ b/src/algorithms/a_nsga3.rs @@ -3,6 +3,17 @@ use crate::core::{OError, Problem}; /// Adaptive `NSGA3` algorithm. This is an alias for [`NSGA3`] when the `adaptive` option is set to /// `true`. +/// This implements the new algorithm from Jain and Deb (2014) to handle problems where not all +/// reference points intersect the optimal Pareto front. This helps to reduce crowding and enhance +/// the solution quality. +/// +/// Implemented based on: +/// > Jain, Himanshu & Deb, Kalyanmoy. (2014). An Evolutionary Many-Objective Optimization +/// > Algorithm Using Reference-Point Based Non dominated Sorting Approach, Part II: Handling +/// > Constraints and Extending to an Adaptive Approach. Evolutionary Computation, IEEE +/// > Transactions on. 18. 602-622. . +/// +/// For a detailed explanation about the implementation see `AdaptiveReferencePoints`. pub struct AdaptiveNSGA3; impl AdaptiveNSGA3 { diff --git a/src/algorithms/nsga3/adaptive_ref_points.rs b/src/algorithms/nsga3/adaptive_ref_points.rs index cb0d1a4..aba2db4 100644 --- a/src/algorithms/nsga3/adaptive_ref_points.rs +++ b/src/algorithms/nsga3/adaptive_ref_points.rs @@ -18,6 +18,7 @@ use crate::utils::{vector_min, DasDarren1998, NumberOfPartitions}; /// to 1 (ideal case), all new included points with rho_j=0 are deleted. Original points with /// no association and new points with rho_j=1 are preserved. /// +/// Implemented based on: /// > Jain, Himanshu & Deb, Kalyanmoy. (2014). An Evolutionary Many-Objective Optimization /// > Algorithm Using Reference-Point Based Non dominated Sorting Approach, Part II: Handling /// > Constraints and Extending to an Adaptive Approach. Evolutionary Computation, IEEE From a4693d871b0f9a0114ffce44c40b09cce9fafdc4 Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 06:52:30 +0100 Subject: [PATCH 04/14] Updated changelog and readme with new changes --- CHANGELOG.md | 10 ++++++++++ optirustic-py/README.md | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cfaac5..307adb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.7.0 + +- Added new Python API to generate reference points with `DasDarren1998`. The new class + allows getting the weights for the `NSGA3` algorithm and plotting them. See the Python + type hints for name and description of the new class methods. +- Added `AdaptiveNSGA3` to use the adaptive approach to handle the reference points. This + implements the new algorithm from Jain and Deb (2014) (doi.org/10.1109/TEVC.2013.2281534) + to handle problems where not all reference points intersect the optimal Pareto front. This + helps to reduce crowding and enhance the solution quality. + ## 0.6.0 - Removed crate `hv-wfg-sys`. The hyper-volume from `HyperVolumeWhile2012` is now calculated diff --git a/optirustic-py/README.md b/optirustic-py/README.md index 87a12f8..01049f6 100644 --- a/optirustic-py/README.md +++ b/optirustic-py/README.md @@ -9,7 +9,7 @@ exported with the `optirustic` crate. It lets you: # Installation -The package can be installed from Pypi: +The package can be installed from [PyPi](https://pypi.org/project/optirustic/): ``` pip install optirustic_py @@ -102,6 +102,7 @@ plt.show() ``` ## Generate reference points + To generate, plot and inspect the reference points for the `NSGA3` algorithm you can us: ### One layer @@ -116,6 +117,7 @@ ds.plot(points) plt.show() ``` + ### Two layers ```python From a693b44bf983d6932f53b59b9b1a944f46e687e4 Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 06:54:43 +0100 Subject: [PATCH 05/14] Bumped optirustic-py version --- optirustic-py/Cargo.lock | 2 +- optirustic-py/Cargo.toml | 2 +- optirustic-py/src/reference_points.rs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/optirustic-py/Cargo.lock b/optirustic-py/Cargo.lock index 3ddb7e4..a30aa4c 100644 --- a/optirustic-py/Cargo.lock +++ b/optirustic-py/Cargo.lock @@ -577,7 +577,7 @@ dependencies = [ [[package]] name = "optirustic-py" -version = "0.2.0" +version = "0.3.0" dependencies = [ "chrono", "optirustic", diff --git a/optirustic-py/Cargo.toml b/optirustic-py/Cargo.toml index e5458ec..ff7e618 100644 --- a/optirustic-py/Cargo.toml +++ b/optirustic-py/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "optirustic-py" -version = "0.2.0" +version = "0.3.0" edition = "2021" [lib] diff --git a/optirustic-py/src/reference_points.rs b/optirustic-py/src/reference_points.rs index 7e7b470..cffa689 100644 --- a/optirustic-py/src/reference_points.rs +++ b/optirustic-py/src/reference_points.rs @@ -28,7 +28,6 @@ pub struct PyDasDarren1998 { number_of_partitions: PyNumberOfPartitions, } -// TODO number_of_partitions number or dict #[pymethods] impl PyDasDarren1998 { #[new] From cc2847daaf3a7eeea9a140a66eff6a5f0c473892 Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 08:33:13 +0100 Subject: [PATCH 06/14] Fixed gap calculation in AdaptiveReferencePoints. This is now calculated only once to refer to the original ref points --- src/algorithms/nsga3/adaptive_ref_points.rs | 38 +++++++-------------- src/algorithms/nsga3/mod.rs | 6 +++- src/utils/reference_points.rs | 15 ++++++++ 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/algorithms/nsga3/adaptive_ref_points.rs b/src/algorithms/nsga3/adaptive_ref_points.rs index aba2db4..f0521e2 100644 --- a/src/algorithms/nsga3/adaptive_ref_points.rs +++ b/src/algorithms/nsga3/adaptive_ref_points.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use log::debug; use crate::core::OError; -use crate::utils::{vector_min, DasDarren1998, NumberOfPartitions}; +use crate::utils::{DasDarren1998, NumberOfPartitions}; /// This implements the adaptive reference point procedure Jain and Deb (2013) in Section VII. This /// will identify non-useful points and re-position them to try to allocate one point for each @@ -33,7 +33,7 @@ pub(crate) struct AdaptiveReferencePoints<'a> { /// `reference_points` and `rho_j` is an original one, created when the evolution started. number_of_or_reference_points: usize, /// The three points to add around an original reference point. They lie on the plane through - /// the origin + /// the origin. new_points_set: Vec>, } @@ -46,35 +46,18 @@ impl<'a> AdaptiveReferencePoints<'a> { /// * `rho_j`: The map mapping the reference point index to the number of associated /// individuals. /// * `number_of_or_reference_points`: The number of original reference points. + /// * `gap`: The gap to use to separate the new reference points to add. This may differ + /// from the gap used to generate the original reference points. /// /// returns: `Result` pub fn new( reference_points: &'a mut Vec>, rho_j: &'a mut HashMap, number_of_or_reference_points: usize, + gap: f64, ) -> Result { let number_of_objectives = reference_points.first().unwrap().len(); - // measure the minimum gap between the points. This equal to 1 divided by the number of - // partitions for one layer. With two layer, this gives the minimum gap of the two layers. - let gap = (0..reference_points.len() - 1) - .flat_map(|p_id| { - (0..3) - .filter_map(|c_id| { - let d = f64::abs( - reference_points[p_id][c_id] - reference_points[p_id + 1][c_id], - ); - if d > 0.0 { - Some(d) - } else { - None - } - }) - .collect::>() - }) - .collect::>(); - let gap = vector_min(&gap)?; - // create the 3 new points with the gap. These can be shifted with respect to the original // reference point later let ds = DasDarren1998::new(number_of_objectives, &NumberOfPartitions::OneLayer(1))?; @@ -181,7 +164,6 @@ impl<'a> AdaptiveReferencePoints<'a> { .map(|(_, counter)| if *counter == 1 { 1 } else { 0 }) .sum(); - println!("perfect_assoc_counter={perfect_assoc_counter}"); // delete new points without association if perfect_assoc_counter == self.number_of_or_reference_points { let mut points_to_delete = vec![]; @@ -282,7 +264,9 @@ mod test { *rho_j.get_mut(&ref_point_index).unwrap() = 2_usize; let counter = ref_points.len(); - let mut a = AdaptiveReferencePoints::new(&mut ref_points, &mut rho_j, counter).unwrap(); + let mut a = + AdaptiveReferencePoints::new(&mut ref_points, &mut rho_j, counter, ds.gap()) + .unwrap(); a.calculate().unwrap(); // check point counter @@ -331,7 +315,8 @@ mod test { let counter = ref_points.len(); - let mut a = AdaptiveReferencePoints::new(&mut ref_points, &mut rho_j, counter).unwrap(); + let mut a = + AdaptiveReferencePoints::new(&mut ref_points, &mut rho_j, counter, ds.gap()).unwrap(); a.calculate().unwrap(); // one point ([0.33333333 0.13333333 0.53333333]) is in common @@ -362,7 +347,8 @@ mod test { // TODO point 21 will be deleted let counter = ref_points.len(); println!("{:?}", counter); - let mut a = AdaptiveReferencePoints::new(&mut ref_points, &mut rho_j, or_counter).unwrap(); + let mut a = AdaptiveReferencePoints::new(&mut ref_points, &mut rho_j, or_counter, ds.gap()) + .unwrap(); a.calculate().unwrap(); // one additional point is preserved diff --git a/src/algorithms/nsga3/mod.rs b/src/algorithms/nsga3/mod.rs index 1ee5b29..37fa621 100644 --- a/src/algorithms/nsga3/mod.rs +++ b/src/algorithms/nsga3/mod.rs @@ -96,6 +96,8 @@ pub struct NSGA3 { /// The number of original reference points. This equals the size of `reference_points` if /// the `adaptive` option is set to `false`. number_of_or_reference_points: usize, + /// The gap between the reference points. + ref_point_gap: f64, /// The ideal point coordinates when the algorithm starts up to the current evolution ideal_point: Vec, /// The operator to use to select the individuals for reproduction. This is a binary tournament @@ -216,6 +218,7 @@ impl NSGA3 { number_of_individuals, reference_points, number_of_or_reference_points, + ref_point_gap: das_darren.gap(), ideal_point: vec![f64::INFINITY; problem.number_of_objectives()], population, problem, @@ -433,6 +436,7 @@ impl Algorithm for NSGA3 { &mut self.reference_points, &mut rho_j, self.number_of_or_reference_points, + self.ref_point_gap, )?; a.calculate()?; } @@ -482,7 +486,7 @@ mod test_problems { // see Table I let k: usize = 5; let number_variables: usize = number_objectives + k - 1; // M + k - 1 with k = 5 (Section Va) - let problem = DTLZ1Problem::create(number_variables, number_objectives).unwrap(); + let problem = DTLZ1Problem::create(number_variables, number_objectives, false).unwrap(); // The number of partitions used in the paper when from section 5 let number_of_partitions = match number_objectives { 3 => NumberOfPartitions::OneLayer(12), diff --git a/src/utils/reference_points.rs b/src/utils/reference_points.rs index f2891ae..5d41997 100644 --- a/src/utils/reference_points.rs +++ b/src/utils/reference_points.rs @@ -143,6 +143,21 @@ impl DasDarren1998 { } } + /// Get the gap between the points. For a two layer system, this returns the average gap between + /// the inner and boundary layer. + /// + /// returns: `f64` + pub fn gap(&self) -> f64 { + match &self.number_of_partitions { + NumberOfPartitions::OneLayer(l) => 1.0 / *l as f64, + NumberOfPartitions::TwoLayers(l) => { + let g1 = 1.0 / l.inner_layer as f64; + let g2 = 1.0 / l.boundary_layer as f64; + (g1 + g2) / 2.0 + } + } + } + /// Generate the vector of weights of reference points. /// /// return: `Vec>`. The vector of weights of size `self.number_of_points`. Each From ed96b7bc2950bc7a56e9eae0595d57c8a1e37ffd Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 08:33:46 +0100 Subject: [PATCH 07/14] Added inverted DTLZ1 problem example and results with Adaptive NSGA3 --- examples/nsga3_inverted_dtlz1.rs | 74 + examples/nsga3_inverted_dtlz1_plot.py | 70 + .../DTLZ1_3obj_Adaptive_NSGA3_gen400.json | 4310 +++++++++++++++++ ...obj_Adaptive_NSGA3_gen400_Pareto_front.png | Bin 0 -> 63566 bytes ...daptive_NSGA3_gen400_obj_vs_ref_points.png | Bin 0 -> 94819 bytes 5 files changed, 4454 insertions(+) create mode 100644 examples/nsga3_inverted_dtlz1.rs create mode 100644 examples/nsga3_inverted_dtlz1_plot.py create mode 100644 examples/results/DTLZ1_3obj_Adaptive_NSGA3_gen400.json create mode 100644 examples/results/DTLZ1_3obj_Adaptive_NSGA3_gen400_Pareto_front.png create mode 100644 examples/results/DTLZ1_3obj_Adaptive_NSGA3_gen400_obj_vs_ref_points.png diff --git a/examples/nsga3_inverted_dtlz1.rs b/examples/nsga3_inverted_dtlz1.rs new file mode 100644 index 0000000..e17a74e --- /dev/null +++ b/examples/nsga3_inverted_dtlz1.rs @@ -0,0 +1,74 @@ +use std::env; +use std::error::Error; +use std::path::PathBuf; + +use log::LevelFilter; + +use optirustic::algorithms::{ + AdaptiveNSGA3, Algorithm, MaxGeneration, NSGA3Arg, Nsga3NumberOfIndividuals, + StoppingConditionType, +}; +use optirustic::core::builtin_problems::DTLZ1Problem; +use optirustic::operators::SimulatedBinaryCrossoverArgs; +use optirustic::utils::NumberOfPartitions; + +/// Solve the inverted DTLZ1 problem from Deb et al. (2013) with 3 objectives. This is a problem where the +/// optimal solutions or objectives lie on the hyper-plane passing through the intercept point +/// at 0.5 on each objective axis. This code replicates the first testing problem in Deb et al. +/// (2013). +/// +/// Make sure to compile this in release mode to speed up the calculation: +/// +/// `cargo run --example nsga3_inverted_dtlz1 -p optirustic --release` +fn main() -> Result<(), Box> { + // Add log + env_logger::builder().filter_level(LevelFilter::Info).init(); + + let number_objectives: usize = 3; + let k: usize = 5; + // Set the number of variables to use in the DTLZ1 problem + let number_variables: usize = number_objectives + k - 1; + // Get the built-in problem + let problem = DTLZ1Problem::create(number_variables, number_objectives, true)?; + + // Set the number of partitions to create the reference points for the NSGA3 algorithm. This + // uses one layer of 12 uniform gaps + let number_of_partitions = NumberOfPartitions::OneLayer(12); + + // Customise the SBX and PM operators like in the paper + let crossover_operator_options = SimulatedBinaryCrossoverArgs { + distribution_index: 30.0, + crossover_probability: 1.0, + ..SimulatedBinaryCrossoverArgs::default() + }; + + // Set up the adaptive NSGA3 algorithm + let args = NSGA3Arg { + // number of individuals from the paper (possibly equal to number of reference points) + number_of_individuals: Nsga3NumberOfIndividuals::Custom(92), + number_of_partitions, + crossover_operator_options: Some(crossover_operator_options), + mutation_operator_options: None, + // stop at generation 400 + stopping_condition: StoppingConditionType::MaxGeneration(MaxGeneration(400)), + parallel: None, + export_history: None, + // to reproduce results + seed: Some(1), + }; + + // Initialise the algorithm + let mut algo = AdaptiveNSGA3::new(problem, args).unwrap(); + + // Run the algorithm + algo.run()?; + + // Export the last results to a JSON file + let destination = PathBuf::from(&env::current_dir().unwrap()) + .join("examples") + .join("results"); + + algo.save_to_json(&destination, Some("DTLZ1_3obj_Adaptive"))?; + + Ok(()) +} diff --git a/examples/nsga3_inverted_dtlz1_plot.py b/examples/nsga3_inverted_dtlz1_plot.py new file mode 100644 index 0000000..16bba8b --- /dev/null +++ b/examples/nsga3_inverted_dtlz1_plot.py @@ -0,0 +1,70 @@ +from pathlib import Path + +import numpy as np +from matplotlib import pyplot as plt +from optirustic import NSGA3 + +# Generate a 3D Pareto front charts and objective vs. reference point charts +file = Path(__file__).parent / "results" / "DTLZ1_3obj_Adaptive_NSGA3_gen400.json" +data = NSGA3(file.as_posix()) + +# Generate Pareto front chart +data.plot() +plt.gca().view_init( + azim=60, + elev=20, +) +plt.savefig(file.parent / f"{file.stem}_Pareto_front.png") + +# Generate a chart with the normalised objectives against the reference points +# The plane is limited in the [0, 1] range. +normalised_objectives = [ind.data["normalised_objectives"] for ind in data.individuals] +normalised_objectives = np.array(normalised_objectives) +obj_names = data.problem.objective_names + +ref_points = data.additional_data["reference_points"] +ref_points = np.array(ref_points) + +fig = plt.figure() +ax = plt.axes(projection="3d") + +ax.scatter( + ref_points[:91, 0], + ref_points[:91, 1], + ref_points[:91, 2], + color="r", + marker="x", + s=20, + label="Original reference points", +) +ax.scatter( + ref_points[91:, 0], + ref_points[91:, 1], + ref_points[91:, 2], + color="b", + marker="x", + s=20, + label="Adaptive reference points", +) +ax.scatter( + normalised_objectives[:, 0], + normalised_objectives[:, 1], + normalised_objectives[:, 2], + color="k", + marker=".", + label="Normalised objectives", +) + +# TODO highlight or ref points vs new + +ax.set_xlabel(obj_names[0]) +ax.set_ylabel(obj_names[1]) +ax.set_zlabel(obj_names[2]) +ax.view_init(azim=10) + +plt.legend() +plt.title( + f"Normalised objectives vs. reference points \n" + f"for {data.algorithm} @ generation={data.generation}" +) +plt.savefig(file.parent / f"{file.stem}_obj_vs_ref_points.png") diff --git a/examples/results/DTLZ1_3obj_Adaptive_NSGA3_gen400.json b/examples/results/DTLZ1_3obj_Adaptive_NSGA3_gen400.json new file mode 100644 index 0000000..c1fb887 --- /dev/null +++ b/examples/results/DTLZ1_3obj_Adaptive_NSGA3_gen400.json @@ -0,0 +1,4310 @@ +{ + "options": { + "number_of_individuals": { + "Custom": 92 + }, + "number_of_partitions": { + "OneLayer": 12 + }, + "crossover_operator_options": { + "distribution_index": 30.0, + "crossover_probability": 1.0, + "variable_probability": 0.5 + }, + "mutation_operator_options": null, + "seed": 1, + "stopping_condition": { + "MaxGeneration": 400 + }, + "parallel": null, + "export_history": null + }, + "problem": { + "objectives": { + "f3": { + "name": "f3", + "direction": "Minimise" + }, + "f1": { + "name": "f1", + "direction": "Minimise" + }, + "f2": { + "name": "f2", + "direction": "Minimise" + } + }, + "constraints": { + "g": { + "name": "g", + "operator": "GreaterOrEqualTo", + "target": 0.0 + } + }, + "variables": { + "x2": { + "name": "x2", + "min_value": 0.0, + "max_value": 1.0 + }, + "x6": { + "name": "x6", + "min_value": 0.0, + "max_value": 1.0 + }, + "x3": { + "name": "x3", + "min_value": 0.0, + "max_value": 1.0 + }, + "x1": { + "name": "x1", + "min_value": 0.0, + "max_value": 1.0 + }, + "x7": { + "name": "x7", + "min_value": 0.0, + "max_value": 1.0 + }, + "x4": { + "name": "x4", + "min_value": 0.0, + "max_value": 1.0 + }, + "x5": { + "name": "x5", + "min_value": 0.0, + "max_value": 1.0 + } + }, + "constraint_names": [ + "g" + ], + "variable_names": [ + "x1", + "x2", + "x3", + "x4", + "x5", + "x6", + "x7" + ], + "objective_names": [ + "f1", + "f2", + "f3" + ], + "number_of_objectives": 3, + "number_of_constraints": 1, + "number_of_variables": 7 + }, + "individuals": [ + { + "constraint_values": { + "g": 0.004418339435652285 + }, + "objective_values": { + "f3": 0.4170244206971835, + "f1": 0.16882278727647754, + "f2": 0.4185711314619913 + }, + "constraint_violation": 0.0, + "variable_values": { + "x3": 0.5000101858024123, + "x2": 0.7994409101605888, + "x4": 0.49994761035396024, + "x7": 0.4999297853035444, + "x5": 0.49996813791186, + "x1": 0.8303799409546723, + "x6": 0.49988347281537 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.16666666666666666, + 0.4166666666666667, + 0.4166666666666667 + ], + "normalised_objectives": [ + 0.16755516458826844, + 0.41768238378639144, + 0.4146644383567149 + ], + "rank": 1, + "distance": 0.0023760531933039826, + "reference_point_index": 30 + } + }, + { + "constraint_values": { + "g": 0.0038665857318598285 + }, + "objective_values": { + "f1": 0.474783962289604, + "f2": 0.22288542269860973, + "f3": 0.3061972007436461 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.6100356463611463, + "x2": 0.08866616190608417, + "x4": 0.49994818517063716, + "x3": 0.5000062138864385, + "x5": 0.4999685762009038, + "x6": 0.4998876194835983, + "x7": 0.49994309422134836 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.4715356572034552, + 0.22235112065487625, + 0.3044643888168678 + ], + "rank": 1, + "distance": 0.0007726254218612116, + "reference_point": [ + 0.4722222222222222, + 0.2222222222222222, + 0.3055555555555556 + ], + "reference_point_index": 129 + } + }, + { + "constraint_values": { + "g": 0.005072415277584952 + }, + "objective_values": { + "f1": 0.42213665410763485, + "f2": 0.16592220136947872, + "f3": 0.4170135598004714 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.19279841540315001, + "x3": 0.5000083569705042, + "x5": 0.4999685590229177, + "x6": 0.4998660576063331, + "x7": 0.4999368582970679, + "x1": 0.829817938412525, + "x4": 0.49994805344509835 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "distance": 0.003463784364059024, + "reference_point": [ + 0.4166666666666667, + 0.16666666666666666, + 0.4166666666666667 + ], + "reference_point_index": 57, + "normalised_objectives": [ + 0.4192291687238893, + 0.1654910768398557, + 0.41465363892173657 + ] + } + }, + { + "constraint_values": { + "g": 0.004997173582843573 + }, + "objective_values": { + "f2": 0.3358242465529625, + "f3": 0.16716358238095896, + "f1": 0.5020093446489221 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.0029267268356615306, + "x5": 0.4999643188619156, + "x7": 0.4999316206381487, + "x6": 0.49987283026787704, + "x1": 0.33266478110583336, + "x4": 0.4999442373095969, + "x3": 0.5000085297206621 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.5, + 0.3333333333333333, + 0.16666666666666666 + ], + "normalised_objectives": [ + 0.4985847922476884, + 0.33508537835549057, + 0.16621756066674717 + ], + "reference_point_index": 67, + "distance": 0.002274403712122266, + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.005082841835779561 + }, + "objective_values": { + "f2": 0.25354331898757176, + "f1": 0.4196615286704639, + "f3": 0.331877994177744 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.6603992832502646, + "x4": 0.499948220276187, + "x5": 0.49996832178991146, + "x3": 0.5000101883373704, + "x6": 0.4998679717929475, + "x7": 0.49993279025427223, + "x2": 0.2497300022942705 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 58, + "rank": 1, + "distance": 0.004419590549309733, + "reference_point": [ + 0.4166666666666667, + 0.25, + 0.3333333333333333 + ], + "normalised_objectives": [ + 0.41677006635691966, + 0.2529534862794351, + 0.329999854831865 + ] + } + }, + { + "constraint_values": { + "g": 0.004489188874234884 + }, + "objective_values": { + "f1": 0.41945762509294937, + "f2": 0.3338445041899091, + "f3": 0.25118705959137644 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.3295829390209966, + "x5": 0.4999689353697311, + "x4": 0.4999483675367221, + "x3": 0.5000079671035479, + "x1": 0.5001289458832111, + "x6": 0.49987721256843926, + "x7": 0.499937072161924 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.4166666666666667, + 0.3333333333333333, + 0.25 + ], + "reference_point_index": 59, + "normalised_objectives": [ + 0.41656748277769196, + 0.3331092219008678, + 0.24976554964436543 + ], + "rank": 1, + "distance": 0.00016489334717216102 + } + }, + { + "constraint_values": { + "g": 0.004700125275913791 + }, + "objective_values": { + "f1": 0.4750319564846685, + "f2": 0.3900693857618589, + "f3": 0.1395987830293864 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.49994272417944063, + "x4": 0.499948197721753, + "x6": 0.4998714644636049, + "x1": 0.27789144147075595, + "x3": 0.500010074493091, + "x2": 0.19569014543298546, + "x5": 0.4999651822310458 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.4717820459734623, + 0.38923226331391525, + 0.13880875030975431 + ], + "distance": 0.0005472891567523851, + "rank": 1, + "reference_point_index": 114, + "reference_point": [ + 0.4722222222222222, + 0.3888888888888889, + 0.1388888888888889 + ] + } + }, + { + "constraint_values": { + "g": 0.005094375357295178 + }, + "objective_values": { + "f3": 0.4710204188280679, + "f2": 0.1418500385196027, + "f1": 0.39222391800962464 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.49997786976820163, + "x6": 0.499866565590554, + "x7": 0.4999313683164141, + "x3": 0.500010241718625, + "x1": 0.93726605257467, + "x2": 0.23422184104781493, + "x4": 0.4999481756486051 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 93, + "normalised_objectives": [ + 0.38951007690071565, + 0.141462515911784, + 0.4683548735356497 + ], + "rank": 1, + "distance": 0.004258942109202443, + "reference_point": [ + 0.3888888888888889, + 0.1388888888888889, + 0.4722222222222222 + ] + } + }, + { + "constraint_values": { + "g": 0.004130559934800715 + }, + "objective_values": { + "f2": 0.30710277998832525, + "f3": 0.4725764767885398, + "f1": 0.22445130315793566 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.4999442268783177, + "x3": 0.5000100743548126, + "x5": 0.49996927335031877, + "x7": 0.49994277188358593, + "x1": 0.941265002071493, + "x6": 0.4998838801733481, + "x2": 0.5874477263363376 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.22282356150291585, + 0.30641593499903225, + 0.46990212577569296 + ], + "rank": 1, + "reference_point": [ + 0.2222222222222222, + 0.3055555555555555, + 0.4722222222222222 + ], + "reference_point_index": 97, + "distance": 0.002269029607088461 + } + }, + { + "constraint_values": { + "g": 0.004801875570237257 + }, + "objective_values": { + "f3": 0.4183289184499758, + "f2": 0.08441865179777319, + "f1": 0.5020543053224883 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.49994812106350206, + "x6": 0.49987266682874043, + "x3": 0.5000124693244743, + "x5": 0.4999683493609485, + "x2": 0.000828612241091764, + "x7": 0.49993479297876847, + "x1": 0.8326595095427525 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.5, + 0.08333333333333333, + 0.4166666666666667 + ], + "reference_point_index": 64, + "distance": 0.001041937950447949, + "normalised_objectives": [ + 0.4986294618620549, + 0.08413515469229811, + 0.41596155396642337 + ], + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.0039046117380259204 + }, + "objective_values": { + "f3": 0.4725954200704015, + "f1": 0.47560246078765966, + "f2": 0.055706730879964805 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.9415145912164167, + "x3": 0.500010079871487, + "x2": 0.05575560820591115, + "x4": 0.4999479427252771, + "x5": 0.49996594928373866, + "x6": 0.49988760947968125, + "x7": 0.4999437115226333 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.0017174364616744035, + "rank": 1, + "reference_point": [ + 0.4722222222222222, + 0.05555555555555555, + 0.4722222222222222 + ], + "reference_point_index": 91, + "normalised_objectives": [ + 0.47234885703716967, + 0.05547523969263328, + 0.46992096185766347 + ] + } + }, + { + "constraint_values": { + "g": 0.005232876591421132 + }, + "objective_values": { + "f1": 0.16779699788852026, + "f2": 0.5021241594008119, + "f3": 0.3353117193020889 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.9985318768579778, + "x1": 0.6671324169959018, + "x4": 0.4999482142387458, + "x5": 0.4999643987014053, + "x3": 0.500008543067277, + "x6": 0.4998653759381186, + "x7": 0.4999340385210146 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.16653601579117905, + 0.5010840720797709, + 0.33341414853126183 + ], + "rank": 1, + "reference_point": [ + 0.16666666666666666, + 0.5, + 0.3333333333333333 + ], + "reference_point_index": 31, + "distance": 0.0006548722834206702 + } + }, + { + "constraint_values": { + "g": 0.004478348194680848 + }, + "objective_values": { + "f1": 0.08405134626596966, + "f2": 0.5019784411669287, + "f3": 0.4184485607617825 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.49998039052133464, + "x7": 0.4999423219708016, + "x6": 0.4998727227121955, + "x1": 0.8331659144546971, + "x3": 0.5000090183934025, + "x2": 0.9993769056585186, + "x4": 0.4999481921300928 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.08333333333333333, + 0.5, + 0.4166666666666667 + ], + "distance": 0.0010521312017258422, + "rank": 1, + "reference_point_index": 19, + "normalised_objectives": [ + 0.083332503340586, + 0.5009386177854049, + 0.41608051922327716 + ] + } + }, + { + "constraint_values": { + "g": 0.004951547987808169 + }, + "objective_values": { + "f1": 0.31161140931566356, + "f2": 0.38733642929475665, + "f3": 0.30600370937738797 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.49993781056273834, + "x3": 0.5000101883373704, + "x1": 0.6089919658118688, + "x2": 0.6237321928763011, + "x4": 0.4999483671017167, + "x6": 0.4998679717929475, + "x5": 0.49996832178991146 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.30941942454037935, + 0.38650425705236435, + 0.30427199241681274 + ], + "rank": 1, + "distance": 0.004712364099492783, + "reference_point_index": 139, + "reference_point": [ + 0.3055555555555555, + 0.38888888888888884, + 0.3055555555555555 + ] + } + }, + { + "constraint_values": { + "g": 0.0038821752950113364 + }, + "objective_values": { + "f1": 0.39128490135832783, + "f2": 0.39017059116789615, + "f3": 0.22242668276878735 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.44313304537641124, + "x7": 0.49994258107696016, + "x5": 0.49997787196125254, + "x6": 0.49988553773077665, + "x2": 0.4974951067548177, + "x3": 0.5000090172943762, + "x4": 0.4999481547664945 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "distance": 0.0011451388393582116, + "normalised_objectives": [ + 0.388577139104857, + 0.3893332854065449, + 0.22116792758037512 + ], + "reference_point": [ + 0.3888888888888889, + 0.3888888888888889, + 0.2222222222222222 + ], + "reference_point_index": 113 + } + }, + { + "constraint_values": { + "g": 0.005325983278936519 + }, + "objective_values": { + "f3": 0.4184843772127895, + "f2": 0.3354246843225879, + "f1": 0.2514169217435591 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.8325346885949876, + "x4": 0.4999482142025781, + "x5": 0.4999681955190811, + "x6": 0.4998638409786234, + "x7": 0.4999316402178019, + "x3": 0.5000079104018654, + "x2": 0.6003714441367458 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 40, + "rank": 1, + "normalised_objectives": [ + 0.24961461439052288, + 0.3346865398524035, + 0.41611613298925426 + ], + "distance": 0.001495839867574826, + "reference_point": [ + 0.25, + 0.3333333333333333, + 0.4166666666666667 + ] + } + }, + { + "constraint_values": { + "g": 0.004421301873236416 + }, + "objective_values": { + "f3": 0.055769102061662135, + "f2": 0.47290612046854, + "f1": 0.4757460793430342 + }, + "constraint_violation": 0.0, + "variable_values": { + "x6": 0.4998758328093946, + "x7": 0.49993976406196333, + "x2": 0.47453824098374275, + "x3": 0.5000101514976291, + "x1": 0.111047230793798, + "x4": 0.49994812264385563, + "x5": 0.49997660880551625 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 101, + "rank": 1, + "distance": 0.000416989738897909, + "normalised_objectives": [ + 0.47249154585776776, + 0.4719189557974805, + 0.055453460883332806 + ], + "reference_point": [ + 0.4722222222222222, + 0.4722222222222222, + 0.05555555555555555 + ] + } + }, + { + "constraint_values": { + "g": 0.004934855665794657 + }, + "objective_values": { + "f1": 0.1428272880986594, + "f2": 0.3906078542612133, + "f3": 0.47149971330592194 + }, + "constraint_violation": 0.0, + "variable_values": { + "x6": 0.49987259115547356, + "x1": 0.938368712454583, + "x3": 0.5000125731036791, + "x2": 0.7627579181599492, + "x7": 0.4999351328070325, + "x5": 0.4999641205629793, + "x4": 0.4999443086645245 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "reference_point_index": 96, + "normalised_objectives": [ + 0.14172795090499044, + 0.3897697564849807, + 0.46883145568961726 + ], + "reference_point": [ + 0.1388888888888889, + 0.38888888888888884, + 0.4722222222222222 + ], + "distance": 0.004293612507683795 + } + }, + { + "constraint_values": { + "g": 0.00522724595688473 + }, + "objective_values": { + "f3": 0.5014945744640017, + "f1": 0.2512734486895643, + "f2": 0.2524592228033187 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.49997147481845355, + "x3": 0.5000079158241951, + "x6": 0.49986268954689195, + "x1": 0.9977735412187809, + "x7": 0.49993977653305743, + "x4": 0.4999442247337676, + "x2": 0.5011822402216631 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.0022988397917388416, + "rank": 1, + "reference_point_index": 39, + "normalised_objectives": [ + 0.249472070129381, + 0.25187135371919656, + 0.49865657615142234 + ], + "reference_point": [ + 0.25, + 0.25, + 0.5 + ] + } + }, + { + "constraint_values": { + "g": 0.005021362510682081 + }, + "objective_values": { + "f2": 0.5022653302481045, + "f1": 0.3356372121760252, + "f3": 0.16711882008655232 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.33256769720609014, + "x5": 0.49996447405008376, + "x2": 0.9985318768579778, + "x6": 0.4998656199963758, + "x4": 0.4999481858581059, + "x3": 0.5000085388622826, + "x7": 0.49994213760529954 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.001030704001976446, + "normalised_objectives": [ + 0.3332896930104059, + 0.5012249872242303, + 0.16617305168183175 + ], + "reference_point": [ + 0.3333333333333333, + 0.5, + 0.16666666666666666 + ], + "reference_point_index": 52, + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.005098302512696051 + }, + "objective_values": { + "f1": 0.3900470671498624, + "f2": 0.22427181701413812, + "f3": 0.39077941834869545 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.4999465224148905, + "x2": 0.28789152863239875, + "x6": 0.49986763686086516, + "x5": 0.4999689598823185, + "x1": 0.777594425086116, + "x7": 0.49993380453965025, + "x3": 0.5000094949337363 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "distance": 0.002083216364114592, + "reference_point": [ + 0.38888888888888884, + 0.2222222222222222, + 0.3888888888888889 + ], + "reference_point_index": 152, + "normalised_objectives": [ + 0.3873473181890199, + 0.22373500379361871, + 0.38856795628137913 + ] + } + }, + { + "constraint_values": { + "g": 0.008675237308342076 + }, + "objective_values": { + "f1": 0.3103770288216081, + "f2": 0.3083791680107996, + "f3": 0.38991904047593434 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.49993690769288224, + "x1": 0.7731309861763562, + "x2": 0.49743810816680056, + "x3": 0.5000101453959953, + "x5": 0.4999728375466552, + "x4": 0.4999481187549717, + "x6": 0.5001908256402998 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.00315179933890652, + "reference_point_index": 134, + "normalised_objectives": [ + 0.3081930349808496, + 0.30769001109917976, + 0.38771244728060283 + ], + "reference_point": [ + 0.3055555555555556, + 0.3055555555555555, + 0.3888888888888889 + ], + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.004169173877865973 + }, + "objective_values": { + "f3": 0.3338975403601807, + "f2": 0.4201375342258346, + "f1": 0.25013409929185065 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.7545742546509904, + "x7": 0.49993397602334666, + "x3": 0.5000062118052212, + "x5": 0.4999685521331348, + "x4": 0.49994819359895454, + "x1": 0.6650224863421105, + "x6": 0.4998858070572538 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "distance": 0.003320808443711907, + "normalised_objectives": [ + 0.24834009646911853, + 0.4192459493240474, + 0.3320079724174711 + ], + "reference_point_index": 41, + "reference_point": [ + 0.25, + 0.4166666666666667, + 0.3333333333333333 + ] + } + }, + { + "constraint_values": { + "g": 0.0044122533929602525 + }, + "objective_values": { + "f3": 0.14238400973082305, + "f2": 0.47131090367246187, + "f1": 0.39071733998967534 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.4999424447308126, + "x1": 0.2835170703062253, + "x2": 0.7830147986250307, + "x4": 0.49994819603767116, + "x5": 0.4999680303232014, + "x6": 0.4998766284063604, + "x3": 0.5000101307030312 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.003115065424058471, + "reference_point": [ + 0.38888888888888884, + 0.4722222222222222, + 0.1388888888888889 + ], + "reference_point_index": 108, + "normalised_objectives": [ + 0.3880132519239919, + 0.47032662841846207, + 0.14157821543399637 + ], + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.00457136393183788 + }, + "objective_values": { + "f1": 0.33694338370933896, + "f2": 0.1681607321231559, + "f3": 0.499467248099343 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.4999466387719608, + "x2": 0.3310373180339019, + "x5": 0.49997268941950235, + "x6": 0.499871234524591, + "x7": 0.49994649241393047, + "x3": 0.5000105010396478, + "x1": 0.9943887831810281 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "reference_point": [ + 0.3333333333333333, + 0.16666666666666666, + 0.5 + ], + "normalised_objectives": [ + 0.33458740885987476, + 0.1677255529415481, + 0.49664072241158763 + ], + "distance": 0.0033091995532989332, + "reference_point_index": 48 + } + }, + { + "constraint_values": { + "g": 0.004800000498050849 + }, + "objective_values": { + "f2": 0.002180726845826153, + "f3": 0.5002321382471792, + "f1": 0.5023871354050455 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.9956849880557888, + "x2": 0.000025717747814069103, + "x6": 0.49986925622504963, + "x7": 0.4999434631312218, + "x3": 0.5000085305881463, + "x4": 0.49994819990441725, + "x5": 0.49996452461514457 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.0023241975790328933, + "reference_point": [ + 0.5, + 0.0, + 0.5 + ], + "normalised_objectives": [ + 0.49896013732258865, + 0.0020461873390289808, + 0.4974012840517643 + ], + "rank": 1, + "reference_point_index": 63 + } + }, + { + "constraint_values": { + "g": 0.0037931903077215168 + }, + "objective_values": { + "f2": 0.0874649064307419, + "f3": 0.4970861102918465, + "f1": 0.4192421735851331 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.49994259633076793, + "x3": 0.5000101184293989, + "x5": 0.4999607313188047, + "x4": 0.4999480670196908, + "x1": 0.9904153865388556, + "x2": 0.16627787390840598, + "x6": 0.4998924350454071 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "distance": 0.005572875053479125, + "reference_point": [ + 0.4166666666666667, + 0.08333333333333333, + 0.5 + ], + "reference_point_index": 56, + "normalised_objectives": [ + 0.4163534260253022, + 0.08717589164257537, + 0.4942730594452394 + ] + } + }, + { + "constraint_values": { + "g": 0.008138980067329271 + }, + "objective_values": { + "f3": 0.4735876938043906, + "f1": 0.057232893295082854, + "f2": 0.47731839296785583 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.49997329315954653, + "x6": 0.5001836822551569, + "x3": 0.5000080137742517, + "x2": 0.9435139522927342, + "x7": 0.49993651887685503, + "x1": 0.939528583197451, + "x4": 0.4999483709479674 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.05668766337055504, + 0.4763232363451925, + 0.4709076203219697 + ], + "reference_point": [ + 0.05555555555555555, + 0.4722222222222222, + 0.4722222222222222 + ], + "rank": 1, + "distance": 0.003949103612282894, + "reference_point_index": 109 + } + }, + { + "constraint_values": { + "g": 0.004272123231086056 + }, + "objective_values": { + "f1": 0.25300270448780365, + "f2": 0.49965323493026587, + "f3": 0.25161618381301654 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.49993701165120263, + "x3": 0.5000085489263264, + "x1": 0.5010916423797196, + "x4": 0.49994818634738053, + "x2": 0.9901324841365442, + "x6": 0.4998833129965867, + "x5": 0.49996407213121113 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.25, + 0.5, + 0.25 + ], + "rank": 1, + "normalised_objectives": [ + 0.25119013134869717, + 0.4986176231960769, + 0.2501922454552259 + ], + "distance": 0.0017452341673523223, + "reference_point_index": 42 + } + }, + { + "constraint_values": { + "g": 0.00561683967639226 + }, + "objective_values": { + "f3": 0.22058443450554155, + "f1": 0.48212477959101663, + "f2": 0.3029076255798341 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.09376745142305093, + "x1": 0.4387047348501556, + "x3": 0.5000076176001667, + "x6": 0.49985348123779827, + "x5": 0.49996872586069896, + "x7": 0.4999430486101714, + "x4": 0.4999480992916988 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.4788289526988257, + 0.3022283792760276, + 0.21933610458635347 + ], + "rank": 1, + "reference_point": [ + 0.4722222222222222, + 0.3055555555555556, + 0.2222222222222222 + ], + "reference_point_index": 130, + "distance": 0.007563446756550272 + } + }, + { + "constraint_values": { + "g": 0.004693019820045663 + }, + "objective_values": { + "f2": 0.5015423791357182, + "f1": 0.41956015284938475, + "f3": 0.08359048783494272 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.9903801162652326, + "x1": 0.16640005690477455, + "x4": 0.4999481904840367, + "x5": 0.49996403412856233, + "x6": 0.49986536676066334, + "x7": 0.49996017174824425, + "x3": 0.5000085452205738 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.4166666666666667, + 0.5, + 0.08333333333333333 + ], + "reference_point_index": 61, + "normalised_objectives": [ + 0.41666934680637674, + 0.5005033455935912, + 0.08311740564138101 + ], + "rank": 1, + "distance": 0.0004146652961477131 + } + }, + { + "constraint_values": { + "g": 0.0050817581724871275 + }, + "objective_values": { + "f1": 0.47632791365435256, + "f3": 0.3889789857677908, + "f2": 0.13977485875034373 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.7740245658722544, + "x6": 0.49986763912169824, + "x4": 0.4999465224148905, + "x5": 0.4999603248755927, + "x2": 0.06738915568960674, + "x7": 0.4999391937324744, + "x3": 0.5000089882695575 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "normalised_objectives": [ + 0.473069613583411, + 0.13939109491678195, + 0.38677771233506314 + ], + "reference_point_index": 111, + "distance": 0.002261434547886442, + "reference_point": [ + 0.4722222222222222, + 0.1388888888888889, + 0.3888888888888889 + ] + } + }, + { + "constraint_values": { + "g": 0.0037412324427776866 + }, + "objective_values": { + "f3": 0.5006535586290171, + "f2": 0.3349129296179737, + "f1": 0.16817474419578693 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.4999481738529974, + "x7": 0.4999350882839774, + "x1": 0.9975749574630708, + "x6": 0.49989758329132566, + "x2": 0.6665205235720089, + "x5": 0.4999618753795587, + "x3": 0.5000100798695907 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.1669113167049684, + 0.33417571208936714, + 0.49782031961879475 + ], + "reference_point": [ + 0.16666666666666666, + 0.3333333333333333, + 0.5 + ], + "reference_point_index": 29, + "distance": 0.0020006739681021997, + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.007454370630011198 + }, + "objective_values": { + "f1": 0.31116481472643726, + "f2": 0.22285493808193024, + "f3": 0.4734346178216437 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.4999340534118315, + "x4": 0.4999506853520941, + "x1": 0.939863147401071, + "x2": 0.40673487603120745, + "x3": 0.5000083653526335, + "x5": 0.49996854777385047, + "x6": 0.49982706835231305 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.003670934918327911, + "reference_point": [ + 0.3055555555555555, + 0.2222222222222222, + 0.4722222222222222 + ], + "normalised_objectives": [ + 0.3089757210435992, + 0.22232069125499973, + 0.47075541059507103 + ], + "reference_point_index": 138, + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.004696180516194914 + }, + "objective_values": { + "f2": 0.4725764467160561, + "f3": 0.22179315245306425, + "f1": 0.3103265813470746 + }, + "constraint_violation": 0.0, + "variable_values": { + "x3": 0.50001245606396, + "x5": 0.49996450040586904, + "x2": 0.8657684278673048, + "x7": 0.4999377898704528, + "x4": 0.499944319580593, + "x1": 0.4415128807180512, + "x6": 0.4998759299218329 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "reference_point_index": 106, + "normalised_objectives": [ + 0.30814291408508815, + 0.4715898791832457, + 0.22053798240799824 + ], + "distance": 0.0031453248472592746, + "reference_point": [ + 0.3055555555555555, + 0.4722222222222222, + 0.2222222222222222 + ] + } + }, + { + "constraint_values": { + "g": 0.004895129405557697 + }, + "objective_values": { + "f1": 0.22600184859736444, + "f3": 0.38819337275768145, + "f2": 0.39069990805051186 + }, + "constraint_violation": 0.0, + "variable_values": { + "x3": 0.4999506233092752, + "x5": 0.4999646308344785, + "x1": 0.7726047453077336, + "x2": 0.712134043251629, + "x6": 0.4998757181605956, + "x7": 0.4999431762277468, + "x4": 0.49995078016226113 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.2243640692698885, + 0.3898616435372001, + 0.3859965451031368 + ], + "rank": 1, + "reference_point": [ + 0.2222222222222222, + 0.3888888888888889, + 0.3888888888888889 + ], + "reference_point_index": 115, + "distance": 0.003700188177463015 + } + }, + { + "constraint_values": { + "g": 0.004416817616270663 + }, + "objective_values": { + "f3": 0.249300988756397, + "f1": 0.336141310116594, + "f2": 0.4189745187432797 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.4999686659034741, + "x2": 0.6661309267963348, + "x6": 0.4998772757883688, + "x7": 0.4999431790238922, + "x1": 0.49640942760805196, + "x3": 0.5000106570200368, + "x4": 0.4999454165082865 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "reference_point": [ + 0.3333333333333333, + 0.4166666666666667, + 0.25 + ], + "reference_point_index": 51, + "distance": 0.002556949896904415, + "normalised_objectives": [ + 0.3337905276025525, + 0.4180850404120754, + 0.24789015207021775 + ] + } + }, + { + "constraint_values": { + "g": 0.005189680848616263 + }, + "objective_values": { + "f2": 0.5019890811394921, + "f3": 0.0008231079648146622, + "f1": 0.5023774917443095 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.49994824756458545, + "x3": 0.5000079672302504, + "x2": 0.2640585309456656, + "x1": 0.001637716702622305, + "x5": 0.49998194516361727, + "x7": 0.499937072161924, + "x6": 0.4998612543120676 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 69, + "reference_point": [ + 0.5, + 0.5, + 0.0 + ], + "rank": 1, + "distance": 0.0016331422602897802, + "normalised_objectives": [ + 0.49895055609143724, + 0.5009492384857802, + 0.0008184057585428665 + ] + } + }, + { + "constraint_values": { + "g": 0.004718601917641507 + }, + "objective_values": { + "f3": 0.3905226293425982, + "f1": 0.1410906329020164, + "f2": 0.47310533967302687 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.777377125490128, + "x5": 0.49997284795487595, + "x3": 0.5000079675746735, + "x4": 0.4999481187549717, + "x2": 0.9250902275879898, + "x6": 0.4998718642113838, + "x7": 0.49993690048225875 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.0012439356128079266, + "rank": 1, + "reference_point": [ + 0.1388888888888889, + 0.4722222222222222, + 0.38888888888888884 + ], + "normalised_objectives": [ + 0.14000253818830957, + 0.4721178141561127, + 0.3883126204423581 + ], + "reference_point_index": 103 + } + }, + { + "constraint_values": { + "g": 0.0043192314882922744 + }, + "objective_values": { + "f2": 0.4745435865636194, + "f1": 0.22358098934267034, + "f3": 0.30619465558200254 + }, + "constraint_violation": 0.0, + "variable_values": { + "x6": 0.49987597347996976, + "x7": 0.4999424214861477, + "x3": 0.5000101636583402, + "x5": 0.49998039052133464, + "x2": 0.9098089118242926, + "x1": 0.609755635423321, + "x4": 0.49994818502170474 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.2219588817856844, + 0.4735534559493216, + 0.30446185805827514 + ], + "reference_point_index": 105, + "reference_point": [ + 0.2222222222222222, + 0.4722222222222222, + 0.3055555555555555 + ], + "rank": 1, + "distance": 0.0016986788208345849 + } + }, + { + "constraint_values": { + "g": 0.005431587358817325 + }, + "objective_values": { + "f2": 0.2528468286437342, + "f1": 0.502518955815533, + "f3": 0.25006580289955016 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.4999480992916988, + "x5": 0.4999684142092595, + "x1": 0.49742977253470144, + "x2": 0.0007871442700013841, + "x6": 0.49986227338547656, + "x7": 0.49993154316636956, + "x3": 0.5000125153530997 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 66, + "distance": 0.0027584259474285003, + "reference_point": [ + 0.5, + 0.25, + 0.25 + ], + "normalised_objectives": [ + 0.49909110437523835, + 0.25225825748894026, + 0.24865063813582136 + ], + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.007868295735491415 + }, + "objective_values": { + "f1": 0.391922821736836, + "f2": 0.3081907951253472, + "f3": 0.3077546788733082 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.6107041568337545, + "x6": 0.5001791565085553, + "x2": 0.3639630323119175, + "x7": 0.49993653278241645, + "x4": 0.4999482921913064, + "x3": 0.5000089732348769, + "x5": 0.49996898296925096 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.38921092981670097, + 0.3075019794136383, + 0.30601305318937444 + ], + "rank": 1, + "distance": 0.0013835991775136146, + "reference_point_index": 140, + "reference_point": [ + 0.38888888888888884, + 0.3055555555555555, + 0.3055555555555555 + ] + } + }, + { + "constraint_values": { + "g": 0.004405285458464192 + }, + "objective_values": { + "f3": 0.1671238347868157, + "f2": 0.41927971062613995, + "f1": 0.41800174004550855 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.49998141064542123, + "x3": 0.5000101650673665, + "x1": 0.332781671316139, + "x4": 0.4999482475750206, + "x6": 0.4998766246941253, + "x2": 0.5038234240563639, + "x7": 0.49993709095555094 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 60, + "distance": 0.0023656701754368997, + "reference_point": [ + 0.4166666666666667, + 0.4166666666666667, + 0.16666666666666666 + ], + "rank": 1, + "normalised_objectives": [ + 0.4151210226054392, + 0.4183896795007105, + 0.16617803800394362 + ] + } + }, + { + "constraint_values": { + "g": 0.005411893821438696 + }, + "objective_values": { + "f2": 0.3334361664817792, + "f1": 0.33735074660445385, + "f3": 0.33462498073520563 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.4999467892032951, + "x5": 0.499969356238715, + "x6": 0.4998612643515503, + "x7": 0.499934063081946, + "x1": 0.6656475476201897, + "x2": 0.4941507951467431, + "x3": 0.5000061267016322 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.33499213463439453, + 0.33270162381505314, + 0.33273129621282244 + ], + "reference_point": [ + 0.3333333333333333, + 0.3333333333333333, + 0.3333333333333333 + ], + "distance": 0.0018581990055934973, + "rank": 1, + "reference_point_index": 50 + } + }, + { + "constraint_values": { + "g": 0.004648548650898476 + }, + "objective_values": { + "f1": 0.5021316909925022, + "f3": 0.08350879542807105, + "f2": 0.41900806223032516 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.49996834973581616, + "x1": 0.16624479384399965, + "x6": 0.49988072736661987, + "x3": 0.4999794598673534, + "x4": 0.49994647055289226, + "x2": 0.0023061443044385954, + "x7": 0.49992912703607667 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.5, + 0.4166666666666667, + 0.08333333333333333 + ], + "reference_point_index": 68, + "normalised_objectives": [ + 0.4987063465651261, + 0.4181185231417844, + 0.08303617553123242 + ], + "rank": 1, + "distance": 0.001964538591000177 + } + }, + { + "constraint_values": { + "g": 0.0054237832920023266 + }, + "objective_values": { + "f2": 0.5022914101056868, + "f3": 0.5017568442555019, + "f1": 0.0013755289308136076 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.9991619814555031, + "x7": 0.4999319402476777, + "x4": 0.4999480492087009, + "x3": 0.5000078876796702, + "x5": 0.49996898069023293, + "x6": 0.4998617683240999, + "x1": 0.9981002092722093 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.0, + 0.5, + 0.5 + ], + "rank": 1, + "distance": 0.00203558451979703, + "reference_point_index": 6, + "normalised_objectives": [ + 0.0011918994557116537, + 0.5012510198433522, + 0.4989173617601225 + ] + } + }, + { + "constraint_values": { + "g": 0.004256562548388132 + }, + "objective_values": { + "f3": 0.41835616864137926, + "f1": 0.3351053238579875, + "f2": 0.25079507004902135 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.49995071364616744, + "x5": 0.49998039052133464, + "x3": 0.5000090163182976, + "x6": 0.4998757940267122, + "x7": 0.4999431575121659, + "x1": 0.8331659144546971, + "x2": 0.39923627266837547 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.0005670778358059886, + "reference_point": [ + 0.3333333333333333, + 0.25, + 0.4166666666666667 + ], + "normalised_objectives": [ + 0.3327612479456802, + 0.25021021524569803, + 0.4159886499491963 + ], + "rank": 1, + "reference_point_index": 49 + } + }, + { + "constraint_values": { + "g": 0.004776192863520379 + }, + "objective_values": { + "f3": 0.3373800263062572, + "f1": 0.5018899212539795, + "f2": 0.16550624530328367 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.4999678984182231, + "x3": 0.5000102025450818, + "x6": 0.4998715676667779, + "x4": 0.49994797796692997, + "x7": 0.4999379632260893, + "x1": 0.6715525879345428, + "x2": 0.0014765994988940184 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.49846614195677197, + 0.16507587419511205, + 0.33547075100147183 + ], + "distance": 0.0030313788760410005, + "reference_point": [ + 0.5, + 0.16666666666666666, + 0.3333333333333333 + ], + "rank": 1, + "reference_point_index": 65 + } + }, + { + "constraint_values": { + "g": 0.005144265073386833 + }, + "objective_values": { + "f1": 0.0822224587196908, + "f2": 0.4214686299546849, + "f3": 0.5014531763990111 + }, + "constraint_violation": 0.0, + "variable_values": { + "x3": 0.5000079158932793, + "x4": 0.4999482540233166, + "x5": 0.49997147481845355, + "x7": 0.49993977653305743, + "x2": 0.8382630594457066, + "x1": 0.9977735412187809, + "x6": 0.49986264200135355 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.08151545535326613, + 0.42057463403847223, + 0.49861541235777374 + ], + "reference_point_index": 18, + "rank": 1, + "distance": 0.004366283448482341, + "reference_point": [ + 0.08333333333333333, + 0.4166666666666667, + 0.5 + ] + } + }, + { + "constraint_values": { + "g": 0.004968955145745468 + }, + "objective_values": { + "f3": 0.3348870003711899, + "f2": 0.4994073737595208, + "f1": 0.17067458101503474 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.6664623790744322, + "x4": 0.49994817588876667, + "x2": 0.9908115160936637, + "x6": 0.49986561154407894, + "x3": 0.5000080892501607, + "x5": 0.49996834745183505, + "x7": 0.4999421461083989 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.0031039715893217495, + "rank": 1, + "reference_point": [ + 0.16666666666666666, + 0.5, + 0.3333333333333333 + ], + "normalised_objectives": [ + 0.1693949704814318, + 0.49837220735380555, + 0.3329918330816349 + ], + "reference_point_index": 31 + } + }, + { + "constraint_values": { + "g": 0.004661069031985932 + }, + "objective_values": { + "f2": 0.21380658574664385, + "f3": 0.4713712569003948, + "f1": 0.3194832263849473 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.938368712454583, + "x2": 0.3879050863928325, + "x7": 0.49994238753753634, + "x3": 0.5000089420460422, + "x5": 0.49996414196898487, + "x6": 0.49987248155584235, + "x4": 0.49994846864606485 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 138, + "reference_point": [ + 0.3055555555555555, + 0.2222222222222222, + 0.4722222222222222 + ], + "normalised_objectives": [ + 0.3172402823024626, + 0.2132887282052728, + 0.4687037262179339 + ], + "distance": 0.015122962985673394, + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.0046996710857172275 + }, + "objective_values": { + "f2": 0.2556397133914772, + "f3": 0.24760060934910233, + "f1": 0.5014593483451377 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.4999482475750206, + "x3": 0.5000079671464311, + "x5": 0.49996839188838477, + "x1": 0.492884822150953, + "x2": 0.0035964660994245168, + "x6": 0.49987313315915927, + "x7": 0.4999370651736315 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "normalised_objectives": [ + 0.4980383564217908, + 0.25504608348300417, + 0.24619939509734623 + ], + "reference_point_index": 66, + "distance": 0.006523840270610728, + "reference_point": [ + 0.5, + 0.25, + 0.25 + ] + } + }, + { + "constraint_values": { + "g": 0.004703906973624328 + }, + "objective_values": { + "f3": 0.39037938600314087, + "f2": 0.4680610881759991, + "f1": 0.14626343279448434 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.912160153583168, + "x4": 0.4999476200042035, + "x7": 0.49993690048225875, + "x6": 0.49987224598952407, + "x1": 0.7771033501383392, + "x5": 0.4999734038537133, + "x3": 0.5000080402006962 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.007579302017044527, + "reference_point_index": 103, + "rank": 1, + "normalised_objectives": [ + 0.14514185123822423, + 0.46708269931459473, + 0.3881701877158937 + ], + "reference_point": [ + 0.1388888888888889, + 0.4722222222222222, + 0.38888888888888884 + ] + } + }, + { + "constraint_values": { + "g": 0.004581145123871977 + }, + "objective_values": { + "f2": 0.33236418760029196, + "f1": 0.42100690294110443, + "f3": 0.2512100545824756 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.4999816790287845, + "x6": 0.499872880628952, + "x3": 0.5000079671464311, + "x1": 0.5001289458832111, + "x7": 0.499937072161924, + "x2": 0.32356853612380004, + "x4": 0.4999482475750206 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.41810673115932, + 0.33163158660950326, + 0.24978841450698092 + ], + "reference_point_index": 59, + "distance": 0.0022390467602971106, + "rank": 1, + "reference_point": [ + 0.4166666666666667, + 0.3333333333333333, + 0.25 + ] + } + }, + { + "constraint_values": { + "g": 0.00538248971562183 + }, + "objective_values": { + "f1": 0.13078300990824732, + "f2": 0.4014131343767988, + "f3": 0.4731863454305757 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.499934063081946, + "x5": 0.499969356238715, + "x1": 0.9413061203491203, + "x6": 0.4998612643515503, + "x4": 0.49994820004300494, + "x2": 0.7859656952086094, + "x3": 0.50000606646789 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 96, + "rank": 1, + "distance": 0.014386555661154272, + "reference_point": [ + 0.1388888888888889, + 0.38888888888888884, + 0.4722222222222222 + ], + "normalised_objectives": [ + 0.12976164303158544, + 0.4005554649907524, + 0.4705085431756181 + ] + } + }, + { + "constraint_values": { + "g": 0.003876219037035611 + }, + "objective_values": { + "f3": 0.3062001390734208, + "f2": 0.2843430925620244, + "f1": 0.4133329874015904 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.6100356463611463, + "x2": 0.28936996039600626, + "x4": 0.49994818517063716, + "x5": 0.4999685877798481, + "x7": 0.49994313994950124, + "x3": 0.5000096602501991, + "x6": 0.4998876194835983 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.38888888888888884, + 0.3055555555555555, + 0.3055555555555555 + ], + "distance": 0.03065222190704732, + "rank": 1, + "reference_point_index": 140, + "normalised_objectives": [ + 0.410482493783814, + 0.28369747220707936, + 0.3044673105186562 + ] + } + }, + { + "constraint_values": { + "g": 0.005094375147507435 + }, + "objective_values": { + "f1": 0.29926696313432966, + "f2": 0.4941265457855427, + "f3": 0.21170086622763507 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.9602238671089962, + "x7": 0.49994661136802654, + "x1": 0.421255697897157, + "x3": 0.5000125153530997, + "x4": 0.49994681473704694, + "x5": 0.4999684788062328, + "x6": 0.49986228208576783 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.024160741798124725, + "rank": 1, + "reference_point": [ + 0.3055555555555555, + 0.4722222222222222, + 0.2222222222222222 + ], + "normalised_objectives": [ + 0.2971548918554642, + 0.49310094454644, + 0.21050280835528024 + ], + "reference_point_index": 106 + } + }, + { + "constraint_values": { + "g": 0.0089690762439254 + }, + "objective_values": { + "f1": 0.5042958058563536, + "f2": 0.4533900846753691, + "f3": 0.051283185712202695 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.0036801977682945778, + "x3": 0.5000124693244743, + "x7": 0.49993479297876847, + "x1": 0.10165462335696918, + "x5": 0.49996817533854776, + "x4": 0.4999481248628738, + "x6": 0.500193142567228 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "reference_point": [ + 0.4722222222222222, + 0.4722222222222222, + 0.05555555555555555 + ], + "reference_point_index": 101, + "distance": 0.034609562626417824, + "normalised_objectives": [ + 0.5008564517291593, + 0.4524382694106712, + 0.050992930301141104 + ] + } + }, + { + "constraint_values": { + "g": 0.004504584852771387 + }, + "objective_values": { + "f3": 0.22175085647641862, + "f2": 0.3937640764402471, + "f1": 0.3889896519361057 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.5107652898843461, + "x4": 0.49995061171115507, + "x6": 0.4998759299218329, + "x5": 0.4999681503396249, + "x7": 0.49993787748849167, + "x1": 0.4415128807180512, + "x3": 0.5000101404511683 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.3862967483003313, + 0.39292026179704637, + 0.22049592578396998 + ], + "reference_point": [ + 0.3888888888888889, + 0.3888888888888889, + 0.2222222222222222 + ], + "rank": 1, + "reference_point_index": 113, + "distance": 0.005085581836601194 + } + }, + { + "constraint_values": { + "g": 0.003808244345115952 + }, + "objective_values": { + "f1": 0.2552823567374421, + "f2": 0.49046508941077316, + "f3": 0.2580607981969007 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.5141635360153063, + "x4": 0.4999466387719608, + "x3": 0.5000105010396478, + "x5": 0.49997268941950235, + "x7": 0.49994649241393047, + "x2": 0.9556731094311471, + "x6": 0.49988723272196667 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.012104861773948228, + "rank": 1, + "reference_point": [ + 0.25, + 0.5, + 0.25 + ], + "reference_point_index": 42, + "normalised_objectives": [ + 0.25345502595111424, + 0.48944612016961503, + 0.2566003898142289 + ] + } + }, + { + "constraint_values": { + "g": 0.004975446786836812 + }, + "objective_values": { + "f3": 0.3944731906560273, + "f1": 0.388922233530955, + "f2": 0.2215800225998545 + }, + "constraint_violation": 0.0, + "variable_values": { + "x6": 0.49986757877719024, + "x3": 0.5000085090693751, + "x4": 0.4999484936017882, + "x5": 0.4999689598823185, + "x7": 0.4999369994339842, + "x1": 0.7850404543061402, + "x2": 0.28789152863239875 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "reference_point": [ + 0.38888888888888884, + 0.2222222222222222, + 0.3888888888888889 + ], + "normalised_objectives": [ + 0.3862297663376422, + 0.22104808502803758, + 0.3922408255586879 + ], + "distance": 0.004436756088245365, + "reference_point_index": 152 + } + }, + { + "constraint_values": { + "g": 0.004776192863520379 + }, + "objective_values": { + "f2": 0.1653862990465293, + "f3": 0.3373800263062572, + "f1": 0.502009867510734 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.4999379632260893, + "x4": 0.49994797796692997, + "x3": 0.5000102025450818, + "x1": 0.6715525879345428, + "x6": 0.4998715676667779, + "x2": 0.0011210768022256873, + "x5": 0.4999678984182231 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.4985853117246813, + 0.16495614519707846, + 0.33547075100147183 + ], + "distance": 0.003048645710420085, + "reference_point_index": 65, + "rank": 1, + "reference_point": [ + 0.5, + 0.16666666666666666, + 0.3333333333333333 + ] + } + }, + { + "constraint_values": { + "g": 0.0044818746754771155 + }, + "objective_values": { + "f3": 0.47856621729185367, + "f1": 0.3438176602638138, + "f2": 0.18209799711980962 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.49997268941950235, + "x6": 0.49987285608818316, + "x7": 0.49994649241393047, + "x4": 0.4999466387719608, + "x2": 0.3310373180339019, + "x1": 0.9528618272907441, + "x3": 0.5000084919018116 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.02739622474018004, + "normalised_objectives": [ + 0.34141718382499125, + 0.18163757336245098, + 0.4758579703820337 + ], + "reference_point_index": 48, + "rank": 1, + "reference_point": [ + 0.3333333333333333, + 0.16666666666666666, + 0.5 + ] + } + }, + { + "constraint_values": { + "g": 0.004358122059322511 + }, + "objective_values": { + "f1": 0.3552280397583534, + "f2": 0.34400606627307617, + "f3": 0.30512401602789296 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.49993709095555094, + "x1": 0.6076000369315891, + "x3": 0.5000101650673665, + "x5": 0.49998141064542123, + "x4": 0.4999482475750206, + "x2": 0.4816107993868116, + "x6": 0.49987759635569096 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.037034939663040764, + "reference_point": [ + 0.3333333333333333, + 0.3333333333333333, + 0.3333333333333333 + ], + "reference_point_index": 50, + "rank": 1, + "normalised_objectives": [ + 0.35275369663426376, + 0.34325237834104705, + 0.3033972772454418 + ] + } + }, + { + "constraint_values": { + "g": 0.004697186415647536 + }, + "objective_values": { + "f3": 0.5001809530279743, + "f2": 0.002295176118573772, + "f1": 0.5022210572690995 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.49994819949967406, + "x3": 0.5000085305881463, + "x1": 0.9956849880557888, + "x7": 0.4999434631312218, + "x5": 0.499972836381514, + "x2": 0.0002549795987877078, + "x6": 0.49986925622504963 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 63, + "reference_point": [ + 0.5, + 0.0, + 0.5 + ], + "rank": 1, + "distance": 0.0023897907973677046, + "normalised_objectives": [ + 0.4987951343166507, + 0.0021604293097459504, + 0.4973503884893343 + ] + } + }, + { + "constraint_values": { + "g": 0.003970901135019744 + }, + "objective_values": { + "f3": 0.3363819678692982, + "f1": 0.24832273937524518, + "f2": 0.41926619389047626 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.4999481814080373, + "x3": 0.5000062118052212, + "x2": 0.7540912873511273, + "x1": 0.6701030228844445, + "x5": 0.49996803046725297, + "x6": 0.4998858070572538, + "x7": 0.49994237306118705 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "distance": 0.004006339814840283, + "reference_point_index": 41, + "normalised_objectives": [ + 0.24654046264391338, + 0.41837618724791753, + 0.3344783405697868 + ], + "reference_point": [ + 0.25, + 0.4166666666666667, + 0.3333333333333333 + ] + } + }, + { + "constraint_values": { + "g": 0.008847970292791274 + }, + "objective_values": { + "f1": 0.5023636140806307, + "f2": 0.07842781469202309, + "f3": 0.4280565415201375 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.8486046542689787, + "x3": 0.5000101462448879, + "x4": 0.4999481726223684, + "x5": 0.4999681377359038, + "x2": 0.00481331521870465, + "x6": 0.5001917019022833, + "x7": 0.4999348213951771 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 64, + "distance": 0.009512919636867826, + "reference_point": [ + 0.5, + 0.08333333333333333, + 0.4166666666666667 + ], + "normalised_objectives": [ + 0.4989367682667525, + 0.07815516879309128, + 0.42563412848995824 + ], + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.004643565694895102 + }, + "objective_values": { + "f3": 0.4036266671422296, + "f1": 0.25950277883533546, + "f2": 0.34151411971733003 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.8035221265027419, + "x2": 0.6015930655209849, + "x6": 0.4998723184030728, + "x3": 0.5000086022373529, + "x4": 0.4999482000454044, + "x7": 0.4999434631312218, + "x5": 0.49996455258681877 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.25764812655711955, + 0.34076494544946734, + 0.40134250258951304 + ], + "reference_point": [ + 0.25, + 0.3333333333333333, + 0.4166666666666667 + ], + "reference_point_index": 40, + "rank": 1, + "distance": 0.018359756549762157 + } + }, + { + "constraint_values": { + "g": 0.005225554412380262 + }, + "objective_values": { + "f2": 0.31328742784441715, + "f3": 0.47424607861558965, + "f1": 0.21769204795237346 + }, + "constraint_violation": 0.0, + "variable_values": { + "x3": 0.5000086059688381, + "x2": 0.6007866845953729, + "x5": 0.49996455258681877, + "x6": 0.49986125758830924, + "x4": 0.4999482000454044, + "x7": 0.4999434631312218, + "x1": 0.943561525140131 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "distance": 0.009309464750826096, + "normalised_objectives": [ + 0.21610806327994553, + 0.3125893805990622, + 0.47156227933841743 + ], + "reference_point": [ + 0.2222222222222222, + 0.3055555555555555, + 0.4722222222222222 + ], + "reference_point_index": 97 + } + }, + { + "constraint_values": { + "g": 0.004321056030054393 + }, + "objective_values": { + "f3": 0.3061952118443133, + "f1": 0.19695662094005312, + "f2": 0.501169223245688 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.49994818502170474, + "x2": 0.9967625072796918, + "x3": 0.5000101636583402, + "x6": 0.49987597347996976, + "x5": 0.49998039052133464, + "x7": 0.49994234131605736, + "x1": 0.609755635423321 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 105, + "normalised_objectives": [ + 0.19550686995036387, + 0.5001308656010298, + 0.3044624111727016 + ], + "distance": 0.036923015607137885, + "reference_point": [ + 0.2222222222222222, + 0.4722222222222222, + 0.3055555555555555 + ], + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.00462830642309342 + }, + "objective_values": { + "f3": 0.16643955762189494, + "f1": 0.5017805192277189, + "f2": 0.3364082295734795 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.0032061728080292062, + "x5": 0.4999813064804549, + "x7": 0.4999316206381487, + "x4": 0.4999442273622111, + "x6": 0.4998766049830354, + "x3": 0.5000085665773468, + "x1": 0.3313455465225561 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.003061258118677848, + "normalised_objectives": [ + 0.49835744815980787, + 0.3356683036072414, + 0.1654976331584114 + ], + "rank": 1, + "reference_point": [ + 0.5, + 0.3333333333333333, + 0.16666666666666666 + ], + "reference_point_index": 67 + } + }, + { + "constraint_values": { + "g": 0.007105476345969919 + }, + "objective_values": { + "f2": 0.5015248134371021, + "f3": 0.4833326334015651, + "f1": 0.022248029507302758 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.4999697323832607, + "x2": 0.9958042875739407, + "x4": 0.49994817597425883, + "x7": 0.4999422584744255, + "x3": 0.500009025003201, + "x1": 0.9598451100776784, + "x6": 0.4998298194308173 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.0, + 0.5, + 0.5 + ], + "rank": 1, + "normalised_objectives": [ + 0.021929278984600353, + 0.5004858117117347, + 0.48059741337841977 + ], + "distance": 0.02605124701270049, + "reference_point_index": 6 + } + }, + { + "constraint_values": { + "g": 0.004691185473326698 + }, + "objective_values": { + "f3": 0.07649186549159792, + "f1": 0.4436114493476452, + "f2": 0.48458787063408365 + }, + "constraint_violation": 0.0, + "variable_values": { + "x6": 0.4998654307422889, + "x7": 0.4999585009939243, + "x2": 0.7678482281945357, + "x3": 0.5000101424192689, + "x4": 0.4999484751905585, + "x5": 0.4999658653589149, + "x1": 0.15226940695326457 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.4166666666666667, + 0.5, + 0.08333333333333333 + ], + "distance": 0.029843773090312685, + "rank": 1, + "normalised_objectives": [ + 0.4405649438776766, + 0.4835795468025269, + 0.07605895434909726 + ], + "reference_point_index": 61 + } + }, + { + "constraint_values": { + "g": 0.00472777683526715 + }, + "objective_values": { + "f3": 0.1375605937097889, + "f1": 0.37494468820727256, + "f2": 0.4922224949182057 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.49997284795487595, + "x3": 0.5000100182587783, + "x6": 0.4998718642113838, + "x7": 0.4999368246642774, + "x4": 0.4999481187549717, + "x1": 0.27382659638033074, + "x2": 0.9262768993217408 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 108, + "rank": 1, + "reference_point": [ + 0.38888888888888884, + 0.4722222222222222, + 0.1388888888888889 + ], + "normalised_objectives": [ + 0.37234270660576024, + 0.4912003424874858, + 0.136782095088362 + ], + "distance": 0.02501387545375317 + } + }, + { + "constraint_values": { + "g": 0.00412219522969437 + }, + "objective_values": { + "f1": 0.08467776994151288, + "f2": 0.4210110475474799, + "f3": 0.49843337774070157 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.8373904042406813, + "x4": 0.4999481571996942, + "x6": 0.49988254229542917, + "x5": 0.4999683472407416, + "x1": 0.9927743458089465, + "x3": 0.5000125572038209, + "x7": 0.4999431738560055 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.08333333333333333, + 0.4166666666666667, + 0.5 + ], + "normalised_objectives": [ + 0.0839548717749773, + 0.42011788045053294, + 0.49561270271761865 + ], + "reference_point_index": 18, + "rank": 1, + "distance": 0.005513161783976009 + } + }, + { + "constraint_values": { + "g": 0.005323946285518133 + }, + "objective_values": { + "f3": 0.41848352927894894, + "f1": 0.22325122842620393, + "f2": 0.36358918858036526 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.8325346885949876, + "x7": 0.4999317162929959, + "x6": 0.4998638409786234, + "x2": 0.6676744128926233, + "x3": 0.5000079104018654, + "x5": 0.4999681942481566, + "x4": 0.4999482142025781 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "distance": 0.037709146650393995, + "reference_point_index": 115, + "normalised_objectives": [ + 0.2216312556225662, + 0.36280002972813463, + 0.416115289853865 + ], + "reference_point": [ + 0.2222222222222222, + 0.3888888888888889, + 0.3888888888888889 + ] + } + }, + { + "constraint_values": { + "g": 0.005068758734161349 + }, + "objective_values": { + "f3": 0.41700385553431396, + "f1": 0.4221366968030609, + "f2": 0.16592820639678652 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.49994805344509835, + "x5": 0.4999685590229177, + "x3": 0.5000083569705042, + "x1": 0.8298016467241733, + "x2": 0.19279841540315001, + "x6": 0.4998660576063331, + "x7": 0.49993700508183087 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.0034674787565943466, + "reference_point": [ + 0.4166666666666667, + 0.16666666666666666, + 0.4166666666666667 + ], + "rank": 1, + "normalised_objectives": [ + 0.41922921114292055, + 0.16549707099025424, + 0.41464398957194915 + ], + "reference_point_index": 57 + } + }, + { + "constraint_values": { + "g": 0.004577949117301472 + }, + "objective_values": { + "f2": 0.2994812559289614, + "f3": 0.25124791935459334, + "f1": 0.4538487738337467 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.19279841540315001, + "x5": 0.4999683545376515, + "x6": 0.49987278984473016, + "x7": 0.4999431812735788, + "x1": 0.5002059214526038, + "x4": 0.49994805344509835, + "x3": 0.5000083569705042 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.4722222222222222, + 0.3055555555555556, + 0.2222222222222222 + ], + "reference_point_index": 130, + "rank": 1, + "normalised_objectives": [ + 0.4507359956139407, + 0.29880821581038725, + 0.2498260650026348 + ], + "distance": 0.034180270392301954 + } + }, + { + "constraint_values": { + "g": 0.004644214382132361 + }, + "objective_values": { + "f2": 0.439219828416788, + "f1": 0.5004476825383388, + "f3": 0.06497670342700551 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.49993690769288224, + "x4": 0.4999481187549717, + "x3": 0.5000109823632539, + "x1": 0.12935266534524742, + "x6": 0.4998746345014167, + "x5": 0.4999682727655678, + "x2": 0.028847641598700624 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "normalised_objectives": [ + 0.4970332397748846, + 0.43829367974504174, + 0.06460895650101041 + ], + "reference_point": [ + 0.5, + 0.4166666666666667, + 0.08333333333333333 + ], + "reference_point_index": 68, + "distance": 0.027284094356082936, + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.004024095908139458 + }, + "objective_values": { + "f2": 0.24986510969425862, + "f1": 0.25671583473267834, + "f3": 0.4974431514812025 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.4999481548524169, + "x6": 0.4998852811580682, + "x3": 0.5000085320662605, + "x1": 0.9908988310310727, + "x7": 0.4999434631312218, + "x2": 0.49311406236268324, + "x5": 0.49996452461514457 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.006779234792812468, + "normalised_objectives": [ + 0.25487922412634434, + 0.24928193932863715, + 0.4946280801411595 + ], + "reference_point_index": 39, + "rank": 1, + "reference_point": [ + 0.25, + 0.25, + 0.5 + ] + } + }, + { + "constraint_values": { + "g": 0.004440517106196751 + }, + "objective_values": { + "f1": 0.4294215711034929, + "f3": 0.14820582753081457, + "f2": 0.4268131184718893 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.49119989856316126, + "x3": 0.5000101307030312, + "x4": 0.4999468326800156, + "x6": 0.4998766284063604, + "x1": 0.2951012529000662, + "x5": 0.4999680303232014, + "x7": 0.4999424447308126 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.4166666666666667, + 0.4166666666666667, + 0.16666666666666666 + ], + "rank": 1, + "normalised_objectives": [ + 0.42646692579214046, + 0.4259094420806871, + 0.14736708761034434 + ], + "reference_point_index": 60, + "distance": 0.02223935625827006 + } + }, + { + "constraint_values": { + "g": 0.00532818904099841 + }, + "objective_values": { + "f3": 0.3277875703957897, + "f1": 0.28389148695324096, + "f2": 0.39364913169196775 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.6521006253857707, + "x4": 0.4999481745533915, + "x6": 0.4998618380962295, + "x7": 0.49993693916503523, + "x5": 0.4999658659082865, + "x2": 0.667421913842247, + "x3": 0.5000079364543192 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 139, + "reference_point": [ + 0.3055555555555555, + 0.38888888888888884, + 0.3055555555555555 + ], + "normalised_objectives": [ + 0.28187895096682075, + 0.3928055252482528, + 0.3259325787276795 + ], + "rank": 1, + "distance": 0.03146998814313111 + } + }, + { + "constraint_values": { + "g": 0.004939226618105863 + }, + "objective_values": { + "f1": 0.32526533536681096, + "f2": 0.2631311076353386, + "f3": 0.4165427836159563 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.49994652331056644, + "x7": 0.49993714598430955, + "x2": 0.42541675168143256, + "x3": 0.5000061893524216, + "x1": 0.8289909928538389, + "x5": 0.4999689771110623, + "x6": 0.49986885603962083 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.016273492483906596, + "reference_point_index": 49, + "reference_point": [ + 0.3333333333333333, + 0.25, + 0.4166666666666667 + ], + "rank": 1, + "normalised_objectives": [ + 0.3229849599942848, + 0.2625239085603531, + 0.4141855268561493 + ] + } + }, + { + "constraint_values": { + "g": 0.007844215175634162 + }, + "objective_values": { + "f3": 0.4787154562210454, + "f2": 0.11480645717048427, + "f1": 0.4143223017841045 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.18716714624384334, + "x3": 0.5000101070006848, + "x6": 0.500178194880412, + "x4": 0.4999478382416217, + "x1": 0.9499790721875027, + "x7": 0.4999358503747642, + "x5": 0.49996793933969663 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "reference_point": [ + 0.3888888888888889, + 0.1388888888888889, + 0.4722222222222222 + ], + "reference_point_index": 93, + "normalised_objectives": [ + 0.4114654037015022, + 0.11446791861643112, + 0.4760063647692348 + ], + "distance": 0.03145766129821112 + } + }, + { + "constraint_values": { + "g": 0.004614577521522278 + }, + "objective_values": { + "f2": 0.10086493493683985, + "f3": 0.47134944381098787, + "f1": 0.4324001987736946 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.49997630175885394, + "x7": 0.49993789798549493, + "x1": 0.938368712454583, + "x2": 0.148312660394481, + "x3": 0.5000101424192689, + "x4": 0.4999484726201625, + "x6": 0.4998727609625522 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.4166666666666667, + 0.08333333333333333, + 0.5 + ], + "reference_point_index": 56, + "distance": 0.03543735217689114, + "rank": 1, + "normalised_objectives": [ + 0.4294262709001147, + 0.10055164866967321, + 0.4686820365686377 + ] + } + }, + { + "constraint_values": { + "g": 0.004004477333818812 + }, + "objective_values": { + "f1": 0.4754463618269626, + "f2": 0.05277113860643934, + "f3": 0.4757869769004168 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.4999591958431356, + "x6": 0.49988760947968125, + "x2": 0.05581463581233118, + "x4": 0.4999479427252771, + "x7": 0.4999437115226333, + "x3": 0.5000100868817393, + "x1": 0.9477785958960891 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 91, + "rank": 1, + "normalised_objectives": [ + 0.4721937686048959, + 0.05254496465900677, + 0.4730944576913077 + ], + "distance": 0.0031154829658919677, + "reference_point": [ + 0.4722222222222222, + 0.05555555555555555, + 0.4722222222222222 + ] + } + }, + { + "constraint_values": { + "g": 0.005191299247186976 + }, + "objective_values": { + "f1": 0.5022985824923925, + "f3": 0.0008231092900538028, + "f2": 0.5020696074647406 + }, + "constraint_violation": 0.0, + "variable_values": { + "x1": 0.001637716702622305, + "x5": 0.499981719565505, + "x2": 0.36090849027052824, + "x6": 0.4998612543120676, + "x7": 0.499937072161924, + "x4": 0.4999482475750206, + "x3": 0.5000079671464311 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "rank": 1, + "normalised_objectives": [ + 0.4988721576695832, + 0.5010296189536515, + 0.0008184070762824886 + ], + "reference_point": [ + 0.5, + 0.5, + 0.0 + ], + "reference_point_index": 69, + "distance": 0.0017312162599271246 + } + }, + { + "constraint_values": { + "g": 0.005358304789560009 + }, + "objective_values": { + "f3": 0.2492842129771352, + "f2": 0.43244384797554886, + "f1": 0.3236302438368759 + }, + "constraint_violation": 0.0, + "variable_values": { + "x4": 0.49994678830972356, + "x3": 0.5000079408765761, + "x2": 0.7182520963504687, + "x1": 0.4959111826888723, + "x7": 0.499934073730831, + "x5": 0.4999685488085838, + "x6": 0.4998625158961244 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 51, + "normalised_objectives": [ + 0.32136045345773073, + 0.43152997264090104, + 0.24787347122496606 + ], + "rank": 1, + "distance": 0.01899351102688927, + "reference_point": [ + 0.3333333333333333, + 0.4166666666666667, + 0.25 + ] + } + }, + { + "constraint_values": { + "g": 0.004875984029695246 + }, + "objective_values": { + "f3": 0.42433981070345156, + "f2": 0.4227917410311717, + "f1": 0.157744432295072 + }, + "constraint_violation": 0.0, + "variable_values": { + "x7": 0.49993161199215264, + "x3": 0.5000085297206621, + "x1": 0.8445615527635335, + "x2": 0.812305494382811, + "x4": 0.49994754420718196, + "x5": 0.49996812234148297, + "x6": 0.49987283026787704 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 30, + "distance": 0.01175703575851929, + "reference_point": [ + 0.16666666666666666, + 0.4166666666666667, + 0.4166666666666667 + ], + "normalised_objectives": [ + 0.15654852688507265, + 0.4218953485631387, + 0.42193843062532915 + ], + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.004825099339988981 + }, + "objective_values": { + "f2": 0.3847871781592991, + "f3": 0.146243852220382, + "f1": 0.4737940689603079 + }, + "constraint_violation": 0.0, + "variable_values": { + "x6": 0.4998714644636049, + "x2": 0.19569014543298546, + "x7": 0.4999318761836119, + "x1": 0.29108319908895797, + "x3": 0.500010074493091, + "x5": 0.4999779829417041, + "x4": 0.499948197721753 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point_index": 114, + "distance": 0.007840182589151595, + "reference_point": [ + 0.4722222222222222, + 0.3888888888888889, + 0.1388888888888889 + ], + "normalised_objectives": [ + 0.4705521720868779, + 0.38395962337688994, + 0.14541621510360575 + ], + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.004644830040501091 + }, + "objective_values": { + "f2": 0.11393924730039762, + "f1": 0.4776801367603592, + "f3": 0.4130254459797443 + }, + "constraint_violation": 0.0, + "variable_values": { + "x2": 0.05966285733663936, + "x5": 0.49996834973581616, + "x6": 0.49988067492324795, + "x4": 0.4999464658419249, + "x7": 0.4999293520656677, + "x3": 0.4999794598673534, + "x1": 0.8222317651564357 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "distance": 0.03206142669605567, + "reference_point": [ + 0.4722222222222222, + 0.1388888888888889, + 0.3888888888888889 + ], + "normalised_objectives": [ + 0.4744130828842852, + 0.11360227952405892, + 0.41068809380746835 + ], + "reference_point_index": 111, + "rank": 1 + } + }, + { + "constraint_values": { + "g": 0.008773078466184359 + }, + "objective_values": { + "f1": 0.5029363602664948, + "f2": 0.2045518655139767, + "f3": 0.3012848526857128 + }, + "constraint_violation": 0.0, + "variable_values": { + "x5": 0.4999681377359038, + "x6": 0.5001917019022833, + "x7": 0.4999378052577974, + "x1": 0.5973292886519321, + "x2": 0.00481331521870465, + "x3": 0.5000101880089542, + "x4": 0.4999481726223684 + }, + "is_feasible": true, + "evaluated": true, + "data": { + "reference_point": [ + 0.4722222222222222, + 0.2222222222222222, + 0.3055555555555556 + ], + "reference_point_index": 129, + "rank": 1, + "distance": 0.031234071711200195, + "normalised_objectives": [ + 0.49950580670019085, + 0.2040507710524511, + 0.29957983970006996 + ] + } + } + ], + "generation": 400, + "algorithm": "NSGA3", + "additional_data": { + "reference_points": [ + [ + 0.0, + 0.0, + 1.0 + ], + [ + 0.0, + 0.08333333333333333, + 0.9166666666666666 + ], + [ + 0.0, + 0.16666666666666666, + 0.8333333333333334 + ], + [ + 0.0, + 0.25, + 0.75 + ], + [ + 0.0, + 0.3333333333333333, + 0.6666666666666666 + ], + [ + 0.0, + 0.4166666666666667, + 0.5833333333333334 + ], + [ + 0.0, + 0.5, + 0.5 + ], + [ + 0.0, + 0.5833333333333334, + 0.4166666666666667 + ], + [ + 0.0, + 0.6666666666666666, + 0.3333333333333333 + ], + [ + 0.0, + 0.75, + 0.25 + ], + [ + 0.0, + 0.8333333333333334, + 0.16666666666666666 + ], + [ + 0.0, + 0.9166666666666666, + 0.08333333333333333 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.08333333333333333, + 0.0, + 0.9166666666666666 + ], + [ + 0.08333333333333333, + 0.08333333333333333, + 0.8333333333333334 + ], + [ + 0.08333333333333333, + 0.16666666666666666, + 0.75 + ], + [ + 0.08333333333333333, + 0.25, + 0.6666666666666666 + ], + [ + 0.08333333333333333, + 0.3333333333333333, + 0.5833333333333334 + ], + [ + 0.08333333333333333, + 0.4166666666666667, + 0.5 + ], + [ + 0.08333333333333333, + 0.5, + 0.4166666666666667 + ], + [ + 0.08333333333333333, + 0.5833333333333334, + 0.3333333333333333 + ], + [ + 0.08333333333333333, + 0.6666666666666666, + 0.25 + ], + [ + 0.08333333333333333, + 0.75, + 0.16666666666666666 + ], + [ + 0.08333333333333333, + 0.8333333333333334, + 0.08333333333333333 + ], + [ + 0.08333333333333333, + 0.9166666666666666, + 0.0 + ], + [ + 0.16666666666666666, + 0.0, + 0.8333333333333334 + ], + [ + 0.16666666666666666, + 0.08333333333333333, + 0.75 + ], + [ + 0.16666666666666666, + 0.16666666666666666, + 0.6666666666666666 + ], + [ + 0.16666666666666666, + 0.25, + 0.5833333333333334 + ], + [ + 0.16666666666666666, + 0.3333333333333333, + 0.5 + ], + [ + 0.16666666666666666, + 0.4166666666666667, + 0.4166666666666667 + ], + [ + 0.16666666666666666, + 0.5, + 0.3333333333333333 + ], + [ + 0.16666666666666666, + 0.5833333333333334, + 0.25 + ], + [ + 0.16666666666666666, + 0.6666666666666666, + 0.16666666666666666 + ], + [ + 0.16666666666666666, + 0.75, + 0.08333333333333333 + ], + [ + 0.16666666666666666, + 0.8333333333333334, + 0.0 + ], + [ + 0.25, + 0.0, + 0.75 + ], + [ + 0.25, + 0.08333333333333333, + 0.6666666666666666 + ], + [ + 0.25, + 0.16666666666666666, + 0.5833333333333334 + ], + [ + 0.25, + 0.25, + 0.5 + ], + [ + 0.25, + 0.3333333333333333, + 0.4166666666666667 + ], + [ + 0.25, + 0.4166666666666667, + 0.3333333333333333 + ], + [ + 0.25, + 0.5, + 0.25 + ], + [ + 0.25, + 0.5833333333333334, + 0.16666666666666666 + ], + [ + 0.25, + 0.6666666666666666, + 0.08333333333333333 + ], + [ + 0.25, + 0.75, + 0.0 + ], + [ + 0.3333333333333333, + 0.0, + 0.6666666666666666 + ], + [ + 0.3333333333333333, + 0.08333333333333333, + 0.5833333333333334 + ], + [ + 0.3333333333333333, + 0.16666666666666666, + 0.5 + ], + [ + 0.3333333333333333, + 0.25, + 0.4166666666666667 + ], + [ + 0.3333333333333333, + 0.3333333333333333, + 0.3333333333333333 + ], + [ + 0.3333333333333333, + 0.4166666666666667, + 0.25 + ], + [ + 0.3333333333333333, + 0.5, + 0.16666666666666666 + ], + [ + 0.3333333333333333, + 0.5833333333333334, + 0.08333333333333333 + ], + [ + 0.3333333333333333, + 0.6666666666666666, + 0.0 + ], + [ + 0.4166666666666667, + 0.0, + 0.5833333333333334 + ], + [ + 0.4166666666666667, + 0.08333333333333333, + 0.5 + ], + [ + 0.4166666666666667, + 0.16666666666666666, + 0.4166666666666667 + ], + [ + 0.4166666666666667, + 0.25, + 0.3333333333333333 + ], + [ + 0.4166666666666667, + 0.3333333333333333, + 0.25 + ], + [ + 0.4166666666666667, + 0.4166666666666667, + 0.16666666666666666 + ], + [ + 0.4166666666666667, + 0.5, + 0.08333333333333333 + ], + [ + 0.4166666666666667, + 0.5833333333333334, + 0.0 + ], + [ + 0.5, + 0.0, + 0.5 + ], + [ + 0.5, + 0.08333333333333333, + 0.4166666666666667 + ], + [ + 0.5, + 0.16666666666666666, + 0.3333333333333333 + ], + [ + 0.5, + 0.25, + 0.25 + ], + [ + 0.5, + 0.3333333333333333, + 0.16666666666666666 + ], + [ + 0.5, + 0.4166666666666667, + 0.08333333333333333 + ], + [ + 0.5, + 0.5, + 0.0 + ], + [ + 0.5833333333333334, + 0.0, + 0.4166666666666667 + ], + [ + 0.5833333333333334, + 0.08333333333333333, + 0.3333333333333333 + ], + [ + 0.5833333333333334, + 0.16666666666666666, + 0.25 + ], + [ + 0.5833333333333334, + 0.25, + 0.16666666666666666 + ], + [ + 0.5833333333333334, + 0.3333333333333333, + 0.08333333333333333 + ], + [ + 0.5833333333333334, + 0.4166666666666667, + 0.0 + ], + [ + 0.6666666666666666, + 0.0, + 0.3333333333333333 + ], + [ + 0.6666666666666666, + 0.08333333333333333, + 0.25 + ], + [ + 0.6666666666666666, + 0.16666666666666666, + 0.16666666666666666 + ], + [ + 0.6666666666666666, + 0.25, + 0.08333333333333333 + ], + [ + 0.6666666666666666, + 0.3333333333333333, + 0.0 + ], + [ + 0.75, + 0.0, + 0.25 + ], + [ + 0.75, + 0.08333333333333333, + 0.16666666666666666 + ], + [ + 0.75, + 0.16666666666666666, + 0.08333333333333333 + ], + [ + 0.75, + 0.25, + 0.0 + ], + [ + 0.8333333333333334, + 0.0, + 0.16666666666666666 + ], + [ + 0.8333333333333334, + 0.08333333333333333, + 0.08333333333333333 + ], + [ + 0.8333333333333334, + 0.16666666666666666, + 0.0 + ], + [ + 0.9166666666666666, + 0.0, + 0.08333333333333333 + ], + [ + 0.9166666666666666, + 0.08333333333333333, + 0.0 + ], + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.4722222222222222, + 0.05555555555555555, + 0.4722222222222222 + ], + [ + 0.3888888888888889, + 0.05555555555555555, + 0.5555555555555556 + ], + [ + 0.3888888888888889, + 0.1388888888888889, + 0.4722222222222222 + ], + [ + 0.5555555555555556, + 0.3888888888888889, + 0.05555555555555555 + ], + [ + 0.1388888888888889, + 0.3055555555555555, + 0.5555555555555556 + ], + [ + 0.1388888888888889, + 0.38888888888888884, + 0.4722222222222222 + ], + [ + 0.2222222222222222, + 0.3055555555555555, + 0.4722222222222222 + ], + [ + 0.05555555555555555, + 0.3055555555555555, + 0.6388888888888888 + ], + [ + 0.05555555555555555, + 0.8888888888888888, + 0.05555555555555555 + ], + [ + 0.05555555555555555, + 0.3888888888888889, + 0.5555555555555556 + ], + [ + 0.4722222222222222, + 0.4722222222222222, + 0.05555555555555555 + ], + [ + 0.3888888888888889, + 0.5555555555555556, + 0.05555555555555555 + ], + [ + 0.1388888888888889, + 0.4722222222222222, + 0.38888888888888884 + ], + [ + 0.1388888888888889, + 0.5555555555555556, + 0.3055555555555555 + ], + [ + 0.2222222222222222, + 0.4722222222222222, + 0.3055555555555555 + ], + [ + 0.3055555555555555, + 0.4722222222222222, + 0.2222222222222222 + ], + [ + 0.3055555555555555, + 0.5555555555555556, + 0.1388888888888889 + ], + [ + 0.38888888888888884, + 0.4722222222222222, + 0.1388888888888889 + ], + [ + 0.05555555555555555, + 0.4722222222222222, + 0.4722222222222222 + ], + [ + 0.05555555555555555, + 0.5555555555555556, + 0.3888888888888889 + ], + [ + 0.4722222222222222, + 0.1388888888888889, + 0.3888888888888889 + ], + [ + 0.5555555555555556, + 0.05555555555555555, + 0.3888888888888889 + ], + [ + 0.3888888888888889, + 0.3888888888888889, + 0.2222222222222222 + ], + [ + 0.4722222222222222, + 0.3888888888888889, + 0.1388888888888889 + ], + [ + 0.2222222222222222, + 0.3888888888888889, + 0.3888888888888889 + ], + [ + 0.05555555555555555, + 0.8055555555555556, + 0.1388888888888889 + ], + [ + 0.1388888888888889, + 0.7222222222222222, + 0.1388888888888889 + ], + [ + 0.1388888888888889, + 0.8055555555555556, + 0.05555555555555555 + ], + [ + 0.2222222222222222, + 0.7222222222222222, + 0.05555555555555555 + ], + [ + 0.6388888888888888, + 0.05555555555555555, + 0.3055555555555556 + ], + [ + 0.6388888888888888, + 0.1388888888888889, + 0.2222222222222222 + ], + [ + 0.7222222222222222, + 0.05555555555555555, + 0.2222222222222222 + ], + [ + 0.3055555555555555, + 0.638888888888889, + 0.05555555555555555 + ], + [ + 0.2222222222222222, + 0.6388888888888888, + 0.1388888888888889 + ], + [ + 0.7222222222222222, + 0.1388888888888889, + 0.1388888888888889 + ], + [ + 0.8055555555555556, + 0.05555555555555555, + 0.1388888888888889 + ], + [ + 0.7222222222222222, + 0.2222222222222222, + 0.05555555555555555 + ], + [ + 0.8055555555555556, + 0.1388888888888889, + 0.05555555555555555 + ], + [ + 0.4722222222222222, + 0.2222222222222222, + 0.3055555555555556 + ], + [ + 0.4722222222222222, + 0.3055555555555556, + 0.2222222222222222 + ], + [ + 0.5555555555555556, + 0.2222222222222222, + 0.2222222222222222 + ], + [ + 0.5555555555555556, + 0.3055555555555555, + 0.1388888888888889 + ], + [ + 0.638888888888889, + 0.3055555555555555, + 0.05555555555555555 + ], + [ + 0.3055555555555556, + 0.3055555555555555, + 0.3888888888888889 + ], + [ + 0.5555555555555556, + 0.1388888888888889, + 0.3055555555555555 + ], + [ + 0.2222222222222222, + 0.5555555555555556, + 0.2222222222222222 + ], + [ + 0.3055555555555555, + 0.1388888888888889, + 0.5555555555555556 + ], + [ + 0.3055555555555555, + 0.2222222222222222, + 0.4722222222222222 + ], + [ + 0.3055555555555555, + 0.38888888888888884, + 0.3055555555555555 + ], + [ + 0.38888888888888884, + 0.3055555555555555, + 0.3055555555555555 + ], + [ + 0.1388888888888889, + 0.2222222222222222, + 0.638888888888889 + ], + [ + 0.2222222222222222, + 0.2222222222222222, + 0.5555555555555556 + ], + [ + 0.2222222222222222, + 0.1388888888888889, + 0.638888888888889 + ], + [ + 0.05555555555555555, + 0.7222222222222222, + 0.2222222222222222 + ], + [ + 0.05555555555555555, + 0.6388888888888888, + 0.3055555555555556 + ], + [ + 0.1388888888888889, + 0.6388888888888888, + 0.2222222222222222 + ], + [ + 0.2222222222222222, + 0.05555555555555555, + 0.7222222222222222 + ], + [ + 0.05555555555555555, + 0.1388888888888889, + 0.8055555555555556 + ], + [ + 0.05555555555555555, + 0.2222222222222222, + 0.7222222222222222 + ], + [ + 0.1388888888888889, + 0.1388888888888889, + 0.7222222222222222 + ], + [ + 0.1388888888888889, + 0.05555555555555555, + 0.8055555555555556 + ], + [ + 0.38888888888888884, + 0.2222222222222222, + 0.3888888888888889 + ], + [ + 0.6388888888888888, + 0.2222222222222222, + 0.1388888888888889 + ], + [ + 0.3055555555555555, + 0.05555555555555555, + 0.638888888888889 + ], + [ + 0.8888888888888888, + 0.05555555555555555, + 0.05555555555555555 + ], + [ + 0.05555555555555555, + 0.05555555555555555, + 0.8888888888888888 + ] + ], + "ideal_point": [ + 0.00017586327190999285, + 0.00013082652121221283, + 4.4496222706413846e-8 + ] + }, + "took": { + "hours": 0, + "minutes": 0, + "seconds": 3 + }, + "exported_on": "2024-09-01T07:31:09.337120Z" +} \ No newline at end of file diff --git a/examples/results/DTLZ1_3obj_Adaptive_NSGA3_gen400_Pareto_front.png b/examples/results/DTLZ1_3obj_Adaptive_NSGA3_gen400_Pareto_front.png new file mode 100644 index 0000000000000000000000000000000000000000..593baee2c159dd1b44d767190f554c4487c58873 GIT binary patch literal 63566 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

-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

cO*}$QJp-t``FS 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 Dqi8~V literal 0 HcmV?d00001 From a404f3ab2a37e10756f3d33cb77f93c76f3b6cf7 Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 08:34:22 +0100 Subject: [PATCH 08/14] Fixed docstring in examples Fixed typo in two py script names --- examples/convergence.rs | 2 +- examples/nsga2_sch.rs | 2 +- examples/nsga2_zdt1.rs | 2 +- examples/nsga3_dtlz1.rs | 2 +- examples/nsga3_dtlz1_8obj.rs | 2 +- examples/{nsga3_drlz1_8obj_plot.py => nsga3_dtlz1_8obj_plot.py} | 0 examples/{nsga3_drlz1_plot.py => nsga3_dtlz1_plot.py} | 0 examples/nsga3_dtlz2.rs | 2 +- 8 files changed, 6 insertions(+), 6 deletions(-) rename examples/{nsga3_drlz1_8obj_plot.py => nsga3_dtlz1_8obj_plot.py} (100%) rename examples/{nsga3_drlz1_plot.py => nsga3_dtlz1_plot.py} (100%) diff --git a/examples/convergence.rs b/examples/convergence.rs index b15eade..4041165 100644 --- a/examples/convergence.rs +++ b/examples/convergence.rs @@ -23,7 +23,7 @@ use optirustic::metrics::HyperVolume; /// /// Make sure to compile this in release mode to speed up the calculation: /// -/// `cargo run --example convergence --release` +/// `cargo run --example convergence -p optirustic --release` fn main() -> Result<(), OError> { let problem = SCHProblem::create()?; let out_path = PathBuf::from(&env::current_dir().expect("Cannot fetch current directory")) diff --git a/examples/nsga2_sch.rs b/examples/nsga2_sch.rs index 11576d7..81cb653 100644 --- a/examples/nsga2_sch.rs +++ b/examples/nsga2_sch.rs @@ -16,7 +16,7 @@ use optirustic::core::builtin_problems::SCHProblem; /// /// Make sure to compile this in release mode to speed up the calculation: /// -/// `cargo run --example nsga2 --release` +/// `cargo run --example nsga2 -p optirustic --release` fn main() -> Result<(), Box> { // Add log env_logger::builder().filter_level(LevelFilter::Info).init(); diff --git a/examples/nsga2_zdt1.rs b/examples/nsga2_zdt1.rs index 10ea7f0..7de0d80 100644 --- a/examples/nsga2_zdt1.rs +++ b/examples/nsga2_zdt1.rs @@ -17,7 +17,7 @@ use optirustic::core::builtin_problems::ZTD1Problem; /// /// Make sure to compile this in release mode to speed up the calculation: /// -/// `cargo run --example nsga2_zdt1 --release` +/// `cargo run --example nsga2_zdt1 -p optirustic --release` fn main() -> Result<(), Box> { // Add log env_logger::builder().filter_level(LevelFilter::Info).init(); diff --git a/examples/nsga3_dtlz1.rs b/examples/nsga3_dtlz1.rs index dc9f887..732f176 100644 --- a/examples/nsga3_dtlz1.rs +++ b/examples/nsga3_dtlz1.rs @@ -18,7 +18,7 @@ use optirustic::utils::{DasDarren1998, NumberOfPartitions}; /// /// Make sure to compile this in release mode to speed up the calculation: /// -/// `cargo run --example nsga3_dtlz1 --release` +/// `cargo run --example nsga3_dtlz1 -p optirustic --release` fn main() -> Result<(), Box> { // Add log env_logger::builder().filter_level(LevelFilter::Info).init(); diff --git a/examples/nsga3_dtlz1_8obj.rs b/examples/nsga3_dtlz1_8obj.rs index 0c900ff..404bf61 100644 --- a/examples/nsga3_dtlz1_8obj.rs +++ b/examples/nsga3_dtlz1_8obj.rs @@ -15,7 +15,7 @@ use optirustic::utils::{NumberOfPartitions, TwoLayerPartitions}; /// /// Make sure to compile this in release mode to speed up the calculation: /// -/// `cargo run --example nsga3_dtlz1_8obj --release` +/// `cargo run --example nsga3_dtlz1_8obj -p optirustic --release` fn main() -> Result<(), Box> { // Add log env_logger::builder().filter_level(LevelFilter::Info).init(); diff --git a/examples/nsga3_drlz1_8obj_plot.py b/examples/nsga3_dtlz1_8obj_plot.py similarity index 100% rename from examples/nsga3_drlz1_8obj_plot.py rename to examples/nsga3_dtlz1_8obj_plot.py diff --git a/examples/nsga3_drlz1_plot.py b/examples/nsga3_dtlz1_plot.py similarity index 100% rename from examples/nsga3_drlz1_plot.py rename to examples/nsga3_dtlz1_plot.py diff --git a/examples/nsga3_dtlz2.rs b/examples/nsga3_dtlz2.rs index b045ea3..ed995e4 100644 --- a/examples/nsga3_dtlz2.rs +++ b/examples/nsga3_dtlz2.rs @@ -15,7 +15,7 @@ use optirustic::utils::{DasDarren1998, NumberOfPartitions}; /// /// Make sure to compile this in release mode to speed up the calculation: /// -/// `cargo run --example nsga3_dtlz2 --release` +/// `cargo run --example nsga3_dtlz2 -p optirustic --release` fn main() -> Result<(), Box> { // Add log env_logger::builder().filter_level(LevelFilter::Info).init(); From 641c41600ca0b921e5296ee1e99d432ec7983d82 Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 08:34:47 +0100 Subject: [PATCH 09/14] Added option to invert DTLZ1Problem --- src/core/problem.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/core/problem.rs b/src/core/problem.rs index bec5f2a..0d2ae1a 100644 --- a/src/core/problem.rs +++ b/src/core/problem.rs @@ -815,6 +815,8 @@ pub mod builtin_problems { n_vars: usize, /// The number of objectives. n_objectives: usize, + /// Whether to invert the problem + invert: bool, } impl DTLZ1Problem { @@ -824,7 +826,11 @@ pub mod builtin_problems { /// /// * `n_vars`: The number of variables. /// * `n_objectives`: The number of objectives. - pub fn create(n_vars: usize, n_objectives: usize) -> Result { + /// * `invert`: Whether to invert the problem based on Section VIIIA of Jain and Deb (2014)'s + /// paper. + /// + /// returns: `Result` + pub fn create(n_vars: usize, n_objectives: usize, invert: bool) -> Result { // if k must be > 0, then n + 1 >= M if n_vars + 1 < n_objectives { return Err(OError::Generic( @@ -853,6 +859,7 @@ pub mod builtin_problems { let e = Box::new(DTLZ1Problem { n_vars, n_objectives, + invert, }); Problem::new(objectives, variables, Some(constraints), e) } @@ -908,7 +915,11 @@ pub mod builtin_problems { .as_real()?; 1.0 - x }; - objectives.insert(format!("f{o}"), 0.5 * prod * delta * (1.0 + g)); + let mut obj_value = 0.5 * prod * delta * (1.0 + g); + if self.invert { + obj_value = 0.5 * (1.0 + g) - obj_value; + } + objectives.insert(format!("f{o}"), obj_value); } Ok(EvaluationResult { constraints: Some(constraints), @@ -1067,7 +1078,7 @@ mod test { #[test] /// Test the DTLZ1 problem implementation with the optimal solution fn test_dtlz1_optimal_solutions() { - let problem = Arc::new(DTLZ1Problem::create(4, 3).unwrap()); + let problem = Arc::new(DTLZ1Problem::create(4, 3, false).unwrap()); let mut individual = Individual::new(problem.clone()); individual .update_variable("x1", VariableValue::Real(0.2)) @@ -1114,7 +1125,7 @@ mod test { let all_expected_objectives = read_csv_test_file(&obj_file, None); for (expected_objectives, vars) in all_expected_objectives.iter().zip(all_vars) { - let problem = Arc::new(DTLZ1Problem::create(vars.len(), 3).unwrap()); + let problem = Arc::new(DTLZ1Problem::create(vars.len(), 3, false).unwrap()); let mut individual = Individual::new(problem.clone()); for (i, var) in vars.iter().enumerate() { individual From 5cd0237724cb043b7e8d265a2ee21accac8fd937 Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 08:36:32 +0100 Subject: [PATCH 10/14] Updated changelog to link to new example --- CHANGELOG.md | 4 +++- examples/nsga3_inverted_dtlz1_plot.py | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 307adb5..cdcd159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,9 @@ - Added `AdaptiveNSGA3` to use the adaptive approach to handle the reference points. This implements the new algorithm from Jain and Deb (2014) (doi.org/10.1109/TEVC.2013.2281534) to handle problems where not all reference points intersect the optimal Pareto front. This - helps to reduce crowding and enhance the solution quality. + helps to reduce crowding and enhance the solution quality. See the + new [example file](./examples/nsga3_inverted_dtlz1.rs) + and [results](./examples/results/DTLZ1_3obj_Adaptive_NSGA3_gen400_obj_vs_ref_points.png). ## 0.6.0 diff --git a/examples/nsga3_inverted_dtlz1_plot.py b/examples/nsga3_inverted_dtlz1_plot.py index 16bba8b..685a214 100644 --- a/examples/nsga3_inverted_dtlz1_plot.py +++ b/examples/nsga3_inverted_dtlz1_plot.py @@ -55,8 +55,6 @@ label="Normalised objectives", ) -# TODO highlight or ref points vs new - ax.set_xlabel(obj_names[0]) ax.set_ylabel(obj_names[1]) ax.set_zlabel(obj_names[2]) From 337ea59b1eb4fb72b5d97dfddb5a1776ef871cd3 Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 09:16:40 +0100 Subject: [PATCH 11/14] Added Adaptive NSGA3 tests with inverted DTLZ1 problem --- src/algorithms/a_nsga3.rs | 77 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/algorithms/a_nsga3.rs b/src/algorithms/a_nsga3.rs index 451a0f6..0ef7d80 100644 --- a/src/algorithms/a_nsga3.rs +++ b/src/algorithms/a_nsga3.rs @@ -24,3 +24,80 @@ impl AdaptiveNSGA3 { NSGA3::new(problem, options, true) } } + +#[cfg(test)] +mod test_problems { + use float_cmp::approx_eq; + + use optirustic_macros::test_with_retries; + + use crate::algorithms::{ + AdaptiveNSGA3, Algorithm, MaxGeneration, NSGA3Arg, Nsga3NumberOfIndividuals, + StoppingConditionType, + }; + use crate::core::builtin_problems::DTLZ1Problem; + use crate::core::test_utils::assert_approx_array_eq; + use crate::operators::{PolynomialMutationArgs, SimulatedBinaryCrossoverArgs}; + use crate::utils::NumberOfPartitions; + + #[test_with_retries(10)] + /// Test the inverted DTLZ1 problem with M=3 and MaxGeneration = 400 + fn test_inverted_dtlz1_obj_3() { + let k: usize = 5; + let number_variables: usize = 3 + k - 1; + let problem = DTLZ1Problem::create(number_variables, 3, true).unwrap(); + let number_of_partitions = NumberOfPartitions::OneLayer(12); + let pop_size: usize = 92; + let expected_ref_points: usize = 91; + + let crossover_operator_options = SimulatedBinaryCrossoverArgs { + distribution_index: 30.0, + ..SimulatedBinaryCrossoverArgs::default() + }; + let mutation_operator_options = PolynomialMutationArgs::default(&problem); + + let args = NSGA3Arg { + number_of_individuals: Nsga3NumberOfIndividuals::Custom(pop_size), + number_of_partitions, + crossover_operator_options: Some(crossover_operator_options), + mutation_operator_options: Some(mutation_operator_options), + stopping_condition: StoppingConditionType::MaxGeneration(MaxGeneration(400)), + parallel: None, + export_history: None, + seed: Some(1), + }; + + let mut algo = AdaptiveNSGA3::new(problem, args).unwrap(); + assert_eq!(algo.reference_points().len(), expected_ref_points); + + algo.run().unwrap(); + let results = algo.get_results(); + + let expected_vars = vec![0.5; number_variables]; + let mut invalid_individuals: usize = 0; + for ind in results.individuals { + let obj_sum: f64 = ind.get_objective_values().unwrap().iter().sum(); + // objective target sum is 1 + let outside_range_data = approx_eq!(f64, obj_sum, 1.0, epsilon = 0.01); + if !outside_range_data { + invalid_individuals += 1; + } + + // All variables in x_M must be 0.5 + let vars: Vec = ((number_variables - k + 1)..=number_variables) + .map(|i| { + ind.get_variable_value(format!("x{i}").as_str()) + .unwrap() + .as_real() + .unwrap() + }) + .collect(); + assert_approx_array_eq(&vars, &expected_vars, Some(0.01)); + } + + // about 90% of solutions are ideal + if invalid_individuals > 10 { + panic!("Found {invalid_individuals} individuals not meeting the ideal solution"); + } + } +} From 22db289856de6015970be0e56832d0fb9ab22afd Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 09:23:53 +0100 Subject: [PATCH 12/14] Fixed example with new NSGA3 API New version is now 1.0.0 to reflect API breaking change with NSGA3 --- CHANGELOG.md | 2 +- Cargo.lock | 2 +- Cargo.toml | 2 +- examples/nsga3_dtlz1.rs | 4 ++-- examples/nsga3_dtlz1_8obj.rs | 4 ++-- examples/nsga3_dtlz2.rs | 2 +- optirustic-py/Cargo.lock | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdcd159..8831bd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.7.0 +## 1.0.0 - Added new Python API to generate reference points with `DasDarren1998`. The new class allows getting the weights for the `NSGA3` algorithm and plotting them. See the Python diff --git a/Cargo.lock b/Cargo.lock index 8b6b06b..54f53d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -530,7 +530,7 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "optirustic" -version = "0.6.0" +version = "1.0.0" dependencies = [ "chrono", "env_logger", diff --git a/Cargo.toml b/Cargo.toml index 7855989..3366033 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "optirustic" -version = "0.6.0" +version = "1.0.0" authors = ["Stefano Simoncelli <16114781+s-simoncelli@users.noreply.github.com>"] edition = "2021" rust-version = "1.80" diff --git a/examples/nsga3_dtlz1.rs b/examples/nsga3_dtlz1.rs index 732f176..ea351fc 100644 --- a/examples/nsga3_dtlz1.rs +++ b/examples/nsga3_dtlz1.rs @@ -28,7 +28,7 @@ fn main() -> Result<(), Box> { let k: usize = 5; let number_variables: usize = number_objectives + k - 1; // Get the built-in problem - let problem = DTLZ1Problem::create(number_variables, number_objectives)?; + let problem = DTLZ1Problem::create(number_variables, number_objectives, false)?; // Set the number of partitions to create the reference points for the NSGA3 algorithm. This // uses one layer of 12 uniform gaps @@ -64,7 +64,7 @@ fn main() -> Result<(), Box> { }; // Initialise the algorithm - let mut algo = NSGA3::new(problem, args).unwrap(); + let mut algo = NSGA3::new(problem, args, false).unwrap(); // Run the algorithm algo.run()?; diff --git a/examples/nsga3_dtlz1_8obj.rs b/examples/nsga3_dtlz1_8obj.rs index 404bf61..46f8143 100644 --- a/examples/nsga3_dtlz1_8obj.rs +++ b/examples/nsga3_dtlz1_8obj.rs @@ -24,7 +24,7 @@ fn main() -> Result<(), Box> { let number_objectives = 8; let k: usize = 5; let number_variables: usize = number_objectives + k - 1; // M + k - 1 with k = 5 (Section Va) - let problem = DTLZ1Problem::create(number_variables, number_objectives)?; + let problem = DTLZ1Problem::create(number_variables, number_objectives, false)?; // The number of partitions used in the paper when from section 5 let number_of_partitions = NumberOfPartitions::TwoLayers(TwoLayerPartitions { boundary_layer: 3, @@ -54,7 +54,7 @@ fn main() -> Result<(), Box> { }; // Initialise the algorithm - let mut algo = NSGA3::new(problem, args).unwrap(); + let mut algo = NSGA3::new(problem, args, false).unwrap(); // Run the algorithm algo.run()?; diff --git a/examples/nsga3_dtlz2.rs b/examples/nsga3_dtlz2.rs index ed995e4..7933dbe 100644 --- a/examples/nsga3_dtlz2.rs +++ b/examples/nsga3_dtlz2.rs @@ -62,7 +62,7 @@ fn main() -> Result<(), Box> { }; // Initialise the algorithm - let mut algo = NSGA3::new(problem, args).unwrap(); + let mut algo = NSGA3::new(problem, args, false).unwrap(); // Run the algorithm algo.run()?; diff --git a/optirustic-py/Cargo.lock b/optirustic-py/Cargo.lock index a30aa4c..7d98918 100644 --- a/optirustic-py/Cargo.lock +++ b/optirustic-py/Cargo.lock @@ -549,7 +549,7 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "optirustic" -version = "0.6.0" +version = "1.0.0" dependencies = [ "chrono", "env_logger", From 9cb46566951a2a215dffb2b18f185961f707353f Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 13:02:46 +0100 Subject: [PATCH 13/14] Export additional_data in AlgorithmExport Improved AdaptiveNSGA3 test --- src/algorithms/a_nsga3.rs | 37 ++++++++++++++++++++++++++++++++++++- src/algorithms/algorithm.rs | 4 ++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/algorithms/a_nsga3.rs b/src/algorithms/a_nsga3.rs index 0ef7d80..742481a 100644 --- a/src/algorithms/a_nsga3.rs +++ b/src/algorithms/a_nsga3.rs @@ -75,7 +75,7 @@ mod test_problems { let expected_vars = vec![0.5; number_variables]; let mut invalid_individuals: usize = 0; - for ind in results.individuals { + for ind in &results.individuals { let obj_sum: f64 = ind.get_objective_values().unwrap().iter().sum(); // objective target sum is 1 let outside_range_data = approx_eq!(f64, obj_sum, 1.0, epsilon = 0.01); @@ -99,5 +99,40 @@ mod test_problems { if invalid_individuals > 10 { panic!("Found {invalid_individuals} individuals not meeting the ideal solution"); } + + // all new associated reference points have at least one associated individuals. These + // are only the points within the optimal Pareto front (when objective is <= 0.5) + let new_assoc_ref_points: Vec<_> = results + .individuals + .iter() + .filter_map(|i| { + let index = i + .get_data("reference_point_index") + .unwrap() + .as_usize() + .unwrap(); + if index > 92 { + Some(index) + } else { + None + } + }) + .collect(); + + for (ri, r) in results.additional_data["reference_points"] + .as_data_vec() + .unwrap() + .iter() + .enumerate() + { + if r.as_f64_vec().unwrap().iter().all(|coord| *coord <= 0.5) && ri > 92 { + if !new_assoc_ref_points.contains(&ri) { + panic!( + "Reference point #{ri} ({:?}) is not associated with any individual", + ri + ); + } + } + } } } diff --git a/src/algorithms/algorithm.rs b/src/algorithms/algorithm.rs index 04f1c41..75ade2e 100644 --- a/src/algorithms/algorithm.rs +++ b/src/algorithms/algorithm.rs @@ -100,6 +100,7 @@ impl TryInto for AlgorithmSerialisedExport { generation: self.generation, algorithm: self.algorithm, took: self.took, + additional_data: self.additional_data.unwrap_or_default(), }; Ok(data) } @@ -118,6 +119,8 @@ pub struct AlgorithmExport { pub algorithm: String, /// The time the algorithm took to reach the current generation. pub took: Elapsed, + /// Additional data stored in the algorithm (such as reference points for [`NSGA3`]). + pub additional_data: HashMap, } impl AlgorithmExport { @@ -437,6 +440,7 @@ pub trait Algorithm: Display { minutes, seconds, }, + additional_data: self.additional_export_data().unwrap_or_default(), } } From 57a427069fc47c6e2eab7433b7b7eb35b7f194a8 Mon Sep 17 00:00:00 2001 From: Stefano Simonelli <16114781+s-simoncelli@users.noreply.github.com> Date: Sun, 1 Sep 2024 13:04:06 +0100 Subject: [PATCH 14/14] Updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8831bd2..67f313c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ helps to reduce crowding and enhance the solution quality. See the new [example file](./examples/nsga3_inverted_dtlz1.rs) and [results](./examples/results/DTLZ1_3obj_Adaptive_NSGA3_gen400_obj_vs_ref_points.png). +- The algorithm additional data are now exported in `AlgorithExport` in the `Export additional_data in AlgorithmExport` + field. This contains, for example, the reference points for `NSGA3`. ## 0.6.0