Skip to main content

conjure_cp_core/ast/domains/
attrs.rs

1use crate::ast::domains::Int;
2use crate::ast::domains::range::Range;
3use itertools::Itertools;
4use polyquine::Quine;
5use serde::{Deserialize, Serialize};
6use std::fmt::{Display, Formatter};
7
8#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
9#[path_prefix(conjure_cp::ast)]
10pub struct SetAttr<A = Int> {
11    pub size: Range<A>,
12}
13
14impl<A> SetAttr<A> {
15    pub fn new(size: Range<A>) -> Self {
16        Self { size }
17    }
18
19    pub fn new_min_max_size(min: A, max: A) -> Self {
20        Self::new(Range::Bounded(min, max))
21    }
22
23    pub fn new_min_size(min: A) -> Self {
24        Self::new(Range::UnboundedR(min))
25    }
26
27    pub fn new_max_size(max: A) -> Self {
28        Self::new(Range::UnboundedL(max))
29    }
30
31    pub fn new_size(sz: A) -> Self {
32        Self::new(Range::Single(sz))
33    }
34}
35
36impl<A> Default for SetAttr<A> {
37    fn default() -> Self {
38        SetAttr {
39            size: Range::Unbounded,
40        }
41    }
42}
43
44impl<A: Display> Display for SetAttr<A> {
45    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
46        match &self.size {
47            Range::Single(x) => write!(f, "(size {x})"),
48            Range::Bounded(l, r) => write!(f, "(minSize {l}, maxSize {r})"),
49            Range::UnboundedL(r) => write!(f, "(maxSize {r})"),
50            Range::UnboundedR(l) => write!(f, "(minSize {l})"),
51            Range::Unbounded => write!(f, ""),
52        }
53    }
54}
55
56#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
57#[path_prefix(conjure_cp::ast)]
58pub struct MSetAttr<A = Int> {
59    pub size: Range<A>,
60    pub occurrence: Range<A>,
61}
62
63impl<A> MSetAttr<A> {
64    pub fn new(size: Range<A>, occurrence: Range<A>) -> Self {
65        Self { size, occurrence }
66    }
67
68    pub fn new_min_max_size(min: A, max: A) -> Self {
69        Self::new(Range::Bounded(min, max), Range::Unbounded)
70    }
71
72    pub fn new_min_size(min: A) -> Self {
73        Self::new(Range::UnboundedR(min), Range::Unbounded)
74    }
75
76    pub fn new_max_size(max: A) -> Self {
77        Self::new(Range::UnboundedL(max), Range::Unbounded)
78    }
79
80    pub fn new_size(sz: A) -> Self {
81        Self::new(Range::Single(sz), Range::Unbounded)
82    }
83}
84
85impl<A: Display> Display for MSetAttr<A> {
86    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
87        let size_str = match &self.size {
88            Range::Single(x) => format!("size {x}"),
89            Range::Bounded(l, r) => format!("minSize {l}, maxSize {r}"),
90            Range::UnboundedL(r) => format!("maxSize {r}"),
91            Range::UnboundedR(l) => format!("minSize {l}"),
92            Range::Unbounded => "".to_string(),
93        };
94
95        // It only makes sense in terms of min and max occurrence for the essence language,
96        // so for single ranges it is still presented as min and max occurrence.
97        let occ_str = match &self.occurrence {
98            Range::Single(x) => format!("minOccur {x}, maxOccur {x}"),
99            Range::Bounded(l, r) => format!("minOccur {l} , maxOccur {r}"),
100            Range::UnboundedL(r) => format!("maxOccur {r}"),
101            Range::UnboundedR(l) => format!("minOccur {l}"),
102            Range::Unbounded => "".to_string(),
103        };
104
105        let mut strs = [size_str, occ_str]
106            .iter()
107            .filter(|s| !s.is_empty())
108            .join(", ");
109        if !strs.is_empty() {
110            strs = format!("({})", strs);
111        }
112        write!(f, "{strs}")
113    }
114}
115
116impl<A> Default for MSetAttr<A> {
117    fn default() -> Self {
118        MSetAttr {
119            size: Range::Unbounded,
120            occurrence: Range::Unbounded,
121        }
122    }
123}
124
125#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
126#[path_prefix(conjure_cp::ast)]
127pub struct FuncAttr<A = Int> {
128    pub size: Range<A>,
129    pub partiality: PartialityAttr,
130    pub jectivity: JectivityAttr,
131}
132
133impl<A: Display> Display for FuncAttr<A> {
134    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
135        let size_str = match &self.size {
136            Range::Single(x) => format!("size({x})"),
137            Range::Bounded(l, r) => format!("minSize({l}), maxSize({r})"),
138            Range::UnboundedL(r) => format!("maxSize({r})"),
139            Range::UnboundedR(l) => format!("minSize({l})"),
140            Range::Unbounded => "".to_string(),
141        };
142        let mut strs = [
143            size_str,
144            self.partiality.to_string(),
145            self.jectivity.to_string(),
146        ]
147        .iter()
148        .filter(|s| !s.is_empty())
149        .join(", ");
150        if !strs.is_empty() {
151            strs = format!("({})", strs);
152        }
153        write!(f, "{strs}")
154    }
155}
156
157#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
158#[path_prefix(conjure_cp::ast)]
159pub struct SequenceAttr<A = Int> {
160    pub size: Range<A>,
161    pub jectivity: JectivityAttr,
162}
163
164impl<A> Default for SequenceAttr<A> {
165    fn default() -> Self {
166        SequenceAttr {
167            size: Range::Unbounded,
168            jectivity: JectivityAttr::None,
169        }
170    }
171}
172
173impl<A: Display> Display for SequenceAttr<A> {
174    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
175        let size_str = match &self.size {
176            Range::Single(x) => format!("size {x}"),
177            Range::Bounded(l, r) => format!("minSize {l}, maxSize {r}"),
178            Range::UnboundedL(r) => format!("maxSize {r}"),
179            Range::UnboundedR(l) => format!("minSize {l}"),
180            Range::Unbounded => "".to_string(),
181        };
182        let mut strs = [size_str, self.jectivity.to_string()]
183            .iter()
184            .filter(|s| !s.is_empty())
185            .join(", ");
186        if !strs.is_empty() {
187            strs = format!("({})", strs);
188        }
189        write!(f, "{strs}")
190    }
191}
192
193#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
194#[path_prefix(conjure_cp::ast)]
195pub struct PartitionAttr<A = Int> {
196    pub num_parts: Range<A>, // i.e. how many parts there are in the partition
197    pub part_len: Range<A>,  // i.e. the size of each constitutent part
198    pub is_regular: bool,
199}
200
201impl<A: Display> Display for PartitionAttr<A> {
202    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
203        let num_parts_str = match &self.num_parts {
204            Range::Single(x) => format!("numParts {x}"),
205            Range::Bounded(l, r) => format!("minNumParts {l}, maxNumParts {r}"),
206            Range::UnboundedL(r) => format!("maxNumParts {r}"),
207            Range::UnboundedR(l) => format!("minNumParts {l}"),
208            Range::Unbounded => "".to_string(),
209        };
210
211        let part_len_str = match &self.part_len {
212            Range::Single(x) => format!("partSize {x}"),
213            Range::Bounded(l, r) => format!("minPartSize {l} , maxPartSize {r}"),
214            Range::UnboundedL(r) => format!("maxPartSize {r}"),
215            Range::UnboundedR(l) => format!("minPartSize {l}"),
216            Range::Unbounded => "".to_string(),
217        };
218
219        let regular_str = match &self.is_regular {
220            true => "regular".to_string(),
221            false => String::new(),
222        };
223
224        let mut strs = [num_parts_str, part_len_str, regular_str]
225            .iter()
226            .filter(|s| !s.is_empty())
227            .join(", ");
228        if !strs.is_empty() {
229            strs = format!("({})", strs);
230        }
231        write!(f, "{strs}")
232    }
233}
234
235impl<A> Default for PartitionAttr<A> {
236    fn default() -> Self {
237        PartitionAttr {
238            num_parts: Range::Unbounded,
239            part_len: Range::Unbounded,
240            is_regular: false,
241        }
242    }
243}
244
245#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
246pub enum PartialityAttr {
247    Total,
248    Partial,
249}
250
251impl Display for PartialityAttr {
252    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
253        match self {
254            PartialityAttr::Total => write!(f, "total"),
255            PartialityAttr::Partial => write!(f, ""),
256        }
257    }
258}
259
260#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
261pub enum JectivityAttr {
262    None,
263    Injective,
264    Surjective,
265    Bijective,
266}
267
268impl Display for JectivityAttr {
269    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
270        match self {
271            JectivityAttr::None => write!(f, ""),
272            JectivityAttr::Injective => write!(f, "injective"),
273            JectivityAttr::Surjective => write!(f, "surjective"),
274            JectivityAttr::Bijective => write!(f, "bijective"),
275        }
276    }
277}
278
279#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
280#[path_prefix(conjure_cp::ast)]
281pub struct RelAttr<A = Int> {
282    pub size: Range<A>,
283    pub binary: Vec<BinaryAttr>,
284}
285
286impl<A> Default for RelAttr<A> {
287    fn default() -> Self {
288        RelAttr {
289            size: Range::Unbounded,
290            binary: Vec::new(),
291        }
292    }
293}
294
295impl<A: Display> Display for RelAttr<A> {
296    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
297        let size_str = match &self.size {
298            Range::Single(x) => format!("size {x}"),
299            Range::Bounded(l, r) => format!("minSize {l}, maxSize {r}"),
300            Range::UnboundedL(r) => format!("maxSize {r}"),
301            Range::UnboundedR(l) => format!("minSize {l}"),
302            Range::Unbounded => "".to_string(),
303        };
304        let mut strs = [size_str, self.binary.iter().join(", ")]
305            .iter()
306            .filter(|s| !s.is_empty())
307            .join(", ");
308        if !strs.is_empty() {
309            strs = format!("({})", strs);
310        }
311        write!(f, "{strs}")
312    }
313}
314
315#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
316pub enum BinaryAttr {
317    Reflexive,
318    Irreflexive,
319    Coreflexive,
320    Symmetric,
321    AntiSymmetric,
322    ASymmetric,
323    Transitive,
324    Total,
325    Connex,
326    Euclidean,
327    Serial,
328    Equivalence,
329    PartialOrder,
330}
331
332impl Display for BinaryAttr {
333    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
334        match self {
335            BinaryAttr::Reflexive => write!(f, "reflexive"),
336            BinaryAttr::Irreflexive => write!(f, "irreflexive"),
337            BinaryAttr::Coreflexive => write!(f, "coreflexive"),
338            BinaryAttr::Symmetric => write!(f, "symmetric"),
339            BinaryAttr::AntiSymmetric => write!(f, "antiSymmetric"),
340            BinaryAttr::ASymmetric => write!(f, "aSymmetric"),
341            BinaryAttr::Transitive => write!(f, "transitive"),
342            BinaryAttr::Total => write!(f, "total"),
343            BinaryAttr::Connex => write!(f, "connex"),
344            BinaryAttr::Euclidean => write!(f, "Euclidean"),
345            BinaryAttr::Serial => write!(f, "serial"),
346            BinaryAttr::Equivalence => write!(f, "equivalence"),
347            BinaryAttr::PartialOrder => write!(f, "partialOrder"),
348        }
349    }
350}