Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup project structure #102

Merged
merged 12 commits into from
Jul 23, 2022
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ derive_deref = "1.1.1"
embed-doc-image = "0.1.4"
erased-serde = "0.3.16"
float_eq = "0.7.0"
itoa = "1.0.1"
num_cpus = "1.13.0"
pest = "2.1.3"
pest_consume = "1.1.1"
Expand All @@ -24,7 +23,6 @@ rand = "0.8.4"
rand_distr = "0.4.2"
ron = "0.7.0"
rprompt = "1.0.5"
ryu = "1.0.9"
serde = {version = "1.0.131", features = ["derive"]}
trait-set = "0.3.0"

Expand Down
4 changes: 2 additions & 2 deletions param-study/src/instances/iwo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use crate::{
util::{print_result, ArgsIter, Setup},
};
use mahf::{
float_eq::float_eq, framework, heuristics::iwo, operators::termination,
problems::bmf::BenchmarkFunction, random::Random, tracking,
float_eq::float_eq, framework, framework::Random, heuristics::iwo, operators::termination,
problems::bmf::BenchmarkFunction, tracking,
};
use std::time::Instant;

Expand Down
3 changes: 1 addition & 2 deletions param-study/src/instances/pso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ use std::time::Instant;

use mahf::{
float_eq::float_eq,
framework::{self},
framework::{self, Random},
heuristics::pso,
problems::bmf::BenchmarkFunction,
random::Random,
};

use crate::{
Expand Down
121 changes: 23 additions & 98 deletions src/framework/components.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
//! Framework components.

pub use crate::framework::conditions::Condition;

use crate::{
framework::{common_state, Fitness, State},
framework::{
state::{common, State},
Fitness,
},
problems::Problem,
};
use serde::Serialize;
Expand All @@ -26,22 +31,13 @@ trait_set! {
/// Most of the time, execution should be multi threaded and having
/// components implement [Send] makes this much easier.
///
pub trait Component<P>: AnyComponent {
pub trait Component<P: Problem>: AnyComponent {
#[allow(unused_variables)]
fn initialize(&self, problem: &P, state: &mut State) {}
fn execute(&self, problem: &P, state: &mut State);
}
erased_serde::serialize_trait_object!(<P: Problem> Component<P>);

pub trait Condition<P>: AnyComponent {
#[allow(unused_variables)]
fn initialize(&self, problem: &P, state: &mut State) {}
fn evaluate(&self, problem: &P, state: &mut State) -> bool;
}
erased_serde::serialize_trait_object!(<P: Problem> Condition<P>);

pub type Configuration<P> = Box<dyn Component<P>>;

#[derive(Serialize)]
#[serde(bound = "")]
pub struct Scope<P: Problem> {
Expand All @@ -51,10 +47,7 @@ pub struct Scope<P: Problem> {
init: fn(&mut State),
}

impl<P> Component<P> for Scope<P>
where
P: Problem + 'static,
{
impl<P: Problem> Component<P> for Scope<P> {
fn execute(&self, problem: &P, state: &mut State) {
state.with_substate(|state| {
(self.init)(state);
Expand All @@ -64,7 +57,7 @@ where
}
}

impl<P: Problem + 'static> Scope<P> {
impl<P: Problem> Scope<P> {
pub fn new(body: Vec<Box<dyn Component<P>>>) -> Box<dyn Component<P>> {
Self::new_with(|_| {}, body)
}
Expand All @@ -83,10 +76,7 @@ impl<P: Problem + 'static> Scope<P> {
#[serde(transparent)]
pub struct Block<P: Problem>(Vec<Box<dyn Component<P>>>);

impl<P> Component<P> for Block<P>
where
P: Problem + 'static,
{
impl<P: Problem> Component<P> for Block<P> {
fn initialize(&self, problem: &P, state: &mut State) {
for component in &self.0 {
component.initialize(problem, state);
Expand All @@ -100,7 +90,7 @@ where
}
}

impl<P: Problem + 'static> Block<P> {
impl<P: Problem> Block<P> {
pub fn new(components: Vec<Box<dyn Component<P>>>) -> Box<dyn Component<P>> {
Box::new(Block(components))
}
Expand All @@ -115,12 +105,9 @@ pub struct Loop<P: Problem> {
body: Box<dyn Component<P>>,
}

impl<P> Component<P> for Loop<P>
where
P: Problem + 'static,
{
impl<P: Problem> Component<P> for Loop<P> {
fn initialize(&self, problem: &P, state: &mut State) {
state.insert(common_state::Iterations(0));
state.insert(common::Iterations(0));

self.condition.initialize(problem, state);
self.body.initialize(problem, state);
Expand All @@ -130,12 +117,12 @@ where
self.condition.initialize(problem, state);
while self.condition.evaluate(problem, state) {
self.body.execute(problem, state);
*state.get_value_mut::<common_state::Iterations>() += 1;
*state.get_value_mut::<common::Iterations>() += 1;
}
}
}

impl<P: Problem + 'static> Loop<P> {
impl<P: Problem> Loop<P> {
pub fn new(
condition: Box<dyn Condition<P>>,
body: Vec<Box<dyn Component<P>>>,
Expand All @@ -153,10 +140,7 @@ pub struct Branch<P: Problem> {
else_body: Option<Box<dyn Component<P>>>,
}

impl<P> Component<P> for Branch<P>
where
P: Problem + 'static,
{
impl<P: Problem> Component<P> for Branch<P> {
fn initialize(&self, problem: &P, state: &mut State) {
self.condition.initialize(problem, state);
self.if_body.initialize(problem, state);
Expand Down Expand Up @@ -213,10 +197,10 @@ impl SimpleEvaluator {

impl<P: Problem> Component<P> for SimpleEvaluator {
fn initialize(&self, _problem: &P, state: &mut State) {
state.require::<common_state::Population>();
state.insert(common_state::Evaluations(0));
state.insert(common_state::BestFitness(Fitness::default()));
state.insert(common_state::BestIndividual(None));
state.require::<common::Population>();
state.insert(common::Evaluations(0));
state.insert(common::BestFitness(Fitness::default()));
state.insert(common::BestIndividual(None));
}

fn execute(&self, problem: &P, state: &mut State) {
Expand All @@ -239,72 +223,13 @@ impl<P: Problem> Component<P> for SimpleEvaluator {
let best_individual = population.best();

if mut_state
.get_mut::<common_state::BestIndividual>()
.get_mut::<common::BestIndividual>()
.replace_if_better(best_individual)
{
mut_state.set_value::<common_state::BestFitness>(best_individual.fitness());
mut_state.set_value::<common::BestFitness>(best_individual.fitness());
}

// Update evaluations
*mut_state.get_value_mut::<common_state::Evaluations>() +=
population.current().len() as u32;
}
}

#[derive(Serialize)]
#[serde(bound = "")]
pub struct And<P: Problem>(Vec<Box<dyn Condition<P>>>);
impl<P: Problem + 'static> And<P> {
pub fn new(conditions: Vec<Box<dyn Condition<P>>>) -> Box<dyn Condition<P>> {
Box::new(Self(conditions))
}
}
impl<P: Problem + 'static> Condition<P> for And<P> {
fn initialize(&self, problem: &P, state: &mut State) {
for condition in self.0.iter() {
condition.initialize(problem, state);
}
}

fn evaluate(&self, problem: &P, state: &mut State) -> bool {
self.0
.iter()
.all(|condition| condition.evaluate(problem, state))
}
}
impl<P: Problem + 'static> std::ops::BitAnd for Box<dyn Condition<P>> {
type Output = Box<dyn Condition<P>>;

fn bitand(self, rhs: Self) -> Self::Output {
And::new(vec![self, rhs])
}
}

#[derive(Serialize)]
#[serde(bound = "")]
pub struct Or<P: Problem>(Vec<Box<dyn Condition<P>>>);
impl<P: Problem + 'static> Or<P> {
pub fn new(conditions: Vec<Box<dyn Condition<P>>>) -> Box<dyn Condition<P>> {
Box::new(Self(conditions))
}
}
impl<P: Problem + 'static> Condition<P> for Or<P> {
fn initialize(&self, problem: &P, state: &mut State) {
for condition in self.0.iter() {
condition.initialize(problem, state);
}
}

fn evaluate(&self, problem: &P, state: &mut State) -> bool {
self.0
.iter()
.any(|condition| condition.evaluate(problem, state))
}
}
impl<P: Problem + 'static> std::ops::BitOr for Box<dyn Condition<P>> {
type Output = Box<dyn Condition<P>>;

fn bitor(self, rhs: Self) -> Self::Output {
Or::new(vec![self, rhs])
*mut_state.get_value_mut::<common::Evaluations>() += population.current().len() as u32;
}
}
70 changes: 70 additions & 0 deletions src/framework/conditions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use crate::{
framework::{components::AnyComponent, state::State},
problems::Problem,
};
use serde::Serialize;

pub trait Condition<P>: AnyComponent {
#[allow(unused_variables)]
fn initialize(&self, problem: &P, state: &mut State) {}
fn evaluate(&self, problem: &P, state: &mut State) -> bool;
}
erased_serde::serialize_trait_object!(<P: Problem> Condition<P>);

#[derive(Serialize)]
#[serde(bound = "")]
pub struct And<P: Problem>(Vec<Box<dyn Condition<P>>>);
impl<P: Problem + 'static> And<P> {
pub fn new(conditions: Vec<Box<dyn Condition<P>>>) -> Box<dyn Condition<P>> {
Box::new(Self(conditions))
}
}
impl<P: Problem + 'static> Condition<P> for And<P> {
fn initialize(&self, problem: &P, state: &mut State) {
for condition in self.0.iter() {
condition.initialize(problem, state);
}
}

fn evaluate(&self, problem: &P, state: &mut State) -> bool {
self.0
.iter()
.all(|condition| condition.evaluate(problem, state))
}
}
impl<P: Problem + 'static> std::ops::BitAnd for Box<dyn Condition<P>> {
type Output = Box<dyn Condition<P>>;

fn bitand(self, rhs: Self) -> Self::Output {
And::new(vec![self, rhs])
}
}

#[derive(Serialize)]
#[serde(bound = "")]
pub struct Or<P: Problem>(Vec<Box<dyn Condition<P>>>);
impl<P: Problem + 'static> Or<P> {
pub fn new(conditions: Vec<Box<dyn Condition<P>>>) -> Box<dyn Condition<P>> {
Box::new(Self(conditions))
}
}
impl<P: Problem + 'static> Condition<P> for Or<P> {
fn initialize(&self, problem: &P, state: &mut State) {
for condition in self.0.iter() {
condition.initialize(problem, state);
}
}

fn evaluate(&self, problem: &P, state: &mut State) -> bool {
self.0
.iter()
.any(|condition| condition.evaluate(problem, state))
}
}
impl<P: Problem + 'static> std::ops::BitOr for Box<dyn Condition<P>> {
type Output = Box<dyn Condition<P>>;

fn bitor(self, rhs: Self) -> Self::Output {
Or::new(vec![self, rhs])
}
}
35 changes: 23 additions & 12 deletions src/framework/builder.rs → src/framework/configuration.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
use crate::framework::components::{Block, Branch, Component, Condition, Loop, Scope};
use crate::framework::Configuration;
use crate::problems::Problem;
use crate::{
framework::components::{Block, Branch, Component, Condition, Loop, Scope},
problems::Problem,
};

pub struct ConfigurationBuilder<P> {
components: Vec<Box<dyn Component<P>>>,
}
pub struct Configuration<P: Problem>(Box<dyn Component<P>>);

impl<P: Problem + 'static> Default for ConfigurationBuilder<P> {
fn default() -> Self {
Self::new()
impl<P: Problem> Configuration<P> {
pub fn new(heuristic: Box<dyn Component<P>>) -> Self {
Configuration(heuristic)
}

pub fn builder() -> ConfigurationBuilder<P> {
ConfigurationBuilder::new()
}

pub fn heuristic(&self) -> &dyn Component<P> {
self.0.as_ref()
}
}

pub struct ConfigurationBuilder<P: Problem> {
components: Vec<Box<dyn Component<P>>>,
}

impl<P: Problem + 'static> ConfigurationBuilder<P> {
pub fn new() -> Self {
impl<P: Problem> ConfigurationBuilder<P> {
fn new() -> Self {
Self {
components: Vec::new(),
}
Expand Down Expand Up @@ -66,6 +77,6 @@ impl<P: Problem + 'static> ConfigurationBuilder<P> {
}

pub fn build(self) -> Configuration<P> {
Block::new(self.components)
Configuration::new(Block::new(self.components))
}
}
Loading