Skip to main content

solverforge_solver/
runtime.rs

1use std::fmt;
2use std::marker::PhantomData;
3
4use solverforge_core::domain::PlanningSolution;
5
6use crate::heuristic::selector::nearby_list_change::CrossEntityDistanceMeter;
7use crate::scope::{ProgressCallback, SolverScope};
8
9// The immutable recursive graph compiler is the sole runtime construction
10// entrypoint for typed and dynamic models.
11#[path = "runtime/compiler/mod.rs"]
12pub(crate) mod compiler;
13#[path = "runtime/provider_cursor.rs"]
14pub(crate) mod provider_cursor;
15
16#[cfg(test)]
17#[path = "runtime/provider_cursor_tests.rs"]
18mod provider_cursor_tests;
19
20pub struct ListVariableMetadata<S, DM, IDM> {
21    pub cross_distance_meter: DM,
22    pub intra_distance_meter: IDM,
23    pub route_get_fn: Option<fn(&S, usize) -> Vec<usize>>,
24    pub route_set_fn: Option<fn(&mut S, usize, Vec<usize>)>,
25    pub route_depot_fn: Option<fn(&S, usize) -> usize>,
26    pub route_distance_fn: Option<fn(&S, usize, usize, usize) -> i64>,
27    pub route_feasible_fn: Option<fn(&S, usize, &[usize]) -> bool>,
28    pub savings_depot_fn: Option<fn(&S, usize) -> usize>,
29    pub savings_metric_class_fn: Option<fn(&S, usize) -> usize>,
30    pub savings_distance_fn: Option<fn(&S, usize, usize, usize) -> i64>,
31    pub savings_feasible_fn: Option<fn(&S, usize, &[usize]) -> bool>,
32    pub element_owner_fn: Option<fn(&S, &usize) -> Option<usize>>,
33    _phantom: PhantomData<fn() -> S>,
34}
35
36pub trait ListVariableEntity<S> {
37    type CrossDistanceMeter: CrossEntityDistanceMeter<S> + Clone + fmt::Debug;
38    type IntraDistanceMeter: CrossEntityDistanceMeter<S> + Clone + fmt::Debug + 'static;
39
40    const HAS_LIST_VARIABLE: bool;
41    const LIST_VARIABLE_NAME: &'static str;
42    const LIST_ELEMENT_SOURCE: Option<&'static str>;
43
44    fn list_field(entity: &Self) -> &[usize];
45    fn list_field_mut(entity: &mut Self) -> &mut Vec<usize>;
46    fn list_metadata() -> ListVariableMetadata<S, Self::CrossDistanceMeter, Self::IntraDistanceMeter>;
47}
48
49impl<S, DM, IDM> ListVariableMetadata<S, DM, IDM> {
50    #[allow(clippy::too_many_arguments)]
51    pub fn new(
52        cross_distance_meter: DM,
53        intra_distance_meter: IDM,
54        route_get_fn: Option<fn(&S, usize) -> Vec<usize>>,
55        route_set_fn: Option<fn(&mut S, usize, Vec<usize>)>,
56        route_depot_fn: Option<fn(&S, usize) -> usize>,
57        route_distance_fn: Option<fn(&S, usize, usize, usize) -> i64>,
58        route_feasible_fn: Option<fn(&S, usize, &[usize]) -> bool>,
59        savings_depot_fn: Option<fn(&S, usize) -> usize>,
60        savings_metric_class_fn: Option<fn(&S, usize) -> usize>,
61        savings_distance_fn: Option<fn(&S, usize, usize, usize) -> i64>,
62        savings_feasible_fn: Option<fn(&S, usize, &[usize]) -> bool>,
63    ) -> Self {
64        Self {
65            cross_distance_meter,
66            intra_distance_meter,
67            route_get_fn,
68            route_set_fn,
69            route_depot_fn,
70            route_distance_fn,
71            route_feasible_fn,
72            savings_depot_fn,
73            savings_metric_class_fn,
74            savings_distance_fn,
75            savings_feasible_fn,
76            element_owner_fn: None,
77            _phantom: PhantomData,
78        }
79    }
80
81    pub fn with_element_owner_fn(
82        mut self,
83        element_owner_fn: Option<fn(&S, &usize) -> Option<usize>>,
84    ) -> Self {
85        self.element_owner_fn = element_owner_fn;
86        self
87    }
88}
89
90pub(crate) fn finalize_noop_construction<S, D, ProgressCb>(
91    solver_scope: &mut SolverScope<'_, S, D, ProgressCb>,
92) where
93    S: PlanningSolution,
94    D: solverforge_scoring::Director<S>,
95    ProgressCb: ProgressCallback<S>,
96{
97    let had_best = solver_scope.best_score().is_some();
98    solver_scope.update_best_solution();
99    if had_best {
100        solver_scope.promote_current_solution_on_score_tie();
101    }
102}