@@ -56,7 +56,7 @@ namespace lp {
56
56
ret.add_monomial (p.coeff (), p.j ());
57
57
}
58
58
ret.c () = c ();
59
- ret.j () = j ( );
59
+ ret.set_j ( j () );
60
60
return ret;
61
61
}
62
62
term_o (const lar_term& t) : lar_term(t), m_c(0 ) {
@@ -233,7 +233,12 @@ namespace lp {
233
233
// {coeff*lar.get_term(k)})
234
234
235
235
std_vector<unsigned > m_k2s;
236
- std_vector<unsigned > m_fresh_definitions;
236
+ struct fresh_definition {
237
+ unsigned m_ei;
238
+ unsigned m_origin;
239
+ fresh_definition (unsigned i, unsigned o) : m_ei(i), m_origin(o) {}
240
+ };
241
+ std_vector<fresh_definition> m_fresh_definitions;
237
242
238
243
unsigned m_conflict_index = -1 ; // m_entries[m_conflict_index] gives the conflict
239
244
unsigned m_max_number_of_iterations = 100 ;
@@ -281,9 +286,14 @@ namespace lp {
281
286
undo_add_term (imp& s, const lar_term &t): m_s(s), m_t (t) {
282
287
}
283
288
void undo () {
289
+ TRACE (" dioph_eq" , m_s.lra .print_term (m_t , tout););
284
290
for (const auto & p: m_t ) {
285
291
auto it = m_s.m_columns_to_terms .find (p.var ());
286
292
it->second .erase (m_t .j ());
293
+ if (it->second .size () == 0 ) {
294
+ m_s.m_columns_to_terms .erase (it);
295
+ }
296
+
287
297
}
288
298
}
289
299
};
@@ -303,7 +313,7 @@ namespace lp {
303
313
};
304
314
305
315
std::unordered_set<unsigned > m_changed_columns;
306
- // m_column_to_terms[j] is the set of k such lra.get_term(k) depends on j
316
+ // m_column_to_terms[j] is the set of all k such lra.get_term(k) depends on j
307
317
std::unordered_map<unsigned , std::unordered_set<unsigned >> m_columns_to_terms;
308
318
friend undo_fixed_column;
309
319
void add_changed_column (unsigned j) {
@@ -326,7 +336,6 @@ namespace lp {
326
336
TRACE (" dioph_eq" , tout << " not all vars are integrall\n " ;);
327
337
return ;
328
338
}
329
- TRACE (" dioph_eq" , tout << " inserted" << std::endl;);
330
339
m_added_terms.push_back (t);
331
340
auto undo = undo_add_term (*this , *t);
332
341
lra.trail ().push (undo);
@@ -364,6 +373,7 @@ namespace lp {
364
373
}
365
374
366
375
void register_columns_to_term (const lar_term& t) {
376
+ TRACE (" dioph_eq" , tout << " register term:" ; lra.print_term (t, tout););
367
377
for (const auto &p: t) {
368
378
auto it = m_columns_to_terms.find (p.var ());
369
379
if (it != m_columns_to_terms.end ()) {
@@ -373,12 +383,12 @@ namespace lp {
373
383
std::unordered_set<unsigned > s;
374
384
s.insert (t.j ());
375
385
m_columns_to_terms[p.var ()] = s;
386
+ TRACE (" dioph_eq" , tout << " insert " << p.var (););
376
387
}
377
388
}
378
389
}
379
390
// the term has form sum(a_i*x_i) - t.j() = 0,
380
- void fill_entry (const lar_term& t) {
381
- register_columns_to_term (t);
391
+ void fill_entry (const lar_term& t) {
382
392
TRACE (" dioph_eq" , print_lar_term_L (t, tout) << std::endl;);
383
393
entry te = { mpq (0 ), entry_status::F};
384
394
unsigned entry_index = (unsigned ) m_entries.size ();
@@ -462,45 +472,54 @@ namespace lp {
462
472
std::unordered_set<unsigned > entries_to_recalculate;
463
473
std::unordered_set<unsigned > changed_terms; // a term is signified by the term column, like j in lra.get_term(j)
464
474
std_vector<unsigned > fresh_entries_to_remove;
465
- for (unsigned j = 0 ; j < m_fresh_definitions.size (); j++) {
466
- unsigned k = m_fresh_definitions[j];
467
- if (k == UINT_MAX) continue ;
468
- for (const auto & p: m_e_matrix.m_rows [k]) {
469
- if (contains (m_changed_columns, p.var ())) {
470
- fresh_entries_to_remove.push_back (k);
471
- continue ;
475
+
476
+ for (unsigned j : m_changed_columns) {
477
+ const auto it = m_columns_to_terms.find (j);
478
+ if (it != m_columns_to_terms.end ())
479
+ for (unsigned k : it->second ) {
480
+ changed_terms.insert (k);
472
481
}
473
-
474
- }
475
- }
476
- TRACE (" dioph_eq" , tout << " found " << fresh_entries_to_remove.size () << " fresh entries to remove\n " ;
477
- tout << " m_changed_columns:\n " ;
478
- for (unsigned j : m_changed_columns) {
479
- tout << j << " " ;
480
- }
481
- tout << std::endl;
482
- );
483
- if (fresh_entries_to_remove.size ()) {
484
- NOT_IMPLEMENTED_YET ();
485
- }
486
- for (unsigned j : m_changed_columns) {
487
- for (unsigned k : m_columns_to_terms[j]) {
488
- changed_terms.insert (k);
489
- }
482
+ if (!m_var_register.external_is_used (j))
483
+ continue ;
490
484
for (const auto & p : m_e_matrix.column (this ->lar_solver_to_local (j))) {
491
- TRACE (" dioph_eq" , tout << " insert into entries_to_recalculate " << p.var () << " for changed_column j=" << j<< std::endl;
492
- tout << " p.coeff:" << p.coeff () << std::endl;
493
- );
494
485
entries_to_recalculate.insert (p.var ());
495
486
}
496
487
}
497
488
for (unsigned j : changed_terms) {
498
489
for (const auto & cs: m_l_matrix.column (j)) {
499
- TRACE (" dioph_eq" , tout << " insert into entries_to_recalculate " << cs.var () << " for changed_term j=" << j<< std::endl;);
500
490
entries_to_recalculate.insert (cs.var ());
501
491
}
502
492
}
503
- for (unsigned k : entries_to_recalculate) {
493
+
494
+ for (const lar_term* t : m_added_terms) {
495
+ register_columns_to_term (*t);
496
+ }
497
+
498
+ SASSERT (is_in_sync ());
499
+ TRACE (" dioph_eq" , tout << " entries_to_recalculate:" ; for (unsigned j : entries_to_recalculate) {tout << " " << j;});
500
+ for (unsigned j = 0 ; j < m_fresh_definitions.size (); j++) {
501
+ const fresh_definition& fd = m_fresh_definitions[j];
502
+ if (fd.m_ei == UINT_MAX) continue ;
503
+ if (contains (entries_to_recalculate, fd.m_origin )) {
504
+ fresh_entries_to_remove.push_back (j);
505
+ continue ;
506
+ }
507
+ }
508
+
509
+ TRACE (" dioph_eq" , tout << " found " << fresh_entries_to_remove.size () << " fresh entries to remove\n " ;
510
+ tout << " m_changed_columns:\n " ;
511
+ std::vector<unsigned > v (m_changed_columns.begin (), m_changed_columns.end ());
512
+ std::sort (v.begin (), v.end ());
513
+ for (unsigned j : v) {
514
+ tout << j << " " ;
515
+ }
516
+ tout << std::endl;
517
+ );
518
+ if (fresh_entries_to_remove.size ()) {
519
+ NOT_IMPLEMENTED_YET ();
520
+ }
521
+
522
+ for (unsigned k : entries_to_recalculate) {
504
523
recalculate_entry (k);
505
524
}
506
525
move_recalculated_to_F (entries_to_recalculate);
@@ -528,6 +547,16 @@ namespace lp {
528
547
}
529
548
}
530
549
550
+ bool entries_are_ok () {
551
+ for (unsigned ei = 0 ; ei < m_entries.size (); ei++) {
552
+ if (entry_invariant (ei) == false ) {
553
+ TRACE (" dioph_eq" , tout << " bad entry:" ; print_entry (ei, tout););
554
+ return false ;
555
+ }
556
+ }
557
+ return true ;
558
+ }
559
+
531
560
void init () {
532
561
m_report_branch = false ;
533
562
m_conflict_index = -1 ;
@@ -541,18 +570,8 @@ namespace lp {
541
570
fill_entry (*t);
542
571
}
543
572
m_added_terms.clear ();
544
- /*
545
- for (unsigned j = 0; j < lra.column_count(); j++) {
546
- if (!lra.column_is_int(j) || !lra.column_has_term(j))
547
- continue;
548
- const lar_term& t = lra.get_term(j);
549
- if (!all_vars_are_int(t)) {
550
- TRACE("dioph_eq", tout << "not all vars are integrall\n";);
551
- continue;
552
- }
553
- fill_entry(t);
554
- }*/
555
- }
573
+ SASSERT (entries_are_ok ());
574
+ }
556
575
557
576
template <typename K>
558
577
mpq gcd_of_coeffs (const K& k) {
@@ -573,10 +592,6 @@ namespace lp {
573
592
return lra.print_expl (out, ex);
574
593
}
575
594
576
- std::string var_str (unsigned j) {
577
- return std::string (is_fresh_var (j) ? " ~" : " " ) + std::to_string (j);
578
- }
579
-
580
595
bool has_fresh_var (unsigned row_index) const {
581
596
for (const auto & p : m_e_matrix.m_rows [row_index]) {
582
597
if (is_fresh_var (p.var ()))
@@ -671,6 +686,7 @@ namespace lp {
671
686
if (m_indexed_work_vector[k].is_zero ())
672
687
return ;
673
688
const entry& e = entry_for_subs (k);
689
+ SASSERT (e.m_entry_status == entry_status::S);
674
690
TRACE (" dioph_eq" , tout << " k:" << k << " , in " ;
675
691
print_term_o (create_term_from_ind_c (), tout) << std::endl;
676
692
tout << " subs with e:" ;
@@ -854,7 +870,10 @@ namespace lp {
854
870
tout << " term_to_tighten + open_ml:" ;
855
871
print_term_o (term_to_tighten + open_ml (m_tmp_l), tout)
856
872
<< std::endl;
857
- );
873
+ tout << " ls:" ; print_term_o (fix_vars (term_to_tighten + open_ml (m_tmp_l)),tout) << std::endl;
874
+ tout << " rs:" ; print_term_o (term_to_lar_solver (remove_fresh_vars (create_term_from_ind_c ())), tout ) << std::endl;
875
+
876
+ );
858
877
SASSERT (
859
878
fix_vars (term_to_tighten + open_ml (m_tmp_l)) ==
860
879
term_to_lar_solver (remove_fresh_vars (create_term_from_ind_c ())));
@@ -1283,6 +1302,69 @@ namespace lp {
1283
1302
return br;
1284
1303
}
1285
1304
1305
+ bool columns_to_terms_is_correct () const {
1306
+ std::unordered_map<unsigned , std::unordered_set<unsigned >> c2t;
1307
+ for (unsigned k = 0 ; k < lra.terms ().size (); k ++ ) {
1308
+ const lar_term* t = lra.terms ()[k];
1309
+ if (!all_vars_are_int (*t)) continue ;
1310
+ for (const auto & p: *t) {
1311
+ unsigned j = p.var ();
1312
+ auto it = c2t.find (j);
1313
+ if (it == c2t.end ()) {
1314
+ std::unordered_set<unsigned > s;
1315
+ s.insert (t->j ());
1316
+ c2t[j] = s;
1317
+ } else {
1318
+ it->second .insert (t->j ());
1319
+ }
1320
+
1321
+ }
1322
+ }
1323
+ for (const auto & p : c2t) {
1324
+ unsigned j = p.first ;
1325
+ const auto it = m_columns_to_terms.find (j);
1326
+ if (it == m_columns_to_terms.end ()) {
1327
+ TRACE (" dioph_eq" , tout << " column j" << j << " is not registered" << std::endl;
1328
+ tout << " the column belongs to the the following terms:" ;
1329
+ for (unsigned tj : p.second ) {
1330
+ tout << " " << tj;
1331
+ }
1332
+ tout << std::endl;
1333
+ );
1334
+
1335
+ return false ;
1336
+ }
1337
+ if (it->second != p.second ) {
1338
+ return false ;
1339
+ }
1340
+ }
1341
+ // reverse inclusion
1342
+ for (const auto & p : m_columns_to_terms) {
1343
+ unsigned j = p.first ;
1344
+ const auto it = c2t.find (j);
1345
+ if (it == c2t.end ()) {
1346
+ TRACE (" dioph_eq" , tout << " should not be registered j " << j << std::endl;
1347
+ lra.print_terms (tout););
1348
+ return false ;
1349
+ }
1350
+ if (it->second != p.second ) {
1351
+ return false ;
1352
+ }
1353
+ }
1354
+ return true ;
1355
+ }
1356
+ bool is_in_sync () const {
1357
+ unsigned n_local_columns = m_e_matrix.column_count ();
1358
+ for (unsigned j = 0 ; j < n_local_columns; j++) {
1359
+ unsigned external_j = m_var_register.local_to_external (j);
1360
+ if (external_j == UINT_MAX) continue ;
1361
+ if (external_j >= lra.column_count ())
1362
+ return false ;
1363
+ }
1364
+
1365
+ return columns_to_terms_is_correct ();
1366
+ }
1367
+
1286
1368
public:
1287
1369
lia_move check () {
1288
1370
lra.stats ().m_dio_calls ++;
@@ -1443,9 +1525,7 @@ namespace lp {
1443
1525
}
1444
1526
while (!q.empty ()) {
1445
1527
unsigned xt = pop_front (q);
1446
- term_o fresh_t = get_term_from_entry (m_fresh_definitions[xt]);
1447
- if (fresh_t .get_coeff (xt).is_minus_one () == false )
1448
- std::cout << " coeff:" << fresh_t .get_coeff (xt) << std::endl;
1528
+ term_o fresh_t = get_term_from_entry (m_fresh_definitions[xt].m_ei );
1449
1529
SASSERT (fresh_t .get_coeff (xt).is_minus_one ());
1450
1530
fresh_t .erase_var (xt);
1451
1531
if (!t.contains (xt))
@@ -1551,8 +1631,10 @@ namespace lp {
1551
1631
1552
1632
m_k2s.resize (k + 1 , -1 );
1553
1633
m_k2s[k] = fresh_row;
1554
- m_fresh_definitions.resize (xt + 1 , -1 );
1555
- m_fresh_definitions[xt] = fresh_row;
1634
+ fresh_definition fd (-1 , -1 );
1635
+
1636
+ m_fresh_definitions.resize (xt + 1 , fd);
1637
+ m_fresh_definitions[xt] = fresh_definition (fresh_row, h);
1556
1638
TRACE (" dioph_eq" , tout << " changed entry:" ;
1557
1639
print_entry (h, tout) << std::endl;
1558
1640
tout << " added entry for fresh var:\n " ;
@@ -1576,8 +1658,10 @@ namespace lp {
1576
1658
if (need_print_dep) {
1577
1659
out << " \t m_l:{" ;
1578
1660
print_lar_term_L (l_term_from_row (ei), out) << " }, " ;
1579
- print_ml (l_term_from_row (ei), out << " \n\t expl of fixed in m_l:\n " ) << " \n " ;
1661
+ print_ml (l_term_from_row (ei), out) << std::endl;
1662
+ out << " expl of fixed in m_l:{\n " ;
1580
1663
print_dep (out, explain_fixed_in_meta_term (l_term_from_row (ei)));
1664
+ out << " }\n " ;
1581
1665
}
1582
1666
switch (e.m_entry_status ) {
1583
1667
case entry_status::F:
0 commit comments