Skip to content

Commit 4f46292

Browse files
fix #4116
delta has to be computed based on Simplex tableau not on difference graph.
1 parent 3a63c37 commit 4f46292

File tree

7 files changed

+91
-21
lines changed

7 files changed

+91
-21
lines changed

src/math/simplex/simplex.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,50 @@ Module Name:
2020
#include "math/simplex/simplex.h"
2121
#include "math/simplex/sparse_matrix_def.h"
2222
#include "math/simplex/simplex_def.h"
23+
#include "util/rational.h"
24+
#include "util/inf_rational.h"
25+
2326
namespace simplex {
2427
template class simplex<mpz_ext>;
2528
template class simplex<mpq_ext>;
29+
30+
static void refine_delta(rational& delta, inf_rational const& l, inf_rational const& u) {
31+
if (l.get_rational() < u.get_rational() && l.get_infinitesimal() > u.get_infinitesimal()) {
32+
rational new_delta = (u.get_rational() - l.get_rational()) / (l.get_infinitesimal() - u.get_infinitesimal());
33+
if (new_delta < delta) {
34+
delta = new_delta;
35+
}
36+
}
37+
}
38+
39+
40+
void ensure_rational_solution(simplex<mpq_ext>& S) {
41+
rational delta(1);
42+
for (unsigned i = 0; i < S.get_num_vars(); ++i) {
43+
auto const& _value = S.get_value(i);
44+
inf_rational value(rational(_value.first), rational(_value.second));
45+
if (S.lower_valid(i)) {
46+
auto const& _bound = S.get_lower(i);
47+
inf_rational bound(rational(_bound.first), rational(_bound.second));
48+
refine_delta(delta, bound, value);
49+
}
50+
if (S.upper_valid(i)) {
51+
auto const& _bound = S.get_upper(i);
52+
inf_rational bound(rational(_bound.first), rational(_bound.second));
53+
refine_delta(delta, value, bound);
54+
}
55+
}
56+
unsynch_mpq_inf_manager inf_mgr;
57+
scoped_mpq_inf q(inf_mgr);
58+
for (unsigned i = 0; i < S.get_num_vars(); ++i) {
59+
auto const& _value = S.get_value(i);
60+
rational inf(_value.second);
61+
if (!inf.is_zero()) {
62+
rational fin = rational(_value.first) + inf * delta;
63+
inf = 0;
64+
inf_mgr.set(q, fin.to_mpq(), inf.to_mpq());
65+
S.set_value(i, q);
66+
}
67+
}
68+
}
2669
};

src/math/simplex/simplex.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ namespace simplex {
133133
void set_upper(var_t var, eps_numeral const& b);
134134
void get_lower(var_t var, scoped_eps_numeral& b) const { b = m_vars[var].m_lower; }
135135
void get_upper(var_t var, scoped_eps_numeral& b) const { b = m_vars[var].m_upper; }
136+
eps_numeral const& get_lower(var_t var) const { return m_vars[var].m_lower; }
137+
eps_numeral const& get_upper(var_t var) const { return m_vars[var].m_upper; }
136138
bool above_lower(var_t var, eps_numeral const& b) const;
137139
bool below_upper(var_t var, eps_numeral const& b) const;
138140
bool below_lower(var_t v) const;
@@ -198,6 +200,7 @@ namespace simplex {
198200
bool is_feasible() const;
199201
};
200202

203+
void ensure_rational_solution(simplex<mpq_ext>& s);
201204
};
202205

203206
#endif

src/math/simplex/simplex_def.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ Module Name:
55
66
simplex_def.h
77
8-
Abstract:
9-
108
Author:
119
1210
Nikolaj Bjorner (nbjorner) 2014-01-15

src/smt/diff_logic.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ class dl_graph {
414414
}
415415
break;
416416
case DL_PROCESSED:
417+
TRACE("arith", display_edge(tout << "processed twice: ", e););
417418
// if two edges with the same source/target occur in the graph.
418419
break;
419420
default:
@@ -514,10 +515,8 @@ class dl_graph {
514515
// The method assumes the graph is feasible before the invocation.
515516
bool enable_edge(edge_id id) {
516517
edge& e = m_edges[id];
518+
SASSERT(is_feasible());
517519
bool r = true;
518-
if (!is_feasible()) {
519-
return false;
520-
}
521520
if (!e.is_enabled()) {
522521
e.enable(m_timestamp);
523522
m_last_enabled_edge = id;

src/smt/theory_dense_diff_logic_def.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,8 @@ namespace smt {
985985
TRACE("opt", S.display(tout); );
986986
SASSERT(is_sat != l_false);
987987
lbool is_fin = S.minimize(w);
988+
989+
ensure_rational_solution(S);
988990

989991
switch (is_fin) {
990992
case l_true: {
@@ -1010,10 +1012,10 @@ namespace smt {
10101012
}
10111013
for (unsigned i = 0; i < num_nodes; ++i) {
10121014
mpq_inf const& val = S.get_value(i);
1013-
rational q(val.first), eps(val.second);
1015+
rational q(val.first);
1016+
SASSERT(rational(val.second).is_zero());
10141017
numeral a(q);
10151018
m_assignment[i] = a;
1016-
// TBD: if epsilon is != 0, then adjust a by some small fraction.
10171019
}
10181020
inf_eps result(rational(0), r);
10191021
blocker = mk_gt(v, result);

src/smt/theory_diff_logic_def.h

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,9 @@ void theory_diff_logic<Ext>::pop_scope_eh(unsigned num_scopes) {
341341
m_scopes.shrink(new_lvl);
342342
unsigned num_edges = m_graph.get_num_edges();
343343
m_graph.pop(num_scopes);
344-
if (num_edges != m_graph.get_num_edges() && m_num_simplex_edges > 0) {
344+
TRACE("arith", m_graph.display(tout););
345+
SASSERT(m_graph.is_feasible());
346+
if (true || (num_edges != m_graph.get_num_edges() && m_num_simplex_edges > 0)) {
345347
m_S.reset();
346348
m_num_simplex_edges = 0;
347349
m_objective_rows.reset();
@@ -565,6 +567,7 @@ bool theory_diff_logic<Ext>::propagate_atom(atom* a) {
565567
}
566568
int edge_id = a->get_asserted_edge();
567569
if (!m_graph.enable_edge(edge_id)) {
570+
TRACE("arith", display(tout););
568571
set_neg_cycle_conflict();
569572
return false;
570573
}
@@ -685,11 +688,8 @@ void theory_diff_logic<Ext>::set_neg_cycle_conflict() {
685688
context & ctx = get_context();
686689
TRACE("arith_conflict",
687690
tout << "conflict: ";
688-
for (unsigned i = 0; i < lits.size(); ++i) {
689-
ctx.display_literal_info(tout, lits[i]);
690-
}
691-
tout << "\n";
692-
);
691+
for (literal lit : lits) ctx.display_literal_info(tout, lit);
692+
tout << "\n";);
693693

694694
if (dump_lemmas()) {
695695
symbol logic(m_lia_or_lra == is_lia ? "QF_LIA" : "QF_LRA");
@@ -911,6 +911,7 @@ void theory_diff_logic<Ext>::compute_delta() {
911911
}
912912

913913

914+
914915
template<typename Ext>
915916
void theory_diff_logic<Ext>::init_model(smt::model_generator & m) {
916917
m_factory = alloc(arith_factory, get_manager());
@@ -935,9 +936,11 @@ model_value_proc * theory_diff_logic<Ext>::mk_value(enode * n, model_generator &
935936

936937
template<typename Ext>
937938
void theory_diff_logic<Ext>::display(std::ostream & out) const {
938-
for (unsigned i = 0; i < m_atoms.size(); ++i) {
939-
m_atoms[i]->display(*this, out);
939+
out << "atoms\n";
940+
for (atom* a : m_atoms) {
941+
a->display(*this, out) << "\n";
940942
}
943+
out << "graph\n";
941944
m_graph.display(out);
942945
}
943946

@@ -1150,6 +1153,8 @@ void theory_diff_logic<Ext>::update_simplex(Simplex& S) {
11501153
}
11511154
S.set_lower(node2simplex(get_zero(true)), mpq_inf(mpq(0), mpq(0)));
11521155
S.set_upper(node2simplex(get_zero(true)), mpq_inf(mpq(0), mpq(0)));
1156+
S.set_lower(node2simplex(get_zero(false)), mpq_inf(mpq(0), mpq(0)));
1157+
S.set_upper(node2simplex(get_zero(false)), mpq_inf(mpq(0), mpq(0)));
11531158
svector<unsigned> vars;
11541159
scoped_mpq_vector coeffs(mgr);
11551160
coeffs.push_back(mpq(1));
@@ -1215,6 +1220,8 @@ typename theory_diff_logic<Ext>::inf_eps theory_diff_logic<Ext>::value(theory_va
12151220
return r;
12161221
}
12171222

1223+
1224+
12181225
template<typename Ext>
12191226
typename theory_diff_logic<Ext>::inf_eps
12201227
theory_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker, bool& has_shared) {
@@ -1224,6 +1231,9 @@ theory_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker, bool& has_shar
12241231
Simplex& S = m_S;
12251232
ast_manager& m = get_manager();
12261233

1234+
CTRACE("arith",!m_graph.is_feasible(), m_graph.display(tout););
1235+
SASSERT(m_graph.is_feasible());
1236+
12271237
update_simplex(S);
12281238

12291239
TRACE("arith",
@@ -1235,7 +1245,12 @@ theory_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker, bool& has_shar
12351245
tout << "Free coefficient " << m_objective_consts[v] << "\n";
12361246
);
12371247

1238-
TRACE("opt", S.display(tout); display(tout););
1248+
TRACE("opt",
1249+
S.display(tout);
1250+
for (unsigned i = 0; i < m_graph.get_num_nodes(); ++i)
1251+
tout << "$" << i << ": " << node2simplex(i) << "\n";
1252+
display(tout);
1253+
);
12391254

12401255
// optimize
12411256
lbool is_sat = S.make_feasible();
@@ -1252,8 +1267,6 @@ theory_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker, bool& has_shar
12521267
simplex::mpq_ext::eps_numeral const& val = S.get_value(w);
12531268
inf_rational r(-rational(val.first), -rational(val.second));
12541269
Simplex::row row = m_objective_rows[v];
1255-
TRACE("opt", tout << r << " " << "\n";
1256-
S.display_row(tout, row, true););
12571270
Simplex::row_iterator it = S.row_begin(row), end = S.row_end(row);
12581271
expr_ref_vector& core = m_objective_assignments[v];
12591272
expr_ref tmp(m);
@@ -1269,13 +1282,21 @@ theory_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker, bool& has_shar
12691282
}
12701283
}
12711284
}
1272-
compute_delta();
1285+
ensure_rational_solution(S);
1286+
TRACE("opt", tout << r << " " << "\n";
1287+
S.display_row(tout, row, true);
1288+
S.display(tout);
1289+
);
1290+
12731291
for (unsigned i = 0; i < m_graph.get_num_nodes(); ++i) {
12741292
unsigned w = node2simplex(i);
1275-
simplex::mpq_ext::eps_numeral const& val = S.get_value(w);
1276-
rational r = rational(val.first) + m_delta*rational(val.second);
1293+
auto const& val = S.get_value(w);
1294+
SASSERT(rational(val.second).is_zero());
1295+
rational r = rational(val.first);
12771296
m_graph.set_assignment(i, numeral(r));
12781297
}
1298+
CTRACE("arith",!m_graph.is_feasible(), m_graph.display(tout););
1299+
SASSERT(m_graph.is_feasible());
12791300
inf_eps r1(rational(0), r);
12801301
blocker = mk_gt(v, r1);
12811302
return inf_eps(rational(0), r + m_objective_consts[v]);

src/util/mpq_inf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,4 +286,8 @@ typedef mpq_inf_manager<false> synch_mpq_inf_manager;
286286
#endif
287287
typedef mpq_inf_manager<false> unsynch_mpq_inf_manager;
288288

289+
typedef _scoped_numeral<unsynch_mpq_inf_manager> scoped_mpq_inf;
290+
typedef _scoped_numeral<synch_mpq_inf_manager> scoped_synch_mpq_inf;
291+
typedef _scoped_numeral_vector<unsynch_mpq_inf_manager> scoped_mpq_inf_vector;
292+
289293
#endif

0 commit comments

Comments
 (0)