23
23
-- lia: point to int_solver.
24
24
-- m_entries: it keeps all "entry" objects.
25
25
-- m_e_matrix: i-th row of this matrix keeps the term corresponding to
26
- m_entries[i]. The actual term is the sum of the matrix row and the constant
27
- m_c of the entry. The column j of the matrix corresponds to j column of
28
- lar_solver if j < lra.column_count(). Otherwise, j is a fresh column. It has
29
- to change in the interactive version. Implementation remarks:
26
+ m_entries[i]. The actual term corresponding to m_entry[i] is the sum of the
27
+ matrix i-th row and the constant m_entry[].m_c.
28
+ The mapping between the columns of lar_solver and m_e_matrix is controlled by m_var_register.
29
+ local_to_lar_solver(lar_solver_to_local(j)) == j. If local_to_lar_solver(j) == -1
30
+ then j is a fresh variable, that is such that got introduced when normalizing a term like 3x-6y + 5z +11 = 0,
31
+ when no variable has a coefficient +-1.
32
+
30
33
-- get_term_from_entry(unsigned i) return a term corresponding i-th entry.
31
34
If t = get_term_from_entry(i) then we have equality t = 0. Initially
32
35
get_term_from_entry(i) is set to initt(j) = lra.get_term(j) - j, for some
@@ -246,6 +249,7 @@ namespace lp {
246
249
bool m_left;
247
250
bool m_fully_explored = false ;
248
251
void flip () {
252
+ SASSERT (m_fully_explored == false );
249
253
m_left = !m_left;
250
254
m_fully_explored = true ;
251
255
}
@@ -415,6 +419,8 @@ namespace lp {
415
419
416
420
// A conflict is reported when the gcd of the monomial coefficients does not divide the free coefficent.
417
421
// If there is no conflict the entry is divided, normalized, by gcd.
422
+ // The function returns true if and only if there is no conflict. In the case of a conflict a branch
423
+ // can be returned as well.
418
424
bool normalize_e_by_gcd (unsigned ei) {
419
425
entry& e = m_entries[ei];
420
426
TRACE (" dioph_eq" , print_entry (ei, tout) << std::endl;);
@@ -437,7 +443,7 @@ namespace lp {
437
443
return true ;
438
444
}
439
445
// c_g is not integral
440
- if (lra.settings (). stats ().m_dio_conflicts %
446
+ if (lra.stats ().m_dio_calls %
441
447
lra.settings ().dio_cut_from_proof_period () ==
442
448
0 &&
443
449
!has_fresh_var (ei))
@@ -563,7 +569,7 @@ namespace lp {
563
569
subs_front_in_indexed_vector (q);
564
570
}
565
571
566
- lia_move tighten_with_S () {
572
+ lia_move tighten_terms_with_S () {
567
573
for (unsigned j = 0 ; j < lra.column_count (); j++) {
568
574
if (!lra.column_has_term (j) || lra.column_is_free (j) ||
569
575
is_fixed (j) || !lia.column_is_int (j))
@@ -792,26 +798,35 @@ namespace lp {
792
798
return dep;
793
799
}
794
800
795
- lia_move iterate () {
801
+ lia_move process_f () {
796
802
while (m_f.size ()) {
797
803
if (!normalize_by_gcd ()) {
798
- lra.settings ().stats ().m_dio_conflicts ++;
799
804
if (m_report_branch) {
805
+ lra.stats ().m_dio_cut_from_proofs ++;
800
806
m_report_branch = false ;
801
807
return lia_move::branch;
808
+ } else {
809
+ lra.stats ().m_dio_normalize_conflicts ++;
802
810
}
803
811
return lia_move::conflict;
804
812
}
805
813
rewrite_eqs ();
806
814
if (m_conflict_index != UINT_MAX) {
807
- lra.settings (). stats ().m_dio_conflicts ++;
815
+ lra.stats ().m_dio_rewrite_conflicts ++;
808
816
return lia_move::conflict;
809
817
}
810
818
}
819
+ return lia_move::undef;
820
+ }
821
+
822
+ lia_move process_f_and_tighten_terms () {
823
+ lia_move ret = process_f ();
824
+ if (ret != lia_move::undef)
825
+ return ret;
811
826
TRACE (" dioph_eq" , print_S (tout););
812
- lia_move ret = tighten_with_S ();
827
+ ret = tighten_terms_with_S ();
813
828
if (ret == lia_move::conflict) {
814
- lra.settings (). stats ().m_dio_conflicts ++;
829
+ lra.stats ().m_dio_tighten_conflicts ++;
815
830
return lia_move::conflict;
816
831
}
817
832
return lia_move::undef;
@@ -835,16 +850,13 @@ namespace lp {
835
850
}
836
851
837
852
// returns true if the left and the right branches were explored
838
- bool undo_last_branch () {
839
- if ( m_branch_stack.back (). m_fully_explored ) {
840
- TRACE ( " dio_br " , tout << " pop fully explored, m_branch_stack.size(): " << m_branch_stack.size () << std::endl;);
853
+ void undo_explored_branches () {
854
+ TRACE ( " dio_br " , tout << " m_branch_stack.size(): " << m_branch_stack. size () << std::endl;);
855
+ while ( m_branch_stack.size () && m_branch_stack.back (). m_fully_explored ) {
841
856
m_branch_stack.pop_back ();
842
- return true ;
857
+ lra_pop () ;
843
858
}
844
- // exploring the other side of the branch
845
- TRACE (" dio_br" , tout << " flipped branch" << std::endl;);
846
- m_branch_stack.back ().flip ();
847
- return false ;
859
+ TRACE (" dio_br" , tout << " after pop:m_branch_stack.size():" << m_branch_stack.size () << std::endl;);
848
860
}
849
861
850
862
lia_move check_fixing (unsigned j) const {
@@ -903,6 +915,7 @@ namespace lp {
903
915
if (br.m_j == UINT_MAX)
904
916
return false ;
905
917
m_branch_stack.push_back (br);
918
+ lra.stats ().m_dio_branching_depth = std::max (lra.stats ().m_dio_branching_depth , (unsigned )m_branch_stack.size ());
906
919
return true ;
907
920
}
908
921
@@ -912,10 +925,10 @@ namespace lp {
912
925
} else {
913
926
lra.add_var_bound (b->m_j , lconstraint_kind::GE, b->m_rs + mpq (1 ));
914
927
}
915
- if (lra.column_is_fixed (b->m_j )) {
916
- if (fix_var (lar_solver_to_local (b->m_j )) == lia_move::conflict)
917
- return lia_move::conflict;
918
- }
928
+ // if (lra.column_is_fixed(b->m_j)) {
929
+ // if (fix_var(lar_solver_to_local(b->m_j)) == lia_move::conflict)
930
+ // return lia_move::conflict;
931
+ // }
919
932
return lia_move::undef;
920
933
}
921
934
@@ -927,20 +940,32 @@ namespace lp {
927
940
}
928
941
void lra_pop () {
929
942
m_lra_level--;
943
+ SASSERT (m_lra_level != UINT_MAX);
930
944
lra.pop ();
931
945
lra.find_feasible_solution ();
932
946
SASSERT (lra.get_status () == lp_status::CANCELLED || lra.is_feasible ());
933
947
}
934
948
935
- lia_move process_undef () {
949
+ void transfer_explanations_from_closed_branches () {
950
+ m_infeas_explanation.clear ();
951
+ for (auto ci : m_explanation_of_branches) {
952
+ if (this ->lra .constraints ().valid_index (ci))
953
+ m_infeas_explanation.push_back (ci);
954
+ }
955
+
956
+ }
957
+
958
+ lia_move branching_on_undef () {
936
959
m_explanation_of_branches.clear ();
937
960
branch* b;
938
961
bool need_create_branch = true ;
939
962
m_number_of_iterations = 0 ;
940
963
while (++m_number_of_iterations < m_max_number_of_iterations) {
964
+ lra.stats ().m_dio_branch_iterations ++;
941
965
if (need_create_branch) {
942
966
if (!push_branch ()) {
943
967
undo_branching ();
968
+ lra.stats ().m_dio_branching_sats ++;
944
969
return lia_move::sat;
945
970
}
946
971
need_create_branch = false ;
@@ -950,13 +975,16 @@ namespace lp {
950
975
951
976
if (add_var_bound_for_branch (b) == lia_move::conflict) {
952
977
collect_evidence ();
953
- if (m_branch_stack.size () == 0 )
978
+ undo_explored_branches ();
979
+ if (m_branch_stack.size () == 0 ) {
980
+ lra.stats ().m_dio_branching_infeasibles ++;
981
+ transfer_explanations_from_closed_branches ();
954
982
return lia_move::conflict;
983
+ }
955
984
TRACE (" dio_br" , tout << lp_status_to_string (lra.get_status ()) << std::endl;
956
985
tout << " explanation:\n " ; lra.print_expl (tout, m_infeas_explanation););
957
- if (undo_last_branch ())
958
- need_create_branch = true ;
959
- lra_pop ();
986
+ need_create_branch = false ;
987
+ m_branch_stack.back ().flip ();
960
988
continue ;
961
989
}
962
990
auto st = lra.find_feasible_solution ();
@@ -966,6 +994,7 @@ namespace lp {
966
994
TRACE (" dio_br" , tout << " n_of_ii:" << n_of_ii << " \n " ;);
967
995
if (n_of_ii == 0 ) {
968
996
undo_branching ();
997
+ lra.stats ().m_dio_branching_sats ++;
969
998
return lia_move::sat;
970
999
}
971
1000
// got to create a new branch
@@ -974,13 +1003,19 @@ namespace lp {
974
1003
} else {
975
1004
if (st == lp_status::CANCELLED) return lia_move::undef;
976
1005
collect_evidence ();
977
- if (m_branch_stack.size () == 0 )
978
- return lia_move::conflict;
1006
+ undo_explored_branches ();
1007
+ if (m_branch_stack.size () == 0 ) {
1008
+ lra.stats ().m_dio_branching_infeasibles ++;
1009
+ transfer_explanations_from_closed_branches ();
1010
+ enable_trace (" dioph_eq" );
1011
+ return lia_move::conflict;
1012
+ }
979
1013
TRACE (" dio_br" , tout << lp_status_to_string (lra.get_status ()) << std::endl;
980
1014
tout << " explanation:\n " ; lra.print_expl (tout, m_infeas_explanation););
981
- if ( undo_last_branch ())
982
- need_create_branch = true ;
1015
+
1016
+ need_create_branch = false ;
983
1017
lra_pop ();
1018
+ m_branch_stack.back ().flip ();
984
1019
}
985
1020
}
986
1021
undo_branching ();
@@ -1049,20 +1084,20 @@ namespace lp {
1049
1084
br.m_left = (lra.settings ().random_next () % 2 == 0 );
1050
1085
br.m_rs = floor (lra.get_column_value (bj).x );
1051
1086
1052
- TRACE (" dio_br" , tout << " br.m_j:" << br.m_j << " ,"
1087
+ TRACE (" dio_br" , tout << " score: " << score << " ; br.m_j:" << br.m_j << " ,"
1053
1088
<< (br.m_left ? " left" : " right" ) << " , br.m_rs:" << br.m_rs << std::endl;);
1054
1089
return br;
1055
1090
}
1056
1091
1057
1092
public:
1058
1093
lia_move check () {
1059
- lra.settings (). stats ().m_dio_calls ++;
1094
+ lra.stats ().m_dio_calls ++;
1060
1095
init ();
1061
- lia_move ret = iterate ();
1096
+ lia_move ret = process_f_and_tighten_terms ();
1062
1097
if (ret == lia_move::branch || ret == lia_move::conflict)
1063
1098
return ret;
1064
1099
SASSERT (ret == lia_move::undef);
1065
- ret = process_undef ();
1100
+ ret = branching_on_undef ();
1066
1101
if (ret == lia_move::sat || ret == lia_move::conflict)
1067
1102
return ret;
1068
1103
SASSERT (ret == lia_move::undef);
@@ -1382,8 +1417,6 @@ namespace lp {
1382
1417
public:
1383
1418
void explain (explanation& ex) {
1384
1419
if (m_conflict_index == UINT_MAX) {
1385
- SASSERT (!(lra.get_status () == lp_status::FEASIBLE ||
1386
- lra.get_status () == lp_status::OPTIMAL));
1387
1420
for (auto ci : m_infeas_explanation) {
1388
1421
ex.push_back (ci.ci ());
1389
1422
}
0 commit comments