1pub mod ac_matching;
4pub mod advanced_analysis;
5pub mod advanced_rewriting;
6mod analysis;
7pub mod confluence;
8pub mod defuzzification;
9pub mod distributive_laws;
10mod domain_validation;
11pub mod ltl_ctl_utilities;
12pub mod modal_axioms;
13pub mod modal_equivalences;
14pub mod normal_forms;
15pub mod optimization;
16pub mod optimization_pipeline;
17pub mod probabilistic_reasoning;
18pub mod rewriting;
19pub mod strategy_selector;
20pub mod temporal_equivalences;
21mod validation;
22
23use serde::{Deserialize, Serialize};
24
25use crate::term::Term;
26
27#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
29pub enum AggregateOp {
30 Count,
32 Sum,
34 Average,
36 Max,
38 Min,
40 Product,
42 Any,
44 All,
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
55pub enum TNormKind {
56 Minimum,
59
60 Product,
63
64 Lukasiewicz,
67
68 Drastic,
71
72 NilpotentMinimum,
74
75 Hamacher,
78}
79
80#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
83pub enum TCoNormKind {
84 Maximum,
87
88 ProbabilisticSum,
91
92 BoundedSum,
95
96 Drastic,
99
100 NilpotentMaximum,
103
104 Hamacher,
106}
107
108#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
110pub enum FuzzyNegationKind {
111 Standard,
113
114 Sugeno {
117 lambda: i32, },
120
121 Yager {
123 w: u32,
125 },
126}
127
128#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
130pub enum FuzzyImplicationKind {
131 Godel,
133
134 Lukasiewicz,
136
137 Reichenbach,
139
140 KleeneDienes,
142
143 Rescher,
145
146 Goguen,
148}
149
150#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
151pub enum TLExpr {
152 Pred {
153 name: String,
154 args: Vec<Term>,
155 },
156 And(Box<TLExpr>, Box<TLExpr>),
157 Or(Box<TLExpr>, Box<TLExpr>),
158 Not(Box<TLExpr>),
159 Exists {
160 var: String,
161 domain: String,
162 body: Box<TLExpr>,
163 },
164 ForAll {
165 var: String,
166 domain: String,
167 body: Box<TLExpr>,
168 },
169 Imply(Box<TLExpr>, Box<TLExpr>),
170 Score(Box<TLExpr>),
171
172 Add(Box<TLExpr>, Box<TLExpr>),
174 Sub(Box<TLExpr>, Box<TLExpr>),
175 Mul(Box<TLExpr>, Box<TLExpr>),
176 Div(Box<TLExpr>, Box<TLExpr>),
177 Pow(Box<TLExpr>, Box<TLExpr>),
178 Mod(Box<TLExpr>, Box<TLExpr>),
179 Min(Box<TLExpr>, Box<TLExpr>),
180 Max(Box<TLExpr>, Box<TLExpr>),
181
182 Abs(Box<TLExpr>),
184 Floor(Box<TLExpr>),
185 Ceil(Box<TLExpr>),
186 Round(Box<TLExpr>),
187 Sqrt(Box<TLExpr>),
188 Exp(Box<TLExpr>),
189 Log(Box<TLExpr>),
190 Sin(Box<TLExpr>),
191 Cos(Box<TLExpr>),
192 Tan(Box<TLExpr>),
193
194 Eq(Box<TLExpr>, Box<TLExpr>),
196 Lt(Box<TLExpr>, Box<TLExpr>),
197 Gt(Box<TLExpr>, Box<TLExpr>),
198 Lte(Box<TLExpr>, Box<TLExpr>),
199 Gte(Box<TLExpr>, Box<TLExpr>),
200
201 IfThenElse {
203 condition: Box<TLExpr>,
204 then_branch: Box<TLExpr>,
205 else_branch: Box<TLExpr>,
206 },
207
208 Constant(f64),
210
211 Aggregate {
213 op: AggregateOp,
214 var: String,
215 domain: String,
216 body: Box<TLExpr>,
217 group_by: Option<Vec<String>>,
219 },
220
221 Let {
223 var: String,
224 value: Box<TLExpr>,
225 body: Box<TLExpr>,
226 },
227
228 Box(Box<TLExpr>),
232
233 Diamond(Box<TLExpr>),
237
238 Next(Box<TLExpr>),
241
242 Eventually(Box<TLExpr>),
244
245 Always(Box<TLExpr>),
247
248 Until {
250 before: Box<TLExpr>,
251 after: Box<TLExpr>,
252 },
253
254 TNorm {
257 kind: TNormKind,
258 left: Box<TLExpr>,
259 right: Box<TLExpr>,
260 },
261
262 TCoNorm {
264 kind: TCoNormKind,
265 left: Box<TLExpr>,
266 right: Box<TLExpr>,
267 },
268
269 FuzzyNot {
271 kind: FuzzyNegationKind,
272 expr: Box<TLExpr>,
273 },
274
275 FuzzyImplication {
277 kind: FuzzyImplicationKind,
278 premise: Box<TLExpr>,
279 conclusion: Box<TLExpr>,
280 },
281
282 SoftExists {
288 var: String,
289 domain: String,
290 body: Box<TLExpr>,
291 temperature: f64,
293 },
294
295 SoftForAll {
300 var: String,
301 domain: String,
302 body: Box<TLExpr>,
303 temperature: f64,
305 },
306
307 WeightedRule {
310 weight: f64,
311 rule: Box<TLExpr>,
312 },
313
314 ProbabilisticChoice {
317 alternatives: Vec<(f64, TLExpr)>, },
319
320 Release {
324 released: Box<TLExpr>,
325 releaser: Box<TLExpr>,
326 },
327
328 WeakUntil {
330 before: Box<TLExpr>,
331 after: Box<TLExpr>,
332 },
333
334 StrongRelease {
336 released: Box<TLExpr>,
337 releaser: Box<TLExpr>,
338 },
339
340 Lambda {
346 var: String,
347 var_type: Option<String>,
349 body: Box<TLExpr>,
350 },
351
352 Apply {
354 function: Box<TLExpr>,
355 argument: Box<TLExpr>,
356 },
357
358 SetMembership {
361 element: Box<TLExpr>,
362 set: Box<TLExpr>,
363 },
364
365 SetUnion {
367 left: Box<TLExpr>,
368 right: Box<TLExpr>,
369 },
370
371 SetIntersection {
373 left: Box<TLExpr>,
374 right: Box<TLExpr>,
375 },
376
377 SetDifference {
379 left: Box<TLExpr>,
380 right: Box<TLExpr>,
381 },
382
383 SetCardinality {
385 set: Box<TLExpr>,
386 },
387
388 EmptySet,
390
391 SetComprehension {
393 var: String,
394 domain: String,
395 condition: Box<TLExpr>,
396 },
397
398 CountingExists {
402 var: String,
403 domain: String,
404 body: Box<TLExpr>,
405 min_count: usize,
407 },
408
409 CountingForAll {
412 var: String,
413 domain: String,
414 body: Box<TLExpr>,
415 min_count: usize,
417 },
418
419 ExactCount {
422 var: String,
423 domain: String,
424 body: Box<TLExpr>,
425 count: usize,
427 },
428
429 Majority {
432 var: String,
433 domain: String,
434 body: Box<TLExpr>,
435 },
436
437 LeastFixpoint {
441 var: String,
443 body: Box<TLExpr>,
445 },
446
447 GreatestFixpoint {
450 var: String,
452 body: Box<TLExpr>,
454 },
455
456 Nominal {
460 name: String,
461 },
462
463 At {
466 nominal: String,
467 formula: Box<TLExpr>,
468 },
469
470 Somewhere {
473 formula: Box<TLExpr>,
474 },
475
476 Everywhere {
479 formula: Box<TLExpr>,
480 },
481
482 AllDifferent {
485 variables: Vec<String>,
486 },
487
488 GlobalCardinality {
491 variables: Vec<String>,
492 values: Vec<TLExpr>,
493 min_occurrences: Vec<usize>,
494 max_occurrences: Vec<usize>,
495 },
496
497 Abducible {
500 name: String,
501 cost: f64, },
503
504 Explain {
506 formula: Box<TLExpr>,
507 },
508
509 SymbolLiteral(String),
513
514 Match {
517 scrutinee: Box<TLExpr>,
518 arms: Vec<(crate::pattern::MatchPattern, Box<TLExpr>)>,
519 },
520}
521
522impl TLExpr {
523 pub fn pred(name: impl Into<String>, args: Vec<Term>) -> Self {
524 TLExpr::Pred {
525 name: name.into(),
526 args,
527 }
528 }
529
530 pub fn and(left: TLExpr, right: TLExpr) -> Self {
531 TLExpr::And(Box::new(left), Box::new(right))
532 }
533
534 pub fn or(left: TLExpr, right: TLExpr) -> Self {
535 TLExpr::Or(Box::new(left), Box::new(right))
536 }
537
538 pub fn negate(expr: TLExpr) -> Self {
539 TLExpr::Not(Box::new(expr))
540 }
541
542 pub fn exists(var: impl Into<String>, domain: impl Into<String>, body: TLExpr) -> Self {
543 TLExpr::Exists {
544 var: var.into(),
545 domain: domain.into(),
546 body: Box::new(body),
547 }
548 }
549
550 pub fn forall(var: impl Into<String>, domain: impl Into<String>, body: TLExpr) -> Self {
551 TLExpr::ForAll {
552 var: var.into(),
553 domain: domain.into(),
554 body: Box::new(body),
555 }
556 }
557
558 pub fn imply(premise: TLExpr, conclusion: TLExpr) -> Self {
559 TLExpr::Imply(Box::new(premise), Box::new(conclusion))
560 }
561
562 pub fn score(expr: TLExpr) -> Self {
563 TLExpr::Score(Box::new(expr))
564 }
565
566 #[allow(clippy::should_implement_trait)]
568 pub fn add(left: TLExpr, right: TLExpr) -> Self {
569 TLExpr::Add(Box::new(left), Box::new(right))
570 }
571
572 #[allow(clippy::should_implement_trait)]
573 pub fn sub(left: TLExpr, right: TLExpr) -> Self {
574 TLExpr::Sub(Box::new(left), Box::new(right))
575 }
576
577 #[allow(clippy::should_implement_trait)]
578 pub fn mul(left: TLExpr, right: TLExpr) -> Self {
579 TLExpr::Mul(Box::new(left), Box::new(right))
580 }
581
582 #[allow(clippy::should_implement_trait)]
583 pub fn div(left: TLExpr, right: TLExpr) -> Self {
584 TLExpr::Div(Box::new(left), Box::new(right))
585 }
586
587 pub fn pow(left: TLExpr, right: TLExpr) -> Self {
588 TLExpr::Pow(Box::new(left), Box::new(right))
589 }
590
591 pub fn modulo(left: TLExpr, right: TLExpr) -> Self {
592 TLExpr::Mod(Box::new(left), Box::new(right))
593 }
594
595 pub fn min(left: TLExpr, right: TLExpr) -> Self {
596 TLExpr::Min(Box::new(left), Box::new(right))
597 }
598
599 pub fn max(left: TLExpr, right: TLExpr) -> Self {
600 TLExpr::Max(Box::new(left), Box::new(right))
601 }
602
603 pub fn abs(expr: TLExpr) -> Self {
605 TLExpr::Abs(Box::new(expr))
606 }
607
608 pub fn floor(expr: TLExpr) -> Self {
609 TLExpr::Floor(Box::new(expr))
610 }
611
612 pub fn ceil(expr: TLExpr) -> Self {
613 TLExpr::Ceil(Box::new(expr))
614 }
615
616 pub fn round(expr: TLExpr) -> Self {
617 TLExpr::Round(Box::new(expr))
618 }
619
620 pub fn sqrt(expr: TLExpr) -> Self {
621 TLExpr::Sqrt(Box::new(expr))
622 }
623
624 pub fn exp(expr: TLExpr) -> Self {
625 TLExpr::Exp(Box::new(expr))
626 }
627
628 pub fn log(expr: TLExpr) -> Self {
629 TLExpr::Log(Box::new(expr))
630 }
631
632 pub fn sin(expr: TLExpr) -> Self {
633 TLExpr::Sin(Box::new(expr))
634 }
635
636 pub fn cos(expr: TLExpr) -> Self {
637 TLExpr::Cos(Box::new(expr))
638 }
639
640 pub fn tan(expr: TLExpr) -> Self {
641 TLExpr::Tan(Box::new(expr))
642 }
643
644 pub fn eq(left: TLExpr, right: TLExpr) -> Self {
646 TLExpr::Eq(Box::new(left), Box::new(right))
647 }
648
649 pub fn lt(left: TLExpr, right: TLExpr) -> Self {
650 TLExpr::Lt(Box::new(left), Box::new(right))
651 }
652
653 pub fn gt(left: TLExpr, right: TLExpr) -> Self {
654 TLExpr::Gt(Box::new(left), Box::new(right))
655 }
656
657 pub fn lte(left: TLExpr, right: TLExpr) -> Self {
658 TLExpr::Lte(Box::new(left), Box::new(right))
659 }
660
661 pub fn gte(left: TLExpr, right: TLExpr) -> Self {
662 TLExpr::Gte(Box::new(left), Box::new(right))
663 }
664
665 pub fn if_then_else(condition: TLExpr, then_branch: TLExpr, else_branch: TLExpr) -> Self {
667 TLExpr::IfThenElse {
668 condition: Box::new(condition),
669 then_branch: Box::new(then_branch),
670 else_branch: Box::new(else_branch),
671 }
672 }
673
674 pub fn constant(value: f64) -> Self {
676 TLExpr::Constant(value)
677 }
678
679 pub fn aggregate(
681 op: AggregateOp,
682 var: impl Into<String>,
683 domain: impl Into<String>,
684 body: TLExpr,
685 ) -> Self {
686 TLExpr::Aggregate {
687 op,
688 var: var.into(),
689 domain: domain.into(),
690 body: Box::new(body),
691 group_by: None,
692 }
693 }
694
695 pub fn aggregate_with_group_by(
696 op: AggregateOp,
697 var: impl Into<String>,
698 domain: impl Into<String>,
699 body: TLExpr,
700 group_by: Vec<String>,
701 ) -> Self {
702 TLExpr::Aggregate {
703 op,
704 var: var.into(),
705 domain: domain.into(),
706 body: Box::new(body),
707 group_by: Some(group_by),
708 }
709 }
710
711 pub fn count(var: impl Into<String>, domain: impl Into<String>, body: TLExpr) -> Self {
712 Self::aggregate(AggregateOp::Count, var, domain, body)
713 }
714
715 pub fn sum(var: impl Into<String>, domain: impl Into<String>, body: TLExpr) -> Self {
716 Self::aggregate(AggregateOp::Sum, var, domain, body)
717 }
718
719 pub fn average(var: impl Into<String>, domain: impl Into<String>, body: TLExpr) -> Self {
720 Self::aggregate(AggregateOp::Average, var, domain, body)
721 }
722
723 pub fn max_agg(var: impl Into<String>, domain: impl Into<String>, body: TLExpr) -> Self {
724 Self::aggregate(AggregateOp::Max, var, domain, body)
725 }
726
727 pub fn min_agg(var: impl Into<String>, domain: impl Into<String>, body: TLExpr) -> Self {
728 Self::aggregate(AggregateOp::Min, var, domain, body)
729 }
730
731 pub fn product(var: impl Into<String>, domain: impl Into<String>, body: TLExpr) -> Self {
732 Self::aggregate(AggregateOp::Product, var, domain, body)
733 }
734
735 pub fn let_binding(var: impl Into<String>, value: TLExpr, body: TLExpr) -> Self {
737 TLExpr::Let {
738 var: var.into(),
739 value: Box::new(value),
740 body: Box::new(body),
741 }
742 }
743
744 pub fn modal_box(expr: TLExpr) -> Self {
749 TLExpr::Box(Box::new(expr))
750 }
751
752 pub fn modal_diamond(expr: TLExpr) -> Self {
756 TLExpr::Diamond(Box::new(expr))
757 }
758
759 pub fn next(expr: TLExpr) -> Self {
764 TLExpr::Next(Box::new(expr))
765 }
766
767 pub fn eventually(expr: TLExpr) -> Self {
771 TLExpr::Eventually(Box::new(expr))
772 }
773
774 pub fn always(expr: TLExpr) -> Self {
778 TLExpr::Always(Box::new(expr))
779 }
780
781 pub fn until(before: TLExpr, after: TLExpr) -> Self {
785 TLExpr::Until {
786 before: Box::new(before),
787 after: Box::new(after),
788 }
789 }
790
791 pub fn tnorm(kind: TNormKind, left: TLExpr, right: TLExpr) -> Self {
795 TLExpr::TNorm {
796 kind,
797 left: Box::new(left),
798 right: Box::new(right),
799 }
800 }
801
802 pub fn fuzzy_and(left: TLExpr, right: TLExpr) -> Self {
804 Self::tnorm(TNormKind::Minimum, left, right)
805 }
806
807 pub fn probabilistic_and(left: TLExpr, right: TLExpr) -> Self {
809 Self::tnorm(TNormKind::Product, left, right)
810 }
811
812 pub fn tconorm(kind: TCoNormKind, left: TLExpr, right: TLExpr) -> Self {
814 TLExpr::TCoNorm {
815 kind,
816 left: Box::new(left),
817 right: Box::new(right),
818 }
819 }
820
821 pub fn fuzzy_or(left: TLExpr, right: TLExpr) -> Self {
823 Self::tconorm(TCoNormKind::Maximum, left, right)
824 }
825
826 pub fn probabilistic_or(left: TLExpr, right: TLExpr) -> Self {
828 Self::tconorm(TCoNormKind::ProbabilisticSum, left, right)
829 }
830
831 pub fn fuzzy_not(kind: FuzzyNegationKind, expr: TLExpr) -> Self {
833 TLExpr::FuzzyNot {
834 kind,
835 expr: Box::new(expr),
836 }
837 }
838
839 pub fn standard_fuzzy_not(expr: TLExpr) -> Self {
841 Self::fuzzy_not(FuzzyNegationKind::Standard, expr)
842 }
843
844 pub fn fuzzy_imply(kind: FuzzyImplicationKind, premise: TLExpr, conclusion: TLExpr) -> Self {
846 TLExpr::FuzzyImplication {
847 kind,
848 premise: Box::new(premise),
849 conclusion: Box::new(conclusion),
850 }
851 }
852
853 pub fn soft_exists(
863 var: impl Into<String>,
864 domain: impl Into<String>,
865 body: TLExpr,
866 temperature: f64,
867 ) -> Self {
868 TLExpr::SoftExists {
869 var: var.into(),
870 domain: domain.into(),
871 body: Box::new(body),
872 temperature,
873 }
874 }
875
876 pub fn soft_forall(
884 var: impl Into<String>,
885 domain: impl Into<String>,
886 body: TLExpr,
887 temperature: f64,
888 ) -> Self {
889 TLExpr::SoftForAll {
890 var: var.into(),
891 domain: domain.into(),
892 body: Box::new(body),
893 temperature,
894 }
895 }
896
897 pub fn weighted_rule(weight: f64, rule: TLExpr) -> Self {
903 TLExpr::WeightedRule {
904 weight,
905 rule: Box::new(rule),
906 }
907 }
908
909 pub fn probabilistic_choice(alternatives: Vec<(f64, TLExpr)>) -> Self {
914 TLExpr::ProbabilisticChoice { alternatives }
915 }
916
917 pub fn release(released: TLExpr, releaser: TLExpr) -> Self {
923 TLExpr::Release {
924 released: Box::new(released),
925 releaser: Box::new(releaser),
926 }
927 }
928
929 pub fn weak_until(before: TLExpr, after: TLExpr) -> Self {
933 TLExpr::WeakUntil {
934 before: Box::new(before),
935 after: Box::new(after),
936 }
937 }
938
939 pub fn strong_release(released: TLExpr, releaser: TLExpr) -> Self {
943 TLExpr::StrongRelease {
944 released: Box::new(released),
945 releaser: Box::new(releaser),
946 }
947 }
948
949 pub fn lambda(var: impl Into<String>, var_type: Option<String>, body: TLExpr) -> Self {
960 TLExpr::Lambda {
961 var: var.into(),
962 var_type,
963 body: Box::new(body),
964 }
965 }
966
967 pub fn lambda_untyped(var: impl Into<String>, body: TLExpr) -> Self {
969 Self::lambda(var, None, body)
970 }
971
972 pub fn apply(function: TLExpr, argument: TLExpr) -> Self {
978 TLExpr::Apply {
979 function: Box::new(function),
980 argument: Box::new(argument),
981 }
982 }
983
984 pub fn set_membership(element: TLExpr, set: TLExpr) -> Self {
988 TLExpr::SetMembership {
989 element: Box::new(element),
990 set: Box::new(set),
991 }
992 }
993
994 pub fn set_union(left: TLExpr, right: TLExpr) -> Self {
996 TLExpr::SetUnion {
997 left: Box::new(left),
998 right: Box::new(right),
999 }
1000 }
1001
1002 pub fn set_intersection(left: TLExpr, right: TLExpr) -> Self {
1004 TLExpr::SetIntersection {
1005 left: Box::new(left),
1006 right: Box::new(right),
1007 }
1008 }
1009
1010 pub fn set_difference(left: TLExpr, right: TLExpr) -> Self {
1012 TLExpr::SetDifference {
1013 left: Box::new(left),
1014 right: Box::new(right),
1015 }
1016 }
1017
1018 pub fn set_cardinality(set: TLExpr) -> Self {
1020 TLExpr::SetCardinality { set: Box::new(set) }
1021 }
1022
1023 pub fn empty_set() -> Self {
1025 TLExpr::EmptySet
1026 }
1027
1028 pub fn set_comprehension(
1030 var: impl Into<String>,
1031 domain: impl Into<String>,
1032 condition: TLExpr,
1033 ) -> Self {
1034 TLExpr::SetComprehension {
1035 var: var.into(),
1036 domain: domain.into(),
1037 condition: Box::new(condition),
1038 }
1039 }
1040
1041 pub fn counting_exists(
1047 var: impl Into<String>,
1048 domain: impl Into<String>,
1049 body: TLExpr,
1050 min_count: usize,
1051 ) -> Self {
1052 TLExpr::CountingExists {
1053 var: var.into(),
1054 domain: domain.into(),
1055 body: Box::new(body),
1056 min_count,
1057 }
1058 }
1059
1060 pub fn counting_forall(
1064 var: impl Into<String>,
1065 domain: impl Into<String>,
1066 body: TLExpr,
1067 min_count: usize,
1068 ) -> Self {
1069 TLExpr::CountingForAll {
1070 var: var.into(),
1071 domain: domain.into(),
1072 body: Box::new(body),
1073 min_count,
1074 }
1075 }
1076
1077 pub fn exact_count(
1081 var: impl Into<String>,
1082 domain: impl Into<String>,
1083 body: TLExpr,
1084 count: usize,
1085 ) -> Self {
1086 TLExpr::ExactCount {
1087 var: var.into(),
1088 domain: domain.into(),
1089 body: Box::new(body),
1090 count,
1091 }
1092 }
1093
1094 pub fn majority(var: impl Into<String>, domain: impl Into<String>, body: TLExpr) -> Self {
1098 TLExpr::Majority {
1099 var: var.into(),
1100 domain: domain.into(),
1101 body: Box::new(body),
1102 }
1103 }
1104
1105 pub fn least_fixpoint(var: impl Into<String>, body: TLExpr) -> Self {
1111 TLExpr::LeastFixpoint {
1112 var: var.into(),
1113 body: Box::new(body),
1114 }
1115 }
1116
1117 pub fn greatest_fixpoint(var: impl Into<String>, body: TLExpr) -> Self {
1121 TLExpr::GreatestFixpoint {
1122 var: var.into(),
1123 body: Box::new(body),
1124 }
1125 }
1126
1127 pub fn nominal(name: impl Into<String>) -> Self {
1131 TLExpr::Nominal { name: name.into() }
1132 }
1133
1134 pub fn at(nominal: impl Into<String>, formula: TLExpr) -> Self {
1138 TLExpr::At {
1139 nominal: nominal.into(),
1140 formula: Box::new(formula),
1141 }
1142 }
1143
1144 pub fn somewhere(formula: TLExpr) -> Self {
1148 TLExpr::Somewhere {
1149 formula: Box::new(formula),
1150 }
1151 }
1152
1153 pub fn everywhere(formula: TLExpr) -> Self {
1157 TLExpr::Everywhere {
1158 formula: Box::new(formula),
1159 }
1160 }
1161
1162 pub fn all_different(variables: Vec<String>) -> Self {
1168 TLExpr::AllDifferent { variables }
1169 }
1170
1171 pub fn global_cardinality(
1175 variables: Vec<String>,
1176 values: Vec<TLExpr>,
1177 min_occurrences: Vec<usize>,
1178 max_occurrences: Vec<usize>,
1179 ) -> Self {
1180 TLExpr::GlobalCardinality {
1181 variables,
1182 values,
1183 min_occurrences,
1184 max_occurrences,
1185 }
1186 }
1187
1188 pub fn abducible(name: impl Into<String>, cost: f64) -> Self {
1194 TLExpr::Abducible {
1195 name: name.into(),
1196 cost,
1197 }
1198 }
1199
1200 pub fn explain(formula: TLExpr) -> Self {
1202 TLExpr::Explain {
1203 formula: Box::new(formula),
1204 }
1205 }
1206
1207 pub fn symbol_literal(s: impl Into<String>) -> Self {
1209 TLExpr::SymbolLiteral(s.into())
1210 }
1211
1212 pub fn match_expr(
1218 scrutinee: TLExpr,
1219 arms: Vec<(crate::pattern::MatchPattern, TLExpr)>,
1220 ) -> Self {
1221 TLExpr::Match {
1222 scrutinee: Box::new(scrutinee),
1223 arms: arms.into_iter().map(|(p, b)| (p, Box::new(b))).collect(),
1224 }
1225 }
1226
1227 pub fn substitute(&self, var: &str, value: &TLExpr) -> Self {
1252 optimization::substitution::substitute(self, var, value)
1253 }
1254}