solverforge_solver/planning/
coverage.rs1use std::marker::PhantomData;
2
3use crate::planning::ScalarTarget;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub struct CoverageGroupLimits {
7 pub value_candidate_limit: Option<usize>,
9 pub group_candidate_limit: Option<usize>,
12 pub max_moves_per_step: Option<usize>,
15 pub max_augmenting_depth: Option<usize>,
17}
18
19impl CoverageGroupLimits {
20 pub const fn new() -> Self {
21 Self {
22 value_candidate_limit: None,
23 group_candidate_limit: None,
24 max_moves_per_step: None,
25 max_augmenting_depth: None,
26 }
27 }
28}
29
30impl Default for CoverageGroupLimits {
31 fn default() -> Self {
32 Self::new()
33 }
34}
35
36pub struct CoverageGroup<S> {
37 group_name: &'static str,
38 target: ScalarTarget<S>,
39 required_slot: Option<fn(&S, usize) -> bool>,
40 capacity_key: Option<fn(&S, usize, usize) -> Option<usize>>,
41 entity_order: Option<fn(&S, usize) -> i64>,
42 value_order: Option<fn(&S, usize, usize) -> i64>,
43 limits: CoverageGroupLimits,
44 _phantom: PhantomData<fn() -> S>,
45}
46
47impl<S> Clone for CoverageGroup<S> {
48 fn clone(&self) -> Self {
49 *self
50 }
51}
52
53impl<S> Copy for CoverageGroup<S> {}
54
55impl<S> CoverageGroup<S> {
56 pub const fn new(group_name: &'static str, target: ScalarTarget<S>) -> Self {
57 Self {
58 group_name,
59 target,
60 required_slot: None,
61 capacity_key: None,
62 entity_order: None,
63 value_order: None,
64 limits: CoverageGroupLimits::new(),
65 _phantom: PhantomData,
66 }
67 }
68
69 pub const fn with_required_slot(mut self, required_slot: fn(&S, usize) -> bool) -> Self {
70 self.required_slot = Some(required_slot);
71 self
72 }
73
74 pub const fn with_capacity_key(
75 mut self,
76 capacity_key: fn(&S, usize, usize) -> Option<usize>,
77 ) -> Self {
78 self.capacity_key = Some(capacity_key);
79 self
80 }
81
82 pub const fn with_entity_order(mut self, entity_order: fn(&S, usize) -> i64) -> Self {
83 self.entity_order = Some(entity_order);
84 self
85 }
86
87 pub const fn with_value_order(mut self, value_order: fn(&S, usize, usize) -> i64) -> Self {
88 self.value_order = Some(value_order);
89 self
90 }
91
92 pub const fn with_limits(mut self, limits: CoverageGroupLimits) -> Self {
93 self.limits = limits;
94 self
95 }
96
97 #[doc(hidden)]
98 #[inline]
99 pub fn group_name(&self) -> &'static str {
100 self.group_name
101 }
102
103 #[doc(hidden)]
104 #[inline]
105 pub fn target(&self) -> ScalarTarget<S> {
106 self.target
107 }
108
109 #[doc(hidden)]
110 #[inline]
111 pub fn required_slot(&self) -> Option<fn(&S, usize) -> bool> {
112 self.required_slot
113 }
114
115 #[doc(hidden)]
116 #[inline]
117 pub fn capacity_key(&self) -> Option<fn(&S, usize, usize) -> Option<usize>> {
118 self.capacity_key
119 }
120
121 #[doc(hidden)]
122 #[inline]
123 pub fn entity_order(&self) -> Option<fn(&S, usize) -> i64> {
124 self.entity_order
125 }
126
127 #[doc(hidden)]
128 #[inline]
129 pub fn value_order(&self) -> Option<fn(&S, usize, usize) -> i64> {
130 self.value_order
131 }
132
133 #[doc(hidden)]
134 #[inline]
135 pub fn limits(&self) -> CoverageGroupLimits {
136 self.limits
137 }
138}
139
140impl<S> std::fmt::Debug for CoverageGroup<S> {
141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 f.debug_struct("CoverageGroup")
143 .field("group_name", &self.group_name)
144 .field("target_descriptor_index", &self.target.descriptor_index())
145 .field("target_variable_name", &self.target.variable_name())
146 .field("has_required_slot", &self.required_slot.is_some())
147 .field("has_capacity_key", &self.capacity_key.is_some())
148 .field("limits", &self.limits)
149 .finish_non_exhaustive()
150 }
151}