Skip to main content

vrp_core/solver/search/recreate/
mod.rs

1//! The recreate module contains logic to build a feasible solution from partially ruined.
2
3use crate::construction::heuristics::*;
4use crate::models::{GoalContext, Problem};
5use crate::solver::RefinementContext;
6use rosomaxa::prelude::SelectionPhase;
7use rosomaxa::HeuristicContext;
8use std::collections::HashMap;
9use std::sync::Arc;
10
11/// A trait which specifies logic to produce a new feasible solution from partial one.
12pub trait Recreate: Send + Sync {
13    /// Recreates a new solution from the given.
14    fn run(&self, refinement_ctx: &RefinementContext, insertion_ctx: InsertionContext) -> InsertionContext;
15}
16
17mod recreate_with_blinks;
18pub use self::recreate_with_blinks::RecreateWithBlinks;
19
20mod recreate_with_cheapest;
21pub use self::recreate_with_cheapest::RecreateWithCheapest;
22
23mod recreate_with_farthest;
24pub use self::recreate_with_farthest::RecreateWithFarthest;
25
26mod recreate_with_gaps;
27pub use self::recreate_with_gaps::RecreateWithGaps;
28
29mod recreate_with_nearest_neighbor;
30pub use self::recreate_with_nearest_neighbor::RecreateWithNearestNeighbor;
31
32mod recreate_with_perturbation;
33pub use self::recreate_with_perturbation::RecreateWithPerturbation;
34
35mod recreate_with_regret;
36pub use self::recreate_with_regret::RecreateWithRegret;
37
38mod recreate_with_skip_best;
39pub use self::recreate_with_skip_best::RecreateWithSkipBest;
40
41mod recreate_with_skip_random;
42pub use self::recreate_with_skip_random::RecreateWithSkipRandom;
43
44mod recreate_with_slice;
45pub use self::recreate_with_slice::RecreateWithSlice;
46
47/// Provides the way to run one of multiple recreate methods.
48pub struct WeightedRecreate {
49    recreates: Vec<Arc<dyn Recreate>>,
50    weights: Vec<usize>,
51}
52
53impl WeightedRecreate {
54    /// Creates a new instance of `WeightedRecreate` using list of recreate strategies.
55    pub fn new(recreates: Vec<(Arc<dyn Recreate>, usize)>) -> Self {
56        let (recreates, weights) = recreates.into_iter().unzip();
57        Self { recreates, weights }
58    }
59}
60
61impl Recreate for WeightedRecreate {
62    fn run(&self, refinement_ctx: &RefinementContext, insertion_ctx: InsertionContext) -> InsertionContext {
63        let index = insertion_ctx.environment.random.weighted(self.weights.as_slice());
64        self.recreates.get(index).unwrap().run(refinement_ctx, insertion_ctx)
65    }
66}
67
68/// Provides way to reuse generic behaviour.
69pub struct ConfigurableRecreate {
70    job_selector: Box<dyn JobSelector>,
71    route_selector: Box<dyn RouteSelector>,
72    leg_selection: LegSelection,
73    result_selection: ResultSelection,
74    insertion_heuristic: InsertionHeuristic,
75}
76
77impl ConfigurableRecreate {
78    /// Creates a new instance of `ConfigurableRecreate`.
79    pub fn new(
80        job_selector: Box<dyn JobSelector>,
81        route_selector: Box<dyn RouteSelector>,
82        leg_selection: LegSelection,
83        result_selection: ResultSelection,
84        insertion_heuristic: InsertionHeuristic,
85    ) -> Self {
86        Self { job_selector, route_selector, leg_selection, result_selection, insertion_heuristic }
87    }
88}
89
90impl Recreate for ConfigurableRecreate {
91    fn run(&self, _: &RefinementContext, insertion_ctx: InsertionContext) -> InsertionContext {
92        let result_selector = match &self.result_selection {
93            ResultSelection::Concrete(concrete) => concrete.as_ref(),
94            ResultSelection::Stochastic(provider) => provider.pick(),
95        };
96
97        self.insertion_heuristic.process(
98            insertion_ctx,
99            self.job_selector.as_ref(),
100            self.route_selector.as_ref(),
101            &self.leg_selection,
102            result_selector,
103        )
104    }
105}
106
107/// Provides way to use different recreate methods on different selection phases.
108pub struct PhasedRecreate {
109    recreates: HashMap<SelectionPhase, Arc<dyn Recreate>>,
110}
111
112impl PhasedRecreate {
113    /// Creates a new instance of `PhasedRecreate`.
114    pub fn new(recreates: HashMap<SelectionPhase, Arc<dyn Recreate>>) -> Self {
115        assert!([SelectionPhase::Initial, SelectionPhase::Exploration, SelectionPhase::Exploitation]
116            .iter()
117            .all(|key| recreates.contains_key(key)));
118
119        Self { recreates }
120    }
121}
122
123impl Recreate for PhasedRecreate {
124    fn run(&self, refinement_ctx: &RefinementContext, insertion_ctx: InsertionContext) -> InsertionContext {
125        self.recreates.get(&refinement_ctx.selection_phase()).unwrap().run(refinement_ctx, insertion_ctx)
126    }
127}
128
129pub(crate) struct RecreateWithGoal<T: Recreate> {
130    goal: Arc<GoalContext>,
131    inner: T,
132}
133
134impl<T: Recreate> RecreateWithGoal<T> {
135    /// Creates a new instance of `RecreateWithGoal`.
136    pub fn new(goal: Arc<GoalContext>, inner: T) -> Self {
137        Self { goal, inner }
138    }
139}
140
141impl<T: Recreate> Recreate for RecreateWithGoal<T> {
142    fn run(&self, refinement_ctx: &RefinementContext, insertion_ctx: InsertionContext) -> InsertionContext {
143        let problem = insertion_ctx.problem.clone();
144
145        let insertion_ctx = InsertionContext {
146            problem: Arc::new(Problem {
147                fleet: problem.fleet.clone(),
148                jobs: problem.jobs.clone(),
149                locks: problem.locks.clone(),
150                goal: self.goal.clone(),
151                activity: problem.activity.clone(),
152                transport: problem.transport.clone(),
153                extras: problem.extras.clone(),
154            }),
155            ..insertion_ctx
156        };
157
158        let mut insertion_ctx = self.inner.run(refinement_ctx, insertion_ctx);
159
160        insertion_ctx.problem = problem;
161
162        insertion_ctx
163    }
164}
165
166/// A recreate strategy which does nothing.
167pub(crate) struct DummyRecreate;
168
169impl Recreate for DummyRecreate {
170    fn run(&self, _: &RefinementContext, insertion_ctx: InsertionContext) -> InsertionContext {
171        insertion_ctx
172    }
173}