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 pub representation: Option<String>,
174}
175
176impl<A> FuncAttr<A> {
177 pub fn with_representation(mut self, name: impl Into<String>) -> Self {
179 self.representation = Some(name.into());
180 self
181 }
182}
183
184impl<A> Default for FuncAttr<A> {
185 fn default() -> Self {
186 FuncAttr {
187 size: Range::Unbounded,
188 partiality: PartialityAttr::Partial,
191 jectivity: JectivityAttr::None,
192 representation: None,
193 }
194 }
195}
196
197impl<A: Display> Display for FuncAttr<A> {
198 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
199 let size_str = fmt_size("size", &self.size);
200 let mut strs = [
201 fmt_representation(&self.representation),
202 size_str,
203 self.partiality.to_string(),
204 self.jectivity.to_string(),
205 ]
206 .iter()
207 .filter(|s| !s.is_empty())
208 .join(", ");
209 if !strs.is_empty() {
210 strs = format!("({})", strs);
211 }
212 write!(f, "{strs}")
213 }
214}
215
216#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, FuncMap, TryFuncMap, Quine)]
217#[path_prefix(conjure_cp::ast)]
218pub struct SequenceAttr<A = Int> {
219 pub size: Range<A>,
220 pub jectivity: JectivityAttr,
221 pub representation: Option<String>,
226}
227
228impl<A> SequenceAttr<A> {
229 pub fn with_representation(mut self, name: impl Into<String>) -> Self {
231 self.representation = Some(name.into());
232 self
233 }
234}
235
236impl<A> Default for SequenceAttr<A> {
237 fn default() -> Self {
238 SequenceAttr {
239 size: Range::Unbounded,
240 jectivity: JectivityAttr::None,
241 representation: None,
242 }
243 }
244}
245
246impl<A: Display> Display for SequenceAttr<A> {
247 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
248 let size_str = fmt_size("size", &self.size);
249 let mut strs = [
250 fmt_representation(&self.representation),
251 size_str,
252 self.jectivity.to_string(),
253 ]
254 .iter()
255 .filter(|s| !s.is_empty())
256 .join(", ");
257 if !strs.is_empty() {
258 strs = format!("({})", strs);
259 }
260 write!(f, "{strs}")
261 }
262}
263
264#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, FuncMap, TryFuncMap, Quine)]
265#[path_prefix(conjure_cp::ast)]
266pub struct PartitionAttr<A = Int> {
267 pub num_parts: Range<A>, pub part_len: Range<A>, pub is_regular: bool,
270 pub representation: Option<String>,
275}
276
277impl<A> PartitionAttr<A> {
278 pub fn with_representation(mut self, name: impl Into<String>) -> Self {
280 self.representation = Some(name.into());
281 self
282 }
283}
284
285impl<A: Display> Display for PartitionAttr<A> {
286 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
287 let num_parts_str = fmt_size("numParts", &self.num_parts);
288 let part_len_str = fmt_size("partSize", &self.part_len);
289
290 let regular_str = match &self.is_regular {
291 true => "regular".to_string(),
292 false => String::new(),
293 };
294
295 let mut strs = [
296 fmt_representation(&self.representation),
297 num_parts_str,
298 part_len_str,
299 regular_str,
300 ]
301 .iter()
302 .filter(|s| !s.is_empty())
303 .join(", ");
304 if !strs.is_empty() {
305 strs = format!("({})", strs);
306 }
307 write!(f, "{strs}")
308 }
309}
310
311impl<A> Default for PartitionAttr<A> {
312 fn default() -> Self {
313 PartitionAttr {
314 num_parts: Range::Unbounded,
315 part_len: Range::Unbounded,
316 is_regular: false,
317 representation: None,
318 }
319 }
320}
321
322#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, FuncMap, TryFuncMap, Quine)]
328#[path_prefix(conjure_cp::ast)]
329pub struct PermutationAttr<A = Int> {
330 pub num_moved: Range<A>,
331 pub representation: Option<String>,
336}
337
338impl<A> PermutationAttr<A> {
339 pub fn with_representation(mut self, name: impl Into<String>) -> Self {
341 self.representation = Some(name.into());
342 self
343 }
344}
345
346impl<A: Display> Display for PermutationAttr<A> {
347 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
348 let size_str = fmt_size("numMoved", &self.num_moved);
349 match &self.representation {
350 None => write!(f, "{size_str}"),
352 Some(representation) if size_str.is_empty() => {
353 write!(f, "(representation {representation})")
354 }
355 Some(representation) => write!(f, "(representation {representation}, {size_str})"),
356 }
357 }
358}
359
360impl<A> Default for PermutationAttr<A> {
361 fn default() -> Self {
362 PermutationAttr {
363 num_moved: Range::Unbounded,
364 representation: None,
365 }
366 }
367}
368
369#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
370pub enum PartialityAttr {
371 Total,
372 Partial,
373}
374
375impl Display for PartialityAttr {
376 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
377 match self {
378 PartialityAttr::Total => write!(f, "total"),
379 PartialityAttr::Partial => write!(f, ""),
380 }
381 }
382}
383
384#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
385pub enum JectivityAttr {
386 None,
387 Injective,
388 Surjective,
389 Bijective,
390}
391
392impl Display for JectivityAttr {
393 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
394 match self {
395 JectivityAttr::None => write!(f, ""),
396 JectivityAttr::Injective => write!(f, "injective"),
397 JectivityAttr::Surjective => write!(f, "surjective"),
398 JectivityAttr::Bijective => write!(f, "bijective"),
399 }
400 }
401}
402
403#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, FuncMap, TryFuncMap, Quine)]
404#[path_prefix(conjure_cp::ast)]
405pub struct RelAttr<A = Int> {
406 pub size: Range<A>,
407 pub binary: Vec<BinaryAttr>,
408 pub representation: Option<String>,
413}
414
415impl<A> RelAttr<A> {
416 pub fn with_representation(mut self, name: impl Into<String>) -> Self {
418 self.representation = Some(name.into());
419 self
420 }
421}
422
423impl<A> Default for RelAttr<A> {
424 fn default() -> Self {
425 RelAttr {
426 size: Range::Unbounded,
427 binary: Vec::new(),
428 representation: None,
429 }
430 }
431}
432
433impl<A: Display> Display for RelAttr<A> {
434 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
435 let size_str = fmt_size("size", &self.size);
436 let mut strs = [
437 fmt_representation(&self.representation),
438 size_str,
439 self.binary.iter().join(", "),
440 ]
441 .iter()
442 .filter(|s| !s.is_empty())
443 .join(", ");
444 if !strs.is_empty() {
445 strs = format!("({})", strs);
446 }
447 write!(f, "{strs}")
448 }
449}
450
451#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
452pub enum BinaryAttr {
453 Reflexive,
454 Irreflexive,
455 Coreflexive,
456 Symmetric,
457 AntiSymmetric,
458 ASymmetric,
459 Transitive,
460 Total,
461 Connex,
462 Euclidean,
463 Serial,
464 Equivalence,
465 PartialOrder,
466 LeftTotal,
467 RightTotal,
468 LinearOrder,
469 WeakOrder,
470 PreOrder,
471 StrictPartialOrder,
472}
473
474impl Display for BinaryAttr {
475 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
476 match self {
477 BinaryAttr::Reflexive => write!(f, "reflexive"),
478 BinaryAttr::Irreflexive => write!(f, "irreflexive"),
479 BinaryAttr::Coreflexive => write!(f, "coreflexive"),
480 BinaryAttr::Symmetric => write!(f, "symmetric"),
481 BinaryAttr::AntiSymmetric => write!(f, "antiSymmetric"),
482 BinaryAttr::ASymmetric => write!(f, "aSymmetric"),
483 BinaryAttr::Transitive => write!(f, "transitive"),
484 BinaryAttr::Total => write!(f, "total"),
485 BinaryAttr::Connex => write!(f, "connex"),
486 BinaryAttr::Euclidean => write!(f, "Euclidean"),
487 BinaryAttr::Serial => write!(f, "serial"),
488 BinaryAttr::Equivalence => write!(f, "equivalence"),
489 BinaryAttr::PartialOrder => write!(f, "partialOrder"),
490 BinaryAttr::LeftTotal => write!(f, "leftTotal"),
491 BinaryAttr::RightTotal => write!(f, "rightTotal"),
492 BinaryAttr::LinearOrder => write!(f, "linearOrder"),
493 BinaryAttr::WeakOrder => write!(f, "weakOrder"),
494 BinaryAttr::PreOrder => write!(f, "preOrder"),
495 BinaryAttr::StrictPartialOrder => write!(f, "strictPartialOrder"),
496 }
497 }
498}
499
500impl BinaryAttr {
501 pub fn from_keyword(s: &str) -> Option<Self> {
505 Some(match s {
506 "reflexive" => BinaryAttr::Reflexive,
507 "irreflexive" => BinaryAttr::Irreflexive,
508 "coreflexive" => BinaryAttr::Coreflexive,
509 "symmetric" => BinaryAttr::Symmetric,
510 "antiSymmetric" => BinaryAttr::AntiSymmetric,
511 "aSymmetric" => BinaryAttr::ASymmetric,
512 "transitive" => BinaryAttr::Transitive,
513 "total" => BinaryAttr::Total,
514 "connex" => BinaryAttr::Connex,
515 "Euclidean" => BinaryAttr::Euclidean,
516 "serial" => BinaryAttr::Serial,
517 "equivalence" => BinaryAttr::Equivalence,
518 "partialOrder" => BinaryAttr::PartialOrder,
519 "leftTotal" => BinaryAttr::LeftTotal,
520 "rightTotal" => BinaryAttr::RightTotal,
521 "linearOrder" => BinaryAttr::LinearOrder,
522 "weakOrder" => BinaryAttr::WeakOrder,
523 "preOrder" => BinaryAttr::PreOrder,
524 "strictPartialOrder" => BinaryAttr::StrictPartialOrder,
525 _ => return None,
526 })
527 }
528}
529
530fn fmt_representation(representation: &Option<String>) -> String {
532 match representation {
533 Some(representation) => format!("representation {representation}"),
534 None => String::new(),
535 }
536}
537
538#[inline]
540fn fmt_size<A: Display>(suffix: &str, sz: &Range<A>) -> String {
541 let cap_suffix = capitalize(suffix);
542 match sz {
543 Range::Single(x) => format!("{suffix} {x}"),
544 Range::Bounded(l, r) => format!("min{cap_suffix} {l}, max{cap_suffix} {r}"),
545 Range::UnboundedL(r) => format!("max{cap_suffix} {r}"),
546 Range::UnboundedR(l) => format!("min{cap_suffix} {l}"),
547 Range::Unbounded => "".to_string(),
548 }
549}
550
551#[inline]
552fn capitalize(s: &str) -> String {
553 let mut c = s.chars();
554 match c.next() {
555 None => String::new(),
556 Some(f) => f.to_uppercase().to_string() + c.as_str(),
557 }
558}