Skip to content

Commit d68ebee

Browse files
committed
use var_register in dioph_eq
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
1 parent 480c48f commit d68ebee

File tree

3 files changed

+66
-56
lines changed

3 files changed

+66
-56
lines changed

src/math/lp/dioph_eq.cpp

+62-54
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
To track the explanations of equality t = 0 we initially set m_entries[i].m_l = lar_term(j), and update m_l
2929
accordingly with the pivot operations. The explanation is obtained by replacing term m_l = sum(aj*j) by the linear
3030
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.
3232
*/
3333
namespace lp {
3434
// 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 {
187187
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
188188
entry_status m_entry_status;
189189
};
190+
var_register m_var_register;
190191
std_vector<entry> m_entries;
191192
// the terms are stored in m_A and m_c
192193
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 {
219220
t.c() = m_entries[i].m_c;
220221
return t;
221222
}
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+
222233
// the term has form sum(a_i*x_i) - t.j() = 0,
223234
// i is the index of the term in the lra.m_terms
224235
void fill_entry(const lar_term& t) {
225236
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};
228238
unsigned entry_index = m_entries.size();
229239
m_f.push_back(entry_index);
230240
m_entries.push_back(te);
@@ -237,64 +247,52 @@ namespace lp {
237247
if (is_fixed(p.var()))
238248
e.m_c += p.coeff()*lia.lower_bound(p.var()).x;
239249
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())
241252
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());
243254
}
244255
}
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;
248258
else {
249-
while (j >= m_e_matrix.column_count())
259+
unsigned lj = add_var(t.j());
260+
while (lj >= m_e_matrix.column_count())
250261
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));
252263
}
253-
e.m_entry_status = entry_status::F;
254264
TRACE("dioph_eq", print_entry(entry_index, tout););
255-
SASSERT(entry_invariant(i));
265+
SASSERT(entry_invariant(entry_index));
256266
}
257267

258-
bool all_vars_are_int_and_small(const lar_term& term) const {
268+
bool all_vars_are_int(const lar_term& term) const {
259269
for (const auto& p : term) {
260270
if (!lia.column_is_int(p.var()))
261271
return false;
262-
if (p.coeff().is_big())
263-
return false;
264272
}
265273
return true;
266274
}
267275

268-
269276
void init() {
270277
m_e_matrix = static_matrix<mpq, mpq>();
271278
m_report_branch = false;
272279
m_k2s.clear();
280+
m_fresh_definitions.clear();
273281
m_conflict_index = -1;
274282
m_infeas_explanation.clear();
275283
lia.get_term().clear();
276284
m_entries.clear();
285+
m_var_register.clear();
286+
277287
for (unsigned j = 0; j < lra.column_count(); j++) {
278288
if (!lra.column_is_int(j)|| !lra.column_has_term(j)) continue;
279289
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";);
282292
continue;
283293
}
284294
fill_entry(t);
285295
}
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;
298296
}
299297

300298
template <typename K> mpq gcd_of_coeffs(const K & k) {
@@ -333,7 +331,7 @@ namespace lp {
333331
*/
334332
lar_term& t = lia.get_term();
335333
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()));
337335
}
338336
lia.offset() = floor(-new_c);
339337
lia.is_upper() = true;
@@ -427,7 +425,7 @@ namespace lp {
427425
term_o create_term_from_l(const lar_term& l) {
428426
term_o ret;
429427
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()));
431429
ret.add_monomial(-mpq(1), p.j());
432430
for (const auto& q: t) {
433431
ret.add_monomial(p.coeff()*q.coeff(), q.j());
@@ -437,7 +435,7 @@ namespace lp {
437435
}
438436

439437
bool is_fixed(unsigned j) const {
440-
return (!is_fresh_var(j)) && lra.column_is_fixed(j);
438+
return lra.column_is_fixed(j);
441439
}
442440

443441
template <typename T> term_o fix_vars(const T& t) const {
@@ -471,9 +469,10 @@ namespace lp {
471469
}
472470

473471
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++) {
475473
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+
477476
if (tighten_bounds_for_term_column(j))
478477
return lia_move::conflict;
479478
}
@@ -509,18 +508,22 @@ namespace lp {
509508
if (is_fixed(p.j()))
510509
m_c += p.coeff()*lia.lower_bound(p.j()).x;
511510
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()));
513512
}
514513

515514
}
515+
unsigned lar_solver_to_local(unsigned j) const {
516+
return m_var_register.external_to_local(j);
517+
}
516518
// j is the index of the column representing a term
517519
// return true if a conflict was found
518520
bool tighten_bounds_for_term_column(unsigned j) {
519521
term_o term_to_tighten = lra.get_term(j); // copy the term aside
522+
if (!all_vars_are_int(term_to_tighten)) return false;
520523
std::queue<unsigned> q;
521524
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()));
524527
}
525528
if (q.empty()) {
526529
return false;
@@ -540,7 +543,9 @@ namespace lp {
540543
tout << "term_to_tighten + open_ml:"; print_term_o(term_to_tighten + open_ml(m_tmp_l), tout) << std::endl;
541544
print_lar_term_L(remove_fresh_vars(term_to_tighten + open_ml(m_tmp_l)), tout) << std::endl;
542545
);
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())));
544549
mpq g = gcd_of_coeffs(m_indexed_work_vector);
545550
TRACE("dioph_eq", tout << "after process_q_with_S\nt:"; print_term_o(create_term_from_ind_c(), tout) << std::endl;
546551
tout << "g:" << g << std::endl; /*tout << "dep:"; print_dep(tout, m_tmp_l) << std::endl;*/);
@@ -743,14 +748,8 @@ namespace lp {
743748
entry& e = m_entries[ei];
744749
TRACE("dioph_eq", tout << "eliminate var:" << j << " by using:"; print_entry(ei, tout) << std::endl;);
745750
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);
754753
if (pivot_col_cell_index != 0) {
755754
// swap the pivot column cell with the head cell
756755
auto c = column[0];
@@ -789,9 +788,18 @@ namespace lp {
789788
}
790789
}
791790

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+
792800
bool entry_invariant(unsigned ei) const {
793801
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));
795803
if (ret) return true;
796804
TRACE("dioph_eq",
797805
tout << "get_term_from_entry("<< ei <<"):";
@@ -861,7 +869,7 @@ namespace lp {
861869
move_row_to_work_vector(h); // it clears the row, and puts the term in the work vector
862870
// step 7 from the paper
863871
// 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);
865873
unsigned fresh_row = m_e_matrix.row_count();
866874
m_e_matrix.add_row(); // for the fresh variable definition
867875
while (xt >= m_e_matrix.column_count())
@@ -914,18 +922,18 @@ namespace lp {
914922
if (need_print_dep) {
915923
out << "\tm_l:{"; print_lar_term_L(e.m_l, out) << "}, ";
916924
print_ml(e.m_l, out<< " \tfixed 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)) << ",";
918926
}
919927
switch (e.m_entry_status)
920928
{
921929
case entry_status::F:
922-
out << "\tin F\n";
930+
out << "in F\n";
923931
break;
924932
case entry_status::S:
925-
out << "\tin S\n";
933+
out << "in S\n";
926934
break;
927935
default:
928-
out << "\tNOSF\n";
936+
out << "NOSF\n";
929937
}
930938
out << "}\n";
931939
return out;
@@ -995,7 +1003,7 @@ namespace lp {
9951003
}
9961004

9971005
bool is_fresh_var(unsigned j) const {
998-
return j >= lra.column_count();
1006+
return m_var_register.local_to_external(j) == UINT_MAX;
9991007
}
10001008
bool can_substitute(unsigned k) {
10011009
return k < m_k2s.size() && m_k2s[k] != UINT_MAX;

src/math/lp/int_solver.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,9 @@ namespace lp {
290290
for (unsigned j : lra.r_basis()) {
291291
if (!column_is_int_inf(j))
292292
continue;
293-
293+
if (settings().get_cancel_flag()){
294+
return -1;
295+
}
294296
SASSERT(!lia.is_fixed(j));
295297

296298
unsigned usage = lra.usage_in_terms(j);

src/math/lp/var_register.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class var_register {
7474
return ret;
7575
}
7676

77-
// returns UINT_MAX if
77+
// returns UINT_MAX if local_var is greater than or equal than the number of local variables
7878
unsigned local_to_external(unsigned local_var) const {
7979
unsigned k = local_var;
8080
if (k >= m_local_to_external.size())

0 commit comments

Comments
 (0)