@@ -215,8 +215,14 @@ namespace lp {
215
215
// Tighten bounds
216
216
// expose at level of lar_solver so it can be invoked by theory_lra after back-jumping
217
217
// consider multi-round bound tightnening as well and deal with divergence issues.
218
+
219
+ unsigned m_bounds_refine_depth = 0 ;
220
+
218
221
lia_move tighten_bounds () {
219
222
223
+ if (m_bounds_refine_depth > 10 )
224
+ return lia_move::undef;
225
+
220
226
struct bound_consumer {
221
227
imp& i;
222
228
bound_consumer (imp& i) : i(i) {}
@@ -227,18 +233,16 @@ namespace lp {
227
233
bound_consumer bc (*this );
228
234
std_vector<implied_bound> ibounds;
229
235
lp_bound_propagator<bound_consumer> bp (bc, ibounds);
230
- bp.init ();
231
-
232
- unsigned num_refined_bounds = 0 ;
233
236
234
- auto set_conflict = [&](unsigned j, u_dependency * d1, u_dependency * d2) {
237
+ auto set_conflict = [&](u_dependency * d1, u_dependency * d2) {
235
238
++settings ().stats ().m_bounds_tightening_conflicts ;
236
239
for (auto e : lra.flatten (d1))
237
240
m_ex->push_back (e);
238
241
for (auto e : lra.flatten (d2))
239
242
m_ex->push_back (e);
240
243
};
241
244
245
+ bool bounds_refined = false ;
242
246
auto refine_bound = [&](implied_bound const & ib) {
243
247
unsigned j = ib.m_j ;
244
248
rational bound = ib.m_bound ;
@@ -249,43 +253,46 @@ namespace lp {
249
253
return l_undef;
250
254
auto d = ib.explain_implied ();
251
255
if (lra.column_has_upper_bound (j) && lra.column_upper_bound (j) < bound) {
252
- set_conflict (j, d, lra.get_column_upper_bound_witness (j));
256
+ set_conflict (d, lra.get_column_upper_bound_witness (j));
253
257
return l_false;
254
258
}
255
-
256
- lra.update_column_type_and_bound (j, ib.m_strict ? lconstraint_kind::GT : lconstraint_kind::GE, bound, d);
257
- ++num_refined_bounds;
258
- } else {
259
+ lra.update_column_type_and_bound (j, ib.m_strict ? lconstraint_kind::GT : lconstraint_kind::GE, bound, d);
260
+ }
261
+ else {
259
262
if (lra.column_is_int (j))
260
263
bound = floor (bound);
261
264
if (lra.column_has_upper_bound (j) && lra.column_upper_bound (j) <= bound)
262
265
return l_undef;
263
266
auto d = ib.explain_implied ();
264
267
if (lra.column_has_lower_bound (j) && lra.column_lower_bound (j) > bound) {
265
- set_conflict (j, d, lra.get_column_lower_bound_witness (j));
268
+ set_conflict (d, lra.get_column_lower_bound_witness (j));
266
269
return l_false;
267
270
}
268
-
269
271
lra.update_column_type_and_bound (j, ib.m_strict ? lconstraint_kind::LT : lconstraint_kind::LE, bound, d);
270
- ++num_refined_bounds;
271
272
}
273
+ ++settings ().stats ().m_bounds_tightenings ;
274
+ bounds_refined = true ;
272
275
return l_true;
273
276
};
274
277
275
278
for (unsigned row_index = 0 ; row_index < lra.row_count (); ++row_index) {
279
+ bp.init ();
276
280
bound_analyzer_on_row<row_strip<mpq>, lp_bound_propagator<bound_consumer>>::analyze_row (
277
281
lra.A_r ().m_rows [row_index],
278
282
zero_of_type<numeric_pair<mpq>>(),
279
283
bp);
280
284
281
- settings ().stats ().m_bounds_tightenings += static_cast <unsigned >(ibounds.size ());
282
285
for (auto const & ib : ibounds)
283
286
if (l_false == refine_bound (ib))
284
287
return lia_move::conflict;
285
- ibounds.clear ();
288
+ }
289
+
290
+ if (bounds_refined) {
291
+ lra.trail ().push (value_trail (m_bounds_refine_depth));
292
+ ++m_bounds_refine_depth;
286
293
}
287
294
288
- return num_refined_bounds > 0 ? lia_move::continue_with_check : lia_move::undef;
295
+ return bounds_refined ? lia_move::continue_with_check : lia_move::undef;
289
296
}
290
297
291
298
0 commit comments