3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-09-03 16:48:06 +00:00
z3/src/ast/sls/sls_basic_plugin.cpp
Nikolaj Bjorner de8faa231f fixes to ite and other
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2024-08-16 16:48:12 -07:00

210 lines
5.8 KiB
C++

/*++
Copyright (c) 2024 Microsoft Corporation
Module Name:
sls_basic_plugin.cpp
Abstract:
Local search dispatch for Boolean connectives
Author:
Nikolaj Bjorner (nbjorner) 2024-07-07
--*/
#include "ast/sls/sls_basic_plugin.h"
#include "ast/ast_ll_pp.h"
#include "ast/ast_pp.h"
#include "ast/ast_util.h"
namespace sls {
expr_ref basic_plugin::get_value(expr* e) {
return expr_ref(m.mk_bool_val(bval0(e)), m);
}
bool basic_plugin::is_basic(expr* e) const {
if (!e || !is_app(e))
return false;
if (m.is_ite(e) && !m.is_bool(e) && false)
return true;
if (m.is_xor(e) && to_app(e)->get_num_args() != 2)
return true;
if (m.is_distinct(e))
return true;
return false;
}
void basic_plugin::propagate_literal(sat::literal lit) {
}
void basic_plugin::register_term(expr* e) {
expr* c, * th, * el;
if (m.is_ite(e, c, th, el) && !m.is_bool(e)) {
ctx.add_clause(m.mk_or(mk_not(m, c), m.mk_eq(e, th)));
ctx.add_clause(m.mk_or(c, m.mk_eq(e, el)));
}
}
void basic_plugin::initialize() {
}
bool basic_plugin::propagate() {
return false;
}
bool basic_plugin::is_sat() {
return true;
}
std::ostream& basic_plugin::display(std::ostream& out) const {
return out;
}
bool basic_plugin::set_value(expr* e, expr* v) {
if (!m.is_bool(e))
return false;
SASSERT(m.is_true(v) || m.is_false(v));
return set_value(e, m.is_true(v));
}
expr_ref basic_plugin::eval_ite(app* e) {
expr* c, * th, * el;
VERIFY(m.is_ite(e, c, th, el));
if (bval0(c))
return ctx.get_value(th);
else
return ctx.get_value(el);
}
expr_ref basic_plugin::eval_distinct(app* e) {
for (unsigned i = 0; i < e->get_num_args(); ++i) {
for (unsigned j = i + 1; j < e->get_num_args(); ++j) {
if (bval0(e->get_arg(i)) == bval0(e->get_arg(j)))
return expr_ref(m.mk_false(), m);
}
}
return expr_ref(m.mk_true(), m);
}
expr_ref basic_plugin::eval_xor(app* e) {
bool b = false;
for (expr* arg : *e)
b ^= bval0(arg);
return expr_ref(m.mk_bool_val(b), m);
}
bool basic_plugin::bval0(expr* e) const {
SASSERT(m.is_bool(e));
return ctx.is_true(ctx.mk_literal(e));
}
bool basic_plugin::try_repair(app* e, unsigned i) {
switch (e->get_decl_kind()) {
case OP_XOR:
return try_repair_xor(e, i);
case OP_ITE:
return try_repair_ite(e, i);
case OP_DISTINCT:
return try_repair_distinct(e, i);
default:
return true;
}
}
bool basic_plugin::try_repair_xor(app* e, unsigned i) {
auto child = e->get_arg(i);
bool bv = false;
for (unsigned j = 0; j < e->get_num_args(); ++j)
if (j != i)
bv ^= bval0(e->get_arg(j));
bool ev = bval0(e);
return set_value(child, ev != bv);
}
bool basic_plugin::try_repair_ite(app* e, unsigned i) {
if (m.is_bool(e))
return true;
auto child = e->get_arg(i);
auto cond = e->get_arg(0);
bool c = bval0(cond);
if (i == 0) {
auto eval = ctx.get_value(e);
auto eval1 = ctx.get_value(e->get_arg(1));
auto eval2 = ctx.get_value(e->get_arg(2));
if (eval == eval1 && eval == eval2)
return true;
if (eval == eval1)
return set_value(cond, true);
if (eval == eval2)
return set_value(cond, false);
return false;
}
if (c != (i == 1))
return false;
if (m.is_value(child))
return false;
bool r = ctx.set_value(child, ctx.get_value(e));
verbose_stream() << "repair-ite-down " << mk_bounded_pp(e, m) << " @ " << mk_bounded_pp(child, m) << " := " << ctx.get_value(e) << " success " << r << "\n";
return r;
}
void basic_plugin::repair_up(app* e) {
expr* c, * th, * el;
expr_ref val(m);
if (!is_basic(e))
return;
if (m.is_ite(e, c, th, el) && !m.is_bool(e))
val = eval_ite(e);
else if (m.is_xor(e))
val = eval_xor(e);
else if (m.is_distinct(e))
val = eval_distinct(e);
else
return;
verbose_stream() << "repair-up " << mk_bounded_pp(e, m) << " " << val << "\n";
if (!ctx.set_value(e, val))
ctx.new_value_eh(e);
}
void basic_plugin::repair_literal(sat::literal lit) {
}
bool basic_plugin::repair_down(app* e) {
if (!is_basic(e))
return true;
if (m.is_xor(e) && eval_xor(e) == ctx.get_value(e))
return true;
if (m.is_ite(e) && eval_ite(e) == ctx.get_value(e))
return true;
if (m.is_distinct(e) && eval_distinct(e) == ctx.get_value(e))
return true;
verbose_stream() << "basic repair down " << mk_bounded_pp(e, m) << "\n";
unsigned n = e->get_num_args();
unsigned s = ctx.rand(n);
for (unsigned i = 0; i < n; ++i) {
auto j = (i + s) % n;
if (try_repair(e, j))
return true;
}
return false;
}
bool basic_plugin::try_repair_distinct(app* e, unsigned i) {
NOT_IMPLEMENTED_YET();
return false;
}
bool basic_plugin::set_value(expr* e, bool b) {
auto lit = ctx.mk_literal(e);
if (ctx.is_true(lit) != b) {
ctx.flip(lit.var());
ctx.new_value_eh(e);
}
return true;
}
}