Skip to main content

solverforge_core/domain/
value_range.rs

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