@@ -119,7 +119,9 @@ bool ModelCopy::ImportAndSimplifyConstraints(
119119 }
120120 break ;
121121 case ConstraintProto::kLinear :
122- if (!CopyLinear (ct)) return CreateUnsatModel (c, ct);
122+ if (!CopyLinear (ct, /* canonicalize=*/ first_copy)) {
123+ return CreateUnsatModel (c, ct);
124+ }
123125 break ;
124126 case ConstraintProto::kIntProd :
125127 if (!CopyIntProd (ct, ignore_names)) return CreateUnsatModel (c, ct);
@@ -407,8 +409,9 @@ bool ModelCopy::CopyBoolAndWithDupSupport(const ConstraintProto& ct) {
407409 return true ;
408410}
409411
410- bool ModelCopy::CopyLinearExpression (const LinearExpressionProto& expr,
411- LinearExpressionProto* dst) {
412+ bool ModelCopy::CopyLinearExpression (
413+ const LinearExpressionProto& expr, LinearExpressionProto* dst,
414+ absl::Span<const int > enforcement_literals) {
412415 non_fixed_variables_.clear ();
413416 non_fixed_coefficients_.clear ();
414417 int64_t offset = expr.offset ();
@@ -436,10 +439,13 @@ bool ModelCopy::CopyLinearExpression(const LinearExpressionProto& expr,
436439 non_fixed_variables_.end ());
437440 dst->mutable_coeffs ()->Add (non_fixed_coefficients_.begin (),
438441 non_fixed_coefficients_.end ());
442+ // TODO(user): We could save work by only doing this if this is the first
443+ // copy.
444+ context_->CanonicalizeLinearExpression (enforcement_literals, dst);
439445 return true ;
440446}
441447
442- bool ModelCopy::CopyLinear (const ConstraintProto& ct) {
448+ bool ModelCopy::CopyLinear (const ConstraintProto& ct, bool canonicalize ) {
443449 non_fixed_variables_.clear ();
444450 non_fixed_coefficients_.clear ();
445451 int64_t offset = 0 ;
@@ -516,6 +522,9 @@ bool ModelCopy::CopyLinear(const ConstraintProto& ct) {
516522 linear->mutable_coeffs ()->Add (non_fixed_coefficients_.begin (),
517523 non_fixed_coefficients_.end ());
518524 FillDomainInProto (tight_domain, linear);
525+ if (canonicalize) {
526+ context_->CanonicalizeLinearConstraint (new_ct);
527+ }
519528 return true ;
520529}
521530
@@ -708,11 +717,14 @@ bool ModelCopy::CopyInterval(const ConstraintProto& ct, int c,
708717 }
709718 *new_ct->mutable_enforcement_literal () = ct.enforcement_literal ();
710719 CopyLinearExpression (ct.interval ().start (),
711- new_ct->mutable_interval ()->mutable_start ());
720+ new_ct->mutable_interval ()->mutable_start (),
721+ ct.enforcement_literal ());
712722 CopyLinearExpression (ct.interval ().size (),
713- new_ct->mutable_interval ()->mutable_size ());
723+ new_ct->mutable_interval ()->mutable_size (),
724+ ct.enforcement_literal ());
714725 CopyLinearExpression (ct.interval ().end (),
715- new_ct->mutable_interval ()->mutable_end ());
726+ new_ct->mutable_interval ()->mutable_end (),
727+ ct.enforcement_literal ());
716728 return true ;
717729}
718730
@@ -778,10 +790,10 @@ bool ModelCopy::AddLinearConstraintForInterval(const ConstraintProto& ct) {
778790 AddLinearExpressionToLinearConstraint (itv.start (), 1 , mutable_linear);
779791 AddLinearExpressionToLinearConstraint (itv.size (), 1 , mutable_linear);
780792 AddLinearExpressionToLinearConstraint (itv.end (), -1 , mutable_linear);
781- if (!CopyLinear (tmp_constraint_)) return false ;
793+ if (!CopyLinear (tmp_constraint_, true )) return false ;
782794 }
783795
784- // An enforced interval must have is size non-negative.
796+ // An enforced interval must have its size non-negative.
785797 const LinearExpressionProto& size_expr = itv.size ();
786798 if (context_->MinOf (size_expr) < 0 ) {
787799 tmp_constraint_.Clear ();
@@ -791,7 +803,7 @@ bool ModelCopy::AddLinearConstraintForInterval(const ConstraintProto& ct) {
791803 tmp_constraint_.mutable_linear ()->add_domain (-size_expr.offset ());
792804 tmp_constraint_.mutable_linear ()->add_domain (
793805 std::numeric_limits<int64_t >::max ());
794- if (!CopyLinear (tmp_constraint_)) return false ;
806+ if (!CopyLinear (tmp_constraint_, true )) return false ;
795807 }
796808
797809 return true ;
0 commit comments