1use std::collections::{HashSet, VecDeque};
2use std::fmt::{Display, Formatter};
3use std::hash::{DefaultHasher, Hash, Hasher};
4use std::sync::atomic::{AtomicU64, Ordering};
5
6static HASH_HITS: AtomicU64 = AtomicU64::new(0);
7static HASH_MISSES: AtomicU64 = AtomicU64::new(0);
8
9pub fn print_hash_stats() {
10 println!(
11 "Expression hash stats: hits={}, misses={}",
12 HASH_HITS.load(Ordering::Relaxed),
13 HASH_MISSES.load(Ordering::Relaxed)
14 );
15}
16use tracing::trace;
17
18use conjure_cp_enum_compatibility_macro::{document_compatibility, generate_discriminants};
19use itertools::Itertools;
20use serde::{Deserialize, Serialize};
21use tree_morph::cache::CacheHashable;
22use ustr::Ustr;
23
24use polyquine::Quine;
25use uniplate::{Biplate, Uniplate};
26
27use crate::ast::FuncAttr;
28use crate::ast::metadata::NO_HASH;
29use crate::bug;
30
31use super::abstract_comprehension::AbstractComprehension;
32use super::ac_operators::ACOperatorKind;
33use super::categories::{Category, CategoryOf};
34use super::comprehension::Comprehension;
35use super::declaration::DeclarationKind;
36use super::domains::HasDomain as _;
37use super::pretty::{pretty_expressions_as_top_level, pretty_vec};
38use super::records::FieldValue;
39use super::sat_encoding::SATIntEncoding;
40use super::{
41 AbstractLiteral, Atom, DeclarationPtr, Domain, DomainPtr, GroundDomain, IntVal, JectivityAttr,
42 Literal, MSetAttr, Metadata, Model, Moo, Name, PartialityAttr, Range, Reference, RelAttr,
43 ReturnType, SetAttr, SymbolTable, SymbolTablePtr, Typeable, UnresolvedDomain, matrix,
44};
45
46static_assertions::assert_eq_size!([u8; 112], Expression);
69
70#[generate_discriminants]
75#[document_compatibility]
76#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Uniplate, Quine)]
77#[biplate(to=AbstractComprehension)]
78#[biplate(to=AbstractLiteral<Expression>)]
79#[biplate(to=AbstractLiteral<Literal>)]
80#[biplate(to=Atom)]
81#[biplate(to=Comprehension)]
82#[biplate(to=DeclarationPtr)]
83#[biplate(to=DomainPtr)]
84#[biplate(to=Literal)]
85#[biplate(to=Metadata)]
86#[biplate(to=Name)]
87#[biplate(to=Option<Expression>)]
88#[biplate(to=FieldValue<Expression>)]
89#[biplate(to=FieldValue<Literal>)]
90#[biplate(to=Reference)]
91#[biplate(to=Model)]
92#[biplate(to=SymbolTable)]
93#[biplate(to=SymbolTablePtr)]
94#[biplate(to=Vec<Expression>)]
95#[path_prefix(conjure_cp::ast)]
96pub enum Expression {
97 AbstractLiteral(Metadata, AbstractLiteral<Expression>),
98 Root(Metadata, Vec<Expression>),
100
101 Bubble(Metadata, Moo<Expression>, Moo<Expression>),
104
105 #[polyquine_skip]
111 Comprehension(Metadata, Moo<Comprehension>),
112
113 #[polyquine_skip] AbstractComprehension(Metadata, Moo<AbstractComprehension>),
116
117 DominanceRelation(Metadata, Moo<Expression>),
119 FromSolution(Metadata, Moo<Atom>),
121
122 #[polyquine_with(arm = (_, name) => {
123 let ident = proc_macro2::Ident::new(name.as_str(), proc_macro2::Span::call_site());
124 quote::quote! { #ident.clone().into() }
125 })]
126 Metavar(Metadata, Ustr),
127
128 Atomic(Metadata, Atom),
129
130 #[compatible(JsonInput)]
134 UnsafeIndex(Metadata, Moo<Expression>, Vec<Expression>),
135
136 #[compatible(SMT)]
140 SafeIndex(Metadata, Moo<Expression>, Vec<Expression>),
141
142 #[compatible(JsonInput)]
152 UnsafeSlice(Metadata, Moo<Expression>, Vec<Option<Expression>>),
153
154 SafeSlice(Metadata, Moo<Expression>, Vec<Option<Expression>>),
158
159 InDomain(Metadata, Moo<Expression>, DomainPtr),
165
166 #[compatible(SMT)]
172 ToInt(Metadata, Moo<Expression>),
173
174 #[compatible(JsonInput, SMT)]
176 Abs(Metadata, Moo<Expression>),
177
178 #[compatible(JsonInput, SMT)]
180 Sum(Metadata, Moo<Expression>),
181
182 #[compatible(JsonInput, SMT)]
184 Product(Metadata, Moo<Expression>),
185
186 #[compatible(JsonInput, SMT)]
188 Min(Metadata, Moo<Expression>),
189
190 #[compatible(JsonInput, SMT)]
192 Max(Metadata, Moo<Expression>),
193
194 #[compatible(JsonInput, SAT, SMT)]
196 Not(Metadata, Moo<Expression>),
197
198 #[compatible(JsonInput, SAT, SMT)]
200 Or(Metadata, Moo<Expression>),
201
202 #[compatible(JsonInput, SAT, SMT)]
204 And(Metadata, Moo<Expression>),
205
206 #[compatible(JsonInput, SMT)]
208 Imply(Metadata, Moo<Expression>, Moo<Expression>),
209
210 #[compatible(JsonInput, SMT)]
212 Iff(Metadata, Moo<Expression>, Moo<Expression>),
213
214 #[compatible(JsonInput)]
215 Union(Metadata, Moo<Expression>, Moo<Expression>),
216
217 #[compatible(JsonInput)]
218 In(Metadata, Moo<Expression>, Moo<Expression>),
219
220 #[compatible(JsonInput)]
221 Intersect(Metadata, Moo<Expression>, Moo<Expression>),
222
223 #[compatible(JsonInput)]
224 Supset(Metadata, Moo<Expression>, Moo<Expression>),
225
226 #[compatible(JsonInput)]
227 SupsetEq(Metadata, Moo<Expression>, Moo<Expression>),
228
229 #[compatible(JsonInput)]
230 Subset(Metadata, Moo<Expression>, Moo<Expression>),
231
232 #[compatible(JsonInput)]
233 SubsetEq(Metadata, Moo<Expression>, Moo<Expression>),
234
235 #[compatible(JsonInput, SMT)]
236 Eq(Metadata, Moo<Expression>, Moo<Expression>),
237
238 #[compatible(JsonInput, SMT)]
239 Neq(Metadata, Moo<Expression>, Moo<Expression>),
240
241 #[compatible(JsonInput, SMT)]
242 Geq(Metadata, Moo<Expression>, Moo<Expression>),
243
244 #[compatible(JsonInput, SMT)]
245 Leq(Metadata, Moo<Expression>, Moo<Expression>),
246
247 #[compatible(JsonInput, SMT)]
248 Gt(Metadata, Moo<Expression>, Moo<Expression>),
249
250 #[compatible(JsonInput, SMT)]
251 Lt(Metadata, Moo<Expression>, Moo<Expression>),
252
253 #[compatible(JsonInput)]
256 Subsequence(Metadata, Moo<Expression>, Moo<Expression>),
257
258 #[compatible(JsonInput)]
261 Substring(Metadata, Moo<Expression>, Moo<Expression>),
262
263 #[compatible(SMT)]
265 SafeDiv(Metadata, Moo<Expression>, Moo<Expression>),
266
267 #[compatible(JsonInput)]
269 UnsafeDiv(Metadata, Moo<Expression>, Moo<Expression>),
270
271 #[compatible(SMT)]
273 SafeMod(Metadata, Moo<Expression>, Moo<Expression>),
274
275 #[compatible(JsonInput)]
277 UnsafeMod(Metadata, Moo<Expression>, Moo<Expression>),
278
279 #[compatible(JsonInput, SMT)]
281 Neg(Metadata, Moo<Expression>),
282
283 #[compatible(JsonInput)]
285 Factorial(Metadata, Moo<Expression>),
286
287 #[compatible(JsonInput)]
289 Defined(Metadata, Moo<Expression>),
290
291 #[compatible(JsonInput)]
293 Range(Metadata, Moo<Expression>),
294
295 #[compatible(JsonInput)]
296 ToSet(Metadata, Moo<Expression>),
297
298 #[compatible(JsonInput)]
299 ToMSet(Metadata, Moo<Expression>),
300
301 #[compatible(JsonInput)]
302 ToRelation(Metadata, Moo<Expression>),
303
304 #[compatible(JsonInput)]
308 UnsafePow(Metadata, Moo<Expression>, Moo<Expression>),
309
310 SafePow(Metadata, Moo<Expression>, Moo<Expression>),
312
313 Flatten(Metadata, Option<Moo<Expression>>, Moo<Expression>),
317
318 #[compatible(JsonInput)]
320 AllDiff(Metadata, Moo<Expression>),
321
322 #[compatible(JsonInput)]
327 Table(Metadata, Moo<Expression>, Moo<Expression>),
328
329 #[compatible(JsonInput)]
334 NegativeTable(Metadata, Moo<Expression>, Moo<Expression>),
335 #[compatible(JsonInput)]
341 Minus(Metadata, Moo<Expression>, Moo<Expression>),
342
343 #[compatible(JsonInput)]
347 Apart(Metadata, Moo<Expression>, Moo<Expression>),
348
349 #[compatible(JsonInput)]
352 Participants(Metadata, Moo<Expression>),
353
354 #[compatible(JsonInput)]
358 Party(Metadata, Moo<Expression>, Moo<Expression>),
359
360 #[compatible(JsonInput)]
363 Parts(Metadata, Moo<Expression>),
364
365 #[compatible(JsonInput)]
369 Together(Metadata, Moo<Expression>, Moo<Expression>),
370
371 #[compatible(Minion)]
379 FlatAbsEq(Metadata, Moo<Atom>, Moo<Atom>),
380
381 #[compatible(Minion)]
389 FlatAllDiff(Metadata, Vec<Atom>),
390
391 #[compatible(Minion)]
399 FlatSumGeq(Metadata, Vec<Atom>, Atom),
400
401 #[compatible(Minion)]
409 FlatSumLeq(Metadata, Vec<Atom>, Atom),
410
411 #[compatible(Minion)]
419 FlatIneq(Metadata, Moo<Atom>, Moo<Atom>, Box<Literal>),
420
421 #[compatible(Minion)]
434 #[polyquine_skip]
435 FlatWatchedLiteral(Metadata, Reference, Literal),
436
437 FlatWeightedSumLeq(Metadata, Vec<Literal>, Vec<Atom>, Moo<Atom>),
449
450 FlatWeightedSumGeq(Metadata, Vec<Literal>, Vec<Atom>, Moo<Atom>),
462
463 #[compatible(Minion)]
471 FlatMinusEq(Metadata, Moo<Atom>, Moo<Atom>),
472
473 #[compatible(Minion)]
481 FlatProductEq(Metadata, Moo<Atom>, Moo<Atom>, Moo<Atom>),
482
483 #[compatible(Minion)]
491 MinionDivEqUndefZero(Metadata, Moo<Atom>, Moo<Atom>, Moo<Atom>),
492
493 #[compatible(Minion)]
501 MinionModuloEqUndefZero(Metadata, Moo<Atom>, Moo<Atom>, Moo<Atom>),
502
503 MinionPow(Metadata, Moo<Atom>, Moo<Atom>, Moo<Atom>),
515
516 #[compatible(Minion)]
525 MinionReify(Metadata, Moo<Expression>, Atom),
526
527 #[compatible(Minion)]
536 MinionReifyImply(Metadata, Moo<Expression>, Atom),
537
538 #[compatible(Minion)]
549 MinionWInIntervalSet(Metadata, Atom, Vec<i32>),
550
551 #[compatible(Minion)]
563 MinionWInSet(Metadata, Atom, Vec<i32>),
564
565 #[compatible(Minion)]
574 MinionElementOne(Metadata, Vec<Atom>, Moo<Atom>, Moo<Atom>),
575
576 #[compatible(Minion)]
580 #[polyquine_skip]
581 AuxDeclaration(Metadata, Reference, Moo<Expression>),
582
583 #[compatible(SAT)]
585 SATInt(Metadata, SATIntEncoding, Moo<Expression>, (i32, i32)),
586
587 #[compatible(SMT)]
590 PairwiseSum(Metadata, Moo<Expression>, Moo<Expression>),
591
592 #[compatible(SMT)]
595 PairwiseProduct(Metadata, Moo<Expression>, Moo<Expression>),
596
597 #[compatible(JsonInput)]
598 Image(Metadata, Moo<Expression>, Moo<Expression>),
599
600 #[compatible(JsonInput)]
601 ImageSet(Metadata, Moo<Expression>, Moo<Expression>),
602
603 #[compatible(JsonInput)]
604 PreImage(Metadata, Moo<Expression>, Moo<Expression>),
605
606 #[compatible(JsonInput)]
607 Inverse(Metadata, Moo<Expression>, Moo<Expression>),
608
609 #[compatible(JsonInput)]
610 Restrict(Metadata, Moo<Expression>, Moo<Expression>),
611
612 LexLt(Metadata, Moo<Expression>, Moo<Expression>),
621
622 LexLeq(Metadata, Moo<Expression>, Moo<Expression>),
624
625 LexGt(Metadata, Moo<Expression>, Moo<Expression>),
628
629 LexGeq(Metadata, Moo<Expression>, Moo<Expression>),
632
633 FlatLexLt(Metadata, Vec<Atom>, Vec<Atom>),
635
636 FlatLexLeq(Metadata, Vec<Atom>, Vec<Atom>),
638
639 #[compatible(JsonInput)]
641 Active(Metadata, Moo<Expression>, Moo<Expression>),
642
643 #[compatible(JsonInput)]
645 RelationProj(Metadata, Moo<Expression>, Vec<Option<Expression>>),
646
647 #[compatible(JsonInput)]
649 Card(Metadata, Moo<Expression>),
650}
651
652fn bounded_i32_domain_for_matrix_literal_monotonic(
659 e: &Expression,
660 op: fn(i32, i32) -> Option<i32>,
661) -> Option<DomainPtr> {
662 let (mut exprs, _) = e.clone().unwrap_matrix_unchecked()?;
664
665 let expr = exprs.pop()?;
681 let dom = expr.domain_of()?;
682 let resolved = dom.resolve()?;
683 let GroundDomain::Int(ranges) = resolved.as_ref() else {
684 return None;
685 };
686
687 let (mut current_min, mut current_max) = range_vec_bounds_i32(ranges)?;
688
689 for expr in exprs {
690 let dom = expr.domain_of()?;
691 let resolved = dom.resolve()?;
692 let GroundDomain::Int(ranges) = resolved.as_ref() else {
693 return None;
694 };
695
696 let (min, max) = range_vec_bounds_i32(ranges)?;
697
698 let minmax = op(min, current_max)?;
700 let minmin = op(min, current_min)?;
701 let maxmin = op(max, current_min)?;
702 let maxmax = op(max, current_max)?;
703 let vals = [minmax, minmin, maxmin, maxmax];
704
705 current_min = *vals
706 .iter()
707 .min()
708 .expect("vals iterator should not be empty, and should have a minimum.");
709 current_max = *vals
710 .iter()
711 .max()
712 .expect("vals iterator should not be empty, and should have a maximum.");
713 }
714
715 if current_min == current_max {
716 Some(Domain::int(vec![Range::Single(current_min)]))
717 } else {
718 Some(Domain::int(vec![Range::Bounded(current_min, current_max)]))
719 }
720}
721
722fn matrix_element_domain(e: &Expression) -> Option<DomainPtr> {
723 let (elem_domain, _) = e.domain_of()?.as_matrix()?;
724 elem_domain.as_ref().as_int()?;
725 Some(elem_domain)
726}
727
728fn range_vec_bounds_i32(ranges: &Vec<Range<i32>>) -> Option<(i32, i32)> {
730 let mut min = i32::MAX;
731 let mut max = i32::MIN;
732 for r in ranges {
733 match r {
734 Range::Single(i) => {
735 if *i < min {
736 min = *i;
737 }
738 if *i > max {
739 max = *i;
740 }
741 }
742 Range::Bounded(i, j) => {
743 if *i < min {
744 min = *i;
745 }
746 if *j > max {
747 max = *j;
748 }
749 }
750 Range::UnboundedR(_) | Range::UnboundedL(_) | Range::Unbounded => return None,
751 }
752 }
753 Some((min, max))
754}
755
756impl Expression {
757 pub fn domain_of(&self) -> Option<DomainPtr> {
759 match self {
760 Expression::Union(_, a, b) => Some(Domain::set(
761 SetAttr::<IntVal>::default(),
762 a.domain_of()?.union(&b.domain_of()?).ok()?,
763 )),
764 Expression::Intersect(_, a, b) => Some(Domain::set(
765 SetAttr::<IntVal>::default(),
766 a.domain_of()?.intersect(&b.domain_of()?).ok()?,
767 )),
768 Expression::In(_, _, _) => Some(Domain::bool()),
769 Expression::Supset(_, _, _) => Some(Domain::bool()),
770 Expression::SupsetEq(_, _, _) => Some(Domain::bool()),
771 Expression::Subset(_, _, _) => Some(Domain::bool()),
772 Expression::SubsetEq(_, _, _) => Some(Domain::bool()),
773 Expression::AbstractLiteral(_, abslit) => abslit.domain_of(),
774 Expression::DominanceRelation(_, _) => Some(Domain::bool()),
775 Expression::FromSolution(_, expr) => Some(expr.domain_of()),
776 Expression::Metavar(_, _) => None,
777 Expression::Comprehension(_, comprehension) => comprehension.domain_of(),
778 Expression::AbstractComprehension(_, comprehension) => comprehension.domain_of(),
779 Expression::UnsafeIndex(_, matrix, index) | Expression::SafeIndex(_, matrix, index) => {
780 let dom = matrix.domain_of()?;
781 if let Some((elem_domain, _)) = dom.as_matrix() {
782 return Some(elem_domain);
783 }
784
785 #[allow(clippy::redundant_pattern_matching)]
787 if let Some(_) = dom.as_tuple() {
788 return None;
790 }
791
792 if let Some(doms) = dom.as_variant().or(dom.as_record()) {
793 let index_expr = index.first()?;
794 return match index_expr {
795 Expression::Atomic(_, atom) => {
796 let decl = atom.clone().into_declaration();
797 for inner_dom in doms {
798 if *decl.name() == inner_dom.name {
799 return Some(inner_dom.domain);
800 }
801 }
802 None
803 }
804 _ => None,
805 };
806 }
807
808 bug!("subject of an index operation should support indexing")
809 }
810 Expression::UnsafeSlice(_, matrix, indices)
811 | Expression::SafeSlice(_, matrix, indices) => {
812 let sliced_dimension = indices.iter().position(Option::is_none);
813
814 let dom = matrix.domain_of()?;
815 let Some((elem_domain, index_domains)) = dom.as_matrix() else {
816 bug!("subject of an index operation should be a matrix");
817 };
818
819 match sliced_dimension {
820 Some(dimension) => Some(Domain::matrix(
821 elem_domain,
822 vec![index_domains[dimension].clone()],
823 )),
824
825 None => Some(elem_domain),
827 }
828 }
829 Expression::InDomain(_, _, _) => Some(Domain::bool()),
830 Expression::Atomic(_, atom) => Some(atom.domain_of()),
831 Expression::Sum(_, e) => {
832 bounded_i32_domain_for_matrix_literal_monotonic(e, |x, y| Some(x + y))
833 }
834 Expression::Product(_, e) => {
835 bounded_i32_domain_for_matrix_literal_monotonic(e, |x, y| Some(x * y))
836 }
837 Expression::Min(_, e) => bounded_i32_domain_for_matrix_literal_monotonic(e, |x, y| {
838 Some(if x < y { x } else { y })
839 })
840 .or_else(|| matrix_element_domain(e)),
841 Expression::Max(_, e) => bounded_i32_domain_for_matrix_literal_monotonic(e, |x, y| {
842 Some(if x > y { x } else { y })
843 })
844 .or_else(|| matrix_element_domain(e)),
845 Expression::UnsafeDiv(_, a, b) => a
846 .domain_of()?
847 .resolve()?
848 .apply_i32(
849 |x, y| {
852 if y != 0 {
853 Some((x as f32 / y as f32).floor() as i32)
854 } else {
855 None
856 }
857 },
858 b.domain_of()?.resolve()?.as_ref(),
859 )
860 .map(DomainPtr::from)
861 .ok(),
862 Expression::SafeDiv(_, a, b) => {
863 let domain = a
866 .domain_of()?
867 .resolve()?
868 .apply_i32(
869 |x, y| {
870 if y != 0 {
871 Some((x as f32 / y as f32).floor() as i32)
872 } else {
873 None
874 }
875 },
876 b.domain_of()?.resolve()?.as_ref(),
877 )
878 .unwrap_or_else(|err| bug!("Got {err} when computing domain of {self}"));
879
880 if let GroundDomain::Int(ranges) = domain {
881 let mut ranges = ranges;
882 ranges.push(Range::Single(0));
883 Some(Domain::int(ranges))
884 } else {
885 bug!("Domain of {self} was not integer")
886 }
887 }
888 Expression::UnsafeMod(_, a, b) => a
889 .domain_of()?
890 .resolve()?
891 .apply_i32(
892 |x, y| if y != 0 { Some(x % y) } else { None },
893 b.domain_of()?.resolve()?.as_ref(),
894 )
895 .map(DomainPtr::from)
896 .ok(),
897 Expression::SafeMod(_, a, b) => {
898 let domain = a
899 .domain_of()?
900 .resolve()?
901 .apply_i32(
902 |x, y| if y != 0 { Some(x % y) } else { None },
903 b.domain_of()?.resolve()?.as_ref(),
904 )
905 .unwrap_or_else(|err| bug!("Got {err} when computing domain of {self}"));
906
907 if let GroundDomain::Int(ranges) = domain {
908 let mut ranges = ranges;
909 ranges.push(Range::Single(0));
910 Some(Domain::int(ranges))
911 } else {
912 bug!("Domain of {self} was not integer")
913 }
914 }
915 Expression::SafePow(_, a, b) | Expression::UnsafePow(_, a, b) => a
916 .domain_of()?
917 .resolve()?
918 .apply_i32(
919 |x, y| {
920 if (x != 0 || y != 0) && y >= 0 {
921 Some(x.pow(y as u32))
922 } else {
923 None
924 }
925 },
926 b.domain_of()?.resolve()?.as_ref(),
927 )
928 .map(DomainPtr::from)
929 .ok(),
930 Expression::Root(_, _) => None,
931 Expression::Bubble(_, inner, _) => inner.domain_of(),
932 Expression::AuxDeclaration(_, _, _) => Some(Domain::bool()),
933 Expression::And(_, _) => Some(Domain::bool()),
934 Expression::Not(_, _) => Some(Domain::bool()),
935 Expression::Or(_, _) => Some(Domain::bool()),
936 Expression::Imply(_, _, _) => Some(Domain::bool()),
937 Expression::Iff(_, _, _) => Some(Domain::bool()),
938 Expression::Eq(_, _, _) => Some(Domain::bool()),
939 Expression::Neq(_, _, _) => Some(Domain::bool()),
940 Expression::Geq(_, _, _) => Some(Domain::bool()),
941 Expression::Leq(_, _, _) => Some(Domain::bool()),
942 Expression::Gt(_, _, _) => Some(Domain::bool()),
943 Expression::Lt(_, _, _) => Some(Domain::bool()),
944 Expression::Factorial(_, _) => None, Expression::FlatAbsEq(_, _, _) => Some(Domain::bool()),
946 Expression::FlatSumGeq(_, _, _) => Some(Domain::bool()),
947 Expression::FlatSumLeq(_, _, _) => Some(Domain::bool()),
948 Expression::MinionDivEqUndefZero(_, _, _, _) => Some(Domain::bool()),
949 Expression::MinionModuloEqUndefZero(_, _, _, _) => Some(Domain::bool()),
950 Expression::FlatIneq(_, _, _, _) => Some(Domain::bool()),
951 Expression::Flatten(_, n, m) => {
952 if let Some(expr) = n {
953 if expr.return_type() == ReturnType::Int {
954 return None;
956 }
957 } else {
958 let dom = m.domain_of()?.resolve()?;
960 let (val_dom, idx_doms) = match dom.as_ref() {
961 GroundDomain::Matrix(val, idx) => (val, idx),
962 _ => return None,
963 };
964 let num_elems = matrix::num_elements(idx_doms).ok()? as i32;
965
966 let new_index_domain = Domain::int(vec![Range::Bounded(1, num_elems)]);
967 return Some(Domain::matrix(
968 val_dom.clone().into(),
969 vec![new_index_domain],
970 ));
971 }
972 None
973 }
974 Expression::AllDiff(_, _) => Some(Domain::bool()),
975 Expression::Table(_, _, _) => Some(Domain::bool()),
976 Expression::NegativeTable(_, _, _) => Some(Domain::bool()),
977 Expression::FlatWatchedLiteral(_, _, _) => Some(Domain::bool()),
978 Expression::MinionReify(_, _, _) => Some(Domain::bool()),
979 Expression::MinionReifyImply(_, _, _) => Some(Domain::bool()),
980 Expression::MinionWInIntervalSet(_, _, _) => Some(Domain::bool()),
981 Expression::MinionWInSet(_, _, _) => Some(Domain::bool()),
982 Expression::MinionElementOne(_, _, _, _) => Some(Domain::bool()),
983 Expression::Neg(_, x) => {
984 let dom = x.domain_of()?;
985 let mut ranges = dom.as_int()?;
986
987 ranges = ranges
988 .into_iter()
989 .map(|r| match r {
990 Range::Single(x) => Range::Single(-x),
991 Range::Bounded(x, y) => Range::Bounded(-y, -x),
992 Range::UnboundedR(i) => Range::UnboundedL(-i),
993 Range::UnboundedL(i) => Range::UnboundedR(-i),
994 Range::Unbounded => Range::Unbounded,
995 })
996 .collect();
997
998 Some(Domain::int(ranges))
999 }
1000 Expression::Minus(_, a, b) => {
1001 let a_resolved = a.domain_of()?.resolve()?;
1002 let b_resolved = b.domain_of()?.resolve()?;
1003
1004 if matches!(a_resolved.as_ref(), GroundDomain::Int(_))
1005 && matches!(b_resolved.as_ref(), GroundDomain::Int(_))
1006 {
1007 a_resolved
1008 .apply_i32(|x, y| Some(x - y), b_resolved.as_ref())
1009 .map(DomainPtr::from)
1010 .ok()
1011 } else if matches!(a_resolved.as_ref(), GroundDomain::Set(_, _))
1012 && matches!(b_resolved.as_ref(), GroundDomain::Set(_, _))
1013 {
1014 Some(DomainPtr::from(a_resolved))
1015 } else {
1016 None
1017 }
1018 }
1019 Expression::FlatAllDiff(_, _) => Some(Domain::bool()),
1020 Expression::FlatMinusEq(_, _, _) => Some(Domain::bool()),
1021 Expression::FlatProductEq(_, _, _, _) => Some(Domain::bool()),
1022 Expression::FlatWeightedSumLeq(_, _, _, _) => Some(Domain::bool()),
1023 Expression::FlatWeightedSumGeq(_, _, _, _) => Some(Domain::bool()),
1024 Expression::Abs(_, a) => a
1025 .domain_of()?
1026 .resolve()?
1027 .apply_i32(|a, _| Some(a.abs()), a.domain_of()?.resolve()?.as_ref())
1028 .map(DomainPtr::from)
1029 .ok(),
1030 Expression::MinionPow(_, _, _, _) => Some(Domain::bool()),
1031 Expression::ToInt(_, _) => Some(Domain::int(vec![Range::Bounded(0, 1)])),
1032 Expression::SATInt(_, _, _, (low, high)) => {
1033 Some(Domain::int_ground(vec![Range::Bounded(*low, *high)]))
1034 }
1035 Expression::PairwiseSum(_, a, b) => a
1036 .domain_of()?
1037 .resolve()?
1038 .apply_i32(|a, b| Some(a + b), b.domain_of()?.resolve()?.as_ref())
1039 .map(DomainPtr::from)
1040 .ok(),
1041 Expression::PairwiseProduct(_, a, b) => a
1042 .domain_of()?
1043 .resolve()?
1044 .apply_i32(|a, b| Some(a * b), b.domain_of()?.resolve()?.as_ref())
1045 .map(DomainPtr::from)
1046 .ok(),
1047 Expression::Defined(_, function) => {
1048 let (attrs, domain, codomain) = function.domain_of()?.as_function()?;
1049 let size = Self::function_elements_size(attrs, &domain, &codomain);
1050 if let Some(size) = size {
1051 Some(Domain::set(SetAttr::new(size), domain))
1052 } else {
1053 Some(Domain::empty(ReturnType::Set(Box::new(
1054 domain.return_type(),
1055 ))))
1056 }
1057 }
1058 Expression::Range(_, function) => {
1059 let (attrs, domain, codomain) = function.domain_of()?.as_function()?;
1060 let jectivity = attrs.resolve()?.jectivity;
1061
1062 let size_size = attrs.resolve()?.size;
1063 let size_size = match size_size {
1064 Range::Unbounded => Range::UnboundedR(0),
1065 Range::Single(x) => match jectivity {
1067 JectivityAttr::Injective | JectivityAttr::Surjective => Range::Single(x),
1068 _ => Range::Bounded(Ord::min(1, x), x),
1069 },
1070 Range::UnboundedL(x) => Range::Bounded(0, x),
1072 Range::UnboundedR(x) => match jectivity {
1074 JectivityAttr::Injective | JectivityAttr::Surjective => {
1075 Range::UnboundedR(x)
1076 }
1077 _ => Range::UnboundedR(Ord::min(1, x)),
1078 },
1079 Range::Bounded(x, y) => Range::Bounded(Ord::min(1, x), y),
1080 };
1081
1082 let partiality = attrs.resolve()?.partiality;
1084 let codomain_length = codomain.length_signed();
1085 let attr_size = match jectivity {
1086 JectivityAttr::Bijective | JectivityAttr::Surjective => match codomain_length {
1088 Ok(co_len) => Some(Range::Single(co_len)),
1089 Err(_) => None,
1090 },
1091 JectivityAttr::Injective => {
1092 let domain_length = domain.length_signed();
1093 match domain_length {
1094 Ok(len) => match codomain_length {
1095 Ok(co_len) => match partiality {
1096 PartialityAttr::Total => {
1098 Some(Range::Single(Ord::min(len, co_len)))
1099 }
1100 PartialityAttr::Partial => {
1101 Some(Range::Bounded(0, Ord::min(len, co_len)))
1102 }
1103 },
1104 Err(_) => None,
1105 },
1106 Err(_) => None,
1107 }
1108 }
1109 JectivityAttr::None => {
1110 let domain_length = domain.length_signed();
1111 match domain_length {
1112 Ok(len) => Some(Range::Bounded(0, len)),
1114 Err(_) => None,
1115 }
1116 }
1117 };
1118
1119 let size = match attr_size {
1120 Some(attr_size) => {
1121 let unsafe_range = Range::minimal(&[size_size, attr_size]);
1122 match unsafe_range {
1123 Ok(range) => range,
1124 Err(_) => {
1125 return Some(Domain::empty(ReturnType::Set(Box::new(
1126 domain.return_type(),
1127 ))));
1128 }
1129 }
1130 }
1131 None => size_size,
1132 };
1133 Some(Domain::set(SetAttr::new(size), codomain))
1134 }
1135 Expression::Image(_, function, _) => get_function_codomain(function),
1136 Expression::ImageSet(_, function, _) => {
1137 let codomain = get_function_codomain(function);
1138 codomain.map(|inner_dom| Domain::set(SetAttr::new(Range::Bounded(0, 1)), inner_dom))
1140 }
1141 Expression::PreImage(_, function, _) => {
1142 let (attrs, domain, codomain) = function.domain_of()?.as_function()?;
1143
1144 let size_size = attrs.resolve()?.size;
1145 let size_size = match size_size {
1146 Range::Unbounded => Range::UnboundedR(0),
1148 Range::Single(x) => Range::Bounded(0, x),
1149 Range::UnboundedL(x) => Range::Bounded(0, x),
1150 Range::UnboundedR(_) => Range::UnboundedR(0),
1151 Range::Bounded(_, y) => Range::Bounded(0, y),
1152 };
1153
1154 let jectivity = attrs.resolve()?.jectivity;
1155 let codomain_length = codomain.length_signed();
1156 let attr_size = match jectivity {
1157 JectivityAttr::Bijective => Some(Range::Single(1)),
1159 JectivityAttr::Injective => match size_size {
1160 Range::Single(x) | Range::UnboundedL(x) | Range::Bounded(x, _) => {
1161 match codomain_length {
1162 Ok(co_len) => {
1163 if x >= co_len {
1164 Some(Range::Single(1))
1165 } else {
1166 Some(Range::Bounded(0, 1))
1167 }
1168 }
1169 Err(_) => Some(Range::Bounded(0, 1)),
1170 }
1171 }
1172 _ => Some(Range::Bounded(0, 1)),
1173 },
1174 JectivityAttr::Surjective => {
1175 let domain_length = domain.length_signed();
1176 match domain_length {
1177 Ok(len) => match codomain_length {
1178 Ok(co_len) => match size_size {
1181 Range::Bounded(_, x)
1182 | Range::UnboundedL(x)
1183 | Range::Single(x) => Some(Range::Bounded(
1184 1,
1185 Ord::max(Ord::min(len, x) - co_len + 1, 0),
1186 )),
1187 _ => Some(Range::Bounded(1, Ord::max(len - co_len + 1, 0))),
1188 },
1189 Err(_) => Some(Range::UnboundedR(1)),
1190 },
1191 Err(_) => Some(Range::UnboundedR(1)),
1192 }
1193 }
1194 JectivityAttr::None => {
1195 let domain_length = domain.length_signed();
1196 match domain_length {
1197 Ok(len) => Some(Range::Bounded(0, len)),
1198 Err(_) => Some(Range::UnboundedR(0)),
1199 }
1200 }
1201 };
1202
1203 let size = match attr_size {
1204 Some(attr_size) => {
1205 let unsafe_range = Range::minimal(&[size_size, attr_size]);
1206 match unsafe_range {
1207 Ok(range) => range,
1208 Err(_) => {
1209 return Some(Domain::empty(ReturnType::Set(Box::new(
1210 domain.return_type(),
1211 ))));
1212 }
1213 }
1214 }
1215 None => size_size,
1216 };
1217 Some(Domain::set(SetAttr::new(size), domain))
1218 }
1219 Expression::Restrict(_, function, new_domain) => {
1220 let mut domain = function.domain_of()?;
1221 let (attrs_mut, dom, codom_mut) = domain.as_function_mut()?;
1222
1223 let attrs: &FuncAttr<IntVal> = attrs_mut;
1225 let codom: &Moo<Domain> = codom_mut;
1226
1227 let mut new_dom = new_domain.domain_of()?;
1229 if let Some(new_rng) = new_dom.as_int_ground_mut()
1231 && let Some(old_rng) = dom.as_int_ground_mut()
1232 {
1233 new_rng.append(old_rng);
1234 if let Ok(rng) = Range::minimal(new_rng) {
1235 let ranges = vec![rng];
1236 new_dom = Domain::int(ranges);
1237 }
1238 }
1239 let attr_size = attrs.resolve()?.size;
1240 let new_size = match new_dom.length_signed() {
1241 Ok(len) => match Range::minimal(&[attr_size, Range::Bounded(0, len)]) {
1243 Ok(size) => size,
1244 Err(_) => {
1245 return Some(Domain::empty(ReturnType::Function(
1247 Box::new(new_dom.return_type()),
1248 Box::new(codom.return_type()),
1249 )));
1250 }
1251 },
1252 Err(_) => attr_size,
1253 };
1254 let jectivity = attrs.jectivity.clone();
1255 let partiality = attrs.partiality.clone();
1256 let new_attrs = FuncAttr {
1257 size: new_size,
1258 jectivity,
1259 partiality,
1260 };
1261 Some(Domain::function(new_attrs, new_dom, codom.clone()))
1262 }
1263 Expression::Subsequence(_, _, _) => Some(Domain::bool()),
1264 Expression::Substring(_, _, _) => Some(Domain::bool()),
1265 Expression::Inverse(..) => Some(Domain::bool()),
1266 Expression::LexLt(..) => Some(Domain::bool()),
1267 Expression::LexLeq(..) => Some(Domain::bool()),
1268 Expression::LexGt(..) => Some(Domain::bool()),
1269 Expression::LexGeq(..) => Some(Domain::bool()),
1270 Expression::FlatLexLt(..) => Some(Domain::bool()),
1271 Expression::FlatLexLeq(..) => Some(Domain::bool()),
1272 Expression::Active(..) => Some(Domain::bool()),
1273 Expression::ToSet(_, other) => {
1274 if let Some((attrs, dom, codom)) = other.domain_of()?.as_function() {
1275 let set_attrs = SetAttr { size: attrs.size };
1276 Some(Domain::set(set_attrs, Domain::tuple(vec![dom, codom])))
1277 } else if let Some((attrs, doms)) = other.domain_of()?.as_relation() {
1278 let set_attrs = SetAttr { size: attrs.size };
1279 Some(Domain::set(set_attrs, Domain::tuple(doms)))
1280 } else if let Some((attrs, dom)) = other.domain_of()?.as_mset() {
1281 let set_attrs = SetAttr { size: attrs.size };
1282 Some(Domain::set(set_attrs, dom))
1283 } else if let Some((dom, dimensions)) = other.domain_of()?.as_matrix() {
1284 let mut doms = vec![];
1286 for _ in dimensions {
1287 doms.push(dom.clone());
1288 }
1289 let doms_sizes: Result<Vec<i32>, _> =
1290 doms.iter().map(|x| x.length_signed()).collect();
1291 let attr = match doms_sizes {
1292 Ok(vals) => {
1293 if let Some(&size) = vals.iter().min() {
1294 SetAttr::new(Range::Single(size))
1295 } else {
1296 SetAttr::<i32>::default()
1297 }
1298 }
1299 Err(_) => SetAttr::<i32>::default(),
1301 };
1302 Some(Domain::set(attr, Domain::tuple(doms)))
1303 } else {
1304 bug!(
1305 "Domain of {self} needed to be a function, relation, mset, or matrix for ToSet"
1306 )
1307 }
1308 }
1309 Expression::ToMSet(_, other) => {
1310 if let Some((attrs, dom, codom)) = other.domain_of()?.as_function() {
1311 let set_attrs = MSetAttr {
1312 size: attrs.size,
1313 occurrence: Range::Single(IntVal::Const(1)),
1314 };
1315 Some(Domain::mset(set_attrs, Domain::tuple(vec![dom, codom])))
1316 } else if let Some((attrs, doms)) = other.domain_of()?.as_relation() {
1317 let set_attrs = MSetAttr {
1318 size: attrs.size,
1319 occurrence: Range::Single(IntVal::Const(1)),
1320 };
1321 Some(Domain::mset(set_attrs, Domain::tuple(doms)))
1322 } else if let Some((attrs, dom)) = other.domain_of()?.as_set() {
1323 let set_attrs = MSetAttr {
1324 size: attrs.size,
1325 occurrence: Range::Single(IntVal::Const(1)),
1326 };
1327 Some(Domain::mset(set_attrs, dom))
1328 } else {
1329 bug!("Domain of {self} needed to be a function, relation, or set for ToMSet")
1330 }
1331 }
1332 Expression::ToRelation(_, function) => {
1333 let (attrs, domain, codomain) = function.domain_of()?.as_function()?;
1334 let rel_attrs = RelAttr {
1336 size: attrs.size,
1337 binary: vec![],
1338 };
1339 Some(Domain::relation(rel_attrs, vec![domain, codomain]))
1340 }
1341 Expression::RelationProj(_, relation, projections) => {
1342 let (_, domains) = relation.domain_of()?.as_relation()?;
1343 let new_doms = domains
1344 .iter()
1345 .zip(projections.iter())
1346 .filter_map(|(domain, included)| {
1347 if included.is_none() {
1348 Some(domain.clone())
1350 } else {
1351 None
1352 }
1353 })
1354 .collect();
1355 Some(Domain::relation(RelAttr::<IntVal>::default(), new_doms))
1356 }
1357 Expression::Apart(_, _, _) => Some(Domain::bool()),
1358 Expression::Together(_, _, _) => Some(Domain::bool()),
1359 Expression::Participants(_, p) => {
1360 let (attr, inner) = p.domain_of()?.as_partition()?;
1362 let len = inner.length_signed().ok()?;
1363
1364 let p_parts = attr.resolve()?.num_parts;
1365 let p_card = attr.resolve()?.part_len;
1366
1367 match (p_parts.low(), p_parts.high(), p_card.low(), p_card.high()) {
1369 (Some(p), Some(q), Some(r), Some(s)) => {
1370 let lo = p * r;
1371 let hi = q * s;
1372 if len < lo || len > hi {
1373 return Some(Domain::empty(ReturnType::Set(Box::new(
1374 inner.return_type(),
1375 ))));
1376 }
1377 }
1378
1379 (None, Some(q), None, Some(s)) => {
1380 let hi = q * s;
1381 if len > hi {
1382 return Some(Domain::empty(ReturnType::Set(Box::new(
1383 inner.return_type(),
1384 ))));
1385 }
1386 }
1387
1388 (Some(p), None, Some(r), None) => {
1389 let lo = p * r;
1390 if len < lo {
1391 return Some(Domain::empty(ReturnType::Set(Box::new(
1392 inner.return_type(),
1393 ))));
1394 }
1395 }
1396
1397 _ => {}
1398 }
1399
1400 Some(Domain::set(
1401 SetAttr::new_size(len),
1402 Domain::int(inner.as_int()?),
1403 ))
1404 }
1405 Expression::Party(_, _, p) => {
1406 let (attr, inner) = p.domain_of()?.as_partition()?;
1408
1409 Some(Domain::set(SetAttr::new(attr.part_len), inner))
1410 }
1411 Expression::Parts(_, p) => {
1412 let (attr, inner) = p.domain_of()?.as_partition()?;
1413
1414 Some(Domain::set(
1415 SetAttr::new(attr.num_parts.clone()),
1416 Domain::set(SetAttr::new(attr.part_len), inner),
1417 ))
1418 }
1419 Expression::Card(_, collection) => {
1420 let domain = collection.domain_of()?;
1421 if let Some((_, dimensions)) = domain.as_matrix() {
1422 let doms_ground: Result<Vec<i32>, _> =
1423 dimensions.iter().map(|x| x.length_signed()).collect();
1424 if let Ok(doms_ground) = doms_ground {
1425 let size: Range<i32> = Range::Single(doms_ground.iter().product());
1426 Some(Domain::int(vec![size]))
1427 } else {
1428 Some(Domain::int(vec![Range::<i32>::Unbounded]))
1429 }
1430 } else if let Some((attr, dom)) = domain.as_set() {
1431 let attr_size = attr.resolve()?.size;
1432 if let Ok(length) = dom.length_signed() {
1433 let unsafe_range = Range::minimal(&[attr_size, Range::Bounded(0, length)]);
1434 match unsafe_range {
1435 Ok(range) => return Some(Domain::int(vec![range])),
1436 Err(_) => return None,
1437 }
1438 }
1439 Some(Domain::int(vec![attr_size]))
1441 } else if let Some((attrs, dom)) = domain.as_mset() {
1442 let attr_size = attrs.resolve()?.size;
1443 let attr_occ_range = attrs.resolve()?.occurrence;
1444 let attr_occ = match attr_occ_range {
1446 Range::Single(x) => Some(x),
1447 Range::Unbounded | Range::UnboundedR(_) => None,
1448 Range::Bounded(_, x) => Some(x),
1449 Range::UnboundedL(x) => Some(x),
1450 };
1451 if let Some(occ) = attr_occ {
1452 if let Ok(length) = dom.length_signed() {
1453 let unsafe_range =
1454 Range::minimal(&[attr_size, Range::Bounded(0, length * occ)]);
1455 match unsafe_range {
1456 Ok(range) => Some(Domain::int(vec![range])),
1457 Err(_) => None,
1458 }
1459 } else {
1460 Some(Domain::int(vec![attr_size]))
1462 }
1463 } else {
1464 Some(Domain::int(vec![attr_size]))
1466 }
1467 } else if let Some((attrs, doms)) = domain.as_relation() {
1468 let attr_size = attrs.resolve()?.size;
1471 let doms_sizes: Result<Vec<i32>, _> =
1473 doms.iter().map(|x| x.length_signed()).collect();
1474 if let Ok(doms_sizes) = doms_sizes {
1475 let length = Range::Bounded(0, doms_sizes.iter().product());
1476 let unsafe_range = Range::minimal(&[attr_size, length]);
1478 match unsafe_range {
1479 Ok(range) => return Some(Domain::int(vec![range])),
1480 Err(_) => return None,
1481 }
1482 }
1483 Some(Domain::int(vec![attr_size]))
1485 } else if let Some((attrs, dom, codom)) = domain.as_function() {
1486 let size = Self::function_elements_size(attrs, &dom, &codom);
1487 size.map(|size| Domain::int(vec![size]))
1488 } else {
1489 bug!(
1490 "Domain of {self} needed to be a matrix, set, mset, relation, or function for cardinality"
1491 )
1492 }
1493 }
1494 }
1495 }
1496
1497 fn function_elements_size(
1499 attrs: FuncAttr<IntVal>,
1500 domain: &DomainPtr,
1501 codomain: &DomainPtr,
1502 ) -> Option<Range> {
1503 let size_size = attrs.resolve()?.size;
1506 let partiality = attrs.resolve()?.partiality;
1508 let jectivity = attrs.resolve()?.jectivity;
1509 let domain_length = domain.length_signed();
1510 let attr_size = match domain_length {
1512 Ok(len) => match partiality {
1513 PartialityAttr::Total => Some(Range::Single(len)),
1514 PartialityAttr::Partial => {
1515 let codomain_length = codomain.length_signed();
1517 match codomain_length {
1518 Ok(co_len) => match jectivity {
1519 JectivityAttr::Bijective => Some(Range::Single(co_len)),
1520 JectivityAttr::Surjective => Some(Range::Bounded(co_len, len)),
1521 JectivityAttr::Injective => {
1522 Some(Range::Bounded(0, Ord::min(len, co_len)))
1523 }
1524 JectivityAttr::None => Some(Range::Bounded(0, len)),
1525 },
1526 Err(_) => None,
1527 }
1528 }
1529 },
1530 Err(_) => None,
1531 };
1532 match attr_size {
1538 Some(attr_size) => {
1539 let unsafe_range = Range::minimal(&[size_size, attr_size]);
1540 unsafe_range.ok()
1541 }
1542 None => Some(size_size),
1543 }
1544 }
1545
1546 pub fn meta_ref(&self) -> &Metadata {
1548 macro_rules! match_meta_ref {
1549 ($($variant:ident),* $(,)?) => {
1550 match self {
1551 $(Expression::$variant(meta, ..) => meta,)*
1552 }
1553 };
1554 }
1555 match_meta_ref!(
1556 AbstractLiteral,
1557 Root,
1558 Bubble,
1559 Comprehension,
1560 AbstractComprehension,
1561 DominanceRelation,
1562 FromSolution,
1563 Metavar,
1564 Atomic,
1565 UnsafeIndex,
1566 SafeIndex,
1567 UnsafeSlice,
1568 SafeSlice,
1569 InDomain,
1570 ToInt,
1571 Abs,
1572 Sum,
1573 Product,
1574 Min,
1575 Max,
1576 Not,
1577 Or,
1578 And,
1579 Imply,
1580 Iff,
1581 Union,
1582 In,
1583 Intersect,
1584 Supset,
1585 SupsetEq,
1586 Subset,
1587 SubsetEq,
1588 Eq,
1589 Neq,
1590 Geq,
1591 Leq,
1592 Gt,
1593 Lt,
1594 SafeDiv,
1595 UnsafeDiv,
1596 SafeMod,
1597 UnsafeMod,
1598 Apart,
1599 Together,
1600 Participants,
1601 Party,
1602 Parts,
1603 Neg,
1604 Defined,
1605 Range,
1606 UnsafePow,
1607 SafePow,
1608 Flatten,
1609 AllDiff,
1610 Minus,
1611 Factorial,
1612 FlatAbsEq,
1613 FlatAllDiff,
1614 FlatSumGeq,
1615 FlatSumLeq,
1616 FlatIneq,
1617 FlatWatchedLiteral,
1618 FlatWeightedSumLeq,
1619 FlatWeightedSumGeq,
1620 FlatMinusEq,
1621 FlatProductEq,
1622 MinionDivEqUndefZero,
1623 MinionModuloEqUndefZero,
1624 MinionPow,
1625 MinionReify,
1626 MinionReifyImply,
1627 MinionWInIntervalSet,
1628 MinionWInSet,
1629 MinionElementOne,
1630 AuxDeclaration,
1631 SATInt,
1632 PairwiseSum,
1633 PairwiseProduct,
1634 Image,
1635 ImageSet,
1636 PreImage,
1637 Inverse,
1638 Restrict,
1639 LexLt,
1640 LexLeq,
1641 LexGt,
1642 LexGeq,
1643 FlatLexLt,
1644 FlatLexLeq,
1645 NegativeTable,
1646 Table,
1647 Active,
1648 ToSet,
1649 ToMSet,
1650 ToRelation,
1651 RelationProj,
1652 Card,
1653 Subsequence,
1654 Substring,
1655 )
1656 }
1657
1658 pub fn get_meta(&self) -> Metadata {
1659 let metas: VecDeque<Metadata> = self.children_bi();
1660 metas[0].clone()
1661 }
1662
1663 pub fn set_meta(&self, meta: Metadata) {
1664 self.transform_bi(&|_| meta.clone());
1665 }
1666
1667 pub fn is_safe(&self) -> bool {
1674 for expr in self.universe() {
1676 match expr {
1677 Expression::UnsafeDiv(_, _, _)
1678 | Expression::UnsafeMod(_, _, _)
1679 | Expression::UnsafePow(_, _, _)
1680 | Expression::UnsafeIndex(_, _, _)
1681 | Expression::Bubble(_, _, _)
1682 | Expression::UnsafeSlice(_, _, _) => {
1683 return false;
1684 }
1685 _ => {}
1686 }
1687 }
1688 true
1689 }
1690
1691 pub fn is_associative_commutative_operator(&self) -> bool {
1693 TryInto::<ACOperatorKind>::try_into(self).is_ok()
1694 }
1695
1696 pub fn is_matrix_literal(&self) -> bool {
1701 matches!(
1702 self,
1703 Expression::AbstractLiteral(_, AbstractLiteral::Matrix(_, _))
1704 | Expression::Atomic(
1705 _,
1706 Atom::Literal(Literal::AbstractLiteral(AbstractLiteral::Matrix(_, _))),
1707 )
1708 )
1709 }
1710
1711 pub fn identical_atom_to(&self, other: &Expression) -> bool {
1717 let atom1: Result<&Atom, _> = self.try_into();
1718 let atom2: Result<&Atom, _> = other.try_into();
1719
1720 if let (Ok(atom1), Ok(atom2)) = (atom1, atom2) {
1721 atom2 == atom1
1722 } else {
1723 false
1724 }
1725 }
1726
1727 pub fn unwrap_list(&self) -> Option<Vec<Expression>> {
1732 match self {
1733 Expression::AbstractLiteral(_, matrix @ AbstractLiteral::Matrix(_, _)) => {
1734 matrix.unwrap_list().cloned()
1735 }
1736 Expression::Atomic(
1737 _,
1738 Atom::Literal(Literal::AbstractLiteral(matrix @ AbstractLiteral::Matrix(_, _))),
1739 ) => matrix.unwrap_list().map(|elems| {
1740 elems
1741 .clone()
1742 .into_iter()
1743 .map(|x: Literal| Expression::Atomic(Metadata::new(), Atom::Literal(x)))
1744 .collect_vec()
1745 }),
1746 _ => None,
1747 }
1748 }
1749
1750 pub fn unwrap_matrix_unchecked(self) -> Option<(Vec<Expression>, DomainPtr)> {
1758 match self {
1759 Expression::AbstractLiteral(_, AbstractLiteral::Matrix(elems, domain)) => {
1760 Some((elems, domain))
1761 }
1762 Expression::Atomic(
1763 _,
1764 Atom::Literal(Literal::AbstractLiteral(AbstractLiteral::Matrix(elems, domain))),
1765 ) => Some((
1766 elems
1767 .into_iter()
1768 .map(|x: Literal| Expression::Atomic(Metadata::new(), Atom::Literal(x)))
1769 .collect_vec(),
1770 domain.into(),
1771 )),
1772
1773 _ => None,
1774 }
1775 }
1776
1777 pub fn extend_root(self, exprs: Vec<Expression>) -> Expression {
1782 match self {
1783 Expression::Root(meta, mut children) => {
1784 children.extend(exprs);
1785 Expression::Root(meta, children)
1786 }
1787 _ => panic!("extend_root called on a non-Root expression"),
1788 }
1789 }
1790
1791 pub fn into_literal(self) -> Option<Literal> {
1793 match self {
1794 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1795 Expression::AbstractLiteral(_, abslit) => {
1796 Some(Literal::AbstractLiteral(abslit.into_literals()?))
1797 }
1798 Expression::Neg(_, e) => {
1799 let Literal::Int(i) = Moo::unwrap_or_clone(e).into_literal()? else {
1800 bug!("negated literal should be an int");
1801 };
1802
1803 Some(Literal::Int(-i))
1804 }
1805
1806 _ => None,
1807 }
1808 }
1809
1810 pub fn to_ac_operator_kind(&self) -> Option<ACOperatorKind> {
1812 TryFrom::try_from(self).ok()
1813 }
1814
1815 pub fn universe_categories(&self) -> HashSet<Category> {
1817 self.universe()
1818 .into_iter()
1819 .map(|x| x.category_of())
1820 .collect()
1821 }
1822}
1823
1824pub fn get_function_codomain(function: &Moo<Expression>) -> Option<DomainPtr> {
1825 let function_domain = function.domain_of()?;
1826 match function_domain.resolve().as_ref() {
1827 Some(d) => {
1828 match d.as_ref() {
1829 GroundDomain::Function(_, _, codomain) => Some(codomain.clone().into()),
1830 _ => None,
1832 }
1833 }
1834 None => {
1835 match function_domain.as_unresolved()? {
1836 UnresolvedDomain::Function(_, _, codomain) => Some(codomain.clone()),
1837 _ => None,
1839 }
1840 }
1841 }
1842}
1843
1844impl TryFrom<&Expression> for i32 {
1845 type Error = ();
1846
1847 fn try_from(value: &Expression) -> Result<Self, Self::Error> {
1848 let Expression::Atomic(_, atom) = value else {
1849 return Err(());
1850 };
1851
1852 let Atom::Literal(lit) = atom else {
1853 return Err(());
1854 };
1855
1856 let Literal::Int(i) = lit else {
1857 return Err(());
1858 };
1859
1860 Ok(*i)
1861 }
1862}
1863
1864impl TryFrom<Expression> for i32 {
1865 type Error = ();
1866
1867 fn try_from(value: Expression) -> Result<Self, Self::Error> {
1868 TryFrom::<&Expression>::try_from(&value)
1869 }
1870}
1871impl From<i32> for Expression {
1872 fn from(i: i32) -> Self {
1873 Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(i)))
1874 }
1875}
1876
1877impl From<bool> for Expression {
1878 fn from(b: bool) -> Self {
1879 Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(b)))
1880 }
1881}
1882
1883impl From<Atom> for Expression {
1884 fn from(value: Atom) -> Self {
1885 Expression::Atomic(Metadata::new(), value)
1886 }
1887}
1888
1889impl From<Literal> for Expression {
1890 fn from(value: Literal) -> Self {
1891 Expression::Atomic(Metadata::new(), value.into())
1892 }
1893}
1894
1895impl From<Moo<Expression>> for Expression {
1896 fn from(val: Moo<Expression>) -> Self {
1897 val.as_ref().clone()
1898 }
1899}
1900
1901impl CategoryOf for Expression {
1902 fn category_of(&self) -> Category {
1903 let category = self.cata(&move |x,children| {
1905
1906 if let Some(max_category) = children.iter().max() {
1907 *max_category
1910 } else {
1911 let mut max_category = Category::Bottom;
1913
1914 if !Biplate::<Model>::universe_bi(&x).is_empty() {
1921 return Category::Decision;
1923 }
1924
1925 if let Some(max_atom_category) = Biplate::<Atom>::universe_bi(&x).iter().map(|x| x.category_of()).max()
1927 && max_atom_category > max_category{
1929 max_category = max_atom_category;
1931 }
1932
1933 if let Some(max_declaration_category) = Biplate::<DeclarationPtr>::universe_bi(&x).iter().map(|x| x.category_of()).max()
1935 && max_declaration_category > max_category{
1937 max_category = max_declaration_category;
1939 }
1940 max_category
1941
1942 }
1943 });
1944
1945 if cfg!(debug_assertions) {
1946 trace!(
1947 category= %category,
1948 expression= %self,
1949 "Called Expression::category_of()"
1950 );
1951 };
1952 category
1953 }
1954}
1955
1956impl Display for Expression {
1957 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1958 match &self {
1959 Expression::Union(_, box1, box2) => {
1960 write!(f, "({} union {})", box1.clone(), box2.clone())
1961 }
1962 Expression::In(_, e1, e2) => {
1963 write!(f, "{e1} in {e2}")
1964 }
1965 Expression::Intersect(_, box1, box2) => {
1966 write!(f, "({} intersect {})", box1.clone(), box2.clone())
1967 }
1968 Expression::Supset(_, box1, box2) => {
1969 write!(f, "({} supset {})", box1.clone(), box2.clone())
1970 }
1971 Expression::SupsetEq(_, box1, box2) => {
1972 write!(f, "({} supsetEq {})", box1.clone(), box2.clone())
1973 }
1974 Expression::Subset(_, box1, box2) => {
1975 write!(f, "({} subset {})", box1.clone(), box2.clone())
1976 }
1977 Expression::SubsetEq(_, box1, box2) => {
1978 write!(f, "({} subsetEq {})", box1.clone(), box2.clone())
1979 }
1980
1981 Expression::AbstractLiteral(_, l) => l.fmt(f),
1982 Expression::Comprehension(_, c) => c.fmt(f),
1983 Expression::AbstractComprehension(_, c) => c.fmt(f),
1984 Expression::UnsafeIndex(_, e1, e2) => write!(f, "{e1}{}", pretty_vec(e2)),
1985 Expression::SafeIndex(_, e1, e2) => write!(f, "SafeIndex({e1},{})", pretty_vec(e2)),
1986 Expression::UnsafeSlice(_, e1, es) => {
1987 let args = es
1988 .iter()
1989 .map(|x| match x {
1990 Some(x) => format!("{x}"),
1991 None => "..".into(),
1992 })
1993 .join(",");
1994
1995 write!(f, "{e1}[{args}]")
1996 }
1997 Expression::SafeSlice(_, e1, es) => {
1998 let args = es
1999 .iter()
2000 .map(|x| match x {
2001 Some(x) => format!("{x}"),
2002 None => "..".into(),
2003 })
2004 .join(",");
2005
2006 write!(f, "SafeSlice({e1},[{args}])")
2007 }
2008 Expression::InDomain(_, e, domain) => {
2009 write!(f, "__inDomain({e},{domain})")
2010 }
2011 Expression::Root(_, exprs) => {
2012 write!(f, "{}", pretty_expressions_as_top_level(exprs))
2013 }
2014 Expression::DominanceRelation(_, expr) => write!(f, "DominanceRelation({expr})"),
2015 Expression::FromSolution(_, expr) => write!(f, "FromSolution({expr})"),
2016 Expression::Metavar(_, name) => write!(f, "&{name}"),
2017 Expression::Atomic(_, atom) => atom.fmt(f),
2018 Expression::Abs(_, a) | Expression::Card(_, a) => write!(f, "|{a}|"),
2019 Expression::Sum(_, e) => {
2020 write!(f, "sum({e})")
2021 }
2022 Expression::Product(_, e) => {
2023 write!(f, "product({e})")
2024 }
2025 Expression::Min(_, e) => {
2026 write!(f, "min({e})")
2027 }
2028 Expression::Max(_, e) => {
2029 write!(f, "max({e})")
2030 }
2031 Expression::Not(_, expr_box) => {
2032 write!(f, "!({})", expr_box.clone())
2033 }
2034 Expression::Or(_, e) => {
2035 write!(f, "or({e})")
2036 }
2037 Expression::And(_, e) => {
2038 write!(f, "and({e})")
2039 }
2040 Expression::Imply(_, box1, box2) => {
2041 write!(f, "({box1}) -> ({box2})")
2042 }
2043 Expression::Iff(_, box1, box2) => {
2044 write!(f, "({box1}) <-> ({box2})")
2045 }
2046 Expression::Eq(_, box1, box2) => {
2047 write!(f, "({} = {})", box1.clone(), box2.clone())
2048 }
2049 Expression::Neq(_, box1, box2) => {
2050 write!(f, "({} != {})", box1.clone(), box2.clone())
2051 }
2052 Expression::Geq(_, box1, box2) => {
2053 write!(f, "({} >= {})", box1.clone(), box2.clone())
2054 }
2055 Expression::Leq(_, box1, box2) => {
2056 write!(f, "({} <= {})", box1.clone(), box2.clone())
2057 }
2058 Expression::Gt(_, box1, box2) => {
2059 write!(f, "({} > {})", box1.clone(), box2.clone())
2060 }
2061 Expression::Lt(_, box1, box2) => {
2062 write!(f, "({} < {})", box1.clone(), box2.clone())
2063 }
2064 Expression::Apart(_, list, partition) => {
2065 write!(f, "apart({list}, {partition})")
2066 }
2067 Expression::Together(_, list, partition) => {
2068 write!(f, "together({list}, {partition})")
2069 }
2070 Expression::Participants(_, partition) => {
2071 write!(f, "participants({partition})")
2072 }
2073 Expression::Party(_, element, partition) => {
2074 write!(f, "party({element}, {partition})")
2075 }
2076 Expression::Parts(_, partition) => {
2077 write!(f, "parts({partition})")
2078 }
2079 Expression::FlatSumGeq(_, box1, box2) => {
2080 write!(f, "SumGeq({}, {})", pretty_vec(box1), box2.clone())
2081 }
2082 Expression::FlatSumLeq(_, box1, box2) => {
2083 write!(f, "SumLeq({}, {})", pretty_vec(box1), box2.clone())
2084 }
2085 Expression::FlatIneq(_, box1, box2, box3) => write!(
2086 f,
2087 "Ineq({}, {}, {})",
2088 box1.clone(),
2089 box2.clone(),
2090 box3.clone()
2091 ),
2092 Expression::Flatten(_, n, m) => {
2093 if let Some(n) = n {
2094 write!(f, "flatten({n}, {m})")
2095 } else {
2096 write!(f, "flatten({m})")
2097 }
2098 }
2099 Expression::AllDiff(_, e) => {
2100 write!(f, "allDiff({e})")
2101 }
2102 Expression::Table(_, tuple_expr, rows_expr) => {
2103 write!(f, "table({tuple_expr}, {rows_expr})")
2104 }
2105 Expression::NegativeTable(_, tuple_expr, rows_expr) => {
2106 write!(f, "negativeTable({tuple_expr}, {rows_expr})")
2107 }
2108 Expression::Bubble(_, box1, box2) => {
2109 write!(f, "{{{} @ {}}}", box1.clone(), box2.clone())
2110 }
2111 Expression::SafeDiv(_, box1, box2) => {
2112 write!(f, "SafeDiv({}, {})", box1.clone(), box2.clone())
2113 }
2114 Expression::UnsafeDiv(_, box1, box2) => {
2115 write!(f, "({} / {})", box1.clone(), box2.clone())
2116 }
2117 Expression::UnsafePow(_, box1, box2) => {
2118 write!(f, "({} ** {})", box1.clone(), box2.clone())
2119 }
2120 Expression::SafePow(_, box1, box2) => {
2121 write!(f, "SafePow({}, {})", box1.clone(), box2.clone())
2122 }
2123 Expression::Subsequence(_, s, t) => {
2124 write!(f, "{} subsequence {}", s.clone(), t.clone())
2125 }
2126 Expression::Substring(_, s, t) => {
2127 write!(f, "{} substring {}", s.clone(), t.clone())
2128 }
2129 Expression::MinionDivEqUndefZero(_, box1, box2, box3) => {
2130 write!(
2131 f,
2132 "DivEq({}, {}, {})",
2133 box1.clone(),
2134 box2.clone(),
2135 box3.clone()
2136 )
2137 }
2138 Expression::MinionModuloEqUndefZero(_, box1, box2, box3) => {
2139 write!(
2140 f,
2141 "ModEq({}, {}, {})",
2142 box1.clone(),
2143 box2.clone(),
2144 box3.clone()
2145 )
2146 }
2147 Expression::FlatWatchedLiteral(_, x, l) => {
2148 write!(f, "WatchedLiteral({x},{l})")
2149 }
2150 Expression::MinionReify(_, box1, box2) => {
2151 write!(f, "Reify({}, {})", box1.clone(), box2.clone())
2152 }
2153 Expression::MinionReifyImply(_, box1, box2) => {
2154 write!(f, "ReifyImply({}, {})", box1.clone(), box2.clone())
2155 }
2156 Expression::MinionWInIntervalSet(_, atom, intervals) => {
2157 let intervals = intervals.iter().join(",");
2158 write!(f, "__minion_w_inintervalset({atom},[{intervals}])")
2159 }
2160 Expression::MinionWInSet(_, atom, values) => {
2161 let values = values.iter().join(",");
2162 write!(f, "__minion_w_inset({atom},[{values}])")
2163 }
2164 Expression::AuxDeclaration(_, reference, e) => {
2165 write!(f, "{} =aux {}", reference, e.clone())
2166 }
2167 Expression::UnsafeMod(_, a, b) => {
2168 write!(f, "{} % {}", a.clone(), b.clone())
2169 }
2170 Expression::SafeMod(_, a, b) => {
2171 write!(f, "SafeMod({},{})", a.clone(), b.clone())
2172 }
2173 Expression::Neg(_, a) => {
2174 write!(f, "-({})", a.clone())
2175 }
2176 Expression::Factorial(_, a) => {
2177 write!(f, "({})!", a.clone())
2178 }
2179 Expression::Minus(_, a, b) => {
2180 write!(f, "({} - {})", a.clone(), b.clone())
2181 }
2182 Expression::FlatAllDiff(_, es) => {
2183 write!(f, "__flat_alldiff({})", pretty_vec(es))
2184 }
2185 Expression::FlatAbsEq(_, a, b) => {
2186 write!(f, "AbsEq({},{})", a.clone(), b.clone())
2187 }
2188 Expression::FlatMinusEq(_, a, b) => {
2189 write!(f, "MinusEq({},{})", a.clone(), b.clone())
2190 }
2191 Expression::FlatProductEq(_, a, b, c) => {
2192 write!(
2193 f,
2194 "FlatProductEq({},{},{})",
2195 a.clone(),
2196 b.clone(),
2197 c.clone()
2198 )
2199 }
2200 Expression::FlatWeightedSumLeq(_, cs, vs, total) => {
2201 write!(
2202 f,
2203 "FlatWeightedSumLeq({},{},{})",
2204 pretty_vec(cs),
2205 pretty_vec(vs),
2206 total.clone()
2207 )
2208 }
2209 Expression::FlatWeightedSumGeq(_, cs, vs, total) => {
2210 write!(
2211 f,
2212 "FlatWeightedSumGeq({},{},{})",
2213 pretty_vec(cs),
2214 pretty_vec(vs),
2215 total.clone()
2216 )
2217 }
2218 Expression::MinionPow(_, atom, atom1, atom2) => {
2219 write!(f, "MinionPow({atom},{atom1},{atom2})")
2220 }
2221 Expression::MinionElementOne(_, atoms, atom, atom1) => {
2222 let atoms = atoms.iter().join(",");
2223 write!(f, "__minion_element_one([{atoms}],{atom},{atom1})")
2224 }
2225
2226 Expression::ToInt(_, expr) => {
2227 write!(f, "toInt({expr})")
2228 }
2229
2230 Expression::SATInt(_, encoding, bits, (min, max)) => {
2231 write!(f, "SATInt({encoding:?}, {bits} [{min}, {max}])")
2232 }
2233
2234 Expression::PairwiseSum(_, a, b) => write!(f, "PairwiseSum({a}, {b})"),
2235 Expression::PairwiseProduct(_, a, b) => write!(f, "PairwiseProduct({a}, {b})"),
2236
2237 Expression::Defined(_, function) => write!(f, "defined({function})"),
2238 Expression::Range(_, function) => write!(f, "range({function})"),
2239 Expression::Image(_, function, elems) => write!(f, "image({function},{elems})"),
2240 Expression::ImageSet(_, function, elems) => write!(f, "imageSet({function},{elems})"),
2241 Expression::PreImage(_, function, elems) => write!(f, "preImage({function},{elems})"),
2242 Expression::Inverse(_, a, b) => write!(f, "inverse({a},{b})"),
2243 Expression::Restrict(_, function, domain) => write!(f, "restrict({function},{domain})"),
2244
2245 Expression::LexLt(_, a, b) => write!(f, "({a} <lex {b})"),
2246 Expression::LexLeq(_, a, b) => write!(f, "({a} <=lex {b})"),
2247 Expression::LexGt(_, a, b) => write!(f, "({a} >lex {b})"),
2248 Expression::LexGeq(_, a, b) => write!(f, "({a} >=lex {b})"),
2249 Expression::FlatLexLt(_, a, b) => {
2250 write!(f, "FlatLexLt({}, {})", pretty_vec(a), pretty_vec(b))
2251 }
2252 Expression::FlatLexLeq(_, a, b) => {
2253 write!(f, "FlatLexLeq({}, {})", pretty_vec(a), pretty_vec(b))
2254 }
2255 Expression::Active(_, variant, field_name) => {
2256 write!(f, "active({variant}, {field_name})")
2257 }
2258 Expression::ToSet(_, other) => write!(f, "toSet({other})"),
2259 Expression::ToMSet(_, other) => write!(f, "toMSet({other})"),
2260 Expression::ToRelation(_, function) => write!(f, "toRelation({function})"),
2261 Expression::RelationProj(_, relation, projections) => {
2262 let projections_str = projections
2263 .iter()
2264 .map(|x| {
2265 if let Some(x) = x {
2266 x.to_string()
2267 } else {
2268 String::from("_")
2269 }
2270 })
2271 .join(", ");
2272 write!(f, "{relation}({projections_str})")
2273 }
2274 }
2275 }
2276}
2277
2278fn minus_operand_return_type(expr: &Expression) -> ReturnType {
2279 match expr {
2280 Expression::Atomic(_, Atom::Reference(reference)) => {
2281 let decl_kind = reference.ptr.kind().clone();
2282 match decl_kind {
2283 DeclarationKind::Find(var) => var.return_type(),
2284 DeclarationKind::Given(domain)
2285 | DeclarationKind::DomainLetting(domain)
2286 | DeclarationKind::Field(domain) => domain.return_type(),
2287 DeclarationKind::Quantified(inner) => inner.domain().return_type(),
2288 DeclarationKind::QuantifiedExpr(inner)
2289 | DeclarationKind::TemporaryValueLetting(inner)
2290 | DeclarationKind::ValueLetting(inner, _) => inner.return_type(),
2292 }
2293 }
2294 _ => expr.return_type(),
2295 }
2296}
2297
2298impl Typeable for Expression {
2299 fn return_type(&self) -> ReturnType {
2300 match self {
2301 Expression::Union(_, subject, _) => ReturnType::Set(Box::new(subject.return_type())),
2302 Expression::Intersect(_, subject, _) => {
2303 ReturnType::Set(Box::new(subject.return_type()))
2304 }
2305 Expression::In(_, _, _) => ReturnType::Bool,
2306 Expression::Supset(_, _, _) => ReturnType::Bool,
2307 Expression::SupsetEq(_, _, _) => ReturnType::Bool,
2308 Expression::Subset(_, _, _) => ReturnType::Bool,
2309 Expression::SubsetEq(_, _, _) => ReturnType::Bool,
2310 Expression::AbstractLiteral(_, lit) => lit.return_type(),
2311 Expression::UnsafeIndex(_, subject, idx) | Expression::SafeIndex(_, subject, idx) => {
2312 let subject_ty = subject.return_type();
2313 match subject_ty {
2314 ReturnType::Matrix(_) => {
2315 let mut elem_typ = subject_ty;
2318 let mut idx_len = idx.len();
2319 while idx_len > 0
2320 && let ReturnType::Matrix(new_elem_typ) = &elem_typ
2321 {
2322 elem_typ = *new_elem_typ.clone();
2323 idx_len -= 1;
2324 }
2325 elem_typ
2326 }
2327 ReturnType::Record(_) | ReturnType::Tuple(_) | ReturnType::Variant(_) => {
2329 ReturnType::Unknown
2330 }
2331 _ => bug!(
2332 "Invalid indexing operation: expected the operand to be a collection, got {self}: {subject_ty}"
2333 ),
2334 }
2335 }
2336 Expression::UnsafeSlice(_, subject, _) | Expression::SafeSlice(_, subject, _) => {
2337 ReturnType::Matrix(Box::new(subject.return_type()))
2338 }
2339 Expression::InDomain(_, _, _) => ReturnType::Bool,
2340 Expression::Comprehension(_, comp) => comp.return_type(),
2341 Expression::AbstractComprehension(_, comp) => comp.return_type(),
2342 Expression::Root(_, _) => ReturnType::Bool,
2343 Expression::DominanceRelation(_, _) => ReturnType::Bool,
2344 Expression::FromSolution(_, expr) => expr.return_type(),
2345 Expression::Metavar(_, _) => ReturnType::Unknown,
2346 Expression::Atomic(_, atom) => atom.return_type(),
2347 Expression::Abs(_, _) => ReturnType::Int,
2348 Expression::Sum(_, _) => ReturnType::Int,
2349 Expression::Product(_, _) => ReturnType::Int,
2350 Expression::Min(_, _) => ReturnType::Int,
2351 Expression::Max(_, _) => ReturnType::Int,
2352 Expression::Not(_, _) => ReturnType::Bool,
2353 Expression::Or(_, _) => ReturnType::Bool,
2354 Expression::Imply(_, _, _) => ReturnType::Bool,
2355 Expression::Iff(_, _, _) => ReturnType::Bool,
2356 Expression::And(_, _) => ReturnType::Bool,
2357 Expression::Eq(_, _, _) => ReturnType::Bool,
2358 Expression::Neq(_, _, _) => ReturnType::Bool,
2359 Expression::Geq(_, _, _) => ReturnType::Bool,
2360 Expression::Leq(_, _, _) => ReturnType::Bool,
2361 Expression::Gt(_, _, _) => ReturnType::Bool,
2362 Expression::Lt(_, _, _) => ReturnType::Bool,
2363 Expression::Apart(_, _, _) => ReturnType::Bool,
2364 Expression::Together(_, _, _) => ReturnType::Bool,
2365 Expression::Party(_, _, subject) => ReturnType::Set(Box::new(subject.return_type())),
2366 Expression::Participants(_, subject) => {
2367 ReturnType::Set(Box::new(subject.return_type()))
2368 }
2369 Expression::Parts(_, subject) => {
2370 ReturnType::Set(Box::new(ReturnType::Set(Box::new(subject.return_type()))))
2371 }
2372 Expression::SafeDiv(_, _, _) => ReturnType::Int,
2373 Expression::UnsafeDiv(_, _, _) => ReturnType::Int,
2374 Expression::FlatAllDiff(_, _) => ReturnType::Bool,
2375 Expression::FlatSumGeq(_, _, _) => ReturnType::Bool,
2376 Expression::FlatSumLeq(_, _, _) => ReturnType::Bool,
2377 Expression::MinionDivEqUndefZero(_, _, _, _) => ReturnType::Bool,
2378 Expression::FlatIneq(_, _, _, _) => ReturnType::Bool,
2379 Expression::Flatten(_, _, matrix) => {
2380 let matrix_type = matrix.return_type();
2381 match matrix_type {
2382 ReturnType::Matrix(_) => {
2383 let mut elem_type = matrix_type;
2385 while let ReturnType::Matrix(new_elem_type) = &elem_type {
2386 elem_type = *new_elem_type.clone();
2387 }
2388 ReturnType::Matrix(Box::new(elem_type))
2389 }
2390 _ => bug!(
2391 "Invalid indexing operation: expected the operand to be a collection, got {self}: {matrix_type}"
2392 ),
2393 }
2394 }
2395 Expression::AllDiff(_, _) => ReturnType::Bool,
2396 Expression::Table(_, _, _) => ReturnType::Bool,
2397 Expression::NegativeTable(_, _, _) => ReturnType::Bool,
2398 Expression::Bubble(_, inner, _) => inner.return_type(),
2399 Expression::FlatWatchedLiteral(_, _, _) => ReturnType::Bool,
2400 Expression::MinionReify(_, _, _) => ReturnType::Bool,
2401 Expression::MinionReifyImply(_, _, _) => ReturnType::Bool,
2402 Expression::MinionWInIntervalSet(_, _, _) => ReturnType::Bool,
2403 Expression::MinionWInSet(_, _, _) => ReturnType::Bool,
2404 Expression::MinionElementOne(_, _, _, _) => ReturnType::Bool,
2405 Expression::AuxDeclaration(_, _, _) => ReturnType::Bool,
2406 Expression::UnsafeMod(_, _, _) => ReturnType::Int,
2407 Expression::SafeMod(_, _, _) => ReturnType::Int,
2408 Expression::MinionModuloEqUndefZero(_, _, _, _) => ReturnType::Bool,
2409 Expression::Neg(_, _) => ReturnType::Int,
2410 Expression::Factorial(_, _) => ReturnType::Int,
2411 Expression::UnsafePow(_, _, _) => ReturnType::Int,
2412 Expression::SafePow(_, _, _) => ReturnType::Int,
2413 Expression::Minus(_, a, b) => {
2414 let a_type = minus_operand_return_type(a);
2417 let b_type = minus_operand_return_type(b);
2418
2419 if a_type == ReturnType::Int && b_type == ReturnType::Int {
2420 ReturnType::Int
2421 } else if let ReturnType::Set(a_inner) = a_type
2422 && let ReturnType::Set(b_inner) = b_type
2423 && a_inner == b_inner
2424 {
2425 ReturnType::Set(a_inner)
2426 } else {
2427 bug!(
2428 "Invalid minus operation: operands are of different or invalid types for this operation"
2429 )
2430 }
2431 }
2432 Expression::FlatAbsEq(_, _, _) => ReturnType::Bool,
2433 Expression::FlatMinusEq(_, _, _) => ReturnType::Bool,
2434 Expression::FlatProductEq(_, _, _, _) => ReturnType::Bool,
2435 Expression::FlatWeightedSumLeq(_, _, _, _) => ReturnType::Bool,
2436 Expression::FlatWeightedSumGeq(_, _, _, _) => ReturnType::Bool,
2437 Expression::MinionPow(_, _, _, _) => ReturnType::Bool,
2438 Expression::ToInt(_, _) => ReturnType::Int,
2439 Expression::SATInt(..) => ReturnType::Int,
2440 Expression::PairwiseSum(_, _, _) => ReturnType::Int,
2441 Expression::PairwiseProduct(_, _, _) => ReturnType::Int,
2442 Expression::Defined(_, function) => {
2443 let subject = function.return_type();
2444 match subject {
2445 ReturnType::Function(domain, _) => ReturnType::Set(Box::new(*domain)),
2446 _ => bug!(
2447 "Invalid defined operation: expected the operand to be a function, got {self}: {subject}"
2448 ),
2449 }
2450 }
2451 Expression::Range(_, function) => {
2452 let subject = function.return_type();
2453 match subject {
2454 ReturnType::Function(_, codomain) => ReturnType::Set(Box::new(*codomain)),
2455 _ => bug!(
2456 "Invalid range operation: expected the operand to be a function, got {self}: {subject}"
2457 ),
2458 }
2459 }
2460 Expression::Image(_, function, _) => {
2461 let subject = function.return_type();
2462 match subject {
2463 ReturnType::Function(_, codomain) => *codomain,
2464 _ => bug!(
2465 "Invalid image operation: expected the operand to be a function, got {self}: {subject}"
2466 ),
2467 }
2468 }
2469 Expression::ImageSet(_, function, _) => {
2470 let subject = function.return_type();
2471 match subject {
2472 ReturnType::Function(_, codomain) => ReturnType::Set(Box::new(*codomain)),
2473 _ => bug!(
2474 "Invalid imageSet operation: expected the operand to be a function, got {self}: {subject}"
2475 ),
2476 }
2477 }
2478 Expression::PreImage(_, function, _) => {
2479 let subject = function.return_type();
2480 match subject {
2481 ReturnType::Function(domain, _) => ReturnType::Set(Box::new(*domain)),
2482 _ => bug!(
2483 "Invalid preImage operation: expected the operand to be a function, got {self}: {subject}"
2484 ),
2485 }
2486 }
2487 Expression::Restrict(_, function, new_domain) => {
2488 let subject = function.return_type();
2489 match subject {
2490 ReturnType::Function(_, codomain) => {
2491 ReturnType::Function(Box::new(new_domain.return_type()), codomain)
2492 }
2493 _ => bug!(
2494 "Invalid preImage operation: expected the operand to be a function, got {self}: {subject}"
2495 ),
2496 }
2497 }
2498 Expression::Inverse(..) => ReturnType::Bool,
2499 Expression::LexLt(..) => ReturnType::Bool,
2500 Expression::LexGt(..) => ReturnType::Bool,
2501 Expression::LexLeq(..) => ReturnType::Bool,
2502 Expression::LexGeq(..) => ReturnType::Bool,
2503 Expression::FlatLexLt(..) => ReturnType::Bool,
2504 Expression::FlatLexLeq(..) => ReturnType::Bool,
2505 Expression::Active(..) => ReturnType::Bool,
2506 Expression::ToSet(_, other) => {
2507 let subject = other.return_type();
2508 match subject {
2509 ReturnType::Function(domain, codomain) => {
2510 ReturnType::Set(Box::new(ReturnType::Tuple(vec![*domain, *codomain])))
2511 }
2512 ReturnType::Relation(domains) => {
2513 ReturnType::Set(Box::new(ReturnType::Tuple(domains)))
2514 }
2515 ReturnType::MSet(domain) => ReturnType::Set(Box::new(*domain)),
2516 ReturnType::Matrix(domain) => ReturnType::Set(Box::new(*domain)),
2517 _ => bug!(
2518 "Invalid toSet operation: expected the operand to be a mset, matrix, relation, or function, got {self}: {subject}"
2519 ),
2520 }
2521 }
2522 Expression::ToMSet(_, other) => {
2523 let subject = other.return_type();
2524 match subject {
2525 ReturnType::Function(domain, codomain) => {
2526 ReturnType::MSet(Box::new(ReturnType::Tuple(vec![*domain, *codomain])))
2527 }
2528 ReturnType::Relation(domains) => {
2529 ReturnType::MSet(Box::new(ReturnType::Tuple(domains)))
2530 }
2531 ReturnType::Set(domain) => ReturnType::MSet(Box::new(*domain)),
2532 _ => bug!(
2533 "Invalid toMSet operation: expected the operand to be a set, relation, or function, got {self}: {subject}"
2534 ),
2535 }
2536 }
2537 Expression::ToRelation(_, function) => {
2538 let subject = function.return_type();
2539 match subject {
2540 ReturnType::Function(domain, codomain) => {
2541 ReturnType::Relation(vec![*domain, *codomain])
2542 }
2543 _ => bug!(
2544 "Invalid toRelation operation: expected the operand to be a function, got {self}: {subject}"
2545 ),
2546 }
2547 }
2548 Expression::RelationProj(_, relation, projections) => {
2549 let subject = relation.return_type();
2550 match subject {
2551 ReturnType::Relation(domains) => {
2552 let new_doms = domains
2553 .iter()
2554 .zip(projections.iter())
2555 .filter_map(|(domain, included)| {
2556 if included.is_none() {
2557 Some(domain.clone())
2559 } else {
2560 None
2561 }
2562 })
2563 .collect();
2564 ReturnType::Relation(new_doms)
2565 }
2566 _ => bug!(
2567 "Invalid RelationProj operation: expected the operand to be a relation, got {self}: {subject}"
2568 ),
2569 }
2570 }
2571 Expression::Card(..) => ReturnType::Int,
2572 Expression::Subsequence(_, _, _) => ReturnType::Bool,
2573 Expression::Substring(_, _, _) => ReturnType::Bool,
2574 }
2575 }
2576}
2577
2578impl Expression {
2579 fn for_each_expr_child(&self, f: &mut impl FnMut(&Expression)) {
2581 match self {
2582 Expression::AbstractLiteral(_, alit) => match alit {
2584 AbstractLiteral::Set(v) | AbstractLiteral::MSet(v) | AbstractLiteral::Tuple(v) => {
2585 for expr in v {
2586 f(expr);
2587 }
2588 }
2589 AbstractLiteral::Partition(two_d_v) => {
2590 for part in two_d_v {
2591 for expr in part {
2592 f(expr);
2593 }
2594 }
2595 }
2596 AbstractLiteral::Matrix(v, _domain) => {
2597 for expr in v {
2598 f(expr);
2599 }
2600 }
2601 AbstractLiteral::Record(rs) => {
2602 for r in rs {
2603 f(&r.value);
2604 }
2605 }
2606 AbstractLiteral::Sequence(v) => {
2607 for expr in v {
2608 f(expr);
2609 }
2610 }
2611 AbstractLiteral::Function(vs) => {
2612 for (a, b) in vs {
2613 f(a);
2614 f(b);
2615 }
2616 }
2617 AbstractLiteral::Variant(v) => {
2618 f(&v.value);
2619 }
2620 AbstractLiteral::Relation(vs) => {
2621 for exprs in vs {
2622 for expr in exprs {
2623 f(expr);
2624 }
2625 }
2626 }
2627 },
2628 Expression::Root(_, vs) => {
2629 for expr in vs {
2630 f(expr);
2631 }
2632 }
2633
2634 Expression::DominanceRelation(_, m1)
2636 | Expression::ToInt(_, m1)
2637 | Expression::Abs(_, m1)
2638 | Expression::Sum(_, m1)
2639 | Expression::Product(_, m1)
2640 | Expression::Min(_, m1)
2641 | Expression::Max(_, m1)
2642 | Expression::Not(_, m1)
2643 | Expression::Or(_, m1)
2644 | Expression::And(_, m1)
2645 | Expression::Neg(_, m1)
2646 | Expression::Defined(_, m1)
2647 | Expression::AllDiff(_, m1)
2648 | Expression::Factorial(_, m1)
2649 | Expression::Range(_, m1)
2650 | Expression::Participants(_, m1)
2651 | Expression::Parts(_, m1)
2652 | Expression::ToSet(_, m1)
2653 | Expression::ToMSet(_, m1)
2654 | Expression::ToRelation(_, m1)
2655 | Expression::Card(_, m1) => {
2656 f(m1);
2657 }
2658
2659 Expression::Table(_, m1, m2)
2661 | Expression::NegativeTable(_, m1, m2)
2662 | Expression::Bubble(_, m1, m2)
2663 | Expression::Imply(_, m1, m2)
2664 | Expression::Iff(_, m1, m2)
2665 | Expression::Union(_, m1, m2)
2666 | Expression::In(_, m1, m2)
2667 | Expression::Intersect(_, m1, m2)
2668 | Expression::Supset(_, m1, m2)
2669 | Expression::SupsetEq(_, m1, m2)
2670 | Expression::Subset(_, m1, m2)
2671 | Expression::SubsetEq(_, m1, m2)
2672 | Expression::Eq(_, m1, m2)
2673 | Expression::Neq(_, m1, m2)
2674 | Expression::Geq(_, m1, m2)
2675 | Expression::Leq(_, m1, m2)
2676 | Expression::Gt(_, m1, m2)
2677 | Expression::Lt(_, m1, m2)
2678 | Expression::SafeDiv(_, m1, m2)
2679 | Expression::UnsafeDiv(_, m1, m2)
2680 | Expression::SafeMod(_, m1, m2)
2681 | Expression::UnsafeMod(_, m1, m2)
2682 | Expression::UnsafePow(_, m1, m2)
2683 | Expression::SafePow(_, m1, m2)
2684 | Expression::Minus(_, m1, m2)
2685 | Expression::PairwiseSum(_, m1, m2)
2686 | Expression::PairwiseProduct(_, m1, m2)
2687 | Expression::Image(_, m1, m2)
2688 | Expression::ImageSet(_, m1, m2)
2689 | Expression::PreImage(_, m1, m2)
2690 | Expression::Inverse(_, m1, m2)
2691 | Expression::Restrict(_, m1, m2)
2692 | Expression::Apart(_, m1, m2)
2693 | Expression::Together(_, m1, m2)
2694 | Expression::Party(_, m1, m2)
2695 | Expression::LexLt(_, m1, m2)
2696 | Expression::LexLeq(_, m1, m2)
2697 | Expression::LexGt(_, m1, m2)
2698 | Expression::LexGeq(_, m1, m2)
2699 | Expression::Active(_, m1, m2)
2700 | Expression::Subsequence(_, m1, m2)
2701 | Expression::Substring(_, m1, m2) => {
2702 f(m1);
2703 f(m2);
2704 }
2705
2706 Expression::UnsafeIndex(_, m, vs) | Expression::SafeIndex(_, m, vs) => {
2708 f(m);
2709 for v in vs {
2710 f(v);
2711 }
2712 }
2713 Expression::UnsafeSlice(_, m, vs)
2715 | Expression::SafeSlice(_, m, vs)
2716 | Expression::RelationProj(_, m, vs) => {
2717 f(m);
2718 for e in vs.iter().flatten() {
2719 f(e);
2720 }
2721 }
2722
2723 Expression::InDomain(_, m, _) => {
2725 f(m);
2726 }
2727
2728 Expression::Flatten(_, opt, m) => {
2730 if let Some(e) = opt {
2731 f(e);
2732 }
2733 f(m);
2734 }
2735
2736 Expression::MinionReify(_, m, _) | Expression::MinionReifyImply(_, m, _) => {
2738 f(m);
2739 }
2740
2741 Expression::AuxDeclaration(_, _, m) => {
2743 f(m);
2744 }
2745
2746 Expression::SATInt(_, _, m, _) => {
2748 f(m);
2749 }
2750
2751 Expression::Comprehension(_, _)
2753 | Expression::AbstractComprehension(_, _)
2754 | Expression::Atomic(_, _)
2755 | Expression::FromSolution(_, _)
2756 | Expression::Metavar(_, _)
2757 | Expression::FlatAbsEq(_, _, _)
2758 | Expression::FlatMinusEq(_, _, _)
2759 | Expression::FlatProductEq(_, _, _, _)
2760 | Expression::MinionDivEqUndefZero(_, _, _, _)
2761 | Expression::MinionModuloEqUndefZero(_, _, _, _)
2762 | Expression::MinionPow(_, _, _, _)
2763 | Expression::FlatAllDiff(_, _)
2764 | Expression::FlatSumGeq(_, _, _)
2765 | Expression::FlatSumLeq(_, _, _)
2766 | Expression::FlatIneq(_, _, _, _)
2767 | Expression::FlatWatchedLiteral(_, _, _)
2768 | Expression::FlatWeightedSumLeq(_, _, _, _)
2769 | Expression::FlatWeightedSumGeq(_, _, _, _)
2770 | Expression::MinionWInIntervalSet(_, _, _)
2771 | Expression::MinionWInSet(_, _, _)
2772 | Expression::MinionElementOne(_, _, _, _)
2773 | Expression::FlatLexLt(_, _, _)
2774 | Expression::FlatLexLeq(_, _, _) => {}
2775 }
2776 }
2777}
2778
2779impl CacheHashable for Expression {
2780 fn invalidate_cache(&self) {
2781 self.meta_ref()
2782 .stored_hash
2783 .store(NO_HASH, Ordering::Relaxed);
2784 }
2785
2786 fn invalidate_cache_recursive(&self) {
2787 self.invalidate_cache();
2788 self.for_each_expr_child(&mut |child| {
2789 child.invalidate_cache_recursive();
2790 });
2791 }
2792
2793 fn get_cached_hash(&self) -> u64 {
2794 let stored = self.meta_ref().stored_hash.load(Ordering::Relaxed);
2795 if stored != NO_HASH {
2796 HASH_HITS.fetch_add(1, Ordering::Relaxed);
2797 return stored;
2798 }
2799 HASH_MISSES.fetch_add(1, Ordering::Relaxed);
2800 self.calculate_hash()
2801 }
2802
2803 fn calculate_hash(&self) -> u64 {
2804 let mut hasher = DefaultHasher::new();
2805 std::mem::discriminant(self).hash(&mut hasher);
2806 match self {
2807 Expression::AbstractLiteral(_, alit) => match alit {
2809 AbstractLiteral::Set(v)
2810 | AbstractLiteral::MSet(v)
2811 | AbstractLiteral::Tuple(v)
2812 | AbstractLiteral::Sequence(v) => {
2813 for expr in v {
2814 expr.get_cached_hash().hash(&mut hasher);
2815 }
2816 }
2817 AbstractLiteral::Matrix(v, domain) => {
2818 domain.hash(&mut hasher);
2819 for expr in v {
2820 expr.get_cached_hash().hash(&mut hasher);
2821 }
2822 }
2823 AbstractLiteral::Record(rs) => {
2824 for r in rs {
2825 r.name.hash(&mut hasher);
2826 r.value.get_cached_hash().hash(&mut hasher);
2827 }
2828 }
2829 AbstractLiteral::Function(vs) => {
2830 for (a, b) in vs {
2831 a.get_cached_hash().hash(&mut hasher);
2832 b.get_cached_hash().hash(&mut hasher);
2833 }
2834 }
2835 AbstractLiteral::Variant(v) => {
2836 v.name.hash(&mut hasher);
2837 v.value.get_cached_hash().hash(&mut hasher);
2838 }
2839 AbstractLiteral::Relation(v) => {
2840 for exprs in v {
2841 for expr in exprs {
2842 expr.get_cached_hash().hash(&mut hasher);
2843 }
2844 }
2845 }
2846 AbstractLiteral::Partition(v) => {
2847 for exprs in v {
2848 for expr in exprs {
2849 expr.get_cached_hash().hash(&mut hasher);
2850 }
2851 }
2852 }
2853 },
2854 Expression::Root(_, vs) => {
2855 for expr in vs {
2856 expr.get_cached_hash().hash(&mut hasher);
2857 }
2858 }
2859
2860 Expression::DominanceRelation(_, m1)
2862 | Expression::ToInt(_, m1)
2863 | Expression::Abs(_, m1)
2864 | Expression::Sum(_, m1)
2865 | Expression::Product(_, m1)
2866 | Expression::Min(_, m1)
2867 | Expression::Max(_, m1)
2868 | Expression::Not(_, m1)
2869 | Expression::Or(_, m1)
2870 | Expression::And(_, m1)
2871 | Expression::Neg(_, m1)
2872 | Expression::Defined(_, m1)
2873 | Expression::AllDiff(_, m1)
2874 | Expression::Factorial(_, m1)
2875 | Expression::Participants(_, m1)
2876 | Expression::Parts(_, m1)
2877 | Expression::Range(_, m1)
2878 | Expression::ToSet(_, m1)
2879 | Expression::ToMSet(_, m1)
2880 | Expression::ToRelation(_, m1)
2881 | Expression::Card(_, m1) => {
2882 m1.get_cached_hash().hash(&mut hasher);
2883 }
2884
2885 Expression::Table(_, m1, m2)
2887 | Expression::NegativeTable(_, m1, m2)
2888 | Expression::Bubble(_, m1, m2)
2889 | Expression::Imply(_, m1, m2)
2890 | Expression::Iff(_, m1, m2)
2891 | Expression::Union(_, m1, m2)
2892 | Expression::In(_, m1, m2)
2893 | Expression::Intersect(_, m1, m2)
2894 | Expression::Supset(_, m1, m2)
2895 | Expression::SupsetEq(_, m1, m2)
2896 | Expression::Subset(_, m1, m2)
2897 | Expression::SubsetEq(_, m1, m2)
2898 | Expression::Eq(_, m1, m2)
2899 | Expression::Neq(_, m1, m2)
2900 | Expression::Geq(_, m1, m2)
2901 | Expression::Leq(_, m1, m2)
2902 | Expression::Gt(_, m1, m2)
2903 | Expression::Lt(_, m1, m2)
2904 | Expression::Apart(_, m1, m2)
2905 | Expression::Together(_, m1, m2)
2906 | Expression::Party(_, m1, m2)
2907 | Expression::SafeDiv(_, m1, m2)
2908 | Expression::UnsafeDiv(_, m1, m2)
2909 | Expression::SafeMod(_, m1, m2)
2910 | Expression::UnsafeMod(_, m1, m2)
2911 | Expression::UnsafePow(_, m1, m2)
2912 | Expression::SafePow(_, m1, m2)
2913 | Expression::Minus(_, m1, m2)
2914 | Expression::PairwiseSum(_, m1, m2)
2915 | Expression::PairwiseProduct(_, m1, m2)
2916 | Expression::Image(_, m1, m2)
2917 | Expression::ImageSet(_, m1, m2)
2918 | Expression::PreImage(_, m1, m2)
2919 | Expression::Inverse(_, m1, m2)
2920 | Expression::Restrict(_, m1, m2)
2921 | Expression::LexLt(_, m1, m2)
2922 | Expression::LexLeq(_, m1, m2)
2923 | Expression::LexGt(_, m1, m2)
2924 | Expression::LexGeq(_, m1, m2)
2925 | Expression::Active(_, m1, m2)
2926 | Expression::Subsequence(_, m1, m2)
2927 | Expression::Substring(_, m1, m2) => {
2928 m1.get_cached_hash().hash(&mut hasher);
2929 m2.get_cached_hash().hash(&mut hasher);
2930 }
2931 Expression::UnsafeIndex(_, m, vs) | Expression::SafeIndex(_, m, vs) => {
2933 m.get_cached_hash().hash(&mut hasher);
2934 for v in vs {
2935 v.get_cached_hash().hash(&mut hasher);
2936 }
2937 }
2938
2939 Expression::UnsafeSlice(_, m, vs)
2941 | Expression::SafeSlice(_, m, vs)
2942 | Expression::RelationProj(_, m, vs) => {
2943 m.get_cached_hash().hash(&mut hasher);
2944 for v in vs {
2945 match v {
2946 Some(e) => e.get_cached_hash().hash(&mut hasher),
2947 None => 0u64.hash(&mut hasher),
2948 }
2949 }
2950 }
2951
2952 Expression::InDomain(_, m, d) => {
2954 m.get_cached_hash().hash(&mut hasher);
2955 d.hash(&mut hasher);
2956 }
2957
2958 Expression::Flatten(_, opt, m) => {
2960 if let Some(e) = opt {
2961 e.get_cached_hash().hash(&mut hasher);
2962 }
2963 m.get_cached_hash().hash(&mut hasher);
2964 }
2965
2966 Expression::MinionReify(_, m, a) | Expression::MinionReifyImply(_, m, a) => {
2968 m.get_cached_hash().hash(&mut hasher);
2969 a.hash(&mut hasher);
2970 }
2971
2972 Expression::AuxDeclaration(_, r, m) => {
2974 r.hash(&mut hasher);
2975 m.get_cached_hash().hash(&mut hasher);
2976 }
2977
2978 Expression::SATInt(_, enc, m, bounds) => {
2980 enc.hash(&mut hasher);
2981 m.get_cached_hash().hash(&mut hasher);
2982 bounds.hash(&mut hasher);
2983 }
2984
2985 Expression::Comprehension(_, c) => c.hash(&mut hasher),
2987 Expression::AbstractComprehension(_, c) => c.hash(&mut hasher),
2988
2989 Expression::Atomic(_, a) => a.hash(&mut hasher),
2991 Expression::FromSolution(_, a) => a.hash(&mut hasher),
2992 Expression::Metavar(_, u) => u.hash(&mut hasher),
2993
2994 Expression::FlatAbsEq(_, a1, a2) | Expression::FlatMinusEq(_, a1, a2) => {
2996 a1.hash(&mut hasher);
2997 a2.hash(&mut hasher);
2998 }
2999
3000 Expression::FlatProductEq(_, a1, a2, a3)
3002 | Expression::MinionDivEqUndefZero(_, a1, a2, a3)
3003 | Expression::MinionModuloEqUndefZero(_, a1, a2, a3)
3004 | Expression::MinionPow(_, a1, a2, a3) => {
3005 a1.hash(&mut hasher);
3006 a2.hash(&mut hasher);
3007 a3.hash(&mut hasher);
3008 }
3009
3010 Expression::FlatAllDiff(_, vs) => {
3012 for v in vs {
3013 v.hash(&mut hasher);
3014 }
3015 }
3016
3017 Expression::FlatSumGeq(_, vs, a) | Expression::FlatSumLeq(_, vs, a) => {
3019 for v in vs {
3020 v.hash(&mut hasher);
3021 }
3022 a.hash(&mut hasher);
3023 }
3024
3025 Expression::FlatIneq(_, a1, a2, lit) => {
3027 a1.hash(&mut hasher);
3028 a2.hash(&mut hasher);
3029 lit.hash(&mut hasher);
3030 }
3031
3032 Expression::FlatWatchedLiteral(_, r, l) => {
3034 r.hash(&mut hasher);
3035 l.hash(&mut hasher);
3036 }
3037
3038 Expression::FlatWeightedSumLeq(_, lits, atoms, a)
3040 | Expression::FlatWeightedSumGeq(_, lits, atoms, a) => {
3041 for l in lits {
3042 l.hash(&mut hasher);
3043 }
3044 for at in atoms {
3045 at.hash(&mut hasher);
3046 }
3047 a.hash(&mut hasher);
3048 }
3049
3050 Expression::MinionWInIntervalSet(_, a, vs) | Expression::MinionWInSet(_, a, vs) => {
3052 a.hash(&mut hasher);
3053 for v in vs {
3054 v.hash(&mut hasher);
3055 }
3056 }
3057
3058 Expression::MinionElementOne(_, vs, a1, a2) => {
3060 for v in vs {
3061 v.hash(&mut hasher);
3062 }
3063 a1.hash(&mut hasher);
3064 a2.hash(&mut hasher);
3065 }
3066
3067 Expression::FlatLexLt(_, v1, v2) | Expression::FlatLexLeq(_, v1, v2) => {
3069 for v in v1 {
3070 v.hash(&mut hasher);
3071 }
3072 for v in v2 {
3073 v.hash(&mut hasher);
3074 }
3075 }
3076 };
3077
3078 let result = hasher.finish();
3079 self.meta_ref().stored_hash.swap(result, Ordering::Relaxed);
3080 result
3081 }
3082}
3083
3084#[cfg(test)]
3085mod tests {
3086 use crate::matrix_expr;
3087
3088 use super::*;
3089
3090 #[test]
3091 fn test_domain_of_constant_sum() {
3092 let c1 = Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(1)));
3093 let c2 = Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(2)));
3094 let sum = Expression::Sum(Metadata::new(), Moo::new(matrix_expr![c1, c2]));
3095 assert_eq!(sum.domain_of(), Some(Domain::int(vec![Range::Single(3)])));
3096 }
3097
3098 #[test]
3099 fn test_domain_of_constant_invalid_type() {
3100 let c1 = Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(1)));
3101 let c2 = Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(true)));
3102 let sum = Expression::Sum(Metadata::new(), Moo::new(matrix_expr![c1, c2]));
3103 assert_eq!(sum.domain_of(), None);
3104 }
3105
3106 #[test]
3107 fn test_domain_of_empty_sum() {
3108 let sum = Expression::Sum(Metadata::new(), Moo::new(matrix_expr![]));
3109 assert_eq!(sum.domain_of(), None);
3110 }
3111}