mahf/heuristics/
rw.rs

1//! Random Walk (RW).
2
3use eyre::WrapErr;
4
5use crate::{
6    component::ExecResult,
7    components::{boundary, initialization, mutation, replacement, selection, utils},
8    conditions::Condition,
9    configuration::Configuration,
10    identifier::{Global, Identifier},
11    logging::Logger,
12    problems::{LimitedVectorProblem, SingleObjectiveProblem, VectorProblem},
13    Component,
14};
15
16/// Parameters for [`real_rw`].
17pub struct RealProblemParameters {
18    pub deviation: f64,
19}
20
21/// An example single-objective random walk operating on a real search space.
22///
23/// Uses the [`rw`] component internally.
24pub fn real_rw<P>(
25    params: RealProblemParameters,
26    condition: Box<dyn Condition<P>>,
27) -> ExecResult<Configuration<P>>
28where
29    P: SingleObjectiveProblem + LimitedVectorProblem<Element = f64>,
30{
31    let RealProblemParameters { deviation } = params;
32
33    Ok(Configuration::builder()
34        .do_(initialization::RandomSpread::new(1))
35        .do_(rw::<P, Global>(
36            Parameters {
37                neighbor: mutation::NormalMutation::new_dev(deviation),
38                constraints: boundary::Saturation::new(),
39            },
40            condition,
41        ))
42        .build())
43}
44
45/// Parameters for [`permutation_random_walk`].
46pub struct PermutationProblemParameters {
47    pub num_swap: u32,
48}
49
50/// An example single-objective random walk operating on a permutation search space.
51///
52/// Uses the [`rw`] component internally.
53pub fn permutation_random_walk<P>(
54    params: PermutationProblemParameters,
55    condition: Box<dyn Condition<P>>,
56) -> ExecResult<Configuration<P>>
57where
58    P: SingleObjectiveProblem + VectorProblem<Element = usize>,
59{
60    let PermutationProblemParameters { num_swap } = params;
61
62    Ok(Configuration::builder()
63        .do_(initialization::RandomPermutation::new(1))
64        .do_(rw::<P, Global>(
65            Parameters {
66                neighbor: <mutation::SwapMutation>::new(num_swap)
67                    .wrap_err("failed to construct swap mutation")?,
68                constraints: utils::Noop::new(),
69            },
70            condition,
71        ))
72        .build())
73}
74
75/// Basic building blocks of [`rw`].
76pub struct Parameters<P> {
77    pub neighbor: Box<dyn Component<P>>,
78    pub constraints: Box<dyn Component<P>>,
79}
80
81/// A generic single-objective Random Walk (RW) template.
82pub fn rw<P, I>(params: Parameters<P>, condition: Box<dyn Condition<P>>) -> Box<dyn Component<P>>
83where
84    P: SingleObjectiveProblem,
85    I: Identifier,
86{
87    let Parameters {
88        neighbor,
89        constraints,
90    } = params;
91
92    Configuration::builder()
93        .while_(condition, |builder| {
94            builder
95                .do_(selection::All::new())
96                .do_(neighbor)
97                .do_(constraints)
98                .evaluate_with::<I>()
99                .update_best_individual()
100                .do_(replacement::Generational::new(1))
101                .do_(Logger::new())
102        })
103        .build_component()
104}