1use funcmap::FuncMap;
2use itertools::Itertools;
3use serde::{Deserialize, Serialize};
4use std::cmp::Ordering;
5use std::fmt::{Debug, Display, Formatter};
6use std::hash::Hash;
7use ustr::Ustr;
8
9use super::{
10 Atom, Domain, DomainPtr, Expression, GroundDomain, Metadata, Moo, PartitionAttr,
11 PermutationAttr, Range, ReturnType, SetAttr, Typeable, domains::HasDomain, domains::Int,
12 records::Field,
13};
14use crate::ast::domains::{MSetAttr, SequenceAttr};
15use crate::ast::pretty::pretty_vec;
16use crate::bug;
17use crate::bug_assert;
18use polyquine::Quine;
19use uniplate::{Biplate, Tree, Uniplate};
20
21#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate, Hash, Quine)]
22#[uniplate(walk_into=[AbstractLiteral<Literal>])]
23#[biplate(to=Atom)]
24#[biplate(to=AbstractLiteral<Literal>)]
25#[biplate(to=AbstractLiteral<Expression>)]
26#[biplate(to=Field<Literal>)]
27#[biplate(to=Field<Expression>)]
28#[biplate(to=Expression)]
29#[path_prefix(conjure_cp::ast)]
30pub enum Literal {
32 Int(i32),
33 Bool(bool),
34 #[allow(clippy::enum_variant_names)]
36 AbstractLiteral(AbstractLiteral<Literal>),
37}
38
39impl HasDomain for Literal {
40 fn domain_of(&self) -> DomainPtr {
41 match self {
42 Literal::Int(i) => Domain::int(vec![Range::Single(*i)]),
43 Literal::Bool(_) => Domain::bool(),
44 Literal::AbstractLiteral(abstract_literal) => abstract_literal.domain_of(),
45 }
46 }
47}
48
49impl Literal {
50 pub fn essence_cmp(&self, other: &Self) -> Ordering {
56 match (self, other) {
57 (Literal::Bool(lhs), Literal::Bool(rhs)) => lhs.cmp(rhs),
58 (Literal::Int(lhs), Literal::Int(rhs)) => lhs.cmp(rhs),
59 (Literal::AbstractLiteral(lhs), Literal::AbstractLiteral(rhs)) => {
60 abstract_literal_essence_cmp(lhs, rhs)
61 }
62 _ => literal_kind(self).cmp(&literal_kind(other)),
63 }
64 }
65}
66
67fn literal_kind(literal: &Literal) -> u8 {
68 match literal {
69 Literal::Bool(_) => 0,
70 Literal::Int(_) => 1,
71 Literal::AbstractLiteral(_) => 2,
72 }
73}
74
75fn abstract_literal_essence_cmp(
76 lhs: &AbstractLiteral<Literal>,
77 rhs: &AbstractLiteral<Literal>,
78) -> Ordering {
79 match (lhs, rhs) {
80 (AbstractLiteral::Set(lhs), AbstractLiteral::Set(rhs)) => set_essence_cmp(lhs, rhs),
81 (AbstractLiteral::MSet(lhs), AbstractLiteral::MSet(rhs)) => sorted_literals_cmp(lhs, rhs),
82 (AbstractLiteral::Matrix(lhs, _), AbstractLiteral::Matrix(rhs, _))
83 | (AbstractLiteral::Tuple(lhs), AbstractLiteral::Tuple(rhs))
84 | (AbstractLiteral::Sequence(lhs), AbstractLiteral::Sequence(rhs)) => {
85 literal_slice_cmp(lhs, rhs)
86 }
87 (AbstractLiteral::Record(lhs), AbstractLiteral::Record(rhs)) => lhs
88 .iter()
89 .zip(rhs)
90 .find_map(|(lhs, rhs)| {
91 let ordering = lhs.name.to_string().cmp(&rhs.name.to_string());
92 (ordering != Ordering::Equal)
93 .then_some(ordering)
94 .or_else(|| {
95 let ordering = lhs.value.essence_cmp(&rhs.value);
96 (ordering != Ordering::Equal).then_some(ordering)
97 })
98 })
99 .unwrap_or_else(|| lhs.len().cmp(&rhs.len())),
100 (AbstractLiteral::Function(lhs), AbstractLiteral::Function(rhs)) => lhs
101 .iter()
102 .zip(rhs)
103 .find_map(|((lhs_from, lhs_to), (rhs_from, rhs_to))| {
104 let ordering = lhs_from.essence_cmp(rhs_from);
105 (ordering != Ordering::Equal)
106 .then_some(ordering)
107 .or_else(|| {
108 let ordering = lhs_to.essence_cmp(rhs_to);
109 (ordering != Ordering::Equal).then_some(ordering)
110 })
111 })
112 .unwrap_or_else(|| lhs.len().cmp(&rhs.len())),
113 (AbstractLiteral::Variant(lhs), AbstractLiteral::Variant(rhs)) => lhs
114 .name
115 .to_string()
116 .cmp(&rhs.name.to_string())
117 .then_with(|| lhs.value.essence_cmp(&rhs.value)),
118 (AbstractLiteral::Partition(lhs), AbstractLiteral::Partition(rhs))
119 | (AbstractLiteral::Relation(lhs), AbstractLiteral::Relation(rhs))
120 | (AbstractLiteral::Permutation(lhs), AbstractLiteral::Permutation(rhs)) => lhs
121 .iter()
122 .zip(rhs)
123 .find_map(|(lhs, rhs)| {
124 let ordering = literal_slice_cmp(lhs, rhs);
125 (ordering != Ordering::Equal).then_some(ordering)
126 })
127 .unwrap_or_else(|| lhs.len().cmp(&rhs.len())),
128 _ => abstract_literal_kind(lhs).cmp(&abstract_literal_kind(rhs)),
129 }
130}
131
132fn abstract_literal_kind(literal: &AbstractLiteral<Literal>) -> u8 {
133 match literal {
134 AbstractLiteral::Set(_) => 0,
135 AbstractLiteral::MSet(_) => 1,
136 AbstractLiteral::Matrix(..) => 2,
137 AbstractLiteral::Tuple(_) => 3,
138 AbstractLiteral::Record(_) => 4,
139 AbstractLiteral::Sequence(_) => 5,
140 AbstractLiteral::Function(_) => 6,
141 AbstractLiteral::Variant(_) => 7,
142 AbstractLiteral::Partition(_) => 8,
143 AbstractLiteral::Relation(_) => 9,
144 AbstractLiteral::Permutation(_) => 10,
145 }
146}
147
148fn literal_slice_cmp(lhs: &[Literal], rhs: &[Literal]) -> Ordering {
149 lhs.iter()
150 .zip(rhs)
151 .find_map(|(lhs, rhs)| {
152 let ordering = lhs.essence_cmp(rhs);
153 (ordering != Ordering::Equal).then_some(ordering)
154 })
155 .unwrap_or_else(|| lhs.len().cmp(&rhs.len()))
156}
157
158fn sorted_literals_cmp(lhs: &[Literal], rhs: &[Literal]) -> Ordering {
159 let mut lhs = lhs.iter().collect::<Vec<_>>();
160 let mut rhs = rhs.iter().collect::<Vec<_>>();
161 lhs.sort_by(|lhs, rhs| lhs.essence_cmp(rhs));
162 rhs.sort_by(|lhs, rhs| lhs.essence_cmp(rhs));
163 lhs.iter()
164 .zip(&rhs)
165 .find_map(|(lhs, rhs)| {
166 let ordering = lhs.essence_cmp(rhs);
167 (ordering != Ordering::Equal).then_some(ordering)
168 })
169 .unwrap_or_else(|| lhs.len().cmp(&rhs.len()))
170}
171
172fn set_essence_cmp(lhs: &[Literal], rhs: &[Literal]) -> Ordering {
174 let mut lhs = lhs.iter().collect::<Vec<_>>();
175 let mut rhs = rhs.iter().collect::<Vec<_>>();
176 lhs.sort_by(|lhs, rhs| lhs.essence_cmp(rhs));
177 rhs.sort_by(|lhs, rhs| lhs.essence_cmp(rhs));
178
179 let (mut lhs_index, mut rhs_index) = (0, 0);
180 while lhs_index < lhs.len() && rhs_index < rhs.len() {
181 match lhs[lhs_index].essence_cmp(rhs[rhs_index]) {
182 Ordering::Equal => {
183 lhs_index += 1;
184 rhs_index += 1;
185 }
186 Ordering::Less => return Ordering::Greater,
188 Ordering::Greater => return Ordering::Less,
190 }
191 }
192 match (lhs_index < lhs.len(), rhs_index < rhs.len()) {
193 (false, false) => Ordering::Equal,
194 (true, false) => Ordering::Greater,
195 (false, true) => Ordering::Less,
196 (true, true) => unreachable!(),
197 }
198}
199
200pub trait AbstractLiteralValue:
202 Clone + Eq + PartialEq + Display + Uniplate + Biplate<Field<Self>> + 'static
203{
204 type Dom: Clone
205 + Eq
206 + PartialEq
207 + Debug
208 + Display
209 + Quine
210 + From<GroundDomain>
211 + Into<DomainPtr>;
212
213 fn has_implied_list_domain(domain: &Self::Dom) -> bool;
215}
216impl AbstractLiteralValue for Expression {
217 type Dom = DomainPtr;
218
219 fn has_implied_list_domain(domain: &Self::Dom) -> bool {
220 let Domain::Ground(domain) = domain.as_ref() else {
221 return false;
222 };
223 matches!(domain.as_ref(), GroundDomain::Int(ranges) if ranges.as_slice() == [Range::UnboundedR(1)])
224 }
225}
226impl AbstractLiteralValue for Literal {
227 type Dom = Moo<GroundDomain>;
228
229 fn has_implied_list_domain(domain: &Self::Dom) -> bool {
230 matches!(domain.as_ref(), GroundDomain::Int(ranges) if ranges.as_slice() == [Range::UnboundedR(1)])
231 }
232}
233
234#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
235#[path_prefix(conjure_cp::ast)]
236pub enum AbstractLiteral<T: AbstractLiteralValue> {
237 Set(Vec<T>),
238
239 MSet(Vec<T>),
240
241 Matrix(Vec<T>, T::Dom),
243
244 Tuple(Vec<T>),
246
247 Record(Vec<Field<T>>),
248
249 Sequence(Vec<T>),
250
251 Function(Vec<(T, T)>),
252
253 Variant(Moo<Field<T>>),
255
256 Partition(Vec<Vec<T>>),
258 Relation(Vec<Vec<T>>),
259
260 Permutation(Vec<Vec<T>>),
264}
265
266fn union_item_domains(item_domains: Vec<DomainPtr>, literal_kind: &str) -> Option<DomainPtr> {
268 let mut item_domain_iter = item_domains.into_iter();
269 let first_item = item_domain_iter.next()?;
270
271 Some(
272 item_domain_iter
273 .try_fold(first_item, |x, y| x.union(&y))
274 .unwrap_or_else(|error| {
275 bug!(
276 "taking the union of all item domains of a {literal_kind} literal should succeed: {error}"
277 )
278 }),
279 )
280}
281
282impl AbstractLiteral<Expression> {
283 pub fn domain_of(&self) -> Option<DomainPtr> {
284 match self {
285 AbstractLiteral::Set(items) => {
286 let item_domains: Vec<DomainPtr> = items
288 .iter()
289 .map(|x| x.domain_of())
290 .collect::<Option<Vec<DomainPtr>>>()?;
291
292 let item_domain = union_item_domains(item_domains, "set")?;
294
295 Some(Domain::set(SetAttr::<Int>::default(), item_domain))
296 }
297
298 AbstractLiteral::MSet(items) => {
299 let cardinality = i32::try_from(items.len()).ok()?;
300 let item_domains: Vec<DomainPtr> = items
302 .iter()
303 .map(|x| x.domain_of())
304 .collect::<Option<Vec<DomainPtr>>>()?;
305
306 let item_domain = union_item_domains(item_domains, "mset")?;
308
309 let occurrence = if cardinality == 0 {
310 Range::Single(0)
311 } else {
312 Range::Bounded(1, cardinality)
313 };
314 Some(Domain::mset(
315 MSetAttr::new(Range::Single(cardinality), occurrence),
316 item_domain,
317 ))
318 }
319
320 AbstractLiteral::Sequence(elems) => {
321 let item_domains: Vec<DomainPtr> = elems
322 .iter()
323 .map(|x| x.domain_of())
324 .collect::<Option<Vec<DomainPtr>>>()?;
325
326 let item_domain = union_item_domains(item_domains, "sequence")?;
329
330 let size = Range::Single(i32::try_from(elems.len()).ok()?);
333 Some(Domain::sequence(
334 SequenceAttr::<Int> {
335 size,
336 ..SequenceAttr::default()
337 },
338 item_domain,
339 ))
340 }
341
342 AbstractLiteral::Partition(items) => {
343 let item_domains: Vec<DomainPtr> = items
347 .iter()
348 .flatten()
349 .map(|x| x.domain_of())
350 .collect::<Option<Vec<DomainPtr>>>()?;
351
352 let item_domain = union_item_domains(item_domains, "partition")?;
354
355 Some(Domain::partition(
356 PartitionAttr::<Int>::default(),
357 item_domain,
358 ))
359 }
360
361 AbstractLiteral::Permutation(cycles) => {
362 let item_domains: Vec<DomainPtr> = cycles
366 .iter()
367 .flatten()
368 .map(|x| x.domain_of())
369 .collect::<Option<Vec<DomainPtr>>>()?;
370
371 let item_domain = union_item_domains(item_domains, "permutation")?;
372
373 Some(Domain::permutation(
374 PermutationAttr::<Int>::default(),
375 item_domain,
376 ))
377 }
378
379 AbstractLiteral::Matrix(items, _) => {
380 let item_domains = items
382 .iter()
383 .map(|x| x.domain_of())
384 .collect::<Option<Vec<DomainPtr>>>()?;
385
386 let item_domain = union_item_domains(item_domains, "matrix")?;
388
389 let mut new_index_domain = vec![];
390
391 let mut e = Expression::AbstractLiteral(Metadata::new(), self.clone());
393 while let Expression::AbstractLiteral(_, AbstractLiteral::Matrix(elems, idx)) = e {
394 bug_assert!(
395 idx.as_matrix().is_none(),
396 "n-dimensional matrix literals should be represented as a matrix inside a matrix, got {idx}"
397 );
398 new_index_domain.push(idx);
399 e = elems[0].clone();
400 }
401 Some(Domain::matrix(item_domain, new_index_domain))
402 }
403 AbstractLiteral::Tuple(_) => None,
404 AbstractLiteral::Record(_) => None,
405 AbstractLiteral::Function(_) => None,
406 AbstractLiteral::Variant(_) => None,
407 AbstractLiteral::Relation(_) => None,
408 }
409 }
410}
411
412impl HasDomain for AbstractLiteral<Literal> {
413 fn domain_of(&self) -> DomainPtr {
414 Domain::from_literal_vec(&[Literal::AbstractLiteral(self.clone())])
415 .expect("abstract literals should be correctly typed")
416 }
417}
418
419impl Typeable for AbstractLiteral<Expression> {
420 fn return_type(&self) -> ReturnType {
421 match self {
422 AbstractLiteral::Set(items) if items.is_empty() => {
423 ReturnType::Set(Box::new(ReturnType::Unknown))
424 }
425 AbstractLiteral::Set(items) => {
426 let item_type = items[0].return_type();
427
428 let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
430
431 bug_assert!(
432 item_types.iter().all(|x| x == &item_type),
433 "all items in a set should have the same type"
434 );
435
436 ReturnType::Set(Box::new(item_type))
437 }
438 AbstractLiteral::MSet(items) if items.is_empty() => {
439 ReturnType::MSet(Box::new(ReturnType::Unknown))
440 }
441 AbstractLiteral::MSet(items) => {
442 let item_type = items[0].return_type();
443
444 let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
446
447 bug_assert!(
448 item_types.iter().all(|x| x == &item_type),
449 "all items in a set should have the same type"
450 );
451
452 ReturnType::MSet(Box::new(item_type))
453 }
454 AbstractLiteral::Sequence(items) if items.is_empty() => {
455 ReturnType::Sequence(Box::new(ReturnType::Unknown))
456 }
457 AbstractLiteral::Sequence(items) => {
458 let item_type = items[0].return_type();
459
460 let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
462
463 bug_assert!(
464 item_types.iter().all(|x| x == &item_type),
465 "all items in a sequence should have the same type"
466 );
467
468 ReturnType::Sequence(Box::new(item_type))
469 }
470 AbstractLiteral::Partition(items) if items.is_empty() || items[0].is_empty() => {
471 ReturnType::Partition(Box::new(ReturnType::Unknown))
472 }
473 AbstractLiteral::Partition(items) => {
474 let item_type = items[0][0].return_type();
475
476 let item_types: Vec<ReturnType> =
478 items.iter().flatten().map(|x| x.return_type()).collect();
479
480 bug_assert!(
481 item_types.iter().all(|x| x == &item_type),
482 "all items in every part of a partition should have the same type"
483 );
484
485 ReturnType::Partition(Box::new(item_type))
486 }
487 AbstractLiteral::Permutation(items) if items.is_empty() || items[0].is_empty() => {
488 ReturnType::Permutation(Box::new(ReturnType::Unknown))
489 }
490 AbstractLiteral::Permutation(items) => {
491 let item_type = items[0][0].return_type();
492
493 let item_types: Vec<ReturnType> =
494 items.iter().flatten().map(|x| x.return_type()).collect();
495
496 bug_assert!(
497 item_types.iter().all(|x| x == &item_type),
498 "all items in every cycle of a permutation should have the same type"
499 );
500
501 ReturnType::Permutation(Box::new(item_type))
502 }
503 AbstractLiteral::Matrix(items, _) if items.is_empty() => {
504 ReturnType::Matrix(Box::new(ReturnType::Unknown))
505 }
506 AbstractLiteral::Matrix(items, _) => {
507 let item_type = items[0].return_type();
508
509 let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
511
512 bug_assert!(
513 item_types.iter().all(|x| x == &item_type),
514 "all items in a matrix should have the same type. items: {items} types: {types:#?}",
515 items = pretty_vec(items),
516 types = items
517 .iter()
518 .map(|x| x.return_type())
519 .collect::<Vec<ReturnType>>()
520 );
521
522 ReturnType::Matrix(Box::new(item_type))
523 }
524 AbstractLiteral::Tuple(items) => {
525 let mut item_types = vec![];
526 for item in items {
527 item_types.push(item.return_type());
528 }
529 ReturnType::Tuple(item_types)
530 }
531 AbstractLiteral::Record(items) => {
532 let mut item_types = vec![];
533 for item in items {
534 item_types.push(item.clone().func_map(|x| x.return_type()));
535 }
536 ReturnType::Record(item_types)
537 }
538 AbstractLiteral::Function(items) => {
539 if items.is_empty() {
540 return ReturnType::Function(
541 Box::new(ReturnType::Unknown),
542 Box::new(ReturnType::Unknown),
543 );
544 }
545
546 let (x1, y1) = &items[0];
548 let (t1, t2) = (x1.return_type(), y1.return_type());
549 for (x, y) in items {
550 let (tx, ty) = (x.return_type(), y.return_type());
551 if tx != t1 {
552 bug!("Expected {t1}, got {x}: {tx}");
553 }
554 if ty != t2 {
555 bug!("Expected {t2}, got {y}: {ty}");
556 }
557 }
558
559 ReturnType::Function(Box::new(t1), Box::new(t2))
560 }
561 AbstractLiteral::Variant(item) => {
562 ReturnType::Variant(vec![item.as_ref().clone().func_map(|x| x.return_type())])
564 }
565 AbstractLiteral::Relation(items) => {
566 if items.is_empty() {
567 return ReturnType::Relation(vec![ReturnType::Unknown]);
568 }
569 let mut item_types = vec![];
570 let x1 = &items[0];
571 let size = x1.len();
572 for item in x1 {
573 item_types.push(item.return_type());
574 }
575 for x in items {
576 if x.len() != size {
577 let strs = item_types.iter().map(|x| format!("{}", x)).join(",");
578 bug!("Expected ({strs}) with length {size}, got size {}", x.len());
579 }
580 for i in 1..size {
581 if let Some(new_type) = x.get(i)
582 && let Some(old_type) = item_types.get(i)
583 && new_type.return_type() != *old_type
584 {
585 bug!("Expected {old_type}, got {new_type}");
586 }
587 }
588 }
589 ReturnType::Relation(item_types)
590 }
591 }
592 }
593}
594
595impl<T> AbstractLiteral<T>
596where
597 T: AbstractLiteralValue,
598{
599 pub fn matrix_implied_indices(elems: Vec<T>) -> Self {
603 AbstractLiteral::Matrix(elems, GroundDomain::Int(vec![Range::UnboundedR(1)]).into())
604 }
605
606 pub fn unwrap_list(&self) -> Option<&Vec<T>> {
611 let AbstractLiteral::Matrix(elems, domain) = self else {
612 return None;
613 };
614
615 T::has_implied_list_domain(domain).then_some(elems)
616 }
617
618 pub fn into_list(self) -> Option<Vec<T>> {
620 let AbstractLiteral::Matrix(elems, domain) = self else {
621 return None;
622 };
623
624 T::has_implied_list_domain(&domain).then_some(elems)
625 }
626}
627
628impl<T> Display for AbstractLiteral<T>
629where
630 T: AbstractLiteralValue,
631{
632 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
633 match self {
634 AbstractLiteral::Set(elems) => {
635 let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
636 write!(f, "{{{elems_str}}}")
637 }
638 AbstractLiteral::MSet(elems) => {
639 let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
640 write!(f, "mset({elems_str})")
641 }
642 AbstractLiteral::Matrix(elems, index_domain) => {
643 let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
644 write!(f, "[{elems_str};{index_domain}]")
645 }
646 AbstractLiteral::Tuple(elems) => {
647 let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
648 write!(f, "({elems_str})")
649 }
650 AbstractLiteral::Sequence(elems) => {
651 let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
652 write!(f, "sequence({elems_str})")
653 }
654 AbstractLiteral::Partition(parts) => {
655 let elems_str: String = parts
656 .iter()
657 .map(|inner| {
658 let elems_str = inner.iter().map(|x| format!("{x}")).join(",");
659 format!("{{{}}}", elems_str)
660 })
661 .join(", ");
662
663 write!(f, "partition({elems_str})")
664 }
665 AbstractLiteral::Permutation(cycles) => {
666 let cycles_str: String = cycles
667 .iter()
668 .map(|cycle| {
669 let elems_str = cycle.iter().map(|x| format!("{x}")).join(",");
670 format!("({elems_str})")
671 })
672 .join("");
673
674 write!(f, "permutation{cycles_str}")
675 }
676 AbstractLiteral::Record(entries) => {
677 let entries_str: String = entries
678 .iter()
679 .map(|entry| format!("{} = {}", entry.name, entry.value))
680 .join(",");
681 write!(f, "record {{{entries_str}}}")
682 }
683 AbstractLiteral::Function(entries) => {
684 let entries_str: String = entries
685 .iter()
686 .map(|entry| format!("{} --> {}", entry.0, entry.1))
687 .join(",");
688 write!(f, "function({entries_str})")
689 }
690 AbstractLiteral::Variant(entry) => {
691 write!(f, "variant{{{} = {}}}", entry.name, entry.value)
692 }
693 AbstractLiteral::Relation(elems) => {
694 let elems_str: String = elems
695 .iter()
696 .map(|x| format!("({})", x.iter().map(|x| format!("{x}")).join(",")))
697 .join(",");
698 write!(f, "relation({elems_str})")
699 }
700 }
701 }
702}
703
704impl<T> Uniplate for AbstractLiteral<T>
705where
706 T: AbstractLiteralValue + Biplate<AbstractLiteral<T>>,
707{
708 fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
709 match self {
711 AbstractLiteral::Set(vec) => {
712 let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(vec);
713 (f1_tree, Box::new(move |x| AbstractLiteral::Set(f1_ctx(x))))
714 }
715 AbstractLiteral::MSet(vec) => {
716 let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(vec);
717 (f1_tree, Box::new(move |x| AbstractLiteral::MSet(f1_ctx(x))))
718 }
719 AbstractLiteral::Matrix(elems, index_domain) => {
720 let index_domain = index_domain.clone();
721 let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
722 (
723 f1_tree,
724 Box::new(move |x| AbstractLiteral::Matrix(f1_ctx(x), index_domain.clone())),
725 )
726 }
727 AbstractLiteral::Sequence(vec) => {
728 let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(vec);
729 (
730 f1_tree,
731 Box::new(move |x| AbstractLiteral::Sequence(f1_ctx(x))),
732 )
733 }
734 AbstractLiteral::Tuple(elems) => {
735 let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
736 (
737 f1_tree,
738 Box::new(move |x| AbstractLiteral::Tuple(f1_ctx(x))),
739 )
740 }
741 AbstractLiteral::Record(entries) => {
742 let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(entries);
743 (
744 f1_tree,
745 Box::new(move |x| AbstractLiteral::Record(f1_ctx(x))),
746 )
747 }
748 AbstractLiteral::Function(entries) => {
749 let entry_count = entries.len();
750 let flattened: Vec<T> = entries
751 .iter()
752 .flat_map(|(lhs, rhs)| [lhs.clone(), rhs.clone()])
753 .collect();
754
755 let (f1_tree, f1_ctx) =
756 <Vec<T> as Biplate<AbstractLiteral<T>>>::biplate(&flattened);
757 (
758 f1_tree,
759 Box::new(move |x| {
760 let rebuilt = f1_ctx(x);
761 assert_eq!(
762 rebuilt.len(),
763 entry_count * 2,
764 "number of function literal children should remain unchanged"
765 );
766
767 let mut iter = rebuilt.into_iter();
768 let mut pairs = Vec::with_capacity(entry_count);
769 while let (Some(lhs), Some(rhs)) = (iter.next(), iter.next()) {
770 pairs.push((lhs, rhs));
771 }
772
773 AbstractLiteral::Function(pairs)
774 }),
775 )
776 }
777 AbstractLiteral::Variant(entries) => {
778 let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(entries);
779 (
780 f1_tree,
781 Box::new(move |x| AbstractLiteral::Variant(f1_ctx(x))),
782 )
783 }
784 AbstractLiteral::Relation(elems) => {
785 let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
786 (
787 f1_tree,
788 Box::new(move |x| AbstractLiteral::Relation(f1_ctx(x))),
789 )
790 }
791 AbstractLiteral::Partition(elems) => {
792 let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
793 (
794 f1_tree,
795 Box::new(move |x| AbstractLiteral::Partition(f1_ctx(x))),
796 )
797 }
798 AbstractLiteral::Permutation(elems) => {
799 let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
800 (
801 f1_tree,
802 Box::new(move |x| AbstractLiteral::Permutation(f1_ctx(x))),
803 )
804 }
805 }
806 }
807}
808
809impl<U, To> Biplate<To> for AbstractLiteral<U>
810where
811 To: Uniplate,
812 U: AbstractLiteralValue + Biplate<AbstractLiteral<U>> + Biplate<To>,
813 Field<U>: Biplate<AbstractLiteral<U>> + Biplate<To>,
814{
815 fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
816 if std::any::TypeId::of::<To>() == std::any::TypeId::of::<AbstractLiteral<U>>() {
817 unsafe {
820 let self_to = std::mem::transmute::<&AbstractLiteral<U>, &To>(self).clone();
822 let tree = Tree::One(self_to);
823 let ctx = Box::new(move |x| {
824 let Tree::One(x) = x else {
825 panic!();
826 };
827
828 std::mem::transmute::<&To, &AbstractLiteral<U>>(&x).clone()
829 });
830
831 (tree, ctx)
832 }
833 } else {
834 match self {
836 AbstractLiteral::Set(vec) => {
837 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
838 (f1_tree, Box::new(move |x| AbstractLiteral::Set(f1_ctx(x))))
839 }
840 AbstractLiteral::MSet(vec) => {
841 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
842 (f1_tree, Box::new(move |x| AbstractLiteral::MSet(f1_ctx(x))))
843 }
844 AbstractLiteral::Matrix(elems, index_domain) => {
845 let index_domain = index_domain.clone();
846 let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(elems);
847 (
848 f1_tree,
849 Box::new(move |x| AbstractLiteral::Matrix(f1_ctx(x), index_domain.clone())),
850 )
851 }
852 AbstractLiteral::Sequence(vec) => {
853 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
854 (
855 f1_tree,
856 Box::new(move |x| AbstractLiteral::Sequence(f1_ctx(x))),
857 )
858 }
859 AbstractLiteral::Tuple(elems) => {
860 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
861 (
862 f1_tree,
863 Box::new(move |x| AbstractLiteral::Tuple(f1_ctx(x))),
864 )
865 }
866 AbstractLiteral::Record(entries) => {
867 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(entries);
868 (
869 f1_tree,
870 Box::new(move |x| AbstractLiteral::Record(f1_ctx(x))),
871 )
872 }
873 AbstractLiteral::Function(entries) => {
874 let entry_count = entries.len();
875 let flattened: Vec<U> = entries
876 .iter()
877 .flat_map(|(lhs, rhs)| [lhs.clone(), rhs.clone()])
878 .collect();
879
880 let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(&flattened);
881 (
882 f1_tree,
883 Box::new(move |x| {
884 let rebuilt = f1_ctx(x);
885 assert_eq!(
886 rebuilt.len(),
887 entry_count * 2,
888 "number of function literal children should remain unchanged"
889 );
890
891 let mut iter = rebuilt.into_iter();
892 let mut pairs = Vec::with_capacity(entry_count);
893 while let (Some(lhs), Some(rhs)) = (iter.next(), iter.next()) {
894 pairs.push((lhs, rhs));
895 }
896
897 AbstractLiteral::Function(pairs)
898 }),
899 )
900 }
901 AbstractLiteral::Variant(entries) => {
902 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(entries);
903 (
904 f1_tree,
905 Box::new(move |x| AbstractLiteral::Variant(f1_ctx(x))),
906 )
907 }
908 AbstractLiteral::Relation(elems) => {
909 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
910 (
911 f1_tree,
912 Box::new(move |x| AbstractLiteral::Relation(f1_ctx(x))),
913 )
914 }
915 AbstractLiteral::Partition(elems) => {
916 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
917 (
918 f1_tree,
919 Box::new(move |x| AbstractLiteral::Partition(f1_ctx(x))),
920 )
921 }
922 AbstractLiteral::Permutation(elems) => {
923 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
924 (
925 f1_tree,
926 Box::new(move |x| AbstractLiteral::Permutation(f1_ctx(x))),
927 )
928 }
929 }
930 }
931 }
932
933 fn children_bi_count(&self) -> usize {
934 if std::any::TypeId::of::<To>() == std::any::TypeId::of::<AbstractLiteral<U>>() {
937 return 1;
938 }
939 match self {
940 AbstractLiteral::Set(v)
941 | AbstractLiteral::MSet(v)
942 | AbstractLiteral::Sequence(v)
943 | AbstractLiteral::Tuple(v)
944 | AbstractLiteral::Matrix(v, _) => <Vec<U> as Biplate<To>>::children_bi_count(v),
945 AbstractLiteral::Record(entries) => {
946 <Vec<Field<U>> as Biplate<To>>::children_bi_count(entries)
947 }
948 AbstractLiteral::Variant(entry) => {
949 <Moo<Field<U>> as Biplate<To>>::children_bi_count(entry)
950 }
951 AbstractLiteral::Relation(elems)
952 | AbstractLiteral::Partition(elems)
953 | AbstractLiteral::Permutation(elems) => {
954 <Vec<Vec<U>> as Biplate<To>>::children_bi_count(elems)
955 }
956 AbstractLiteral::Function(_) => <Self as Biplate<To>>::children_bi(self).len(),
957 }
958 }
959
960 fn try_replace_child_at_bi(&mut self, index: usize, child: To) -> bool {
961 if std::any::TypeId::of::<To>() == std::any::TypeId::of::<AbstractLiteral<U>>() {
963 if index != 0 {
964 return false;
965 }
966 unsafe {
968 let child_as_self = std::mem::transmute_copy::<To, AbstractLiteral<U>>(&child);
969 std::mem::forget(child);
970 *self = child_as_self;
971 }
972 return true;
973 }
974 match self {
975 AbstractLiteral::Set(v)
976 | AbstractLiteral::MSet(v)
977 | AbstractLiteral::Sequence(v)
978 | AbstractLiteral::Tuple(v)
979 | AbstractLiteral::Matrix(v, _) => {
980 <Vec<U> as Biplate<To>>::try_replace_child_at_bi(v, index, child)
981 }
982 AbstractLiteral::Record(entries) => {
983 <Vec<Field<U>> as Biplate<To>>::try_replace_child_at_bi(entries, index, child)
984 }
985 AbstractLiteral::Variant(entry) => {
986 <Moo<Field<U>> as Biplate<To>>::try_replace_child_at_bi(entry, index, child)
987 }
988 AbstractLiteral::Relation(elems)
989 | AbstractLiteral::Partition(elems)
990 | AbstractLiteral::Permutation(elems) => {
991 <Vec<Vec<U>> as Biplate<To>>::try_replace_child_at_bi(elems, index, child)
992 }
993 AbstractLiteral::Function(_) => {
994 let mut children = <Self as Biplate<To>>::children_bi(self);
995 if index >= children.len() {
996 return false;
997 }
998 children[index] = child;
999 *self = self.with_children_bi(children);
1000 true
1001 }
1002 }
1003 }
1004}
1005
1006impl TryFrom<Literal> for i32 {
1007 type Error = &'static str;
1008
1009 fn try_from(value: Literal) -> Result<Self, Self::Error> {
1010 match value {
1011 Literal::Int(i) => Ok(i),
1012 _ => Err("Cannot convert non-i32 literal to i32"),
1013 }
1014 }
1015}
1016
1017impl TryFrom<Box<Literal>> for i32 {
1018 type Error = &'static str;
1019
1020 fn try_from(value: Box<Literal>) -> Result<Self, Self::Error> {
1021 (*value).try_into()
1022 }
1023}
1024
1025impl TryFrom<&Box<Literal>> for i32 {
1026 type Error = &'static str;
1027
1028 fn try_from(value: &Box<Literal>) -> Result<Self, Self::Error> {
1029 TryFrom::<&Literal>::try_from(value.as_ref())
1030 }
1031}
1032
1033impl TryFrom<&Moo<Literal>> for i32 {
1034 type Error = &'static str;
1035
1036 fn try_from(value: &Moo<Literal>) -> Result<Self, Self::Error> {
1037 TryFrom::<&Literal>::try_from(value.as_ref())
1038 }
1039}
1040
1041impl TryFrom<&Literal> for i32 {
1042 type Error = &'static str;
1043
1044 fn try_from(value: &Literal) -> Result<Self, Self::Error> {
1045 match value {
1046 Literal::Int(i) => Ok(*i),
1047 _ => Err("Cannot convert non-i32 literal to i32"),
1048 }
1049 }
1050}
1051
1052impl TryFrom<Literal> for bool {
1053 type Error = &'static str;
1054
1055 fn try_from(value: Literal) -> Result<Self, Self::Error> {
1056 match value {
1057 Literal::Bool(b) => Ok(b),
1058 _ => Err("Cannot convert non-bool literal to bool"),
1059 }
1060 }
1061}
1062
1063impl TryFrom<&Literal> for bool {
1064 type Error = &'static str;
1065
1066 fn try_from(value: &Literal) -> Result<Self, Self::Error> {
1067 match value {
1068 Literal::Bool(b) => Ok(*b),
1069 _ => Err("Cannot convert non-bool literal to bool"),
1070 }
1071 }
1072}
1073
1074impl From<i32> for Literal {
1075 fn from(i: i32) -> Self {
1076 Literal::Int(i)
1077 }
1078}
1079
1080impl From<bool> for Literal {
1081 fn from(b: bool) -> Self {
1082 Literal::Bool(b)
1083 }
1084}
1085
1086impl From<Literal> for Ustr {
1087 fn from(value: Literal) -> Self {
1088 Ustr::from(&format!("{value}"))
1090 }
1091}
1092
1093impl From<AbstractLiteral<Literal>> for Literal {
1094 fn from(literal: AbstractLiteral<Literal>) -> Self {
1095 Literal::AbstractLiteral(literal)
1096 }
1097}
1098
1099impl AbstractLiteral<Expression> {
1100 pub fn into_literals(self) -> Option<AbstractLiteral<Literal>> {
1103 match self {
1104 AbstractLiteral::Set(elements) => {
1105 let literals = elements
1106 .into_iter()
1107 .map(|expr| match expr {
1108 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1109 Expression::AbstractLiteral(_, abslit) => {
1110 Some(Literal::AbstractLiteral(abslit.into_literals()?))
1111 }
1112 _ => None,
1113 })
1114 .collect::<Option<Vec<_>>>()?;
1115 Some(AbstractLiteral::Set(literals))
1116 }
1117 AbstractLiteral::MSet(elements) => {
1118 let literals = elements
1119 .into_iter()
1120 .map(|expr| match expr {
1121 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1122 Expression::AbstractLiteral(_, abslit) => {
1123 Some(Literal::AbstractLiteral(abslit.into_literals()?))
1124 }
1125 _ => None,
1126 })
1127 .collect::<Option<Vec<_>>>()?;
1128 Some(AbstractLiteral::MSet(literals))
1129 }
1130 AbstractLiteral::Partition(elems) => {
1131 let mut partition: Vec<Vec<_>> = Vec::new();
1134
1135 for part in elems {
1136 let literals = part
1137 .into_iter()
1138 .map(|expr| match expr {
1139 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1140 Expression::AbstractLiteral(_, abslit) => {
1141 Some(Literal::AbstractLiteral(abslit.into_literals()?))
1142 }
1143 _ => None,
1144 })
1145 .collect::<Option<Vec<_>>>()?;
1146
1147 partition.push(literals);
1148 }
1149
1150 Some(AbstractLiteral::Partition(partition))
1151 }
1152 AbstractLiteral::Permutation(elems) => {
1153 let mut permutation: Vec<Vec<_>> = Vec::new();
1154
1155 for cycle in elems {
1156 let literals = cycle
1157 .into_iter()
1158 .map(|expr| match expr {
1159 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1160 Expression::AbstractLiteral(_, abslit) => {
1161 Some(Literal::AbstractLiteral(abslit.into_literals()?))
1162 }
1163 _ => None,
1164 })
1165 .collect::<Option<Vec<_>>>()?;
1166
1167 permutation.push(literals);
1168 }
1169
1170 Some(AbstractLiteral::Permutation(permutation))
1171 }
1172 AbstractLiteral::Matrix(items, domain) => {
1173 let mut literals = vec![];
1174 for item in items {
1175 let literal = match item {
1176 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1177 Expression::AbstractLiteral(_, abslit) => {
1178 Some(Literal::AbstractLiteral(abslit.into_literals()?))
1179 }
1180 _ => None,
1181 }?;
1182 literals.push(literal);
1183 }
1184
1185 Some(AbstractLiteral::Matrix(literals, domain.resolve().ok()?))
1186 }
1187 AbstractLiteral::Sequence(elements) => {
1188 let literals = elements
1189 .into_iter()
1190 .map(|expr| match expr {
1191 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1192 Expression::AbstractLiteral(_, abslit) => {
1193 Some(Literal::AbstractLiteral(abslit.into_literals()?))
1194 }
1195 _ => None,
1196 })
1197 .collect::<Option<Vec<_>>>()?;
1198 Some(AbstractLiteral::Sequence(literals))
1199 }
1200 AbstractLiteral::Tuple(items) => {
1201 let mut literals = vec![];
1202 for item in items {
1203 let literal = match item {
1204 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1205 Expression::AbstractLiteral(_, abslit) => {
1206 Some(Literal::AbstractLiteral(abslit.into_literals()?))
1207 }
1208 _ => None,
1209 }?;
1210 literals.push(literal);
1211 }
1212
1213 Some(AbstractLiteral::Tuple(literals))
1214 }
1215 AbstractLiteral::Record(entries) => {
1216 let mut literals = vec![];
1217 for entry in entries {
1218 let literal = match entry.value {
1219 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1220 Expression::AbstractLiteral(_, abslit) => {
1221 Some(Literal::AbstractLiteral(abslit.into_literals()?))
1222 }
1223 _ => None,
1224 }?;
1225
1226 literals.push((entry.name, literal));
1227 }
1228 Some(AbstractLiteral::Record(
1229 literals
1230 .into_iter()
1231 .map(|(name, literal)| Field {
1232 name,
1233 value: literal,
1234 })
1235 .collect(),
1236 ))
1237 }
1238 AbstractLiteral::Function(_) => todo!("Implement into_literals for functions"),
1239 AbstractLiteral::Variant(entry) => {
1240 let literal = match entry.value.clone() {
1241 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1242 Expression::AbstractLiteral(_, abslit) => {
1243 Some(Literal::AbstractLiteral(abslit.into_literals()?))
1244 }
1245 _ => None,
1246 }?;
1247 Some(AbstractLiteral::Variant(Moo::new(Field {
1248 name: entry.name.clone(),
1249 value: literal,
1250 })))
1251 }
1252 AbstractLiteral::Relation(tuples) => {
1253 let mut literal_tuples = Vec::with_capacity(tuples.len());
1254 for fields in tuples {
1255 let literals = fields
1256 .into_iter()
1257 .map(|expr| match expr {
1258 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1259 Expression::AbstractLiteral(_, abslit) => {
1260 Some(Literal::AbstractLiteral(abslit.into_literals()?))
1261 }
1262 _ => None,
1263 })
1264 .collect::<Option<Vec<_>>>()?;
1265 literal_tuples.push(literals);
1266 }
1267 Some(AbstractLiteral::Relation(literal_tuples))
1268 }
1269 }
1270 }
1271}
1272
1273impl Display for Literal {
1275 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1276 match &self {
1277 Literal::Int(i) => write!(f, "{i}"),
1278 Literal::Bool(b) => write!(f, "{b}"),
1279 Literal::AbstractLiteral(l) => write!(f, "{l}"),
1280 }
1281 }
1282}
1283
1284#[cfg(test)]
1285mod tests {
1286
1287 use super::*;
1288 use crate::ast::matrix::{flatten, partial_flatten, shape_of};
1289 use crate::ast::{DeclarationPtr, Name};
1290 use crate::{domain_int_ground, into_matrix, matrix, matrix_lit, range};
1291 use uniplate::Uniplate;
1292
1293 #[test]
1294 fn essence_value_ordering_uses_occurrence_lex_for_sets() {
1295 let set = |values: &[i32]| {
1296 Literal::AbstractLiteral(AbstractLiteral::Set(
1297 values.iter().copied().map(Literal::Int).collect(),
1298 ))
1299 };
1300 let ordered = [
1301 set(&[]),
1302 set(&[3]),
1303 set(&[2]),
1304 set(&[2, 3]),
1305 set(&[1]),
1306 set(&[1, 3]),
1307 set(&[1, 2]),
1308 set(&[1, 2, 3]),
1309 ];
1310
1311 for pair in ordered.windows(2) {
1312 assert_eq!(pair[0].essence_cmp(&pair[1]), Ordering::Less);
1313 }
1314 }
1315
1316 #[test]
1317 fn essence_value_ordering_is_lexicographic_for_tuples_and_matrices() {
1318 let tuple = |values: &[i32]| {
1319 Literal::AbstractLiteral(AbstractLiteral::Tuple(
1320 values.iter().copied().map(Literal::Int).collect(),
1321 ))
1322 };
1323 assert_eq!(tuple(&[1, 2]).essence_cmp(&tuple(&[1, 3])), Ordering::Less);
1324 assert_eq!(
1325 tuple(&[1, 2]).essence_cmp(&tuple(&[1, 2, 0])),
1326 Ordering::Less
1327 );
1328
1329 let matrix = |values: &[i32]| {
1330 Literal::AbstractLiteral(AbstractLiteral::Matrix(
1331 values.iter().copied().map(Literal::Int).collect(),
1332 Moo::new(GroundDomain::Int(vec![Range::Bounded(
1333 1,
1334 values.len() as i32,
1335 )])),
1336 ))
1337 };
1338 assert_eq!(
1339 matrix(&[1, 2]).essence_cmp(&matrix(&[1, 3])),
1340 Ordering::Less
1341 );
1342 }
1343
1344 #[test]
1345 fn mset_domain_accepts_domain_letting_references() {
1346 let declaration = DeclarationPtr::new_domain_letting(
1347 Name::user("NUM"),
1348 Domain::int(vec![Range::Bounded(1, 999)]),
1349 );
1350 let alias = Domain::reference(declaration).unwrap();
1351 let item = Expression::DomainAnnotation(
1352 Metadata::new(),
1353 Moo::new(Expression::Atomic(
1354 Metadata::new(),
1355 Atom::Literal(Literal::Int(1)),
1356 )),
1357 alias,
1358 );
1359
1360 let domain = AbstractLiteral::MSet(vec![item.clone(), item])
1361 .domain_of()
1362 .unwrap();
1363 let (_, item_domain) = domain.as_mset().unwrap();
1364
1365 assert_eq!(
1366 item_domain.resolve(),
1367 Ok(Moo::new(GroundDomain::Int(vec![Range::Bounded(1, 999)])))
1368 );
1369 }
1370
1371 #[test]
1372 fn matrix_uniplate_universe() {
1373 let my_matrix: AbstractLiteral<Literal> = into_matrix![
1375 vec![Literal::AbstractLiteral(matrix![Literal::Bool(true);Moo::new(GroundDomain::Bool)]); 5];
1376 Moo::new(GroundDomain::Bool)
1377 ];
1378
1379 let expected_index_domains = vec![Moo::new(GroundDomain::Bool); 6];
1380 let actual_index_domains: Vec<Moo<GroundDomain>> =
1381 my_matrix.cata(&move |elem, children| {
1382 let mut res = vec![];
1383 res.extend(children.into_iter().flatten());
1384 if let AbstractLiteral::Matrix(_, index_domain) = elem {
1385 res.push(index_domain);
1386 }
1387
1388 res
1389 });
1390
1391 assert_eq!(actual_index_domains, expected_index_domains);
1392 }
1393
1394 #[test]
1395 fn matrix_flatten() {
1396 let tensor: AbstractLiteral<Literal> = matrix![
1397 [
1398 [1, 2, 3, 4],
1400 [5, 6, 7, 8],
1401 [9, 10, 11, 12]
1402 ],
1403 [
1404 [13, 14, 15, 16],
1406 [17, 18, 19, 20],
1407 [21, 22, 23, 24]
1408 ]
1409 ];
1410
1411 let actual_elems: Vec<Literal> = flatten(&tensor).cloned().collect();
1412 let expected_elems = (1..25).map(Literal::from).collect::<Vec<_>>();
1413 assert_eq!(actual_elems, expected_elems);
1414 }
1415
1416 #[test]
1417 fn matrix_domain_1d() {
1418 let matrix = matrix_lit![10, 11, 12, 13; domain_int_ground!(1..4)];
1419 let dom = matrix.domain_of();
1420
1421 let (inner_dom, idx_doms) = dom.as_matrix_ground().expect("must be ground matrix");
1422 assert_eq!(inner_dom, &domain_int_ground!(10..13));
1423 assert_eq!(idx_doms.len(), 1);
1424 assert_eq!(&idx_doms[0], &domain_int_ground!(1..4));
1425 }
1426
1427 #[test]
1428 fn matrix_domain_2d() {
1429 let matrix = matrix_lit![
1430 [1, 2, 3, 4],
1431 [5, 6, 7, 8];
1432 [
1433 domain_int_ground!(1..2),
1434 domain_int_ground!(1..4)
1435 ]
1436 ];
1437 let dom = matrix.domain_of();
1438
1439 let (inner_dom, idx_doms) = dom.as_matrix_ground().expect("must be ground matrix");
1440 assert_eq!(inner_dom, &domain_int_ground!(1..8));
1441 assert_eq!(idx_doms.len(), 2);
1442 assert_eq!(&idx_doms[0], &domain_int_ground!(1..2));
1443 assert_eq!(&idx_doms[1], &domain_int_ground!(1..4));
1444 }
1445
1446 #[test]
1447 fn matrix_shape_3d() {
1448 let tensor: AbstractLiteral<Literal> = matrix![
1449 [
1450 [1, 2, 3, 4],
1451 [5, 6, 7, 8],
1452 [9, 10, 11, 12]
1453 ],
1454 [
1455 [13, 14, 15, 16],
1456 [17, 18, 19, 20],
1457 [21, 22, 23, 24]
1458 ];
1459 [
1460 domain_int_ground!(1..2),
1461 domain_int_ground!(1..3),
1462 domain_int_ground!(1..4)
1463 ]
1464 ];
1465 let shape = shape_of(&tensor).expect("shape_of to work on a 3D matrix");
1466
1467 assert_eq!(shape.size, 24);
1468 assert_eq!(shape.dims, vec![2, 3, 4]);
1469 assert_eq!(shape.strides, vec![12, 4, 1]);
1470 assert_eq!(
1471 shape.idx_doms,
1472 vec![
1473 domain_int_ground!(1..2),
1474 domain_int_ground!(1..3),
1475 domain_int_ground!(1..4)
1476 ]
1477 );
1478 }
1479
1480 #[test]
1481 fn matrix_partial_flatten() {
1482 let tensor: AbstractLiteral<Literal> = matrix![
1483 [
1484 [1, 2, 3, 4],
1486 [5, 6, 7, 8],
1487 [9, 10, 11, 12]
1488 ],
1489 [
1490 [13, 14, 15, 16],
1492 [17, 18, 19, 20],
1493 [21, 22, 23, 24]
1494 ]
1495 ];
1496 assert_eq!(partial_flatten(0, tensor.clone()), tensor);
1497
1498 let expected_flatten_1: AbstractLiteral<Literal> = matrix![
1499 [1, 2, 3, 4],
1500 [5, 6, 7, 8],
1501 [9, 10, 11, 12],
1502 [13, 14, 15, 16],
1503 [17, 18, 19, 20],
1504 [21, 22, 23, 24]
1505 ];
1506 assert_eq!(partial_flatten(1, tensor.clone()), expected_flatten_1);
1507
1508 let expected_flatten_2 =
1509 AbstractLiteral::matrix_implied_indices((1..25).map(Literal::from).collect());
1510 assert_eq!(partial_flatten(2, tensor), expected_flatten_2);
1511 }
1512}