z3-z3-4.13.0.src.smt.seq_axioms.cpp Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
seq_axioms.cpp
Abstract:
Axiomatize string operations that can be reduced to
more basic operations. These axioms are kept outside
of a particular solver: they are mainly solver independent.
Author:
Nikolaj Bjorner (nbjorner) 2020-4-16
Revision History:
--*/
#include "ast/ast_pp.h"
#include "ast/ast_ll_pp.h"
#include "smt/seq_axioms.h"
#include "smt/smt_context.h"
using namespace smt;
seq_axioms::seq_axioms(theory& th, th_rewriter& r):
th(th),
m_rewrite(r),
m(r.m()),
a(m),
seq(m),
m_sk(m, r),
m_ax(r),
m_digits_initialized(false)
{
std::function _add_clause = [&](expr_ref_vector const& c) { add_clause(c); };
std::function _set_phase = [&](expr* e) { set_phase(e); };
std::function _ensure_digits = [&]() { ensure_digit_axiom(); };
m_ax.set_add_clause(_add_clause);
m_ax.set_phase(_set_phase);
m_ax.set_ensure_digits(_ensure_digits);
}
literal seq_axioms::mk_eq(expr* a, expr* b) {
return th.mk_eq(a, b, false);
}
expr_ref seq_axioms::mk_sub(expr* x, expr* y) {
expr_ref result(a.mk_sub(x, y), m);
m_rewrite(result);
return result;
}
expr_ref seq_axioms::mk_len(expr* s) {
expr_ref result(seq.str.mk_length(s), m);
m_rewrite(result);
return result;
}
literal seq_axioms::mk_literal(expr* _e) {
expr_ref e(_e, m);
if (m.is_not(_e, _e))
return ~mk_literal(_e);
if (m.is_eq(e))
return mk_eq(to_app(e)->get_arg(0), to_app(e)->get_arg(1));
if (a.is_arith_expr(e))
m_rewrite(e);
th.ensure_enode(e);
return ctx().get_literal(e);
}
void seq_axioms::set_phase(expr* e) {
literal lit = mk_literal(e);
ctx().force_phase(lit);
}
void seq_axioms::add_clause(expr_ref_vector const& clause) {
expr* a = nullptr, *b = nullptr;
if (false && clause.size() == 1 && m.is_eq(clause[0], a, b)) {
enode* n1 = th.ensure_enode(a);
enode* n2 = th.ensure_enode(b);
justification* js =
ctx().mk_justification(
ext_theory_eq_propagation_justification(
th.get_id(), ctx(), 0, nullptr, 0, nullptr, n1, n2));
ctx().assign_eq(n1, n2, eq_justification(js));
return;
}
literal lits[5] = { null_literal, null_literal, null_literal, null_literal, null_literal };
unsigned idx = 0;
for (expr* e : clause) {
literal lit = mk_literal(e);
if (lit == true_literal)
return;
if (lit != false_literal)
lits[idx++] = mk_literal(e);
SASSERT(idx <= 5);
}
add_axiom(lits[0], lits[1], lits[2], lits[3], lits[4]);
}
/**
Bridge character digits to integers.
*/
void seq_axioms::ensure_digit_axiom() {
if (!m_digits_initialized) {
for (unsigned i = 0; i < 10; ++i) {
expr_ref cnst(seq.mk_char('0'+i), m);
add_axiom(mk_eq(m_sk.mk_digit2int(cnst), a.mk_int(i)));
}
ctx().push_trail(value_trail(m_digits_initialized));
m_digits_initialized = true;
}
}