Skip to content

Commit

Permalink
Merge pull request #28 from s-simoncelli/add-new-stopping-conditions
Browse files Browse the repository at this point in the history
Add new stopping conditions
  • Loading branch information
s-simoncelli committed Sep 2, 2024
2 parents 59d98f5 + f7343f7 commit b7650df
Show file tree
Hide file tree
Showing 16 changed files with 328 additions and 60 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## 1.1.0

- Added `number_of_function_evaluations` field in algorithms and serialised data. This fields
calculate the number of times individual's objectives and constraints are evaluated during an
evolution.
- Renamed struct to specify stopping condition values. For example,
the `StoppingConditionType::MaxGeneration(MaxGeneration(250))`
can be defined as `StoppingConditionType::MaxGeneration(MaxGenerationValue(250))`. This is done to avoid confusion
between the enum `StoppingConditionType` value and the value of the stopping condition.
- Added the following new stopping conditions: `MaxFunctionEvaluations`, `Any` and `All`. The first one stops the
evolution
after a maximum number of functon evaluations. The second and third allows to combine multiple condition. For example,
they allow to stop the algorithm when either a specific duration or evolution number are reached (using `Any`).

## 1.0.0

- Added new Python API to generate reference points with `DasDarren1998`. The new class
Expand Down
4 changes: 2 additions & 2 deletions examples/convergence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::env;
use std::path::PathBuf;

use optirustic::algorithms::{
Algorithm, ExportHistory, MaxGeneration, NSGA2Arg, StoppingConditionType, NSGA2,
Algorithm, ExportHistory, MaxGenerationValue, NSGA2Arg, StoppingConditionType, NSGA2,
};
use optirustic::core::builtin_problems::SCHProblem;
use optirustic::core::OError;
Expand Down Expand Up @@ -35,7 +35,7 @@ fn main() -> Result<(), OError> {
let export_history = ExportHistory::new(100, &out_path)?;
let args = NSGA2Arg {
number_of_individuals: 10,
stopping_condition: StoppingConditionType::MaxGeneration(MaxGeneration(1000)),
stopping_condition: StoppingConditionType::MaxGeneration(MaxGenerationValue(1000)),
crossover_operator_options: None,
mutation_operator_options: None,
parallel: Some(false),
Expand Down
6 changes: 4 additions & 2 deletions examples/nsga2_sch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use std::path::PathBuf;

use log::LevelFilter;

use optirustic::algorithms::{Algorithm, MaxGeneration, NSGA2Arg, StoppingConditionType, NSGA2};
use optirustic::algorithms::{
Algorithm, MaxGenerationValue, NSGA2Arg, StoppingConditionType, NSGA2,
};
use optirustic::core::builtin_problems::SCHProblem;

/// Solve the Schaffer’s problem (SCH) where the following 2 objectives are minimised:
Expand All @@ -28,7 +30,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let args = NSGA2Arg {
// use 100 individuals and stop the algorithm at 250 generations
number_of_individuals: 100,
stopping_condition: StoppingConditionType::MaxGeneration(MaxGeneration(250)),
stopping_condition: StoppingConditionType::MaxGeneration(MaxGenerationValue(250)),
// use default options for the SBX and PM operators
crossover_operator_options: None,
mutation_operator_options: None,
Expand Down
6 changes: 4 additions & 2 deletions examples/nsga2_zdt1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use std::path::PathBuf;

use log::LevelFilter;

use optirustic::algorithms::{Algorithm, MaxGeneration, NSGA2Arg, StoppingConditionType, NSGA2};
use optirustic::algorithms::{
Algorithm, MaxGenerationValue, NSGA2Arg, StoppingConditionType, NSGA2,
};
use optirustic::core::builtin_problems::ZTD1Problem;

/// Solve the ZDT1 problem (SCH) where the following 2 objectives are minimised:
Expand All @@ -29,7 +31,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// Setup and run the NSGA2 algorithm
let args = NSGA2Arg {
number_of_individuals,
stopping_condition: StoppingConditionType::MaxGeneration(MaxGeneration(1000)),
stopping_condition: StoppingConditionType::MaxGeneration(MaxGenerationValue(1000)),
// use default options for the SBX and PM operators
crossover_operator_options: None,
mutation_operator_options: None,
Expand Down
4 changes: 2 additions & 2 deletions examples/nsga3_dtlz1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::path::PathBuf;
use log::LevelFilter;

use optirustic::algorithms::{
Algorithm, MaxGeneration, NSGA3Arg, Nsga3NumberOfIndividuals, StoppingConditionType, NSGA3,
Algorithm, MaxGenerationValue, NSGA3Arg, Nsga3NumberOfIndividuals, StoppingConditionType, NSGA3,
};
use optirustic::core::builtin_problems::DTLZ1Problem;
use optirustic::operators::SimulatedBinaryCrossoverArgs;
Expand Down Expand Up @@ -56,7 +56,7 @@ fn main() -> Result<(), Box<dyn Error>> {
crossover_operator_options: Some(crossover_operator_options),
mutation_operator_options: None,
// stop at generation 400
stopping_condition: StoppingConditionType::MaxGeneration(MaxGeneration(400)),
stopping_condition: StoppingConditionType::MaxGeneration(MaxGenerationValue(400)),
parallel: None,
export_history: None,
// to reproduce results
Expand Down
4 changes: 2 additions & 2 deletions examples/nsga3_dtlz1_8obj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::path::PathBuf;
use log::LevelFilter;

use optirustic::algorithms::{
Algorithm, MaxGeneration, NSGA3Arg, Nsga3NumberOfIndividuals, StoppingConditionType, NSGA3,
Algorithm, MaxGenerationValue, NSGA3Arg, Nsga3NumberOfIndividuals, StoppingConditionType, NSGA3,
};
use optirustic::core::builtin_problems::DTLZ1Problem;
use optirustic::operators::{PolynomialMutationArgs, SimulatedBinaryCrossoverArgs};
Expand Down Expand Up @@ -47,7 +47,7 @@ fn main() -> Result<(), Box<dyn Error>> {
number_of_partitions,
crossover_operator_options: Some(crossover_operator_options),
mutation_operator_options: Some(mutation_operator_options),
stopping_condition: StoppingConditionType::MaxGeneration(MaxGeneration(750)),
stopping_condition: StoppingConditionType::MaxGeneration(MaxGenerationValue(750)),
parallel: None,
export_history: None,
seed: Some(1),
Expand Down
4 changes: 2 additions & 2 deletions examples/nsga3_dtlz2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::path::PathBuf;
use log::LevelFilter;

use optirustic::algorithms::{
Algorithm, MaxGeneration, NSGA3Arg, Nsga3NumberOfIndividuals, StoppingConditionType, NSGA3,
Algorithm, MaxGenerationValue, NSGA3Arg, Nsga3NumberOfIndividuals, StoppingConditionType, NSGA3,
};
use optirustic::core::builtin_problems::DTLZ2Problem;
use optirustic::operators::SimulatedBinaryCrossoverArgs;
Expand Down Expand Up @@ -54,7 +54,7 @@ fn main() -> Result<(), Box<dyn Error>> {
crossover_operator_options: Some(crossover_operator_options),
mutation_operator_options: None,
// stop at generation 400
stopping_condition: StoppingConditionType::MaxGeneration(MaxGeneration(400)),
stopping_condition: StoppingConditionType::MaxGeneration(MaxGenerationValue(400)),
parallel: None,
export_history: None,
// to reproduce results
Expand Down
4 changes: 2 additions & 2 deletions examples/nsga3_inverted_dtlz1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::path::PathBuf;
use log::LevelFilter;

use optirustic::algorithms::{
AdaptiveNSGA3, Algorithm, MaxGeneration, NSGA3Arg, Nsga3NumberOfIndividuals,
AdaptiveNSGA3, Algorithm, MaxGenerationValue, NSGA3Arg, Nsga3NumberOfIndividuals,
StoppingConditionType,
};
use optirustic::core::builtin_problems::DTLZ1Problem;
Expand Down Expand Up @@ -50,7 +50,7 @@ fn main() -> Result<(), Box<dyn Error>> {
crossover_operator_options: Some(crossover_operator_options),
mutation_operator_options: None,
// stop at generation 400
stopping_condition: StoppingConditionType::MaxGeneration(MaxGeneration(400)),
stopping_condition: StoppingConditionType::MaxGeneration(MaxGenerationValue(400)),
parallel: None,
export_history: None,
// to reproduce results
Expand Down
23 changes: 20 additions & 3 deletions libs/optirustic-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub fn as_algorithm_args(_attrs: TokenStream, input: TokenStream) -> TokenStream
}

/// This macro adds the following private fields to the struct defining an algorithm:
/// `problem`, `number_of_individuals`, `population`, `generation`,`stopping_condition`,
/// `problem`, `number_of_individuals`, `population`, `generation`,`stopping_condition`, `number_of_function_evaluations`,
/// `start_time`, `export_history` and `parallel`.
///
/// It also implements the `Display` trait.
Expand Down Expand Up @@ -141,6 +141,14 @@ pub fn as_algorithm(attrs: TokenStream, input: TokenStream) -> TokenStream {
})
.expect("Cannot add `generation` field"),
);
fields.named.push(
syn::Field::parse_named
.parse2(quote! {
/// The number of function evaluations.
number_of_function_evaluations: usize
})
.expect("Cannot add `number_of_function_evaluations` field"),
);
fields.named.push(
syn::Field::parse_named
.parse2(quote! {
Expand Down Expand Up @@ -205,7 +213,7 @@ pub fn as_algorithm(attrs: TokenStream, input: TokenStream) -> TokenStream {
/// This macro adds common items when the `Algorithm` trait is implemented for a new algorithm
/// struct. This adds the following items: `Algorithm::name()`, `Algorithm::stopping_condition()`
/// `Algorithm::start_time()`, `Algorithm::problem()`, `Algorithm::population()`,
/// `Algorithm::generation()` and `Algorithm::export_history()`.
/// `Algorithm::generation()`, `Algorithm::number_of_function_evaluations()` and `Algorithm::export_history()`.
///
#[proc_macro_attribute]
pub fn impl_algorithm_trait_items(attrs: TokenStream, input: TokenStream) -> TokenStream {
Expand Down Expand Up @@ -282,7 +290,16 @@ pub fn impl_algorithm_trait_items(attrs: TokenStream, input: TokenStream) -> Tok
)
.into(),
)
.expect("Failed to parse `export_history` item"),
.expect("Failed to parse `generation` item"),
syn::parse::<syn::ImplItem>(
quote!(
fn number_of_function_evaluations(&self) -> usize {
self.number_of_function_evaluations
}
)
.into(),
)
.expect("Failed to parse `number_of_function_evaluations` item"),
syn::parse::<syn::ImplItem>(
quote!(
fn algorithm_options(&self) -> #arg_type {
Expand Down
2 changes: 1 addition & 1 deletion optirustic-py/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ exported with the `optirustic` crate. It lets you:
The package can be installed from [PyPi](https://pypi.org/project/optirustic/):

```
pip install optirustic_py
pip install optirustic
```

# Usage
Expand Down
4 changes: 2 additions & 2 deletions src/algorithms/a_nsga3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ mod test_problems {
use optirustic_macros::test_with_retries;

use crate::algorithms::{
AdaptiveNSGA3, Algorithm, MaxGeneration, NSGA3Arg, Nsga3NumberOfIndividuals,
AdaptiveNSGA3, Algorithm, MaxGenerationValue, NSGA3Arg, Nsga3NumberOfIndividuals,
StoppingConditionType,
};
use crate::core::builtin_problems::DTLZ1Problem;
Expand Down Expand Up @@ -61,7 +61,7 @@ mod test_problems {
number_of_partitions,
crossover_operator_options: Some(crossover_operator_options),
mutation_operator_options: Some(mutation_operator_options),
stopping_condition: StoppingConditionType::MaxGeneration(MaxGeneration(400)),
stopping_condition: StoppingConditionType::MaxGeneration(MaxGenerationValue(400)),
parallel: None,
export_history: None,
seed: Some(1),
Expand Down
Loading

0 comments on commit b7650df

Please sign in to comment.