Skip to main content

solverforge_config/
phase.rs

1use serde::{Deserialize, Serialize};
2
3use crate::acceptor::AcceptorConfig;
4use crate::forager::ForagerConfig;
5use crate::move_selector::{MoveSelectorConfig, VariableTargetConfig};
6use crate::termination::TerminationConfig;
7
8// Phase configuration.
9#[derive(Debug, Clone, Deserialize, Serialize)]
10#[serde(tag = "type", rename_all = "snake_case")]
11pub enum PhaseConfig {
12    // Construction heuristic phase.
13    ConstructionHeuristic(ConstructionHeuristicConfig),
14
15    // Local search phase.
16    LocalSearch(LocalSearchConfig),
17
18    // Variable neighborhood descent phase.
19    Vnd(VndConfig),
20
21    // Exhaustive search phase.
22    ExhaustiveSearch(ExhaustiveSearchConfig),
23
24    // Partitioned search phase.
25    PartitionedSearch(PartitionedSearchConfig),
26
27    // Custom phase.
28    Custom(CustomPhaseConfig),
29}
30
31fn default_k() -> usize {
32    2
33}
34
35// Construction heuristic configuration.
36#[derive(Debug, Clone, Deserialize, Serialize)]
37#[serde(rename_all = "snake_case")]
38pub struct ConstructionHeuristicConfig {
39    // Type of construction heuristic.
40    #[serde(default)]
41    pub construction_heuristic_type: ConstructionHeuristicType,
42
43    // Whether nullable scalar variables may keep their current unassigned value during
44    // construction, or must receive a candidate when one exists.
45    #[serde(default)]
46    pub construction_obligation: ConstructionObligation,
47
48    // Optional variable target.
49    #[serde(flatten)]
50    pub target: VariableTargetConfig,
51
52    // k for ListKOpt (default 2).
53    #[serde(default = "default_k")]
54    pub k: usize,
55
56    // Optional cap for scalar value candidates generated per entity.
57    pub value_candidate_limit: Option<usize>,
58
59    // Optional named scalar group for atomic grouped scalar construction.
60    pub group_name: Option<String>,
61
62    // Optional cap for grouped scalar candidates generated per provider call.
63    pub group_candidate_limit: Option<usize>,
64
65    // Phase termination configuration.
66    pub termination: Option<TerminationConfig>,
67}
68
69impl Default for ConstructionHeuristicConfig {
70    fn default() -> Self {
71        Self {
72            construction_heuristic_type: ConstructionHeuristicType::default(),
73            construction_obligation: ConstructionObligation::default(),
74            target: VariableTargetConfig::default(),
75            k: default_k(),
76            value_candidate_limit: None,
77            group_name: None,
78            group_candidate_limit: None,
79            termination: None,
80        }
81    }
82}
83
84// Construction obligation for nullable scalar variables.
85#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Deserialize, Serialize)]
86#[serde(rename_all = "snake_case")]
87pub enum ConstructionObligation {
88    // Preserve current behavior: unassigned nullable variables may remain unassigned.
89    #[default]
90    PreserveUnassigned,
91
92    // If a nullable scalar variable is unassigned and has a doable candidate, construction
93    // must assign one instead of comparing against the unassigned baseline.
94    AssignWhenCandidateExists,
95}
96
97// Construction heuristic types.
98#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Deserialize, Serialize)]
99#[serde(rename_all = "snake_case")]
100pub enum ConstructionHeuristicType {
101    // First fit heuristic (scalar variables).
102    #[default]
103    FirstFit,
104
105    // First fit decreasing. Scalar-only; requires `construction_entity_order_key`.
106    FirstFitDecreasing,
107
108    // Weakest fit heuristic. Scalar-only; requires `construction_value_order_key`.
109    WeakestFit,
110
111    // Weakest fit decreasing. Scalar-only; requires both scalar construction order keys.
112    WeakestFitDecreasing,
113
114    // Strongest fit heuristic. Scalar-only; requires `construction_value_order_key`.
115    StrongestFit,
116
117    // Strongest fit decreasing. Scalar-only; requires both scalar construction order keys.
118    StrongestFitDecreasing,
119
120    // Cheapest insertion (greedy, scalar variables).
121    CheapestInsertion,
122
123    // Coverage-first scalar construction over a named coverage group.
124    CoverageFirstFit,
125
126    // Allocate entity from queue. Scalar-only; requires `construction_entity_order_key`.
127    AllocateEntityFromQueue,
128
129    // Allocate to value from queue. Scalar-only; requires `construction_value_order_key`.
130    AllocateToValueFromQueue,
131
132    // List round-robin construction: distributes elements evenly across entities and validates the
133    // list construction hook surface before phase build.
134    ListRoundRobin,
135
136    // List cheapest insertion: inserts each element at the score-minimizing position and validates
137    // the list construction hook surface before phase build.
138    ListCheapestInsertion,
139
140    // List regret insertion: inserts elements in order of highest placement regret and validates
141    // the list construction hook surface before phase build.
142    ListRegretInsertion,
143
144    // List Clarke-Wright savings: greedy route merging by savings value; requires the declared
145    // `cw_*` list hooks and validates them before phase build.
146    ListClarkeWright,
147
148    // List k-opt: per-route k-opt polishing (k=2 is exact 2-opt); requires the declared
149    // `k_opt_*` list hooks and validates them before phase build.
150    ListKOpt,
151}
152
153// Local search configuration.
154#[derive(Debug, Clone, Default, Deserialize, Serialize)]
155#[serde(rename_all = "snake_case")]
156pub struct LocalSearchConfig {
157    // Acceptor configuration.
158    pub acceptor: Option<AcceptorConfig>,
159
160    // Forager configuration.
161    pub forager: Option<ForagerConfig>,
162
163    // Move selector configuration.
164    pub move_selector: Option<MoveSelectorConfig>,
165
166    // Phase termination configuration.
167    pub termination: Option<TerminationConfig>,
168}
169
170// VND configuration.
171#[derive(Debug, Clone, Default, Deserialize, Serialize)]
172#[serde(rename_all = "snake_case")]
173pub struct VndConfig {
174    // Ordered neighborhood selectors.
175    #[serde(default)]
176    pub neighborhoods: Vec<MoveSelectorConfig>,
177
178    // Phase termination configuration.
179    pub termination: Option<TerminationConfig>,
180}
181
182// Exhaustive search configuration.
183#[derive(Debug, Clone, Default, Deserialize, Serialize)]
184#[serde(rename_all = "snake_case")]
185pub struct ExhaustiveSearchConfig {
186    // Exhaustive search type.
187    #[serde(default)]
188    pub exhaustive_search_type: ExhaustiveSearchType,
189
190    // Phase termination configuration.
191    pub termination: Option<TerminationConfig>,
192}
193
194// Exhaustive search types.
195#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Deserialize, Serialize)]
196#[serde(rename_all = "snake_case")]
197pub enum ExhaustiveSearchType {
198    // Branch and bound.
199    #[default]
200    BranchAndBound,
201
202    // Brute force.
203    BruteForce,
204}
205
206// Partitioned search configuration.
207#[derive(Debug, Clone, Default, Deserialize, Serialize)]
208#[serde(rename_all = "snake_case")]
209pub struct PartitionedSearchConfig {
210    // Number of partitions.
211    pub partition_count: Option<usize>,
212
213    // Phase termination configuration.
214    pub termination: Option<TerminationConfig>,
215}
216
217// Custom phase configuration.
218#[derive(Debug, Clone, Default, Deserialize, Serialize)]
219#[serde(rename_all = "snake_case")]
220pub struct CustomPhaseConfig {
221    // Custom phase class name.
222    pub custom_phase_class: Option<String>,
223}