Skip to content

Commit

Permalink
Merge pull request #10 from s-simoncelli/add-ci
Browse files Browse the repository at this point in the history
Added CI
  • Loading branch information
s-simoncelli committed Aug 4, 2024
2 parents f800df7 + b8b0f74 commit c085e5d
Show file tree
Hide file tree
Showing 26 changed files with 281 additions and 136 deletions.
55 changes: 55 additions & 0 deletions .github/workflows/check-and-lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
on:
pull_request:
push:
branches:
- main


name: Check and Lint

jobs:
check:
name: Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions-rs/cargo@v1
with:
command: check

fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- run: rustup component add rustfmt
- uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check

clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: clippy
override: true
- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
name: Clippy Output
36 changes: 36 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Build and test
on:
push:
branches: [ main ]
pull_request:

env:
CARGO_TERM_COLOR: always

jobs:
test-linux:
name: Cargo check and test on Unix systems
runs-on: ubuntu-latest
steps:
# Enable this when testing with nektos/act
# - uses: actions-rs/toolchain@v1
# with:
# toolchain: stable
# override: true
# - name: Install Clang
# run: sudo apt update && sudo apt install --yes clang
- uses: actions/checkout@v4
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
# NOTE disabled due to compiler failure in hv-fonseca crate
# test-windows:
# name: Cargo check and test on Windows
# runs-on: windows-latest
# steps:
# - uses: actions/checkout@v4
# - name: Build
# run: cargo build --verbose
# - name: Run tests
# run: cargo test --verbose
8 changes: 4 additions & 4 deletions hv-fonseca-et-al-2006-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ include!("bindings.rs");
///
/// **IMPLEMENTATION NOTES**:
/// 1) The reference point must dominate the values of all objectives. Dominated solutions by the
/// reference point are automatically excluded from the calculation.
/// reference point are automatically excluded from the calculation.
/// 2) The program assumes that all objectives are minimised. Maximisation objectives may be
/// multiplied by -1 to convert them to minimisation.
/// multiplied by -1 to convert them to minimisation.
///
/// # Arguments
///
/// * `data`: The vector with the objective values. The size of this vector must correspond to the
/// number of individuals `n` in the population. Each sub-vector must have size `d` equal to the
/// number of problem objectives.
/// number of individuals `n` in the population. Each sub-vector must have size `d` equal to the
/// number of problem objectives.
/// * `ref_point`: The reference or anti-optimal point to use in the calculation of length `d`.
///
/// returns: `f64`. The hyper-volume.
Expand Down
15 changes: 8 additions & 7 deletions hv-wfg-sys/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(clippy::all)]

use std::ffi::c_int;

Expand All @@ -12,18 +13,18 @@ include!("bindings.rs");
///
/// **IMPLEMENTATION NOTES**:
/// 1) The program assumes that all objectives are minimised (`MAXIMISATION` is set to `false`
/// during conditional compilation ). Maximisation objectives may be multiplied by -1 to convert
/// them to minimisation.
/// during conditional compilation ). Maximisation objectives may be multiplied by -1 to convert
/// them to minimisation.
/// 2) The `opt` numeric variable is set to `2` in the conditional compilation of the `wfg.c` file.
/// This means that some optimisations, such as dominated point exclusion when calculating the
/// exclusive hyper-volume or reverting to simple calculation for the 2-dimensional case, are
/// included.
/// This means that some optimisations, such as dominated point exclusion when calculating the
/// exclusive hyper-volume or reverting to simple calculation for the 2-dimensional case, are
/// included.
///
/// # Arguments
///
/// * `objective_values`: The vector with the objective values. The size of this vector must
/// correspond to the number of individuals `n` in the population. Each sub-vector must have size
/// `d` equal to the number of problem objectives.
/// correspond to the number of individuals `n` in the population. Each sub-vector must have size
/// `d` equal to the number of problem objectives.
/// * `ref_point`: The reference or anti-optimal point to use in the calculation of length `d`.
///
/// returns: `Result<f64, String>`. The hyper-volume.
Expand Down
31 changes: 16 additions & 15 deletions optirustic/examples/nsga2_sch.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use std::env;
use std::error::Error;
use std::path::PathBuf;
use std::path::{Path, PathBuf};

use log::LevelFilter;
use plotters::chart::ChartBuilder;
use plotters::backend::BitMapBackend;
use plotters::chart::{ChartBuilder, SeriesLabelPosition};
use plotters::drawing::IntoDrawingArea;
use plotters::prelude::*;
use plotters::element::{Circle, PathElement, Rectangle};
use plotters::prelude::full_palette::{GREY_A400, RED_700};
use plotters::prelude::{Color, LineSeries, Palette, Palette99, ShapeStyle, BLACK, WHITE};

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

Expand Down Expand Up @@ -46,25 +49,23 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut algo = NSGA2::new(problem, args)?;
algo.run()?;

let out_path = PathBuf::from(&env::current_dir().unwrap())
.join("examples")
.join("results");

// Plot the results
plot(&algo.get_results().individuals)?;
plot(&algo.get_results().individuals, &out_path)?;

// Export serialised results at last generation
algo.save_to_json(
&PathBuf::from("optirustic/examples/results"),
Some("SCH_2obj"),
)?;
algo.save_to_json(&out_path, Some("SCH_2obj"))?;

Ok(())
}

/// Draw the expected objective functions and the solutions from the algorithm.
fn plot(individuals: &[Individual]) -> Result<(), Box<dyn Error>> {
let root = BitMapBackend::new(
"optirustic/examples/results/SCH_2_obj_NSGA2_solutions.png",
(1024, 768),
)
.into_drawing_area();
fn plot(individuals: &[Individual], out_path: &Path) -> Result<(), Box<dyn Error>> {
let png_file = out_path.join("SCH_2_obj_NSGA2_solutions.png");
let root = BitMapBackend::new(&png_file, (1024, 768)).into_drawing_area();
static FONT: &str = "sans-serif";

root.fill(&WHITE)?;
Expand Down
11 changes: 6 additions & 5 deletions optirustic/examples/nsga2_zdt1.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::env;
use std::error::Error;
use std::path::PathBuf;

use log::LevelFilter;

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

/// Solve the ZDT1 problem (SCH) where the following 2 objectives are minimised:
Expand Down Expand Up @@ -48,10 +49,10 @@ fn main() -> Result<(), Box<dyn Error>> {
}

// Export serialised results at last generation
algo.save_to_json(
&PathBuf::from("optirustic/examples/results"),
Some("ZDT1_2obj"),
)?;
let out_path = PathBuf::from(&env::current_dir().unwrap())
.join("examples")
.join("results");
algo.save_to_json(&out_path, Some("ZDT1_2obj"))?;

Ok(())
}
20 changes: 20 additions & 0 deletions optirustic/examples/reference_point.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use optirustic::core::OError;
use optirustic::utils::DasDarren1998;

/// Generate and plot reference points using the Ds & Darren (1998) method.
fn main() -> Result<(), OError> {
// Consider the case of a 3D hyperplane with 3 objectives
let number_of_objectives = 3;
// Each objective axis is split into 5 gaps of equal size.
let number_of_partitions = 5;

let m = DasDarren1998::new(number_of_objectives, number_of_partitions);
// This returns the coordinates of the reference points between 0 and 1
println!("Total pints = {:?}", m.number_of_points());

let weights = m.get_weights();
println!("Weights = {:?}", weights);

// Save the charts of points to inspect them
m.plot("ref_points_3obj_5gaps.png")
}
2 changes: 1 addition & 1 deletion optirustic/src/algorithms/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub use algorithm::{Algorithm, AlgorithmExport, AlgorithmSerialisedExport, ExportHistory};
pub use nsga2::{NSGA2, NSGA2Arg};
pub use nsga2::{NSGA2Arg, NSGA2};
pub use stopping_condition::{
MaxDuration, MaxGeneration, StoppingCondition, StoppingConditionType,
};
Expand Down
20 changes: 11 additions & 9 deletions optirustic/src/algorithms/nsga2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ use std::fmt::{Display, Formatter};
use std::ops::Rem;
use std::path::PathBuf;

use log::{debug, info};
use rand::RngCore;

use optirustic_macros::{as_algorithm, as_algorithm_args, impl_algorithm_trait_items};

use crate::algorithms::Algorithm;
use crate::core::utils::{argsort, get_rng, vector_max, vector_min, Sort};
use crate::core::{Individual, Individuals, IndividualsMut, OError, VariableValue};
Expand All @@ -10,9 +15,6 @@ use crate::operators::{
SimulatedBinaryCrossover, SimulatedBinaryCrossoverArgs, TournamentSelector,
};
use crate::utils::fast_non_dominated_sort;
use log::{debug, info};
use optirustic_macros::{as_algorithm, as_algorithm_args, impl_algorithm_trait_items};
use rand::RngCore;

/// Input arguments for the NSGA2 algorithm.
#[as_algorithm_args]
Expand Down Expand Up @@ -614,7 +616,7 @@ mod test_problems {
const BOUND_TOL: f64 = 1.0 / 1000.0;
const LOOSE_BOUND_TOL: f64 = 0.1;

#[test_with_retries(3)]
#[test_with_retries(10)]
/// Test problem 1 from Deb et al. (2002). Optional solution x in [0; 2]
fn test_sch_problem() {
let problem = SCHProblem::create().unwrap();
Expand All @@ -640,7 +642,7 @@ mod test_problems {
}
}

#[test_with_retries(3)]
#[test_with_retries(10)]
/// Test the ZTD1 problem from Deb et al. (2002) with 30 variables. Solution x1 in [0; 1] and
/// x2 to x30 = 0. The exact solutions are tested using a strict and loose bounds.
fn test_ztd1_problem() {
Expand Down Expand Up @@ -687,7 +689,7 @@ mod test_problems {
}
}

#[test_with_retries(3)]
#[test_with_retries(10)]
/// Test the ZTD2 problem from Deb et al. (2002) with 30 variables. Solution x1 in [0; 1] and
/// x2 to x30 = 0. The exact solutions are tested using a strict and loose bounds.
fn test_ztd2_problem() {
Expand Down Expand Up @@ -739,7 +741,7 @@ mod test_problems {
}
}

#[test_with_retries(3)]
#[test_with_retries(10)]
/// Test the ZTD3 problem from Deb et al. (2002) with 30 variables. Solution x1 in [0; 1] and
/// x2 to x30 = 0. The exact solutions are tested using a strict and loose bounds.
fn test_ztd3_problem() {
Expand Down Expand Up @@ -791,7 +793,7 @@ mod test_problems {
}
}

#[test_with_retries(3)]
#[test_with_retries(10)]
/// Test the ZTD4 problem from Deb et al. (2002) with 30 variables. Solution x1 in [0; 1] and
/// x2 to x10 = 0. The exact solutions are tested using a strict and loose bounds.
fn test_ztd4_problem() {
Expand Down Expand Up @@ -844,7 +846,7 @@ mod test_problems {
}
}

#[test_with_retries(3)]
#[test_with_retries(10)]
/// Test the ZTD6 problem from Deb et al. (2002) with 30 variables. Solution x1 in [0; 1] and
/// x2 to x10 = 0. The exact solutions are tested using a strict and loose bounds.
fn test_ztd6_problem() {
Expand Down
6 changes: 3 additions & 3 deletions optirustic/src/core/constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub enum RelationalOperator {
/// # Example
///
/// ```
/// use optirustic::core::constraint::{Constraint, RelationalOperator};
/// use optirustic::core::{Constraint, RelationalOperator};
/// let c = Constraint::new("Z>=5.2",RelationalOperator::GreaterOrEqualTo, 5.2);
/// assert_eq!(c.is_met(10.1), true);
/// assert_eq!(c.is_met(3.11), false);
Expand All @@ -52,7 +52,7 @@ impl Constraint {
///
/// * `name`: The constraint name.
/// * `operator`: The relational operator to use to compare a value against the constraint
/// target value.
/// target value.
/// * `target`: The constraint target.
///
/// returns: `Constraint`
Expand All @@ -71,7 +71,7 @@ impl Constraint {
///
/// * `name`: The constraint name.
/// * `operator`: The relational operator to use to compare a value against the constraint
/// target value.
/// target value.
/// * `target`: The constraint target.
/// * `scale`: Apply a scaling factor to the `target`.
/// * `offset`: Apply an offset to the `target`.
Expand Down
4 changes: 2 additions & 2 deletions optirustic/src/core/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ pub enum OError {
NoObjective,
#[error("You must provide at least one variable to properly define a problem")]
NoVariables,
#[error("The {0} type named '{1}' already exist")]
DuplicatedName(String, String),
#[error("The {0} vector contains duplicated names")]
DuplicatedNames(String),
#[error("The {0} index {1} does not exist")]
NonExistingIndex(String, usize),
#[error("The {0} named '{1}' does not exist")]
Expand Down
4 changes: 2 additions & 2 deletions optirustic/src/core/individual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ impl Individual {
/// # Arguments
///
/// * `transform`: The function to apply to transform each objective value. This function
/// receives the objective value and its name.
/// receives the objective value and its name.
///
/// returns: `Result<Vec<f64>, OError>`
pub fn transform_objective_values<F: Fn(f64, String) -> Result<f64, OError>>(
Expand Down Expand Up @@ -637,11 +637,11 @@ impl_individuals!(Vec<Individual>);
mod test {
use std::sync::Arc;

use crate::core::utils::dummy_evaluator;
use crate::core::{
BoundedNumber, Constraint, Individual, Objective, ObjectiveDirection, Problem,
RelationalOperator, VariableType,
};
use crate::core::utils::dummy_evaluator;

#[test]
/// Test when an objective does not exist
Expand Down
Loading

0 comments on commit c085e5d

Please sign in to comment.