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 pub representation: Option<String>,
18}
19
20impl<A> SetAttr<A> {
21 pub fn new(size: Range<A>) -> Self {
22 Self {
23 size,
24 representation: None,
25 }
26 }
27
28 pub fn new_min_max_size(min: A, max: A) -> Self {
29 Self::new(Range::Bounded(min, max))
30 }
31
32 pub fn new_min_size(min: A) -> Self {
33 Self::new(Range::UnboundedR(min))
34 }
35
36 pub fn new_max_size(max: A) -> Self {
37 Self::new(Range::UnboundedL(max))
38 }
39
40 pub fn new_size(sz: A) -> Self {
41 Self::new(Range::Single(sz))
42 }
43
44 pub fn with_representation(mut self, name: impl Into<String>) -> Self {
46 self.representation = Some(name.into());
47 self
48 }
49}
50
51impl<A> Default for SetAttr<A> {
52 fn default() -> Self {
53 SetAttr {
54 size: Range::Unbounded,
55 representation: None,
56 }
57 }
58}
59
60impl<A: Display> Display for SetAttr<A> {
61 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
62 let mut attrs = Vec::new();
63 if let Some(representation) = &self.representation {
64 attrs.push(format!("representation {representation}"));
65 }
66 let size = fmt_size("size", &self.size);
67 if !size.is_empty() {
68 attrs.push(size);
69 }
70 if attrs.is_empty() {
71 Ok(())
72 } else {
73 write!(f, "({})", attrs.join(", "))
74 }
75 }
76}
77
78#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, FuncMap, TryFuncMap, Quine)]
79#[path_prefix(conjure_cp::ast)]
80pub struct MSetAttr<A = Int> {
81 pub size: Range<A>,
82 pub occurrence: Range<A>,
83 #[serde(default)]
88 pub representation: Option<String>,
89}
90
91impl<A> MSetAttr<A> {
92 pub fn new(size: Range<A>, occurrence: Range<A>) -> Self {
93 Self {
94 size,
95 occurrence,
96 representation: None,
97 }
98 }
99
100 pub fn new_min_max_size(min: A, max: A) -> Self {
101 Self::new(Range::Bounded(min, max), Range::Unbounded)
102 }
103
104 pub fn new_min_size(min: A) -> Self {
105 Self::new(Range::UnboundedR(min), Range::Unbounded)
106 }
107
108 pub fn new_max_size(max: A) -> Self {
109 Self::new(Range::UnboundedL(max), Range::Unbounded)
110 }
111
112 pub fn new_size(sz: A) -> Self {
113 Self::new(Range::Single(sz), Range::Unbounded)
114 }
115
116 pub fn with_representation(mut self, name: impl Into<String>) -> Self {
118 self.representation = Some(name.into());
119 self
120 }
121}
122
123impl<A: Display> Display for MSetAttr<A> {
124 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
125 let size_str = fmt_size("size", &self.size);
126
127 let occ_str = match &self.occurrence {
130 Range::Single(x) => format!("minOccur({x}), maxOccur({x})"),
131 Range::Bounded(l, r) => format!("minOccur({l}), maxOccur({r})"),
132 Range::UnboundedL(r) => format!("maxOccur({r})"),
133 Range::UnboundedR(l) => format!("minOccur({l})"),
134 Range::Unbounded => "".to_string(),
135 };
136
137 let representation_str = self
138 .representation
139 .as_ref()
140 .map(|name| format!("representation {name}"))
141 .unwrap_or_default();
142 let mut strs = [representation_str, size_str, occ_str]
143 .iter()
144 .filter(|s| !s.is_empty())
145 .join(", ");
146 if !strs.is_empty() {
147 strs = format!("({})", strs);
148 }
149 write!(f, "{strs}")
150 }
151}
152
153impl<A> Default for MSetAttr<A> {
154 fn default() -> Self {
155 MSetAttr {
156 size: Range::Unbounded,
157 occurrence: Range::Unbounded,
158 representation: None,
159 }
160 }
161}
162
163#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, FuncMap, TryFuncMap, Quine)]
164#[path_prefix(conjure_cp::ast)]
165pub struct FuncAttr<A = Int> {
166 pub size: Range<A>,
167 pub partiality: PartialityAttr,
168 pub jectivity: JectivityAttr,
169}
170
171impl<A> Default for FuncAttr<A> {
172 fn default() -> Self {
173 FuncAttr {
174 size: Range::Unbounded,
175 partiality: PartialityAttr::Partial,
178 jectivity: JectivityAttr::None,
179 }
180 }
181}
182
183impl<A: Display> Display for FuncAttr<A> {
184 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
185 let size_str = fmt_size("size", &self.size);
186 let mut strs = [
187 size_str,
188 self.partiality.to_string(),
189 self.jectivity.to_string(),
190 ]
191 .iter()
192 .filter(|s| !s.is_empty())
193 .join(", ");
194 if !strs.is_empty() {
195 strs = format!("({})", strs);
196 }
197 write!(f, "{strs}")
198 }
199}
200
201#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, FuncMap, TryFuncMap, Quine)]
202#[path_prefix(conjure_cp::ast)]
203pub struct SequenceAttr<A = Int> {
204 pub size: Range<A>,
205 pub jectivity: JectivityAttr,
206 pub representation: Option<String>,
211}
212
213impl<A> SequenceAttr<A> {
214 pub fn with_representation(mut self, name: impl Into<String>) -> Self {
216 self.representation = Some(name.into());
217 self
218 }
219}
220
221impl<A> Default for SequenceAttr<A> {
222 fn default() -> Self {
223 SequenceAttr {
224 size: Range::Unbounded,
225 jectivity: JectivityAttr::None,
226 representation: None,
227 }
228 }
229}
230
231impl<A: Display> Display for SequenceAttr<A> {
232 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
233 let size_str = fmt_size("size", &self.size);
234 let mut strs = [size_str, self.jectivity.to_string()]
235 .iter()
236 .filter(|s| !s.is_empty())
237 .join(", ");
238 if !strs.is_empty() {
239 strs = format!("({})", strs);
240 }
241 write!(f, "{strs}")
242 }
243}
244
245#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, FuncMap, TryFuncMap, Quine)]
246#[path_prefix(conjure_cp::ast)]
247pub struct PartitionAttr<A = Int> {
248 pub num_parts: Range<A>, pub part_len: Range<A>, pub is_regular: bool,
251}
252
253impl<A: Display> Display for PartitionAttr<A> {
254 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
255 let num_parts_str = fmt_size("numParts", &self.num_parts);
256 let part_len_str = fmt_size("partSize", &self.part_len);
257
258 let regular_str = match &self.is_regular {
259 true => "regular".to_string(),
260 false => String::new(),
261 };
262
263 let mut strs = [num_parts_str, part_len_str, regular_str]
264 .iter()
265 .filter(|s| !s.is_empty())
266 .join(", ");
267 if !strs.is_empty() {
268 strs = format!("({})", strs);
269 }
270 write!(f, "{strs}")
271 }
272}
273
274impl<A> Default for PartitionAttr<A> {
275 fn default() -> Self {
276 PartitionAttr {
277 num_parts: Range::Unbounded,
278 part_len: Range::Unbounded,
279 is_regular: false,
280 }
281 }
282}
283
284#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, FuncMap, TryFuncMap, Quine)]
290#[path_prefix(conjure_cp::ast)]
291pub struct PermutationAttr<A = Int> {
292 pub num_moved: Range<A>,
293}
294
295impl<A: Display> Display for PermutationAttr<A> {
296 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
297 let size_str = fmt_size("numMoved", &self.num_moved);
298 write!(f, "{size_str}")
299 }
300}
301
302impl<A> Default for PermutationAttr<A> {
303 fn default() -> Self {
304 PermutationAttr {
305 num_moved: Range::Unbounded,
306 }
307 }
308}
309
310#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
311pub enum PartialityAttr {
312 Total,
313 Partial,
314}
315
316impl Display for PartialityAttr {
317 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
318 match self {
319 PartialityAttr::Total => write!(f, "total"),
320 PartialityAttr::Partial => write!(f, ""),
321 }
322 }
323}
324
325#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
326pub enum JectivityAttr {
327 None,
328 Injective,
329 Surjective,
330 Bijective,
331}
332
333impl Display for JectivityAttr {
334 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
335 match self {
336 JectivityAttr::None => write!(f, ""),
337 JectivityAttr::Injective => write!(f, "injective"),
338 JectivityAttr::Surjective => write!(f, "surjective"),
339 JectivityAttr::Bijective => write!(f, "bijective"),
340 }
341 }
342}
343
344#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, FuncMap, TryFuncMap, Quine)]
345#[path_prefix(conjure_cp::ast)]
346pub struct RelAttr<A = Int> {
347 pub size: Range<A>,
348 pub binary: Vec<BinaryAttr>,
349}
350
351impl<A> Default for RelAttr<A> {
352 fn default() -> Self {
353 RelAttr {
354 size: Range::Unbounded,
355 binary: Vec::new(),
356 }
357 }
358}
359
360impl<A: Display> Display for RelAttr<A> {
361 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
362 let size_str = fmt_size("size", &self.size);
363 let mut strs = [size_str, self.binary.iter().join(", ")]
364 .iter()
365 .filter(|s| !s.is_empty())
366 .join(", ");
367 if !strs.is_empty() {
368 strs = format!("({})", strs);
369 }
370 write!(f, "{strs}")
371 }
372}
373
374#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
375pub enum BinaryAttr {
376 Reflexive,
377 Irreflexive,
378 Coreflexive,
379 Symmetric,
380 AntiSymmetric,
381 ASymmetric,
382 Transitive,
383 Total,
384 Connex,
385 Euclidean,
386 Serial,
387 Equivalence,
388 PartialOrder,
389 LeftTotal,
390 RightTotal,
391 LinearOrder,
392 WeakOrder,
393 PreOrder,
394 StrictPartialOrder,
395}
396
397impl Display for BinaryAttr {
398 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
399 match self {
400 BinaryAttr::Reflexive => write!(f, "reflexive"),
401 BinaryAttr::Irreflexive => write!(f, "irreflexive"),
402 BinaryAttr::Coreflexive => write!(f, "coreflexive"),
403 BinaryAttr::Symmetric => write!(f, "symmetric"),
404 BinaryAttr::AntiSymmetric => write!(f, "antiSymmetric"),
405 BinaryAttr::ASymmetric => write!(f, "aSymmetric"),
406 BinaryAttr::Transitive => write!(f, "transitive"),
407 BinaryAttr::Total => write!(f, "total"),
408 BinaryAttr::Connex => write!(f, "connex"),
409 BinaryAttr::Euclidean => write!(f, "Euclidean"),
410 BinaryAttr::Serial => write!(f, "serial"),
411 BinaryAttr::Equivalence => write!(f, "equivalence"),
412 BinaryAttr::PartialOrder => write!(f, "partialOrder"),
413 BinaryAttr::LeftTotal => write!(f, "leftTotal"),
414 BinaryAttr::RightTotal => write!(f, "rightTotal"),
415 BinaryAttr::LinearOrder => write!(f, "linearOrder"),
416 BinaryAttr::WeakOrder => write!(f, "weakOrder"),
417 BinaryAttr::PreOrder => write!(f, "preOrder"),
418 BinaryAttr::StrictPartialOrder => write!(f, "strictPartialOrder"),
419 }
420 }
421}
422
423impl BinaryAttr {
424 pub fn from_keyword(s: &str) -> Option<Self> {
428 Some(match s {
429 "reflexive" => BinaryAttr::Reflexive,
430 "irreflexive" => BinaryAttr::Irreflexive,
431 "coreflexive" => BinaryAttr::Coreflexive,
432 "symmetric" => BinaryAttr::Symmetric,
433 "antiSymmetric" => BinaryAttr::AntiSymmetric,
434 "aSymmetric" => BinaryAttr::ASymmetric,
435 "transitive" => BinaryAttr::Transitive,
436 "total" => BinaryAttr::Total,
437 "connex" => BinaryAttr::Connex,
438 "Euclidean" => BinaryAttr::Euclidean,
439 "serial" => BinaryAttr::Serial,
440 "equivalence" => BinaryAttr::Equivalence,
441 "partialOrder" => BinaryAttr::PartialOrder,
442 "leftTotal" => BinaryAttr::LeftTotal,
443 "rightTotal" => BinaryAttr::RightTotal,
444 "linearOrder" => BinaryAttr::LinearOrder,
445 "weakOrder" => BinaryAttr::WeakOrder,
446 "preOrder" => BinaryAttr::PreOrder,
447 "strictPartialOrder" => BinaryAttr::StrictPartialOrder,
448 _ => return None,
449 })
450 }
451}
452
453#[inline]
455fn fmt_size<A: Display>(suffix: &str, sz: &Range<A>) -> String {
456 let cap_suffix = capitalize(suffix);
457 match sz {
458 Range::Single(x) => format!("{suffix} {x}"),
459 Range::Bounded(l, r) => format!("min{cap_suffix} {l}, max{cap_suffix} {r}"),
460 Range::UnboundedL(r) => format!("max{cap_suffix} {r}"),
461 Range::UnboundedR(l) => format!("min{cap_suffix} {l}"),
462 Range::Unbounded => "".to_string(),
463 }
464}
465
466#[inline]
467fn capitalize(s: &str) -> String {
468 let mut c = s.chars();
469 match c.next() {
470 None => String::new(),
471 Some(f) => f.to_uppercase().to_string() + c.as_str(),
472 }
473}