Skip to main content

conjure_cp_core/ast/domains/
attrs.rs

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