1use crate::{
71 model::Model,
72 vars::{Val, VarId},
73 props::PropId,
74};
75
76#[derive(Debug, Clone)]
83pub enum ExprBuilder {
84 Var(VarId),
86 Val(Val),
88 Add(Box<ExprBuilder>, Box<ExprBuilder>),
90 Sub(Box<ExprBuilder>, Box<ExprBuilder>),
92 Mul(Box<ExprBuilder>, Box<ExprBuilder>),
94 Div(Box<ExprBuilder>, Box<ExprBuilder>),
96}
97
98#[derive(Clone)]
100pub struct Constraint {
101 kind: ConstraintKind,
102}
103
104pub struct Builder {
106 model: *mut Model, current_expr: ExprBuilder,
108}
109
110#[derive(Clone)]
111enum ConstraintKind {
112 Binary {
114 left: ExprBuilder,
115 op: ComparisonOp,
116 right: ExprBuilder,
117 },
118 And(Box<Constraint>, Box<Constraint>),
120 Or(Box<Constraint>, Box<Constraint>),
121 Not(Box<Constraint>),
122}
123
124#[derive(Clone, Debug)]
125enum ComparisonOp {
126 Eq, Ne, Lt, Le, Gt, Ge, }
133
134impl ExprBuilder {
135 #[inline]
137 pub fn from_var(var_id: VarId) -> Self {
138 ExprBuilder::Var(var_id)
139 }
140
141 #[inline]
143 pub fn from_val(value: Val) -> Self {
144 ExprBuilder::Val(value)
145 }
146
147 #[inline]
150 pub fn add(self, other: impl Into<ExprBuilder>) -> ExprBuilder {
151 let other = other.into();
152
153 if let (ExprBuilder::Val(a), ExprBuilder::Val(b)) = (&self, &other) {
155 return ExprBuilder::Val(*a + *b);
156 }
157
158 ExprBuilder::Add(Box::new(self), Box::new(other))
159 }
160
161 #[inline]
164 pub fn sub(self, other: impl Into<ExprBuilder>) -> ExprBuilder {
165 let other = other.into();
166
167 if let (ExprBuilder::Val(a), ExprBuilder::Val(b)) = (&self, &other) {
169 return ExprBuilder::Val(*a - *b);
170 }
171
172 ExprBuilder::Sub(Box::new(self), Box::new(other))
173 }
174
175 #[inline]
178 pub fn mul(self, other: impl Into<ExprBuilder>) -> ExprBuilder {
179 let other = other.into();
180
181 if let (ExprBuilder::Val(a), ExprBuilder::Val(b)) = (&self, &other) {
183 return ExprBuilder::Val(*a * *b);
184 }
185
186 if let ExprBuilder::Val(val) = &other {
188 if let Some(1) = val.as_int() {
189 return self;
190 }
191 }
192 if let ExprBuilder::Val(val) = &self {
193 if let Some(1) = val.as_int() {
194 return other;
195 }
196 }
197
198 ExprBuilder::Mul(Box::new(self), Box::new(other))
199 }
200
201 #[inline]
204 pub fn div(self, other: impl Into<ExprBuilder>) -> ExprBuilder {
205 let other = other.into();
206
207 if let (ExprBuilder::Val(a), ExprBuilder::Val(b)) = (&self, &other) {
209 return ExprBuilder::Val(*a / *b);
210 }
211
212 if let ExprBuilder::Val(val) = &other {
214 if let Some(1) = val.as_int() {
215 return self;
216 }
217 }
218
219 ExprBuilder::Div(Box::new(self), Box::new(other))
220 }
221
222 #[inline]
224 pub fn eq(self, other: impl Into<ExprBuilder>) -> Constraint {
225 Constraint {
226 kind: ConstraintKind::Binary {
227 left: self,
228 op: ComparisonOp::Eq,
229 right: other.into(),
230 },
231 }
232 }
233
234 #[inline]
236 pub fn le(self, other: impl Into<ExprBuilder>) -> Constraint {
237 Constraint {
238 kind: ConstraintKind::Binary {
239 left: self,
240 op: ComparisonOp::Le,
241 right: other.into(),
242 },
243 }
244 }
245
246 #[inline]
248 pub fn gt(self, other: impl Into<ExprBuilder>) -> Constraint {
249 Constraint {
250 kind: ConstraintKind::Binary {
251 left: self,
252 op: ComparisonOp::Gt,
253 right: other.into(),
254 },
255 }
256 }
257
258 pub fn lt(self, other: impl Into<ExprBuilder>) -> Constraint {
260 Constraint {
261 kind: ConstraintKind::Binary {
262 left: self,
263 op: ComparisonOp::Lt,
264 right: other.into(),
265 },
266 }
267 }
268
269 pub fn ge(self, other: impl Into<ExprBuilder>) -> Constraint {
271 Constraint {
272 kind: ConstraintKind::Binary {
273 left: self,
274 op: ComparisonOp::Ge,
275 right: other.into(),
276 },
277 }
278 }
279
280 pub fn ne(self, other: impl Into<ExprBuilder>) -> Constraint {
282 Constraint {
283 kind: ConstraintKind::Binary {
284 left: self,
285 op: ComparisonOp::Ne,
286 right: other.into(),
287 },
288 }
289 }
290}
291
292impl Constraint {
293 pub fn and(self, other: Constraint) -> Constraint {
295 Constraint {
296 kind: ConstraintKind::And(Box::new(self), Box::new(other)),
297 }
298 }
299
300 pub fn or(self, other: Constraint) -> Constraint {
302 Constraint {
303 kind: ConstraintKind::Or(Box::new(self), Box::new(other)),
304 }
305 }
306
307 pub fn not(self) -> Constraint {
309 Constraint {
310 kind: ConstraintKind::Not(Box::new(self)),
311 }
312 }
313}
314
315impl Constraint {
318 pub fn and_all(constraints: Vec<Constraint>) -> Option<Constraint> {
320 if constraints.is_empty() {
321 return None;
322 }
323
324 Some(constraints.into_iter().reduce(|acc, c| acc.and(c)).unwrap())
325 }
326
327 pub fn or_all(constraints: Vec<Constraint>) -> Option<Constraint> {
329 if constraints.is_empty() {
330 return None;
331 }
332
333 Some(constraints.into_iter().reduce(|acc, c| acc.or(c)).unwrap())
334 }
335}
336
337pub fn and_all(constraints: Vec<Constraint>) -> Option<Constraint> {
339 Constraint::and_all(constraints)
340}
341
342pub fn or_all(constraints: Vec<Constraint>) -> Option<Constraint> {
343 Constraint::or_all(constraints)
344}
345
346pub fn all_of(constraints: Vec<Constraint>) -> Option<Constraint> {
348 and_all(constraints)
349}
350
351pub fn any_of(constraints: Vec<Constraint>) -> Option<Constraint> {
353 or_all(constraints)
354}
355
356pub trait ConstraintVecExt {
358 fn and_all(self) -> Option<Constraint>;
360
361 fn or_all(self) -> Option<Constraint>;
363
364 fn postall(self, model: &mut Model) -> Vec<PropId>;
366}
367
368impl ConstraintVecExt for Vec<Constraint> {
369 fn and_all(self) -> Option<Constraint> {
370 Constraint::and_all(self)
371 }
372
373 fn or_all(self) -> Option<Constraint> {
374 Constraint::or_all(self)
375 }
376
377 fn postall(self, model: &mut Model) -> Vec<PropId> {
378 self.into_iter()
379 .map(|constraint| model.post(constraint))
380 .collect()
381 }
382}
383
384impl Builder {
385 pub fn new(model: &mut Model, var: VarId) -> Self {
387 Builder {
388 model: model as *mut Model,
389 current_expr: ExprBuilder::from_var(var),
390 }
391 }
392
393 pub fn add(mut self, other: impl Into<ExprBuilder>) -> Self {
395 self.current_expr = self.current_expr.add(other);
396 self
397 }
398
399 pub fn sub(mut self, other: impl Into<ExprBuilder>) -> Self {
401 self.current_expr = self.current_expr.sub(other);
402 self
403 }
404
405 pub fn mul(mut self, other: impl Into<ExprBuilder>) -> Self {
407 self.current_expr = self.current_expr.mul(other);
408 self
409 }
410
411 pub fn div(mut self, other: impl Into<ExprBuilder>) -> Self {
413 self.current_expr = self.current_expr.div(other);
414 self
415 }
416
417 pub fn eq(self, other: impl Into<ExprBuilder>) -> PropId {
419 let constraint = self.current_expr.eq(other);
420 unsafe { &mut *self.model }.post(constraint)
421 }
422
423 pub fn ne(self, other: impl Into<ExprBuilder>) -> PropId {
425 let constraint = self.current_expr.ne(other);
426 unsafe { &mut *self.model }.post(constraint)
427 }
428
429 pub fn lt(self, other: impl Into<ExprBuilder>) -> PropId {
431 let constraint = self.current_expr.lt(other);
432 unsafe { &mut *self.model }.post(constraint)
433 }
434
435 pub fn le(self, other: impl Into<ExprBuilder>) -> PropId {
437 let constraint = self.current_expr.le(other);
438 unsafe { &mut *self.model }.post(constraint)
439 }
440
441 pub fn gt(self, other: impl Into<ExprBuilder>) -> PropId {
443 let constraint = self.current_expr.gt(other);
444 unsafe { &mut *self.model }.post(constraint)
445 }
446
447 pub fn ge(self, other: impl Into<ExprBuilder>) -> PropId {
449 let constraint = self.current_expr.ge(other);
450 unsafe { &mut *self.model }.post(constraint)
451 }
452}
453
454fn create_result_var(model: &mut Model, expr: &ExprBuilder) -> VarId {
456 match expr {
459 ExprBuilder::Var(var_id) => *var_id,
460 ExprBuilder::Val(_) => {
461 model.int(-1000, 1000) }
464 _ => model.int(-1000, 1000), }
466}
467
468fn post_expression_constraint(model: &mut Model, expr: &ExprBuilder, result: VarId) -> PropId {
470 match expr {
471 ExprBuilder::Var(var_id) => {
472 model.props.equals(*var_id, result)
474 }
475 ExprBuilder::Val(val) => {
476 model.props.equals(*val, result)
478 }
479 ExprBuilder::Add(left, right) => {
480 let left_var = create_result_var(model, left);
481 let right_var = create_result_var(model, right);
482
483 if !matches!(**left, ExprBuilder::Var(_)) {
485 post_expression_constraint(model, left, left_var);
486 }
487 if !matches!(**right, ExprBuilder::Var(_)) {
488 post_expression_constraint(model, right, right_var);
489 }
490
491 model.props.add(left_var, right_var, result)
493 }
494 ExprBuilder::Sub(left, right) => {
495 let left_var = create_result_var(model, left);
496 let right_var = create_result_var(model, right);
497
498 if !matches!(**left, ExprBuilder::Var(_)) {
500 post_expression_constraint(model, left, left_var);
501 }
502 if !matches!(**right, ExprBuilder::Var(_)) {
503 post_expression_constraint(model, right, right_var);
504 }
505
506 model.props.sub(left_var, right_var, result)
508 }
509 ExprBuilder::Mul(left, right) => {
510 let left_var = create_result_var(model, left);
511 let right_var = create_result_var(model, right);
512
513 if !matches!(**left, ExprBuilder::Var(_)) {
515 post_expression_constraint(model, left, left_var);
516 }
517 if !matches!(**right, ExprBuilder::Var(_)) {
518 post_expression_constraint(model, right, right_var);
519 }
520
521 model.props.mul(left_var, right_var, result)
523 }
524 ExprBuilder::Div(left, right) => {
525 let left_var = create_result_var(model, left);
526 let right_var = create_result_var(model, right);
527
528 if !matches!(**left, ExprBuilder::Var(_)) {
530 post_expression_constraint(model, left, left_var);
531 }
532 if !matches!(**right, ExprBuilder::Var(_)) {
533 post_expression_constraint(model, right, right_var);
534 }
535
536 model.props.div(left_var, right_var, result)
538 }
539 }
540}
541
542fn get_expr_var(model: &mut Model, expr: &ExprBuilder) -> VarId {
544 match expr {
545 ExprBuilder::Var(var_id) => *var_id,
546 ExprBuilder::Val(val) => {
547 match val {
549 Val::ValI(i) => model.int(*i, *i),
550 Val::ValF(f) => model.float(*f, *f),
551 }
552 }
553 _ => {
554 let result_var = create_result_var(model, expr);
556 post_expression_constraint(model, expr, result_var);
557 result_var
558 }
559 }
560}
561
562#[inline]
564fn post_constraint_kind(model: &mut Model, kind: &ConstraintKind) -> PropId {
565 match kind {
566 ConstraintKind::Binary { left, op, right } => {
567 if let (ExprBuilder::Var(var), ExprBuilder::Val(val)) = (left, right) {
569 return post_var_val_constraint(model, *var, op, *val);
570 }
571 if let (ExprBuilder::Val(val), ExprBuilder::Var(var)) = (left, right) {
572 return post_val_var_constraint(model, *val, op, *var);
573 }
574
575 let left_var = get_expr_var(model, left);
577 let right_var = get_expr_var(model, right);
578
579 match op {
580 ComparisonOp::Eq => model.props.equals(left_var, right_var),
581 ComparisonOp::Ne => model.props.not_equals(left_var, right_var),
582 ComparisonOp::Lt => model.props.less_than(left_var, right_var),
583 ComparisonOp::Le => model.props.less_than_or_equals(left_var, right_var),
584 ComparisonOp::Gt => model.props.greater_than(left_var, right_var),
585 ComparisonOp::Ge => model.props.greater_than_or_equals(left_var, right_var),
586 }
587 }
588 ConstraintKind::And(left, right) => {
589 post_constraint_kind(model, &left.kind);
591 post_constraint_kind(model, &right.kind)
592 }
593 ConstraintKind::Or(left, right) => {
594 post_constraint_kind(model, &left.kind);
597 post_constraint_kind(model, &right.kind)
598 }
599 ConstraintKind::Not(constraint) => {
600 post_constraint_kind(model, &constraint.kind)
603 }
604 }
605}
606
607#[inline]
609fn post_var_val_constraint(model: &mut Model, var: VarId, op: &ComparisonOp, val: Val) -> PropId {
610 let val_var = match val {
611 Val::ValI(i) => model.int(i, i),
612 Val::ValF(f) => model.float(f, f),
613 };
614
615 match op {
616 ComparisonOp::Eq => model.props.equals(var, val_var),
617 ComparisonOp::Ne => model.props.not_equals(var, val_var),
618 ComparisonOp::Lt => model.props.less_than(var, val_var),
619 ComparisonOp::Le => model.props.less_than_or_equals(var, val_var),
620 ComparisonOp::Gt => model.props.greater_than(var, val_var),
621 ComparisonOp::Ge => model.props.greater_than_or_equals(var, val_var),
622 }
623}
624
625#[inline]
627fn post_val_var_constraint(model: &mut Model, val: Val, op: &ComparisonOp, var: VarId) -> PropId {
628 let val_var = match val {
629 Val::ValI(i) => model.int(i, i),
630 Val::ValF(f) => model.float(f, f),
631 };
632
633 match op {
634 ComparisonOp::Eq => model.props.equals(val_var, var),
635 ComparisonOp::Ne => model.props.not_equals(val_var, var),
636 ComparisonOp::Lt => model.props.less_than(val_var, var),
637 ComparisonOp::Le => model.props.less_than_or_equals(val_var, var),
638 ComparisonOp::Gt => model.props.greater_than(val_var, var),
639 ComparisonOp::Ge => model.props.greater_than_or_equals(val_var, var),
640 }
641}
642
643impl From<VarId> for ExprBuilder {
645 fn from(var_id: VarId) -> Self {
646 ExprBuilder::from_var(var_id)
647 }
648}
649
650impl From<i32> for ExprBuilder {
651 fn from(value: i32) -> Self {
652 ExprBuilder::from_val(Val::int(value))
653 }
654}
655
656impl From<f64> for ExprBuilder {
657 fn from(value: f64) -> Self {
658 ExprBuilder::from_val(Val::float(value))
659 }
660}
661
662impl From<Val> for ExprBuilder {
663 fn from(value: Val) -> Self {
664 ExprBuilder::from_val(value)
665 }
666}
667
668impl From<&VarId> for ExprBuilder {
670 fn from(value: &VarId) -> Self {
671 ExprBuilder::from_var(*value)
672 }
673}
674
675pub trait VarIdExt {
677 fn expr(self) -> ExprBuilder;
679
680 fn add(self, other: impl Into<ExprBuilder>) -> ExprBuilder;
682
683 fn sub(self, other: impl Into<ExprBuilder>) -> ExprBuilder;
685
686 fn mul(self, other: impl Into<ExprBuilder>) -> ExprBuilder;
688
689 fn div(self, other: impl Into<ExprBuilder>) -> ExprBuilder;
691
692 fn eq(self, other: impl Into<ExprBuilder>) -> Constraint;
694
695 fn ne(self, other: impl Into<ExprBuilder>) -> Constraint;
697
698 fn lt(self, other: impl Into<ExprBuilder>) -> Constraint;
700
701 fn le(self, other: impl Into<ExprBuilder>) -> Constraint;
703
704 fn gt(self, other: impl Into<ExprBuilder>) -> Constraint;
706
707 fn ge(self, other: impl Into<ExprBuilder>) -> Constraint;
709}
710
711impl VarIdExt for VarId {
712 fn expr(self) -> ExprBuilder {
713 ExprBuilder::from_var(self)
714 }
715
716 fn add(self, other: impl Into<ExprBuilder>) -> ExprBuilder {
717 ExprBuilder::from_var(self).add(other)
718 }
719
720 fn sub(self, other: impl Into<ExprBuilder>) -> ExprBuilder {
721 ExprBuilder::from_var(self).sub(other)
722 }
723
724 fn mul(self, other: impl Into<ExprBuilder>) -> ExprBuilder {
725 ExprBuilder::from_var(self).mul(other)
726 }
727
728 fn div(self, other: impl Into<ExprBuilder>) -> ExprBuilder {
729 ExprBuilder::from_var(self).div(other)
730 }
731
732 fn eq(self, other: impl Into<ExprBuilder>) -> Constraint {
733 ExprBuilder::from_var(self).eq(other)
734 }
735
736 fn ne(self, other: impl Into<ExprBuilder>) -> Constraint {
737 ExprBuilder::from_var(self).ne(other)
738 }
739
740 fn lt(self, other: impl Into<ExprBuilder>) -> Constraint {
741 ExprBuilder::from_var(self).lt(other)
742 }
743
744 fn le(self, other: impl Into<ExprBuilder>) -> Constraint {
745 ExprBuilder::from_var(self).le(other)
746 }
747
748 fn gt(self, other: impl Into<ExprBuilder>) -> Constraint {
749 ExprBuilder::from_var(self).gt(other)
750 }
751
752 fn ge(self, other: impl Into<ExprBuilder>) -> Constraint {
753 ExprBuilder::from_var(self).ge(other)
754 }
755}
756
757pub trait ModelExt {
759 fn post(&mut self, constraint: Constraint) -> PropId;
761
762 fn c(&mut self, var: VarId) -> Builder;
765
766 fn alldiff(&mut self, vars: &[VarId]) -> PropId;
768
769 fn alleq(&mut self, vars: &[VarId]) -> PropId;
771
772 fn elem(&mut self, array: &[VarId], index: VarId, value: VarId) -> PropId;
774
775 fn count(&mut self, vars: &[VarId], value: i32, result: VarId) -> PropId;
777
778 fn betw(&mut self, var: VarId, min: i32, max: i32) -> PropId;
780
781 fn atmost(&mut self, var: VarId, value: i32) -> PropId;
783
784 fn atleast(&mut self, var: VarId, value: i32) -> PropId;
786
787 fn gcc(&mut self, vars: &[VarId], values: &[i32], counts: &[VarId]) -> Vec<PropId>;
789
790 fn postall(&mut self, constraints: Vec<Constraint>) -> Vec<PropId>;
792
793 fn post_and(&mut self, constraints: Vec<Constraint>) -> Option<PropId>;
795
796 fn post_or(&mut self, constraints: Vec<Constraint>) -> Option<PropId>;
798}
799
800impl ModelExt for Model {
801 fn post(&mut self, constraint: Constraint) -> PropId {
802 post_constraint_kind(self, &constraint.kind)
803 }
804
805 fn c(&mut self, var: VarId) -> Builder {
806 Builder::new(self, var)
807 }
808
809 fn alldiff(&mut self, vars: &[VarId]) -> PropId {
810 self.props.all_different(vars.to_vec())
812 }
813
814 fn alleq(&mut self, vars: &[VarId]) -> PropId {
815 self.props.all_equal(vars.to_vec())
817 }
818
819 fn elem(&mut self, array: &[VarId], index: VarId, value: VarId) -> PropId {
820 self.props.element(array.to_vec(), index, value)
822 }
823
824 fn count(&mut self, vars: &[VarId], value: i32, result: VarId) -> PropId {
825 self.props.count_constraint(vars.to_vec(), Val::int(value), result)
827 }
828
829 fn betw(&mut self, var: VarId, min: i32, max: i32) -> PropId {
830 self.props.greater_than_or_equals(var, Val::int(min));
833 self.props.less_than_or_equals(var, Val::int(max))
834 }
835
836 fn atmost(&mut self, var: VarId, value: i32) -> PropId {
837 self.props.less_than_or_equals(var, Val::int(value))
839 }
840
841 fn atleast(&mut self, var: VarId, value: i32) -> PropId {
842 self.props.greater_than_or_equals(var, Val::int(value))
844 }
845
846 fn gcc(&mut self, vars: &[VarId], values: &[i32], counts: &[VarId]) -> Vec<PropId> {
847 let mut prop_ids = Vec::new();
849
850 for (&value, &count_var) in values.iter().zip(counts.iter()) {
851 let prop_id = self.props.count_constraint(vars.to_vec(), Val::int(value), count_var);
853 prop_ids.push(prop_id);
854 }
855
856 prop_ids
857 }
858
859 fn postall(&mut self, constraints: Vec<Constraint>) -> Vec<PropId> {
862 let mut result = Vec::with_capacity(constraints.len());
864
865 for constraint in constraints {
867 result.push(post_constraint_kind(self, &constraint.kind));
868 }
869
870 result
871 }
872
873 fn post_and(&mut self, constraints: Vec<Constraint>) -> Option<PropId> {
875 if constraints.is_empty() {
876 return None;
877 }
878
879 if constraints.len() == 1 {
880 return Some(post_constraint_kind(self, &constraints[0].kind));
881 }
882
883 let mut result = constraints[0].clone();
885 for constraint in constraints.into_iter().skip(1) {
886 result = Constraint {
887 kind: ConstraintKind::And(Box::new(result), Box::new(constraint))
888 };
889 }
890
891 Some(post_constraint_kind(self, &result.kind))
892 }
893
894 fn post_or(&mut self, constraints: Vec<Constraint>) -> Option<PropId> {
896 if constraints.is_empty() {
897 return None;
898 }
899
900 if constraints.len() == 1 {
901 return Some(post_constraint_kind(self, &constraints[0].kind));
902 }
903
904 let mut result = constraints[0].clone();
906 for constraint in constraints.into_iter().skip(1) {
907 result = Constraint {
908 kind: ConstraintKind::Or(Box::new(result), Box::new(constraint))
909 };
910 }
911
912 Some(post_constraint_kind(self, &result.kind))
913 }
914}
915
916#[cfg(test)]
917mod tests;
918
919