3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-12 12:08:18 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2019-01-25 20:01:38 -08:00
parent 1ed68906fa
commit 121211a51c

View file

@ -80,21 +80,23 @@ namespace opt {
} }
void update_assignment(model_ref & mdl) { void update_assignment(model_ref & mdl) {
bool prefix_defined = true; bool first_undef = true, second_undef = false;
for (auto & soft : m_soft) { for (auto & soft : m_soft) {
if (!prefix_defined) { if (first_undef && soft.value != l_undef) {
set_value(soft, l_undef);
continue; continue;
} }
switch (soft.value) { first_undef = false;
case l_undef: if (soft.value != l_false) {
prefix_defined = mdl->is_true(soft.s); lbool v = mdl->is_true(soft.s) ? l_true : l_undef;;
set_value(soft, prefix_defined ? l_true : l_undef); if (v == l_undef) {
break; second_undef = true;
case l_true: }
break; if (second_undef) {
case l_false: soft.set_value(v);
break; }
else {
set_value(soft, v); // also update constraints
}
} }
} }
update_bounds(); update_bounds();
@ -103,15 +105,9 @@ namespace opt {
void update_bounds() { void update_bounds() {
m_lower.reset(); m_lower.reset();
m_upper.reset(); m_upper.reset();
bool prefix_defined = true;
for (auto & soft : m_soft) { for (auto & soft : m_soft) {
if (!prefix_defined) {
m_upper += soft.weight;
continue;
}
switch (soft.value) { switch (soft.value) {
case l_undef: case l_undef:
prefix_defined = false;
m_upper += soft.weight; m_upper += soft.weight;
break; break;
case l_true: case l_true:
@ -126,6 +122,9 @@ namespace opt {
} }
void init() { void init() {
for (auto & soft : m_soft) {
soft.set_value(l_undef);
}
model_ref mdl; model_ref mdl;
s().get_model(mdl); s().get_model(mdl);
update_assignment(mdl); update_assignment(mdl);
@ -211,9 +210,20 @@ namespace opt {
// a, b is unsat, a, not b is unsat -> a is unsat // a, b is unsat, a, not b is unsat -> a is unsat
// b is unsat, a, not b is unsat -> not a, not b // b is unsat, a, not b is unsat -> not a, not b
set_value(soft, l_false); set_value(soft, l_false);
// core1 = { b }
// core2 = { a, not b }
if (!core.contains(a)) { if (!core.contains(a)) {
set_value(soft2, l_false); set_value(soft2, l_false);
} }
else {
// core1 = { a, b}
// core2 = { not_b }
core.reset();
s().get_unsat_core(core);
if (!core.contains(a)) {
set_value(soft2, l_true);
}
}
update_bounds(); update_bounds();
break; break;
case l_undef: case l_undef:
@ -233,6 +243,47 @@ namespace opt {
return l_true; return l_true;
} }
// every time probing whether to include soft_i,
// include suffix that is known to be assignable to T
lbool maxlexN() {
unsigned sz = m_soft.size();
for (unsigned i = 0; i < sz; ++i) {
auto& soft = m_soft[i];
if (soft.value != l_undef) {
continue;
}
expr_ref_vector asms(m);
asms.push_back(soft.s);
for (unsigned j = i + 1; j < sz; ++j) {
auto& soft2 = m_soft[j];
if (soft2.value == l_true) {
asms.push_back(soft2.s);
}
}
lbool is_sat = s().check_sat(asms);
switch (is_sat) {
case l_true:
update_assignment();
SASSERT(soft.value == l_true);
break;
case l_false:
set_value(soft, l_false);
for (unsigned j = i + 1; j < sz; ++j) {
auto& soft2 = m_soft[j];
if (soft2.value != l_true) {
break;
}
assert_value(soft2);
}
update_bounds();
break;
case l_undef:
return l_undef;
}
}
return l_true;
}
public: public:
maxlex(maxsat_context& c, unsigned id, weights_t & ws, expr_ref_vector const& s): maxlex(maxsat_context& c, unsigned id, weights_t & ws, expr_ref_vector const& s):
@ -246,7 +297,7 @@ namespace opt {
lbool operator()() override { lbool operator()() override {
init(); init();
return maxlex1(); return maxlexN();
} }