@@ -169,8 +169,8 @@ void ExpandReservoirUsingCircuit(int64_t sum_of_positive_demand,
169169 context->UpdateRuleStats (" reservoir: expanded using circuit." );
170170}
171171
172- void ExpandReservoirUsingPrecedences (int64_t sum_of_positive_demand ,
173- int64_t sum_of_negative_demand ,
172+ void ExpandReservoirUsingPrecedences (bool max_level_is_constraining ,
173+ bool min_level_is_constraining ,
174174 ConstraintProto* reservoir_ct,
175175 PresolveContext* context) {
176176 const ReservoirConstraintProto& reservoir = reservoir_ct->reservoir ();
@@ -192,23 +192,21 @@ void ExpandReservoirUsingPrecedences(int64_t sum_of_positive_demand,
192192
193193 // No need for some constraints if the reservoir is just constrained in
194194 // one direction.
195- if (demand_i > 0 && sum_of_positive_demand <= reservoir.max_level ()) {
196- continue ;
197- }
198- if (demand_i < 0 && sum_of_negative_demand >= reservoir.min_level ()) {
199- continue ;
200- }
195+ if (demand_i > 0 && !max_level_is_constraining) continue ;
196+ if (demand_i < 0 && !min_level_is_constraining) continue ;
201197
202- ConstraintProto* new_ct = context->working_model ->add_constraints ();
203- LinearConstraintProto* new_linear = new_ct->mutable_linear ();
204-
205- // Add contributions from previous events.
198+ ConstraintProto* new_cumul = context->working_model ->add_constraints ();
199+ LinearConstraintProto* new_linear = new_cumul->mutable_linear ();
206200 int64_t offset = 0 ;
201+
202+ // Add contributions from events that happened at time_j <= time_i.
207203 const LinearExpressionProto& time_i = reservoir.time_exprs (i);
208204 for (int j = 0 ; j < num_events; ++j) {
209205 if (i == j) continue ;
210206 const int active_j = is_active_literal (j);
211207 if (context->LiteralIsFalse (active_j)) continue ;
208+ const int64_t demand_j = context->FixedValue (reservoir.level_changes (j));
209+ if (demand_j == 0 ) continue ;
212210
213211 // Get or create the literal equivalent to
214212 // active_i && active_j && time[j] <= time[i].
@@ -218,44 +216,30 @@ void ExpandReservoirUsingPrecedences(int64_t sum_of_positive_demand,
218216 const LinearExpressionProto& time_j = reservoir.time_exprs (j);
219217 const int j_lesseq_i = context->GetOrCreateReifiedPrecedenceLiteral (
220218 time_j, time_i, active_j, active_i);
221- context->working_model ->mutable_variables (j_lesseq_i)
222- ->set_name (absl::StrCat (j, " before " , i));
223-
224- const int64_t demand = context->FixedValue (reservoir.level_changes (j));
225- if (RefIsPositive (j_lesseq_i)) {
226- new_linear->add_vars (j_lesseq_i);
227- new_linear->add_coeffs (demand);
228- } else {
229- new_linear->add_vars (NegatedRef (j_lesseq_i));
230- new_linear->add_coeffs (-demand);
231- offset -= demand;
232- }
219+ AddWeightedLiteralToLinearConstraint (j_lesseq_i, demand_j, new_linear,
220+ &offset);
233221 }
234222
235223 // Add contribution from event i.
236224 //
237225 // TODO(user): Alternatively we can mark the whole constraint as enforced
238226 // only if active_i is true. Experiments with both version, right now we
239227 // miss enough benchmarks to conclude.
240- if (RefIsPositive (active_i)) {
241- new_linear->add_vars (active_i);
242- new_linear->add_coeffs (demand_i);
243- } else {
244- new_linear->add_vars (NegatedRef (active_i));
245- new_linear->add_coeffs (-demand_i);
246- offset -= demand_i;
247- }
228+ AddWeightedLiteralToLinearConstraint (active_i, demand_i, new_linear,
229+ &offset);
248230
249231 // Note that according to the sign of demand_i, we only need one side.
232+ // We apply the offset here to make sure we use int64_t min and max.
250233 if (demand_i > 0 ) {
251234 new_linear->add_domain (std::numeric_limits<int64_t >::min ());
252- new_linear->add_domain (reservoir.max_level ());
235+ new_linear->add_domain (reservoir.max_level () - offset );
253236 } else {
254- new_linear->add_domain (reservoir.min_level ());
237+ new_linear->add_domain (reservoir.min_level () - offset );
255238 new_linear->add_domain (std::numeric_limits<int64_t >::max ());
256239 }
257240
258- context->CanonicalizeLinearConstraint (new_ct);
241+ // Canonicalize the newly created constraint.
242+ context->CanonicalizeLinearConstraint (new_cumul);
259243 }
260244
261245 reservoir_ct->Clear ();
@@ -367,9 +351,10 @@ void ExpandReservoir(ConstraintProto* reservoir_ct, PresolveContext* context) {
367351 } else {
368352 // This one is the faster option usually.
369353 if (all_demands_are_fixed) {
370- ExpandReservoirUsingPrecedences (sum_of_positive_demand,
371- sum_of_negative_demand, reservoir_ct,
372- context);
354+ ExpandReservoirUsingPrecedences (
355+ sum_of_positive_demand > reservoir_ct->reservoir ().max_level (),
356+ sum_of_negative_demand < reservoir_ct->reservoir ().min_level (),
357+ reservoir_ct, context);
373358 } else {
374359 context->UpdateRuleStats (
375360 " reservoir: skipped expansion due to variable demands" );
0 commit comments