@@ -59,23 +59,6 @@ int64_t AffineValue(const ViewOfAffineLinearExpressionProto& affine,
59
59
return affine.coeff * solution[affine.var ] + affine.offset ;
60
60
}
61
61
62
- LinearExpressionProto ExprDiff (const LinearExpressionProto& a,
63
- const LinearExpressionProto& b) {
64
- LinearExpressionProto result;
65
- result.set_offset (a.offset () - b.offset ());
66
- result.mutable_vars ()->Reserve (a.vars ().size () + b.vars ().size ());
67
- result.mutable_coeffs ()->Reserve (a.vars ().size () + b.vars ().size ());
68
- for (int i = 0 ; i < a.vars ().size (); ++i) {
69
- result.add_vars (a.vars (i));
70
- result.add_coeffs (a.coeffs (i));
71
- }
72
- for (int i = 0 ; i < b.vars ().size (); ++i) {
73
- result.add_vars (b.vars (i));
74
- result.add_coeffs (-b.coeffs (i));
75
- }
76
- return result;
77
- }
78
-
79
62
LinearExpressionProto LinearExprSum (LinearExpressionProto a,
80
63
LinearExpressionProto b) {
81
64
LinearExpressionProto result;
@@ -1105,56 +1088,38 @@ int64_t CompiledAllDiffConstraint::ComputeViolation(
1105
1088
return violation;
1106
1089
}
1107
1090
1108
- // ----- NoOverlapBetweenTwoIntervals -----
1091
+ // ----- CompiledNoOverlapWithTwoIntervals -----
1109
1092
1110
- NoOverlapBetweenTwoIntervals::NoOverlapBetweenTwoIntervals (
1111
- int interval_0, int interval_1, const CpModelProto& cp_model) {
1112
- const ConstraintProto& ct0 = cp_model.constraints (interval_0);
1113
- const ConstraintProto& ct1 = cp_model.constraints (interval_1);
1114
-
1115
- // The more compact the better, hence the size + int[].
1116
- num_enforcements_ =
1117
- ct0.enforcement_literal ().size () + ct1.enforcement_literal ().size ();
1118
- if (num_enforcements_ > 0 ) {
1119
- enforcements_.reset (new int [num_enforcements_]);
1120
- int i = 0 ;
1121
- for (const int lit : ct0.enforcement_literal ()) enforcements_[i++] = lit;
1122
- for (const int lit : ct1.enforcement_literal ()) enforcements_[i++] = lit;
1093
+ template <bool has_enforcement>
1094
+ int64_t CompiledNoOverlapWithTwoIntervals<has_enforcement>::ViolationDelta(
1095
+ int /* var*/ , int64_t /* old_value*/ , absl::Span<const int64_t > solution) {
1096
+ if (has_enforcement) {
1097
+ for (const int lit : enforcements_) {
1098
+ if (!LiteralValue (lit, solution)) return -violation_;
1099
+ }
1123
1100
}
1124
1101
1125
- // We prefer to use start + size instead of end so that moving "start" moves
1126
- // the whole interval around (for the non-fixed duration case).
1127
- end_minus_start_1_ =
1128
- ExprDiff (LinearExprSum (ct0.interval ().start (), ct0.interval ().size ()),
1129
- ct1.interval ().start ());
1130
- end_minus_start_2_ =
1131
- ExprDiff (LinearExprSum (ct1.interval ().start (), ct1.interval ().size ()),
1132
- ct0.interval ().start ());
1102
+ const int64_t s1 = AffineValue (interval1_.start , solution);
1103
+ const int64_t e1 = AffineValue (interval1_.end , solution);
1104
+ const int64_t s2 = AffineValue (interval2_.start , solution);
1105
+ const int64_t e2 = AffineValue (interval2_.end , solution);
1106
+ const int64_t repair = std::min (e2 - s1, e1 - s2);
1107
+ if (repair <= 0 ) return -violation_; // disjoint
1108
+ return repair - violation_;
1133
1109
}
1134
1110
1135
- // Same as NoOverlapMinRepairDistance().
1136
- int64_t NoOverlapBetweenTwoIntervals::ComputeViolationInternal (
1137
- absl::Span<const int64_t > solution) {
1138
- for (int i = 0 ; i < num_enforcements_; ++i) {
1139
- if (!LiteralValue (enforcements_[i], solution)) return 0 ;
1140
- }
1141
- const int64_t diff1 = ExprValue (end_minus_start_1_, solution);
1142
- const int64_t diff2 = ExprValue (end_minus_start_2_, solution);
1143
- return std::max (std::min (diff1, diff2), int64_t {0 });
1144
- }
1145
-
1146
- std::vector<int > NoOverlapBetweenTwoIntervals::UsedVariables (
1111
+ template <bool has_enforcement>
1112
+ std::vector<int >
1113
+ CompiledNoOverlapWithTwoIntervals<has_enforcement>::UsedVariables(
1147
1114
const CpModelProto& /* model_proto*/ ) const {
1148
1115
std::vector<int > result;
1149
- for (int i = 0 ; i < num_enforcements_; ++i) {
1150
- result.push_back (PositiveRef (enforcements_[i]));
1151
- }
1152
- for (const int var : end_minus_start_1_.vars ()) {
1153
- result.push_back (PositiveRef (var));
1154
- }
1155
- for (const int var : end_minus_start_2_.vars ()) {
1156
- result.push_back (PositiveRef (var));
1116
+ if (has_enforcement) {
1117
+ for (const int ref : enforcements_) result.push_back (PositiveRef (ref));
1157
1118
}
1119
+ interval1_.start .AppendVarTo (result);
1120
+ interval1_.end .AppendVarTo (result);
1121
+ interval2_.start .AppendVarTo (result);
1122
+ interval2_.end .AppendVarTo (result);
1158
1123
gtl::STLSortAndRemoveDuplicates (&result);
1159
1124
result.shrink_to_fit ();
1160
1125
return result;
@@ -1291,6 +1256,7 @@ CompiledNoOverlap2dWithTwoBoxes<has_enforcement>::UsedVariables(
1291
1256
box2_.y_min .AppendVarTo (result);
1292
1257
box2_.y_max .AppendVarTo (result);
1293
1258
gtl::STLSortAndRemoveDuplicates (&result);
1259
+ result.shrink_to_fit ();
1294
1260
return result;
1295
1261
}
1296
1262
@@ -1722,20 +1688,31 @@ void LsEvaluator::CompileOneConstraint(const ConstraintProto& ct) {
1722
1688
// We expand the no_overlap constraints into a quadratic number of
1723
1689
// disjunctions.
1724
1690
for (int i = 0 ; i + 1 < size; ++i) {
1725
- const IntervalConstraintProto& interval_i =
1726
- cp_model_.constraints (ct.no_overlap ().intervals (i)).interval ();
1691
+ const ConstraintProto& proto_i =
1692
+ cp_model_.constraints (ct.no_overlap ().intervals (i));
1693
+ const IntervalConstraintProto& interval_i = proto_i.interval ();
1727
1694
const int64_t min_start_i = ExprMin (interval_i.start (), cp_model_);
1728
1695
const int64_t max_end_i = ExprMax (interval_i.end (), cp_model_);
1729
1696
for (int j = i + 1 ; j < size; ++j) {
1730
- const IntervalConstraintProto& interval_j =
1731
- cp_model_.constraints (ct.no_overlap ().intervals (j)).interval ();
1697
+ const ConstraintProto& proto_j =
1698
+ cp_model_.constraints (ct.no_overlap ().intervals (j));
1699
+ const IntervalConstraintProto& interval_j = proto_j.interval ();
1732
1700
const int64_t min_start_j = ExprMin (interval_j.start (), cp_model_);
1733
1701
const int64_t max_end_j = ExprMax (interval_j.end (), cp_model_);
1734
1702
if (min_start_i >= max_end_j || min_start_j >= max_end_i) continue ;
1735
1703
1736
- constraints_.emplace_back (new NoOverlapBetweenTwoIntervals (
1737
- ct.no_overlap ().intervals (i), ct.no_overlap ().intervals (j),
1738
- cp_model_));
1704
+ const bool has_enforcement =
1705
+ !proto_i.enforcement_literal ().empty () ||
1706
+ !proto_j.enforcement_literal ().empty ();
1707
+ if (has_enforcement) {
1708
+ constraints_.emplace_back (
1709
+ new CompiledNoOverlapWithTwoIntervals<true >(proto_i,
1710
+ proto_j));
1711
+ } else {
1712
+ constraints_.emplace_back (
1713
+ new CompiledNoOverlapWithTwoIntervals<false >(proto_i,
1714
+ proto_j));
1715
+ }
1739
1716
}
1740
1717
}
1741
1718
}
@@ -2202,7 +2179,7 @@ int64_t CompiledReservoirConstraint::IncrementalViolation(
2202
2179
int64_t previous_time = std::numeric_limits<int64_t >::min ();
2203
2180
2204
2181
// TODO(user): This code is the hotspot for our local search on cumulative.
2205
- // It can probably be slighlty improved. We might also be able to abort early
2182
+ // It can probably be slightly improved. We might also be able to abort early
2206
2183
// if we know that capacity is high enough compared to the highest point of
2207
2184
// the profile.
2208
2185
int i = 0 ;
0 commit comments