Skip to main content

solverforge_core/domain/
value_range.rs

1/* Value range providers for planning variables.
2
3Value range providers define the possible values that can be assigned to
4planning variables. They can be static (fixed list) or dynamic (computed
5from the solution state).
6*/
7
8/// Provides values for a planning variable.
9///
10/// This trait is implemented for types that can produce a list of valid values
11/// for a planning variable. The values can be static or computed dynamically
12/// based on the solution state.
13///
14/// # Type Parameters
15///
16/// * `S` - The solution type
17/// * `V` - The value type (must match the planning variable's type)
18///
19/// # Example
20///
21/// ```
22/// use solverforge_core::domain::ValueRangeProvider;
23///
24/// // Define a solution with a size field
25/// struct NQueensSolution {
26///     n: i32,
27/// }
28///
29/// // Implement a value range provider that computes row values
30/// struct RowRangeProvider;
31///
32/// impl ValueRangeProvider<NQueensSolution, i32> for RowRangeProvider {
33///     fn get_values(&self, solution: &NQueensSolution) -> Vec<i32> {
34///         (0..solution.n).collect()
35///     }
36/// }
37///
38/// let solution = NQueensSolution { n: 8 };
39/// let provider = RowRangeProvider;
40/// assert_eq!(provider.get_values(&solution), vec![0, 1, 2, 3, 4, 5, 6, 7]);
41/// assert_eq!(provider.value_count(&solution), 8);
42/// ```
43pub trait ValueRangeProvider<S, V>: Send + Sync {
44    /* Returns all possible values for the variable.
45
46    This method is called during move generation to determine which
47    values can be assigned to a planning variable.
48    */
49    fn get_values(&self, solution: &S) -> Vec<V>;
50
51    /* Returns the number of possible values.
52
53    The default implementation calls `get_values` and returns the length,
54    but implementations may override this for efficiency if the count
55    can be computed without materializing the values.
56    */
57    fn value_count(&self, solution: &S) -> usize {
58        self.get_values(solution).len()
59    }
60
61    // Returns whether the value range is empty.
62    fn is_empty(&self, solution: &S) -> bool {
63        self.value_count(solution) == 0
64    }
65}
66
67/// A value range provider backed by a field in the solution.
68///
69/// This is the most common case: a `Vec<V>` field that contains the possible values.
70pub struct FieldValueRangeProvider<S, V, F>
71where
72    F: Fn(&S) -> &Vec<V> + Send + Sync,
73{
74    getter: F,
75    _marker: std::marker::PhantomData<(fn() -> S, fn() -> V)>,
76}
77
78impl<S, V, F> FieldValueRangeProvider<S, V, F>
79where
80    F: Fn(&S) -> &Vec<V> + Send + Sync,
81{
82    pub fn new(getter: F) -> Self {
83        Self {
84            getter,
85            _marker: std::marker::PhantomData,
86        }
87    }
88}
89
90impl<S, V, F> ValueRangeProvider<S, V> for FieldValueRangeProvider<S, V, F>
91where
92    S: Send + Sync,
93    V: Clone + Send + Sync,
94    F: Fn(&S) -> &Vec<V> + Send + Sync,
95{
96    fn get_values(&self, solution: &S) -> Vec<V> {
97        (self.getter)(solution).clone()
98    }
99
100    fn value_count(&self, solution: &S) -> usize {
101        (self.getter)(solution).len()
102    }
103}
104
105/// A value range provider that computes values dynamically.
106///
107/// Use this when values are computed from solution state rather than
108/// stored in a field.
109pub struct ComputedValueRangeProvider<S, V, F>
110where
111    F: Fn(&S) -> Vec<V> + Send + Sync,
112{
113    compute: F,
114    _marker: std::marker::PhantomData<(fn() -> S, fn() -> V)>,
115}
116
117impl<S, V, F> ComputedValueRangeProvider<S, V, F>
118where
119    F: Fn(&S) -> Vec<V> + Send + Sync,
120{
121    pub fn new(compute: F) -> Self {
122        Self {
123            compute,
124            _marker: std::marker::PhantomData,
125        }
126    }
127
128    /// Returns [`ValueRangeType::EntityDependent`] since computed ranges
129    /// derive their values from solution state at runtime.
130    pub fn value_range_type() -> ValueRangeType {
131        ValueRangeType::EntityDependent
132    }
133}
134
135impl<S, V, F> ValueRangeProvider<S, V> for ComputedValueRangeProvider<S, V, F>
136where
137    S: Send + Sync,
138    V: Send + Sync,
139    F: Fn(&S) -> Vec<V> + Send + Sync,
140{
141    fn get_values(&self, solution: &S) -> Vec<V> {
142        (self.compute)(solution)
143    }
144}
145
146/// A static value range with a fixed set of values.
147///
148/// Use this when the possible values don't depend on solution state.
149pub struct StaticValueRange<V> {
150    values: Vec<V>,
151}
152
153impl<V> StaticValueRange<V> {
154    pub fn new(values: Vec<V>) -> Self {
155        Self { values }
156    }
157}
158
159impl<S, V> ValueRangeProvider<S, V> for StaticValueRange<V>
160where
161    S: Send + Sync,
162    V: Clone + Send + Sync,
163{
164    fn get_values(&self, _solution: &S) -> Vec<V> {
165        self.values.clone()
166    }
167
168    fn value_count(&self, _solution: &S) -> usize {
169        self.values.len()
170    }
171}
172
173/// An integer range value provider.
174///
175/// Efficiently provides a contiguous range of integers without storing them.
176pub struct IntegerRange {
177    start: i64,
178    end: i64,
179}
180
181use super::variable::ValueRangeType;
182
183impl IntegerRange {
184    pub fn new(start: i64, end: i64) -> Self {
185        Self { start, end }
186    }
187
188    pub fn from_zero(n: i64) -> Self {
189        Self::new(0, n)
190    }
191
192    /// Returns the [`ValueRangeType`] describing this range.
193    ///
194    /// An `IntegerRange` is a countable range with known bounds.
195    pub fn value_range_type(&self) -> ValueRangeType {
196        ValueRangeType::CountableRange {
197            from: self.start,
198            to: self.end,
199        }
200    }
201}
202
203impl<S> ValueRangeProvider<S, i64> for IntegerRange
204where
205    S: Send + Sync,
206{
207    fn get_values(&self, _solution: &S) -> Vec<i64> {
208        (self.start..self.end).collect()
209    }
210
211    fn value_count(&self, _solution: &S) -> usize {
212        let count = (self.end - self.start).max(0);
213        usize::try_from(count).expect("IntegerRange count overflows usize")
214    }
215}
216
217impl<S> ValueRangeProvider<S, i32> for IntegerRange
218where
219    S: Send + Sync,
220{
221    fn get_values(&self, _solution: &S) -> Vec<i32> {
222        let start_i32 =
223            i32::try_from(self.start).expect("IntegerRange start overflows i32 for i32 provider");
224        let end_i32 =
225            i32::try_from(self.end).expect("IntegerRange end overflows i32 for i32 provider");
226        (start_i32..end_i32).collect()
227    }
228
229    fn value_count(&self, _solution: &S) -> usize {
230        let count = (self.end - self.start).max(0);
231        usize::try_from(count).expect("IntegerRange count overflows usize")
232    }
233}