@@ -596,34 +596,63 @@ namespace lp {
596
596
};
597
597
598
598
struct protected_queue {
599
- std::queue<unsigned > m_q;
600
- indexed_uint_set m_in_q;
599
+ std::list<unsigned > m_q;
600
+ std::unordered_map<unsigned , std::list<unsigned >::iterator> m_positions;
601
+
601
602
bool empty () const {
602
603
return m_q.empty ();
603
604
}
604
605
605
606
unsigned size () const {
606
- return ( unsigned ) m_q.size ();
607
+ return static_cast < unsigned >( m_q.size () );
607
608
}
608
609
609
610
void push (unsigned j) {
610
- if (m_in_q. contains (j )) return ;
611
- m_in_q. insert (j);
612
- m_q.push (j );
611
+ if (m_positions. find (j) != m_positions. end ( )) return ;
612
+ m_q. push_back (j);
613
+ m_positions[j] = std::prev ( m_q.end () );
613
614
}
614
615
615
616
unsigned pop_front () {
616
617
unsigned j = m_q.front ();
617
- m_q.pop ();
618
- SASSERT (m_in_q.contains (j));
619
- m_in_q.remove (j);
618
+ m_q.pop_front ();
619
+ m_positions.erase (j);
620
620
return j;
621
621
}
622
622
623
+ void remove (unsigned j) {
624
+ auto it = m_positions.find (j);
625
+ if (it != m_positions.end ()) {
626
+ m_q.erase (it->second );
627
+ m_positions.erase (it);
628
+ }
629
+ if (!invariant ()) {
630
+ throw std::runtime_error (" Invariant violation in protected_queue" );
631
+ }
632
+ }
633
+
634
+ bool contains (unsigned j) const {
635
+ return m_positions.find (j) != m_positions.end ();
636
+ }
637
+
623
638
void reset () {
624
- while (!m_q.empty ())
625
- m_q.pop ();
626
- m_in_q.reset ();
639
+ m_q.clear ();
640
+ m_positions.clear ();
641
+ }
642
+ // Invariant method to ensure m_q and m_positions are aligned
643
+ bool invariant () const {
644
+ if (m_q.size () != m_positions.size ())
645
+ return false ;
646
+
647
+ for (auto it = m_q.begin (); it != m_q.end (); ++it) {
648
+ auto pos_it = m_positions.find (*it);
649
+ if (pos_it == m_positions.end ())
650
+ return false ;
651
+ if (pos_it->second != it)
652
+ return false ;
653
+ }
654
+
655
+ return true ;
627
656
}
628
657
};
629
658
@@ -750,6 +779,12 @@ namespace lp {
750
779
std_vector<variable_branch_stats> m_branch_stats;
751
780
std_vector<branch> m_branch_stack;
752
781
std_vector<constraint_index> m_explanation_of_branches;
782
+ bool term_has_big_number (const lar_term* t) const {
783
+ for (const auto & p : *t)
784
+ if (p.coeff ().is_big ())
785
+ return true ;
786
+ return false ;
787
+ }
753
788
void add_term_callback (const lar_term* t) {
754
789
unsigned j = t->j ();
755
790
TRACE (" dio" , tout << " term column t->j():" << j << std::endl; lra.print_term (*t, tout) << std::endl;);
@@ -761,8 +796,9 @@ namespace lp {
761
796
762
797
CTRACE (" dio" , !lra.column_has_term (j), tout << " added term that is not associated with a column yet" << std::endl;);
763
798
764
- if (!lia.column_is_int (t->j ())) {
765
- TRACE (" dio" , tout << " not all vars are integrall\n " ;);
799
+ if (term_has_big_number (t)) {
800
+ TRACE (" dio" , tout << " term_has_big_number\n " ;);
801
+ m_has_non_integral_term = true ;
766
802
return ;
767
803
}
768
804
m_added_terms.push_back (t);
@@ -779,10 +815,12 @@ namespace lp {
779
815
void update_column_bound_callback (unsigned j) {
780
816
if (!lra.column_is_int (j))
781
817
return ;
782
- if (lra.column_has_term (j))
818
+ if (lra.column_has_term (j) && ! term_has_big_number (&lra. get_term (j)) )
783
819
m_terms_to_tighten.insert (j); // the boundary of the term has changed: we can be successful to tighten this term
784
820
if (!lra.column_is_fixed (j))
785
821
return ;
822
+ if (lra.get_lower_bound (j).x .is_big ())
823
+ return ;
786
824
TRACE (" dio" , tout << " j:" << j << " \n " ; lra.print_column_info (j, tout););
787
825
m_changed_columns.insert (j);
788
826
lra.trail ().push (undo_fixed_column (*this , j));
@@ -1016,6 +1054,7 @@ namespace lp {
1016
1054
void process_changed_columns (std_vector<unsigned > &f_vector) {
1017
1055
find_changed_terms_and_more_changed_rows ();
1018
1056
for (unsigned j: m_changed_terms) {
1057
+ SASSERT (!term_has_big_number (&lra.get_term (j)));
1019
1058
m_terms_to_tighten.insert (j);
1020
1059
if (j < m_l_matrix.column_count ()) {
1021
1060
for (const auto & cs : m_l_matrix.column (j)) {
@@ -1295,6 +1334,52 @@ namespace lp {
1295
1334
bool is_substituted_by_fresh (unsigned k) const {
1296
1335
return m_fresh_k2xt_terms.has_key (k);
1297
1336
}
1337
+
1338
+ // find a variable in q, not neccessarily at the beginning of the queue, that when substituted would create the minimal
1339
+ // number of non-zeroes
1340
+ unsigned find_var_to_substitute_on_espace (protected_queue& q) {
1341
+ // go over all q elements j
1342
+ // say j is substituted by entry ei = m_k2s[j]
1343
+ // count the number of variables i in m_e_matrix[ei] that m_espace does not contain i,
1344
+ // and choose ei where this number is minimal
1345
+
1346
+ unsigned best_var = UINT_MAX;
1347
+ size_t min_new_vars = std::numeric_limits<size_t >::max ();
1348
+ unsigned num_candidates = 0 ;
1349
+
1350
+ for (unsigned j : q.m_q ) {
1351
+ size_t new_vars = 0 ;
1352
+ if (!m_espace.has (j)) continue ;
1353
+ if (m_k2s.has_key (j)) {
1354
+ unsigned ei = m_k2s[j]; // entry index for substitution
1355
+ for (const auto & p : m_e_matrix.m_rows [ei])
1356
+ if (p.var () != j && !m_espace.has (p.var ()))
1357
+ ++new_vars;
1358
+ }
1359
+ else if (m_fresh_k2xt_terms.has_key (j)) {
1360
+ const lar_term& fresh_term = m_fresh_k2xt_terms.get_by_key (j).first ;
1361
+ for (const auto & p : fresh_term)
1362
+ if (p.var () != j && !m_espace.has (p.var ()))
1363
+ ++new_vars;
1364
+ }
1365
+ if (new_vars < min_new_vars) {
1366
+ min_new_vars = new_vars;
1367
+ best_var = j;
1368
+ num_candidates = 1 ;
1369
+ }
1370
+ else if (new_vars == min_new_vars) {
1371
+ ++num_candidates;
1372
+ if ((lra.settings ().random_next () % num_candidates) == 0 )
1373
+ best_var = j;
1374
+ }
1375
+ }
1376
+
1377
+ if (best_var != UINT_MAX)
1378
+ q.remove (best_var);
1379
+
1380
+ return best_var;
1381
+ }
1382
+
1298
1383
// The term giving the substitution is in form (+-)x_k + sum {a_i*x_i} + c = 0.
1299
1384
// We substitute x_k in t by (+-)coeff*(sum {a_i*x_i} + c), where coeff is
1300
1385
// the coefficient of x_k in t.
@@ -1303,11 +1388,11 @@ namespace lp {
1303
1388
auto r = tighten_on_espace (j);
1304
1389
if (r == lia_move::conflict)
1305
1390
return lia_move::conflict;
1306
- unsigned k = q.pop_front ();
1307
- if (!m_espace.has (k))
1308
- return lia_move::undef;
1391
+ unsigned k = find_var_to_substitute_on_espace (q);
1392
+ if (k == UINT_MAX)
1393
+ return lia_move::undef;
1394
+ SASSERT (m_espace.has (k));
1309
1395
// we might substitute with a term from S or a fresh term
1310
-
1311
1396
SASSERT (can_substitute (k));
1312
1397
lia_move ret;
1313
1398
if (is_substituted_by_fresh (k))
@@ -2203,6 +2288,7 @@ namespace lp {
2203
2288
public:
2204
2289
lia_move check () {
2205
2290
lra.stats ().m_dio_calls ++;
2291
+ std::cout << " check" << std::endl;
2206
2292
TRACE (" dio" , tout << lra.stats ().m_dio_calls << std::endl;);
2207
2293
std_vector<unsigned > f_vector;
2208
2294
lia_move ret;
0 commit comments