28
28
To track the explanations of equality t = 0 we initially set m_entries[i].m_l = lar_term(j), and update m_l
29
29
accordingly with the pivot operations. The explanation is obtained by replacing term m_l = sum(aj*j) by the linear
30
30
combination sum (aj*initt(j)) and joining the explanations of all fixed variables in the latter sum.
31
- entry_invariant(i) guarantees the validity of entry i .
31
+ entry_invariant(i) guarantees the validity of the i-th entry .
32
32
*/
33
33
namespace lp {
34
34
// This class represents a term with an added constant number c, in form sum {x_i*a_i} + c.
@@ -187,6 +187,7 @@ namespace lp {
187
187
mpq m_c; // the constant of the term, the term is taken from the row of m_e_matrix with the same index as the entry
188
188
entry_status m_entry_status;
189
189
};
190
+ var_register m_var_register;
190
191
std_vector<entry> m_entries;
191
192
// the terms are stored in m_A and m_c
192
193
static_matrix<mpq, mpq> m_e_matrix; // the rows of the matrix are the terms, without the constant part
@@ -219,12 +220,21 @@ namespace lp {
219
220
t.c () = m_entries[i].m_c ;
220
221
return t;
221
222
}
223
+
224
+ // adds variable j of lar_solver to the local diophantine handler
225
+ unsigned add_var (unsigned j) {
226
+ return this ->m_var_register .add_var (j, true );
227
+ }
228
+
229
+ unsigned local_to_lar_solver (unsigned j) const {
230
+ return m_var_register.local_to_external (j);
231
+ }
232
+
222
233
// the term has form sum(a_i*x_i) - t.j() = 0,
223
234
// i is the index of the term in the lra.m_terms
224
235
void fill_entry (const lar_term& t) {
225
236
TRACE (" dioph_eq" , print_lar_term_L (t, tout) << std::endl;);
226
- unsigned i = static_cast <unsigned >(m_entries.size ());
227
- entry te = {lar_term (t.j ()), mpq (0 ), entry_status::NO_S_NO_F};
237
+ entry te = {lar_term (t.j ()), mpq (0 ), entry_status::F};
228
238
unsigned entry_index = m_entries.size ();
229
239
m_f.push_back (entry_index);
230
240
m_entries.push_back (te);
@@ -237,64 +247,52 @@ namespace lp {
237
247
if (is_fixed (p.var ()))
238
248
e.m_c += p.coeff ()*lia.lower_bound (p.var ()).x ;
239
249
else {
240
- while (p.var () >= m_e_matrix.column_count ())
250
+ unsigned lj = add_var (p.var ());
251
+ while (lj >= m_e_matrix.column_count ())
241
252
m_e_matrix.add_column ();
242
- m_e_matrix.add_new_element (entry_index, p. var () , p.coeff ());
253
+ m_e_matrix.add_new_element (entry_index, lj , p.coeff ());
243
254
}
244
255
}
245
- unsigned j = t.j ();
246
- if (is_fixed (j))
247
- e.m_c -= lia.lower_bound (j).x ;
256
+ if (is_fixed (t.j ()))
257
+ e.m_c -= lia.lower_bound (t.j ()).x ;
248
258
else {
249
- while (j >= m_e_matrix.column_count ())
259
+ unsigned lj = add_var (t.j ());
260
+ while (lj >= m_e_matrix.column_count ())
250
261
m_e_matrix.add_column ();
251
- m_e_matrix.add_new_element (entry_index, j , - mpq (1 ));
262
+ m_e_matrix.add_new_element (entry_index, lj , - mpq (1 ));
252
263
}
253
- e.m_entry_status = entry_status::F;
254
264
TRACE (" dioph_eq" , print_entry (entry_index, tout););
255
- SASSERT (entry_invariant (i ));
265
+ SASSERT (entry_invariant (entry_index ));
256
266
}
257
267
258
- bool all_vars_are_int_and_small (const lar_term& term) const {
268
+ bool all_vars_are_int (const lar_term& term) const {
259
269
for (const auto & p : term) {
260
270
if (!lia.column_is_int (p.var ()))
261
271
return false ;
262
- if (p.coeff ().is_big ())
263
- return false ;
264
272
}
265
273
return true ;
266
274
}
267
275
268
-
269
276
void init () {
270
277
m_e_matrix = static_matrix<mpq, mpq>();
271
278
m_report_branch = false ;
272
279
m_k2s.clear ();
280
+ m_fresh_definitions.clear ();
273
281
m_conflict_index = -1 ;
274
282
m_infeas_explanation.clear ();
275
283
lia.get_term ().clear ();
276
284
m_entries.clear ();
285
+ m_var_register.clear ();
286
+
277
287
for (unsigned j = 0 ; j < lra.column_count (); j++) {
278
288
if (!lra.column_is_int (j)|| !lra.column_has_term (j)) continue ;
279
289
const lar_term& t = lra.get_term (j);
280
- if (!all_vars_are_int_and_small (t)) {
281
- TRACE (" dioph_eq" , tout << " not all vars are int and small \n " ;);
290
+ if (!all_vars_are_int (t)) {
291
+ TRACE (" dioph_eq" , tout << " not all vars are integrall \n " ;);
282
292
continue ;
283
293
}
284
294
fill_entry (t);
285
295
}
286
-
287
- }
288
-
289
- // look only at the fixed columns
290
- u_dependency * get_dep_from_row (const row_strip<mpq>& row) {
291
- u_dependency* dep = nullptr ;
292
- for (const auto & p: row) {
293
- if (!is_fixed (p.var ())) continue ;
294
- u_dependency * bound_dep = lra.get_bound_constraint_witnesses_for_column (p.var ());
295
- dep = lra.mk_join (dep, bound_dep);
296
- }
297
- return dep;
298
296
}
299
297
300
298
template <typename K> mpq gcd_of_coeffs (const K & k) {
@@ -333,7 +331,7 @@ namespace lp {
333
331
*/
334
332
lar_term& t = lia.get_term ();
335
333
for (const auto & p: m_e_matrix.m_rows [ei]) {
336
- t.add_monomial (p.coeff ()/g, p.var ());
334
+ t.add_monomial (p.coeff ()/g, local_to_lar_solver ( p.var () ));
337
335
}
338
336
lia.offset () = floor (-new_c);
339
337
lia.is_upper () = true ;
@@ -427,7 +425,7 @@ namespace lp {
427
425
term_o create_term_from_l (const lar_term& l) {
428
426
term_o ret;
429
427
for (const auto & p: l) {
430
- const auto & t = lra.get_term (p.j ());
428
+ const auto & t = lra.get_term (local_to_lar_solver ( p.j () ));
431
429
ret.add_monomial (-mpq (1 ), p.j ());
432
430
for (const auto & q: t) {
433
431
ret.add_monomial (p.coeff ()*q.coeff (), q.j ());
@@ -437,7 +435,7 @@ namespace lp {
437
435
}
438
436
439
437
bool is_fixed (unsigned j) const {
440
- return (! is_fresh_var (j)) && lra.column_is_fixed (j);
438
+ return lra.column_is_fixed (j);
441
439
}
442
440
443
441
template <typename T> term_o fix_vars (const T& t) const {
@@ -471,9 +469,10 @@ namespace lp {
471
469
}
472
470
473
471
lia_move tighten_with_S () {
474
- for (unsigned j = 0 ; j < lra.column_count (); j++) {
472
+ for (unsigned j = 0 ; j < lra.column_count (); j++) {
475
473
if (!lra.column_has_term (j) || lra.column_is_free (j) ||
476
- lra.column_is_fixed (j) || !lia.column_is_int (j)) continue ;
474
+ is_fixed (j) || !lia.column_is_int (j)) continue ;
475
+
477
476
if (tighten_bounds_for_term_column (j))
478
477
return lia_move::conflict;
479
478
}
@@ -509,18 +508,22 @@ namespace lp {
509
508
if (is_fixed (p.j ()))
510
509
m_c += p.coeff ()*lia.lower_bound (p.j ()).x ;
511
510
else
512
- m_indexed_work_vector.set_value (p.coeff (), p.j ());
511
+ m_indexed_work_vector.set_value (p.coeff (), lar_solver_to_local ( p.j () ));
513
512
}
514
513
515
514
}
515
+ unsigned lar_solver_to_local (unsigned j) const {
516
+ return m_var_register.external_to_local (j);
517
+ }
516
518
// j is the index of the column representing a term
517
519
// return true if a conflict was found
518
520
bool tighten_bounds_for_term_column (unsigned j) {
519
521
term_o term_to_tighten = lra.get_term (j); // copy the term aside
522
+ if (!all_vars_are_int (term_to_tighten)) return false ;
520
523
std::queue<unsigned > q;
521
524
for (const auto & p: term_to_tighten) {
522
- if (can_substitute (p.j ()) && !lra. column_is_fixed ( p.j ()))
523
- q.push (p.j ());
525
+ if (!lra. column_is_fixed (p.j ()) && can_substitute ( lar_solver_to_local ( p.j () )))
526
+ q.push (lar_solver_to_local ( p.j () ));
524
527
}
525
528
if (q.empty ()) {
526
529
return false ;
@@ -540,7 +543,9 @@ namespace lp {
540
543
tout << " term_to_tighten + open_ml:" ; print_term_o (term_to_tighten + open_ml (m_tmp_l), tout) << std::endl;
541
544
print_lar_term_L (remove_fresh_vars (term_to_tighten + open_ml (m_tmp_l)), tout) << std::endl;
542
545
);
543
- SASSERT (fix_vars (remove_fresh_vars (term_to_tighten + open_ml (m_tmp_l) - create_term_from_ind_c ())).is_empty ());
546
+ SASSERT (
547
+ fix_vars (term_to_tighten + open_ml (m_tmp_l)) ==
548
+ term_to_lar_solver (remove_fresh_vars (create_term_from_ind_c ())));
544
549
mpq g = gcd_of_coeffs (m_indexed_work_vector);
545
550
TRACE (" dioph_eq" , tout << " after process_q_with_S\n t:" ; print_term_o (create_term_from_ind_c (), tout) << std::endl;
546
551
tout << " g:" << g << std::endl; /* tout << "dep:"; print_dep(tout, m_tmp_l) << std::endl;*/ );
@@ -743,14 +748,8 @@ namespace lp {
743
748
entry& e = m_entries[ei];
744
749
TRACE (" dioph_eq" , tout << " eliminate var:" << j << " by using:" ; print_entry (ei, tout) << std::endl;);
745
750
auto &column = m_e_matrix.m_columns [j];
746
- int pivot_col_cell_index = -1 ;
747
- for (unsigned k = 0 ; k < column.size (); k++) {
748
- if (column[k].var () == ei) {
749
- pivot_col_cell_index = k;
750
- break ;
751
- }
752
- }
753
- SASSERT (pivot_col_cell_index != -1 );
751
+ auto it = std::find_if (column.begin (), column.end (), [ei](const auto &cell) {return cell.var () == ei;});
752
+ unsigned pivot_col_cell_index = std::distance (column.begin (), it);
754
753
if (pivot_col_cell_index != 0 ) {
755
754
// swap the pivot column cell with the head cell
756
755
auto c = column[0 ];
@@ -789,9 +788,18 @@ namespace lp {
789
788
}
790
789
}
791
790
791
+ term_o term_to_lar_solver (const term_o& eterm) const {
792
+ term_o ret;
793
+ for (const auto & p : eterm) {
794
+ ret.add_monomial (p.coeff (), local_to_lar_solver (p.var ()));
795
+ }
796
+ ret.c () = eterm.c ();
797
+ return ret;
798
+ }
799
+
792
800
bool entry_invariant (unsigned ei) const {
793
801
const auto &e = m_entries[ei];
794
- bool ret = remove_fresh_vars (get_term_from_entry (ei)) == fix_vars (open_ml (e.m_l ));
802
+ bool ret = term_to_lar_solver ( remove_fresh_vars (get_term_from_entry (ei) )) == fix_vars (open_ml (e.m_l ));
795
803
if (ret) return true ;
796
804
TRACE (" dioph_eq" ,
797
805
tout << " get_term_from_entry(" << ei <<" ):" ;
@@ -861,7 +869,7 @@ namespace lp {
861
869
move_row_to_work_vector (h); // it clears the row, and puts the term in the work vector
862
870
// step 7 from the paper
863
871
// xt is the fresh variable
864
- unsigned xt = std::max (m_e_matrix. column_count (), lra. column_count ()); // use var_register later
872
+ unsigned xt = add_var (UINT_MAX);
865
873
unsigned fresh_row = m_e_matrix.row_count ();
866
874
m_e_matrix.add_row (); // for the fresh variable definition
867
875
while (xt >= m_e_matrix.column_count ())
@@ -914,18 +922,18 @@ namespace lp {
914
922
if (need_print_dep) {
915
923
out << " \t m_l:{" ; print_lar_term_L (e.m_l , out) << " }, " ;
916
924
print_ml (e.m_l , out<< " \t fixed expl of m_l:" ) << " \n " ;
917
- print_dep (out, explain_fixed_in_meta_term (e.m_l )) << std::endl ;
925
+ print_dep (out, explain_fixed_in_meta_term (e.m_l )) << " , " ;
918
926
}
919
927
switch (e.m_entry_status )
920
928
{
921
929
case entry_status::F:
922
- out << " \t in F\n " ;
930
+ out << " in F\n " ;
923
931
break ;
924
932
case entry_status::S:
925
- out << " \t in S\n " ;
933
+ out << " in S\n " ;
926
934
break ;
927
935
default :
928
- out << " \t NOSF \n " ;
936
+ out << " NOSF \n " ;
929
937
}
930
938
out << " }\n " ;
931
939
return out;
@@ -995,7 +1003,7 @@ namespace lp {
995
1003
}
996
1004
997
1005
bool is_fresh_var (unsigned j) const {
998
- return j >= lra. column_count () ;
1006
+ return m_var_register. local_to_external (j) == UINT_MAX ;
999
1007
}
1000
1008
bool can_substitute (unsigned k) {
1001
1009
return k < m_k2s.size () && m_k2s[k] != UINT_MAX;
0 commit comments