problemreductions/
types.rs1use serde::{Deserialize, Serialize};
4use std::fmt;
5
6pub trait NumericSize:
8 Clone
9 + Default
10 + PartialOrd
11 + num_traits::Num
12 + num_traits::Zero
13 + num_traits::Bounded
14 + std::ops::AddAssign
15 + 'static
16{
17}
18
19impl<T> NumericSize for T where
20 T: Clone
21 + Default
22 + PartialOrd
23 + num_traits::Num
24 + num_traits::Zero
25 + num_traits::Bounded
26 + std::ops::AddAssign
27 + 'static
28{
29}
30
31pub trait WeightElement: Clone + Default + 'static {
37 type Sum: NumericSize;
39 const IS_UNIT: bool;
41 fn to_sum(&self) -> Self::Sum;
43}
44
45impl WeightElement for i32 {
46 type Sum = i32;
47 const IS_UNIT: bool = false;
48 fn to_sum(&self) -> i32 {
49 *self
50 }
51}
52
53impl WeightElement for f64 {
54 type Sum = f64;
55 const IS_UNIT: bool = false;
56 fn to_sum(&self) -> f64 {
57 *self
58 }
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
66pub struct One;
67
68impl WeightElement for One {
69 type Sum = i32;
70 const IS_UNIT: bool = true;
71 fn to_sum(&self) -> i32 {
72 1
73 }
74}
75
76impl std::fmt::Display for One {
77 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 write!(f, "One")
79 }
80}
81
82impl From<i32> for One {
83 fn from(_: i32) -> Self {
84 One
85 }
86}
87
88pub type Unweighted = One;
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
109pub enum SolutionSize<T> {
110 Valid(T),
112 #[default]
114 Invalid,
115}
116
117impl<T> SolutionSize<T> {
118 pub fn is_valid(&self) -> bool {
120 matches!(self, SolutionSize::Valid(_))
121 }
122
123 pub fn size(&self) -> Option<&T> {
125 match self {
126 SolutionSize::Valid(t) => Some(t),
127 SolutionSize::Invalid => None,
128 }
129 }
130
131 pub fn unwrap(self) -> T {
133 match self {
134 SolutionSize::Valid(t) => t,
135 SolutionSize::Invalid => panic!("called unwrap on Invalid SolutionSize"),
136 }
137 }
138
139 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> SolutionSize<U> {
141 match self {
142 SolutionSize::Valid(t) => SolutionSize::Valid(f(t)),
143 SolutionSize::Invalid => SolutionSize::Invalid,
144 }
145 }
146}
147
148impl<T: PartialOrd> SolutionSize<T> {
149 pub fn is_better(&self, other: &Self, direction: Direction) -> bool {
160 match (self, other) {
161 (SolutionSize::Valid(a), SolutionSize::Valid(b)) => {
162 use std::cmp::Ordering;
163 let ord = a.partial_cmp(b).expect("cannot compare values (NaN?)");
164 match direction {
165 Direction::Maximize => ord == Ordering::Greater,
166 Direction::Minimize => ord == Ordering::Less,
167 }
168 }
169 (SolutionSize::Valid(_), SolutionSize::Invalid) => true,
170 (SolutionSize::Invalid, SolutionSize::Valid(_)) => false,
171 (SolutionSize::Invalid, SolutionSize::Invalid) => false,
172 }
173 }
174}
175
176#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
178pub enum Direction {
179 Maximize,
181 Minimize,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
187pub struct ProblemSize {
188 pub components: Vec<(String, usize)>,
190}
191
192impl ProblemSize {
193 pub fn new(components: Vec<(&str, usize)>) -> Self {
195 Self {
196 components: components
197 .into_iter()
198 .map(|(k, v)| (k.to_string(), v))
199 .collect(),
200 }
201 }
202
203 pub fn get(&self, name: &str) -> Option<usize> {
205 self.components
206 .iter()
207 .find(|(k, _)| k == name)
208 .map(|(_, v)| *v)
209 }
210}
211
212impl fmt::Display for ProblemSize {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 write!(f, "ProblemSize{{")?;
215 for (i, (name, value)) in self.components.iter().enumerate() {
216 if i > 0 {
217 write!(f, ", ")?;
218 }
219 write!(f, "{}: {}", name, value)?;
220 }
221 write!(f, "}}")
222 }
223}
224
225use crate::impl_variant_param;
226
227impl_variant_param!(f64, "weight");
228impl_variant_param!(i32, "weight", parent: f64, cast: |w| *w as f64);
229impl_variant_param!(One, "weight", parent: i32, cast: |_| 1i32);
230
231#[cfg(test)]
232#[path = "unit_tests/types.rs"]
233mod tests;