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