use eyre::WrapErr;
use crate::{
component::ExecResult,
components::{boundary, initialization, mapping, mutation, replacement, selection, utils},
conditions::Condition,
configuration::Configuration,
identifier::{Global, Identifier},
lens::ValueOf,
logging::Logger,
problems::{LimitedVectorProblem, SingleObjectiveProblem, VectorProblem},
Component,
};
pub struct RealProblemParameters {
pub t_0: f64,
pub alpha: f64,
pub deviation: f64,
}
pub fn real_sa<P>(
params: RealProblemParameters,
condition: Box<dyn Condition<P>>,
) -> ExecResult<Configuration<P>>
where
P: SingleObjectiveProblem + LimitedVectorProblem<Element = f64>,
{
let RealProblemParameters {
t_0,
alpha,
deviation,
} = params;
Ok(Configuration::builder()
.do_(initialization::RandomSpread::new(1))
.evaluate()
.update_best_individual()
.do_(sa::<P, Global>(
Parameters {
t_0,
generation: mutation::NormalMutation::new_dev(deviation),
cooling_schedule: mapping::sa::GeometricCooling::new(
alpha,
ValueOf::<replacement::sa::Temperature>::new(),
)
.wrap_err("failed to construct geometric cooling component")?,
constraints: boundary::Saturation::new(),
},
condition,
))
.build())
}
pub struct PermutationProblemParameters {
pub t_0: f64,
pub alpha: f64,
pub num_swap: u32,
}
pub fn permutation_sa<P>(
params: PermutationProblemParameters,
condition: Box<dyn Condition<P>>,
) -> ExecResult<Configuration<P>>
where
P: SingleObjectiveProblem + VectorProblem<Element = usize>,
{
let PermutationProblemParameters {
t_0,
alpha,
num_swap,
} = params;
Ok(Configuration::builder()
.do_(initialization::RandomPermutation::new(1))
.evaluate()
.update_best_individual()
.do_(sa::<P, Global>(
Parameters {
t_0,
generation: <mutation::SwapMutation>::new(num_swap)
.wrap_err("failed to construct swap mutation")?,
cooling_schedule: mapping::sa::GeometricCooling::new(
alpha,
ValueOf::<replacement::sa::Temperature>::new(),
)
.wrap_err("failed to construct geometric cooling component")?,
constraints: utils::Noop::new(),
},
condition,
))
.build())
}
pub struct Parameters<P> {
pub t_0: f64,
pub generation: Box<dyn Component<P>>,
pub cooling_schedule: Box<dyn Component<P>>,
pub constraints: Box<dyn Component<P>>,
}
pub fn sa<P, I>(params: Parameters<P>, condition: Box<dyn Condition<P>>) -> Box<dyn Component<P>>
where
P: SingleObjectiveProblem,
I: Identifier,
{
let Parameters {
t_0,
generation,
cooling_schedule,
constraints,
} = params;
Configuration::builder()
.while_(condition, |builder| {
builder
.do_(selection::All::new())
.do_(generation)
.do_(constraints)
.evaluate_with::<I>()
.update_best_individual()
.do_(cooling_schedule)
.do_(replacement::sa::ExponentialAnnealingAcceptance::new(t_0))
.do_(Logger::new())
})
.build_component()
}