88
99
1010namespace lp {
11+ struct column_update {
12+ bool m_is_upper;
13+ unsigned m_j;
14+ impq m_bound;
15+ column m_column;
16+ };
17+
18+ struct imp {
19+ lar_solver &lra;
20+ vector<column_update> m_column_updates;
21+
22+ void set_r_upper_bound (unsigned j, const impq& b) {
23+ lra.m_mpq_lar_core_solver .m_r_upper_bounds [j] = b;
24+ }
25+ void set_r_lower_bound (unsigned j, const impq& b) {
26+ lra.m_mpq_lar_core_solver .m_r_lower_bounds [j] = b;
27+ }
28+
29+ imp (lar_solver& s) : lra(s) {}
30+
31+ void set_column (unsigned j, const column& c) {
32+ lra.m_columns [j] = c;
33+ }
34+
35+ struct column_update_trail : public trail {
36+ imp& m_imp;
37+ column_update_trail (imp & i) : m_imp(i) {}
38+ void undo () override {
39+ auto & [is_upper, j, bound, column] = m_imp.m_column_updates .back ();
40+ if (is_upper)
41+ m_imp.set_r_upper_bound (j, bound);
42+ else
43+ m_imp.set_r_lower_bound (j, bound);
44+ m_imp.set_column (j, column);
45+ m_imp.m_column_updates .pop_back ();
46+ }
47+ };
48+ };
1149
50+ imp* m_imp;
1251 lp_settings& lar_solver::settings () { return m_settings; }
1352
1453 lp_settings const & lar_solver::settings () const { return m_settings; }
@@ -25,7 +64,8 @@ namespace lp {
2564 lar_solver::lar_solver () :
2665 m_mpq_lar_core_solver (m_settings, *this ),
2766 m_var_register (),
28- m_constraints (m_dependencies, *this ) {}
67+ m_constraints (m_dependencies, *this ), m_imp(alloc(imp, *this )) {
68+ }
2969
3070 // start or ends tracking the rows that were changed by solve()
3171 void lar_solver::track_touched_rows (bool v) {
@@ -574,38 +614,25 @@ namespace lp {
574614 A_r ().pop (k);
575615 }
576616
577- struct lar_solver ::column_update_trail : public trail {
578- lar_solver& s;
579- column_update_trail (lar_solver& s) : s(s) {}
580- void undo () override {
581- auto & [is_upper, j, bound, column] = s.m_column_updates .back ();
582- if (is_upper)
583- s.m_mpq_lar_core_solver .m_r_upper_bounds [j] = bound;
584- else
585- s.m_mpq_lar_core_solver .m_r_lower_bounds [j] = bound;
586- s.m_columns [j] = column;
587- s.m_column_updates .pop_back ();
588- }
589- };
590-
617+
591618 void lar_solver::set_upper_bound_witness (lpvar j, u_dependency* dep, impq const & high) {
592619 bool has_upper = m_columns[j].upper_bound_witness () != nullptr ;
593- m_column_updates.push_back ({true , j, get_upper_bound (j), m_columns[j]});
594- m_trail.push (column_update_trail (*this ));
620+ m_imp-> m_column_updates .push_back ({true , j, get_upper_bound (j), m_columns[j]});
621+ m_trail.push (imp:: column_update_trail (*this -> m_imp ));
595622 m_columns[j].set_upper_bound_witness (dep);
596623 if (has_upper)
597- m_columns[j].set_previous_upper (m_column_updates.size () - 1 );
624+ m_columns[j].set_previous_upper (m_imp-> m_column_updates .size () - 1 );
598625 m_mpq_lar_core_solver.m_r_upper_bounds [j] = high;
599626 insert_to_columns_with_changed_bounds (j);
600627 }
601628
602629 void lar_solver::set_lower_bound_witness (lpvar j, u_dependency* dep, impq const & low) {
603630 bool has_lower = m_columns[j].lower_bound_witness () != nullptr ;
604- m_column_updates.push_back ({false , j, get_lower_bound (j), m_columns[j]});
605- m_trail.push (column_update_trail (*this ));
631+ m_imp-> m_column_updates .push_back ({false , j, get_lower_bound (j), m_columns[j]});
632+ m_trail.push (imp:: column_update_trail (*this -> m_imp ));
606633 m_columns[j].set_lower_bound_witness (dep);
607634 if (has_lower)
608- m_columns[j].set_previous_lower (m_column_updates.size () - 1 );
635+ m_columns[j].set_previous_lower (m_imp-> m_column_updates .size () - 1 );
609636 m_mpq_lar_core_solver.m_r_lower_bounds [j] = low;
610637 insert_to_columns_with_changed_bounds (j);
611638 }
@@ -1196,26 +1223,34 @@ namespace lp {
11961223
11971224 #if 1
11981225 if (is_upper) {
1199- if (ul.previous_upper () != UINT_MAX) {
1200- auto const & [_is_upper, _j, _bound, _column] = m_column_updates[ul.previous_upper ()];
1226+ unsigned current_update_index = ul.previous_upper ();
1227+ while (current_update_index != UINT_MAX) {
1228+ auto const & [_is_upper, _j, _bound, _column] = m_imp->m_column_updates [current_update_index];
12011229 auto new_slack = slack + coeff * (_bound - get_upper_bound (j));
12021230 if (sign == get_sign (new_slack)) {
1203- // verbose_stream() << "can weaken j" << j << " " << coeff << " " << get_upper_bound(j) << " " << _bound << "\n";
1231+ // verbose_stream() << "can weaken upper j" << j << " " << coeff << " " << get_upper_bound(j) << " " << _bound << "\n";
12041232 slack = new_slack;
12051233 bound_constr_i = _column.upper_bound_witness ();
1206- }
1234+ current_update_index = _column.previous_upper (); // Move to the next previous bound in the list
1235+ } else
1236+ break ; // Stop if weakening is not possible with this previous bound
1237+
12071238 }
1208- }
1239+ }
12091240 else {
1210- if (ul.previous_lower () != UINT_MAX) {
1211- auto const & [_is_upper, _j, _bound, _column] = m_column_updates[ul.previous_lower ()];
1241+ unsigned prev_l = ul.previous_lower ();
1242+ while (prev_l != UINT_MAX) {
1243+ auto const & [_is_upper, _j, _bound, _column] = m_imp->m_column_updates [prev_l];
12121244 auto new_slack = slack + coeff * (_bound - get_lower_bound (j));
12131245 if (sign == get_sign (new_slack)) {
1214- // verbose_stream() << "can weaken j" << j << " " << coeff << " " << get_lower_bound(j) << " " << _bound << "\n";
1246+ // verbose_stream() << "can weaken lower j" << j << " " << coeff << " " << get_lower_bound(j) << " " << _bound << "\n";
12151247 slack = new_slack;
12161248 bound_constr_i = _column.lower_bound_witness ();
1249+ prev_l = _column.previous_lower ();
12171250 }
1218- }
1251+ else
1252+ break ;
1253+ }
12191254 }
12201255 #endif
12211256
0 commit comments