solverforge_solver/planning/scalar/
group.rs1use super::{
2 ScalarAssignmentDeclaration, ScalarAssignmentRule, ScalarCandidateProvider, ScalarTarget,
3};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub struct ScalarGroupLimits {
7 pub value_candidate_limit: Option<usize>,
8 pub group_candidate_limit: Option<usize>,
9 pub max_moves_per_step: Option<usize>,
10 pub max_augmenting_depth: Option<usize>,
11 pub max_rematch_size: Option<usize>,
12}
13
14impl ScalarGroupLimits {
15 pub const fn new() -> Self {
16 Self {
17 value_candidate_limit: None,
18 group_candidate_limit: None,
19 max_moves_per_step: None,
20 max_augmenting_depth: None,
21 max_rematch_size: None,
22 }
23 }
24}
25
26impl Default for ScalarGroupLimits {
27 fn default() -> Self {
28 Self::new()
29 }
30}
31
32pub struct ScalarGroup<S> {
33 group_name: &'static str,
34 targets: Vec<ScalarTarget<S>>,
35 kind: ScalarGroupKind<S>,
36 limits: ScalarGroupLimits,
37}
38
39pub(crate) enum ScalarGroupKind<S> {
40 Candidates {
41 candidate_provider: ScalarCandidateProvider<S>,
42 },
43 Assignment(ScalarAssignmentDeclaration<S>),
44}
45
46impl<S> Clone for ScalarGroupKind<S> {
47 fn clone(&self) -> Self {
48 *self
49 }
50}
51
52impl<S> Copy for ScalarGroupKind<S> {}
53
54impl<S> Clone for ScalarGroup<S> {
55 fn clone(&self) -> Self {
56 Self {
57 group_name: self.group_name,
58 targets: self.targets.clone(),
59 kind: self.kind,
60 limits: self.limits,
61 }
62 }
63}
64
65impl<S> ScalarGroup<S> {
66 pub fn candidates(
67 group_name: &'static str,
68 targets: Vec<ScalarTarget<S>>,
69 candidate_provider: ScalarCandidateProvider<S>,
70 ) -> Self {
71 Self {
72 group_name,
73 targets,
74 kind: ScalarGroupKind::Candidates { candidate_provider },
75 limits: ScalarGroupLimits::new(),
76 }
77 }
78
79 pub fn assignment(group_name: &'static str, target: ScalarTarget<S>) -> Self {
80 Self {
81 group_name,
82 targets: vec![target],
83 kind: ScalarGroupKind::Assignment(ScalarAssignmentDeclaration::default()),
84 limits: ScalarGroupLimits::new(),
85 }
86 }
87
88 pub fn with_required_entity(mut self, required_entity: fn(&S, usize) -> bool) -> Self {
89 self.assignment_mut().required_entity = Some(required_entity);
90 self
91 }
92
93 pub fn with_capacity_key(
94 mut self,
95 capacity_key: fn(&S, usize, usize) -> Option<usize>,
96 ) -> Self {
97 self.assignment_mut().capacity_key = Some(capacity_key);
98 self
99 }
100
101 pub fn with_assignment_rule(mut self, assignment_rule: ScalarAssignmentRule<S>) -> Self {
102 self.assignment_mut().assignment_rule = Some(assignment_rule);
103 self
104 }
105
106 pub fn with_position_key(mut self, position_key: fn(&S, usize) -> i64) -> Self {
107 self.assignment_mut().position_key = Some(position_key);
108 self
109 }
110
111 pub fn with_sequence_key(
112 mut self,
113 sequence_key: fn(&S, usize, usize) -> Option<usize>,
114 ) -> Self {
115 self.assignment_mut().sequence_key = Some(sequence_key);
116 self
117 }
118
119 pub fn with_entity_order(mut self, entity_order: fn(&S, usize) -> i64) -> Self {
120 self.assignment_mut().entity_order = Some(entity_order);
121 self
122 }
123
124 pub fn with_value_order(mut self, value_order: fn(&S, usize, usize) -> i64) -> Self {
125 self.assignment_mut().value_order = Some(value_order);
126 self
127 }
128
129 pub fn with_limits(mut self, limits: ScalarGroupLimits) -> Self {
130 self.limits = limits;
131 self
132 }
133
134 fn assignment_mut(&mut self) -> &mut ScalarAssignmentDeclaration<S> {
135 let ScalarGroupKind::Assignment(declaration) = &mut self.kind else {
136 panic!(
137 "scalar group `{}` is candidate-backed; assignment hooks require ScalarGroup::assignment",
138 self.group_name
139 );
140 };
141 declaration
142 }
143
144 #[doc(hidden)]
145 #[inline]
146 pub fn group_name(&self) -> &'static str {
147 self.group_name
148 }
149
150 #[doc(hidden)]
151 #[inline]
152 pub fn targets(&self) -> &[ScalarTarget<S>] {
153 &self.targets
154 }
155
156 #[doc(hidden)]
157 #[inline]
158 pub(crate) fn kind(&self) -> ScalarGroupKind<S> {
159 self.kind
160 }
161
162 #[doc(hidden)]
163 #[inline]
164 pub fn limits(&self) -> ScalarGroupLimits {
165 self.limits
166 }
167}
168
169impl<S> std::fmt::Debug for ScalarGroup<S> {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171 f.debug_struct("ScalarGroup")
172 .field("group_name", &self.group_name)
173 .field("target_count", &self.targets.len())
174 .field(
175 "kind",
176 match self.kind {
177 ScalarGroupKind::Assignment(_) => &"assignment",
178 ScalarGroupKind::Candidates { .. } => &"candidates",
179 },
180 )
181 .field("limits", &self.limits)
182 .finish_non_exhaustive()
183 }
184}