3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-04 10:20:23 +00:00
This commit is contained in:
Nikolaj Bjorner 2017-09-05 07:35:46 -07:00
commit d47b2bae4d
41 changed files with 758 additions and 454 deletions

View file

@ -75,7 +75,7 @@ asserted_formulas::asserted_formulas(ast_manager & m, smt_params & p):
void asserted_formulas::setup() {
switch (m_params.m_lift_ite) {
case LI_FULL:
m_params.m_ng_lift_ite = LI_NONE;
m_params.m_ng_lift_ite = LI_NONE;
break;
case LI_CONSERVATIVE:
if (m_params.m_ng_lift_ite == LI_CONSERVATIVE)
@ -84,7 +84,7 @@ void asserted_formulas::setup() {
default:
break;
}
if (m_params.m_relevancy_lvl == 0)
m_params.m_relevancy_lemma = false;
}
@ -97,7 +97,7 @@ void asserted_formulas::setup_simplifier_plugins(simplifier & s, basic_simplifie
s.register_plugin(alloc(array_simplifier_plugin, m, *bsimp, s, m_params));
bvsimp = alloc(bv_simplifier_plugin, m, *bsimp, m_params);
s.register_plugin(bvsimp);
s.register_plugin(alloc(datatype_simplifier_plugin, m, *bsimp));
s.register_plugin(alloc(datatype_simplifier_plugin, m, *bsimp));
s.register_plugin(alloc(fpa_simplifier_plugin, m, *bsimp));
s.register_plugin(alloc(seq_simplifier_plugin, m, *bsimp));
}
@ -140,7 +140,7 @@ void asserted_formulas::set_eliminate_and(bool flag) {
void asserted_formulas::assert_expr(expr * e, proof * _in_pr) {
if (inconsistent())
if (inconsistent())
return;
if (!m_params.m_preprocess) {
push_assertion(e, _in_pr, m_asserted_formulas, m_asserted_formula_prs);
@ -175,7 +175,7 @@ void asserted_formulas::assert_expr(expr * e, proof * _in_pr) {
}
void asserted_formulas::assert_expr(expr * e) {
if (inconsistent())
if (inconsistent())
return;
assert_expr(e, m.mk_asserted(e));
}
@ -197,7 +197,7 @@ void asserted_formulas::push_scope() {
m_bv_sharing.push_scope();
commit();
}
void asserted_formulas::pop_scope(unsigned num_scopes) {
TRACE("asserted_formulas_scopes", tout << "before pop " << num_scopes << "\n"; display(tout););
m_bv_sharing.pop_scope(num_scopes);
@ -228,15 +228,15 @@ void asserted_formulas::reset() {
#ifdef Z3DEBUG
bool asserted_formulas::check_well_sorted() const {
for (unsigned i = 0; i < m_asserted_formulas.size(); i++) {
if (!is_well_sorted(m, m_asserted_formulas.get(i))) return false;
for (unsigned i = 0; i < m_asserted_formulas.size(); i++) {
if (!is_well_sorted(m, m_asserted_formulas.get(i))) return false;
}
return true;
}
#endif
void asserted_formulas::reduce() {
if (inconsistent())
if (inconsistent())
return;
if (canceled()) {
return;
@ -253,7 +253,7 @@ void asserted_formulas::reduce() {
#define INVOKE(COND, FUNC) if (COND) { FUNC; IF_VERBOSE(10000, verbose_stream() << "total size: " << get_total_size() << "\n";); } TRACE("reduce_step_ll", ast_mark visited; display_ll(tout, visited);); TRACE("reduce_step", display(tout << #FUNC << " ");); CASSERT("well_sorted",check_well_sorted()); if (inconsistent() || canceled()) { TRACE("after_reduce", display(tout);); TRACE("after_reduce_ll", ast_mark visited; display_ll(tout, visited);); return; }
set_eliminate_and(false); // do not eliminate and before nnf.
INVOKE(m_params.m_propagate_booleans, propagate_booleans());
INVOKE(m_params.m_propagate_values, propagate_values());
@ -266,18 +266,18 @@ void asserted_formulas::reduce() {
INVOKE(m_params.m_lift_ite != LI_NONE, lift_ite());
INVOKE(m_params.m_eliminate_term_ite && m_params.m_lift_ite != LI_FULL, eliminate_term_ite());
INVOKE(m_params.m_refine_inj_axiom && has_quantifiers(), refine_inj_axiom());
INVOKE(m_params.m_distribute_forall && has_quantifiers(), apply_distribute_forall());
TRACE("qbv_bug", tout << "after distribute_forall:\n"; display(tout););
INVOKE(m_params.m_distribute_forall && has_quantifiers(), apply_distribute_forall());
TRACE("qbv_bug", tout << "after distribute_forall:\n"; display(tout););
INVOKE(m_params.m_macro_finder && has_quantifiers(), find_macros());
INVOKE(m_params.m_quasi_macros && has_quantifiers(), apply_quasi_macros());
INVOKE(m_params.m_quasi_macros && has_quantifiers(), apply_quasi_macros());
INVOKE(m_params.m_simplify_bit2int, apply_bit2int());
INVOKE(m_params.m_eliminate_bounds && has_quantifiers(), cheap_quant_fourier_motzkin());
INVOKE(m_params.m_ematching && has_quantifiers(), infer_patterns());
INVOKE(m_params.m_max_bv_sharing && has_bv(), max_bv_sharing());
INVOKE(m_params.m_bb_quantifiers, elim_bvs_from_quantifiers());
// temporary HACK: make sure that arith & bv are list-assoc
// temporary HACK: make sure that arith & bv are list-assoc
// this may destroy some simplification steps such as max_bv_sharing
reduce_asserted_formulas();
reduce_asserted_formulas();
CASSERT("well_sorted",check_well_sorted());
@ -291,7 +291,7 @@ void asserted_formulas::reduce() {
void asserted_formulas::eliminate_and() {
IF_IVERBOSE(10, verbose_stream() << "(smt.eliminating-and)\n";);
set_eliminate_and(true);
reduce_asserted_formulas();
reduce_asserted_formulas();
TRACE("after_elim_and", display(tout););
}
@ -331,10 +331,10 @@ void asserted_formulas::display(std::ostream & out) const {
void asserted_formulas::display_ll(std::ostream & out, ast_mark & pp_visited) const {
if (!m_asserted_formulas.empty()) {
unsigned sz = m_asserted_formulas.size();
for (unsigned i = 0; i < sz; i++)
for (unsigned i = 0; i < sz; i++)
ast_def_ll_pp(out, m, m_asserted_formulas.get(i), pp_visited, true, false);
out << "asserted formulas:\n";
for (unsigned i = 0; i < sz; i++)
for (unsigned i = 0; i < sz; i++)
out << "#" << m_asserted_formulas[i]->get_id() << " ";
out << "\n";
}
@ -387,8 +387,12 @@ void asserted_formulas::find_macros_core() {
expr_ref_vector new_exprs(m);
proof_ref_vector new_prs(m);
unsigned sz = m_asserted_formulas.size();
m_macro_finder->operator()(sz - m_asserted_qhead, m_asserted_formulas.c_ptr() + m_asserted_qhead,
m_asserted_formula_prs.c_ptr() + m_asserted_qhead, new_exprs, new_prs);
expr_dependency_ref_vector new_deps(m);
m_macro_finder->operator()(sz - m_asserted_qhead,
m_asserted_formulas.c_ptr() + m_asserted_qhead,
m_asserted_formula_prs.c_ptr() + m_asserted_qhead,
0, // 0 == No dependency tracking
new_exprs, new_prs, new_deps);
swap_asserted_formulas(new_exprs, new_prs);
reduce_and_solve();
}
@ -409,12 +413,14 @@ void asserted_formulas::apply_quasi_macros() {
IF_IVERBOSE(10, verbose_stream() << "(smt.find-quasi-macros)\n";);
TRACE("before_quasi_macros", display(tout););
expr_ref_vector new_exprs(m);
proof_ref_vector new_prs(m);
quasi_macros proc(m, m_macro_manager, m_simplifier);
while (proc(m_asserted_formulas.size() - m_asserted_qhead,
m_asserted_formulas.c_ptr() + m_asserted_qhead,
proof_ref_vector new_prs(m);
quasi_macros proc(m, m_macro_manager, m_simplifier);
expr_dependency_ref_vector new_deps(m);
while (proc(m_asserted_formulas.size() - m_asserted_qhead,
m_asserted_formulas.c_ptr() + m_asserted_qhead,
m_asserted_formula_prs.c_ptr() + m_asserted_qhead,
new_exprs, new_prs)) {
0, // 0 == No dependency tracking
new_exprs, new_prs, new_deps)) {
swap_asserted_formulas(new_exprs, new_prs);
new_exprs.reset();
new_prs.reset();
@ -430,7 +436,7 @@ void asserted_formulas::nnf_cnf() {
proof_ref_vector new_prs(m);
expr_ref_vector push_todo(m);
proof_ref_vector push_todo_prs(m);
unsigned i = m_asserted_qhead;
unsigned sz = m_asserted_formulas.size();
TRACE("nnf_bug", tout << "i: " << i << " sz: " << sz << "\n";);
@ -460,8 +466,8 @@ void asserted_formulas::nnf_cnf() {
CASSERT("well_sorted",is_well_sorted(m, r1));
if (canceled()) {
return;
}
}
if (m.proofs_enabled())
pr = m.mk_modus_ponens(push_todo_prs.get(k), pr1);
else
@ -598,7 +604,7 @@ void asserted_formulas::propagate_values() {
// C is a set which contains formulas of the form
// { x = n }, where x is a variable and n a numeral.
// R contains the rest.
//
//
// - new_exprs1 is the set C
// - new_exprs2 is the set R
//
@ -639,7 +645,7 @@ void asserted_formulas::propagate_values() {
new_prs2.push_back(pr);
}
}
TRACE("propagate_values", tout << "found: " << found << "\n";);
TRACE("propagate_values", tout << "found: " << found << "\n" << new_exprs2 << "\n";);
// If C is not empty, then reduce R using the updated simplifier cache with entries
// x -> n for each constraint 'x = n' in C.
if (found) {
@ -650,6 +656,7 @@ void asserted_formulas::propagate_values() {
expr_ref new_n(m);
proof_ref new_pr(m);
m_simplifier(n, new_n, new_pr);
TRACE("propagate_values", tout << mk_pp(n, m) << " -> " << new_n << "\n";);
if (n == new_n.get()) {
push_assertion(n, pr, new_exprs1, new_prs1);
}
@ -663,7 +670,7 @@ void asserted_formulas::propagate_values() {
// x->n will be removed from m_cache. If we don't do that, the next transformation
// may simplify constraints in C using these entries, and the variables x in C
// will be (silently) eliminated, and models produced by Z3 will not contain them.
flush_cache();
flush_cache();
}
TRACE("propagate_values", tout << "after:\n"; display(tout););
}
@ -786,7 +793,7 @@ void asserted_formulas::refine_inj_axiom() {
TRACE("inj_axiom", tout << "simplifying...\n" << mk_pp(n, m) << "\n" << mk_pp(new_n, m) << "\n";);
m_asserted_formulas.set(i, new_n);
if (m.proofs_enabled()) {
proof_ref new_pr(m);
proof_ref new_pr(m);
new_pr = m.mk_rewrite(n, new_n);
new_pr = m.mk_modus_ponens(pr, new_pr);
m_asserted_formula_prs.set(i, new_pr);
@ -860,7 +867,7 @@ void asserted_formulas::max_bv_sharing() {
}
reduce_asserted_formulas();
TRACE("bv_sharing", display(tout););
}
#ifdef Z3DEBUG

View file

@ -49,7 +49,7 @@ class asserted_formulas {
macro_manager m_macro_manager;
scoped_ptr<macro_finder> m_macro_finder;
bit2int m_bit2int;
maximise_bv_sharing m_bv_sharing;
@ -87,7 +87,7 @@ class asserted_formulas {
bool apply_bit2int();
void lift_ite();
bool elim_bvs_from_quantifiers();
void ng_lift_ite();
void ng_lift_ite();
#ifdef Z3DEBUG
bool check_well_sorted() const;
#endif
@ -114,8 +114,8 @@ public:
unsigned get_num_formulas() const { return m_asserted_formulas.size(); }
unsigned get_formulas_last_level() const;
unsigned get_qhead() const { return m_asserted_qhead; }
void commit();
void commit(unsigned new_qhead);
void commit();
void commit(unsigned new_qhead);
expr * get_formula(unsigned idx) const { return m_asserted_formulas.get(idx); }
proof * get_formula_proof(unsigned idx) const { return m.proofs_enabled() ? m_asserted_formula_prs.get(idx) : 0; }
expr * const * get_formulas() const { return m_asserted_formulas.c_ptr(); }
@ -130,7 +130,7 @@ public:
void collect_statistics(statistics & st) const;
// TODO: improve precision of the following method.
bool has_quantifiers() const { return m_simplifier.visited_quantifier(); /* approximation */ }
// -----------------------------------
//
// Macros
@ -141,9 +141,7 @@ public:
func_decl * get_macro_func_decl(unsigned i) const { return m_macro_manager.get_macro_func_decl(i); }
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const { return m_macro_manager.get_macro_interpretation(i, interp); }
quantifier * get_macro_quantifier(func_decl * f) const { return m_macro_manager.get_macro_quantifier(f); }
// auxiliary function used to create a logic context based on a model.
void insert_macro(func_decl * f, quantifier * m, proof * pr) { m_macro_manager.insert(f, m, pr); }
void insert_macro(func_decl * f, quantifier * m, proof * pr, expr_dependency * dep) { m_macro_manager.insert(f, m, pr, dep); }
};
#endif /* ASSERTED_FORMULAS_H_ */

View file

@ -22,6 +22,8 @@ Revision History:
void preprocessor_params::updt_local_params(params_ref const & _p) {
smt_params_helper p(_p);
m_macro_finder = p.macro_finder();
m_quasi_macros = p.quasi_macros();
m_restricted_quasi_macros = p.restricted_quasi_macros();
m_pull_nested_quantifiers = p.pull_nested_quantifiers();
m_refine_inj_axiom = p.refine_inj_axioms();
}

View file

@ -7,6 +7,8 @@ def_module_params(module_name='smt',
('random_seed', UINT, 0, 'random seed for the smt solver'),
('relevancy', UINT, 2, 'relevancy propagation heuristic: 0 - disabled, 1 - relevancy is tracked by only affects quantifier instantiation, 2 - relevancy is tracked, and an atom is only asserted if it is relevant'),
('macro_finder', BOOL, False, 'try to find universally quantified formulas that can be viewed as macros'),
('quasi_macros', BOOL, False, 'try to find universally quantified formulas that are quasi-macros'),
('restricted_quasi_macros', BOOL, False, 'try to find universally quantified formulas that are restricted quasi-macros'),
('ematching', BOOL, True, 'E-Matching based quantifier instantiation'),
('phase_selection', UINT, 3, 'phase selection heuristic: 0 - always false, 1 - always true, 2 - phase caching, 3 - phase caching conservative, 4 - phase caching conservative 2, 5 - random, 6 - number of occurrences'),
('restart_strategy', UINT, 1, '0 - geometric, 1 - inner-outer-geometric, 2 - luby, 3 - fixed, 4 - arithmetic'),

View file

@ -209,7 +209,7 @@ namespace smt {
~scoped_mk_model() {
if (m_ctx.m_proto_model.get() != 0) {
m_ctx.m_model = m_ctx.m_proto_model->mk_model();
m_ctx.add_rec_funs_to_model();
m_ctx.add_rec_funs_to_model();
m_ctx.m_proto_model = 0; // proto_model is not needed anymore.
}
}
@ -1568,7 +1568,7 @@ namespace smt {
func_decl * get_macro_func_decl(unsigned i) const { return m_asserted_formulas.get_macro_func_decl(i); }
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const { return m_asserted_formulas.get_macro_interpretation(i, interp); }
quantifier * get_macro_quantifier(func_decl * f) const { return m_asserted_formulas.get_macro_quantifier(f); }
void insert_macro(func_decl * f, quantifier * m, proof * pr) { m_asserted_formulas.insert_macro(f, m, pr); }
void insert_macro(func_decl * f, quantifier * m, proof * pr, expr_dependency * dep) { m_asserted_formulas.insert_macro(f, m, pr, dep); }
};
};

View file

@ -492,6 +492,7 @@ namespace smt {
virtual void assign_eh(quantifier * q) {
m_active = true;
ast_manager& m = m_context->get_manager();
if (!m_fparams->m_ematching) {
return;
}
@ -514,7 +515,11 @@ namespace smt {
app * mp = to_app(q->get_pattern(i));
SASSERT(m_context->get_manager().is_pattern(mp));
bool unary = (mp->get_num_args() == 1);
if (!unary && j >= num_eager_multi_patterns) {
if (m.is_rec_fun_def(q) && i > 0) {
// add only the first pattern
TRACE("quantifier", tout << "skip recursive function body " << mk_ismt2_pp(mp, m) << "\n";);
}
else if (!unary && j >= num_eager_multi_patterns) {
TRACE("quantifier", tout << "delaying (too many multipatterns):\n" << mk_ismt2_pp(mp, m_context->get_manager()) << "\n"
<< "j: " << j << " unary: " << unary << " m_params.m_qi_max_eager_multipatterns: " << m_fparams->m_qi_max_eager_multipatterns
<< " num_eager_multi_patterns: " << num_eager_multi_patterns << "\n";);

View file

@ -395,7 +395,8 @@ namespace smt {
template<typename Ext>
theory_var theory_arith<Ext>::internalize_div(app * n) {
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
rational r;
if (!m_util.is_numeral(n->get_arg(1), r) || r.is_zero()) found_underspecified_op(n);
found_underspecified_op(n);
theory_var s = mk_binary_op(n);
context & ctx = get_context();
@ -406,7 +407,8 @@ namespace smt {
template<typename Ext>
theory_var theory_arith<Ext>::internalize_idiv(app * n) {
found_underspecified_op(n);
rational r;
if (!m_util.is_numeral(n->get_arg(1), r) || r.is_zero()) found_underspecified_op(n);
theory_var s = mk_binary_op(n);
context & ctx = get_context();
app * mod = m_util.mk_mod(n->get_arg(0), n->get_arg(1));
@ -419,7 +421,8 @@ namespace smt {
template<typename Ext>
theory_var theory_arith<Ext>::internalize_mod(app * n) {
TRACE("arith_mod", tout << "internalizing...\n" << mk_pp(n, get_manager()) << "\n";);
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
rational r;
if (!m_util.is_numeral(n->get_arg(1), r) || r.is_zero()) found_underspecified_op(n);
theory_var s = mk_binary_op(n);
context & ctx = get_context();
if (!ctx.relevancy())
@ -429,7 +432,8 @@ namespace smt {
template<typename Ext>
theory_var theory_arith<Ext>::internalize_rem(app * n) {
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
rational r;
if (!m_util.is_numeral(n->get_arg(1), r) || r.is_zero()) found_underspecified_op(n);
theory_var s = mk_binary_op(n);
context & ctx = get_context();
if (!ctx.relevancy()) {
@ -734,11 +738,6 @@ namespace smt {
return internalize_div(n);
else if (m_util.is_idiv(n))
return internalize_idiv(n);
else if (is_app_of(n, get_id(), OP_IDIV_0) || is_app_of(n, get_id(), OP_DIV_0)) {
ctx.internalize(n->get_arg(0), false);
enode * e = mk_enode(n);
return mk_var(e);
}
else if (m_util.is_mod(n))
return internalize_mod(n);
else if (m_util.is_rem(n))

View file

@ -292,9 +292,6 @@ namespace smt {
}
void found_not_handled(expr* n) {
if (a.is_div0(n)) {
return;
}
m_not_handled = n;
if (is_app(n) && is_underspecified(to_app(n))) {
m_underspecified.push_back(to_app(n));
@ -379,7 +376,12 @@ namespace smt {
}
else if (is_app(n) && a.get_family_id() == to_app(n)->get_family_id()) {
app* t = to_app(n);
found_not_handled(n);
if (a.is_div(n, n1, n2) && is_numeral(n2, r)) {
// skip
}
else {
found_not_handled(n);
}
internalize_args(t);
mk_enode(t);
theory_var v = mk_var(n);

View file

@ -19,11 +19,12 @@ Revision History:
--*/
#include <typeinfo>
#include "ast/ast_pp.h"
#include "ast/ast_trail.h"
#include "smt/proto_model/value_factory.h"
#include "smt/smt_context.h"
#include "smt/smt_model_generator.h"
#include "smt/theory_seq.h"
#include "ast/ast_trail.h"
#include "smt/theory_arith.h"
#include "smt/smt_kernel.h"
@ -150,9 +151,8 @@ void theory_seq::solution_map::pop_scope(unsigned num_scopes) {
}
void theory_seq::solution_map::display(std::ostream& out) const {
eqdep_map_t::iterator it = m_map.begin(), end = m_map.end();
for (; it != end; ++it) {
out << mk_pp(it->m_key, m) << " |-> " << mk_pp(it->m_value.first, m) << "\n";
for (auto const& kv : m_map) {
out << mk_pp(kv.m_key, m) << " |-> " << mk_pp(kv.m_value.first, m) << "\n";
}
}
@ -186,9 +186,8 @@ void theory_seq::exclusion_table::pop_scope(unsigned num_scopes) {
}
void theory_seq::exclusion_table::display(std::ostream& out) const {
table_t::iterator it = m_table.begin(), end = m_table.end();
for (; it != end; ++it) {
out << mk_pp(it->first, m) << " != " << mk_pp(it->second, m) << "\n";
for (auto const& kv : m_table) {
out << mk_pp(kv.first, m) << " != " << mk_pp(kv.second, m) << "\n";
}
}
@ -213,6 +212,7 @@ theory_seq::theory_seq(ast_manager& m):
m_trail_stack(*this),
m_ls(m), m_rs(m),
m_lhs(m), m_rhs(m),
m_res(m),
m_atoms_qhead(0),
m_new_solution(false),
m_new_propagation(false),
@ -936,18 +936,14 @@ bool theory_seq::check_length_coherence0(expr* e) {
bool theory_seq::check_length_coherence() {
obj_hashtable<expr>::iterator it = m_length.begin(), end = m_length.end();
#if 1
for (; it != end; ++it) {
expr* e = *it;
for (expr* e : m_length) {
if (check_length_coherence0(e)) {
return true;
}
}
it = m_length.begin();
#endif
for (; it != end; ++it) {
expr* e = *it;
for (expr* e : m_length) {
if (check_length_coherence(e)) {
return true;
}
@ -956,10 +952,9 @@ bool theory_seq::check_length_coherence() {
}
bool theory_seq::fixed_length() {
obj_hashtable<expr>::iterator it = m_length.begin(), end = m_length.end();
bool found = false;
for (; it != end; ++it) {
if (fixed_length(*it)) {
for (expr* e : m_length) {
if (fixed_length(e)) {
found = true;
}
}
@ -2501,12 +2496,11 @@ void theory_seq::display(std::ostream & out) const {
}
if (!m_re2aut.empty()) {
out << "Regex\n";
obj_map<expr, eautomaton*>::iterator it = m_re2aut.begin(), end = m_re2aut.end();
for (; it != end; ++it) {
out << mk_pp(it->m_key, m) << "\n";
for (auto const& kv : m_re2aut) {
out << mk_pp(kv.m_key, m) << "\n";
display_expr disp(m);
if (it->m_value) {
it->m_value->display(out, disp);
if (kv.m_value) {
kv.m_value->display(out, disp);
}
}
}
@ -2520,9 +2514,7 @@ void theory_seq::display(std::ostream & out) const {
}
if (!m_length.empty()) {
obj_hashtable<expr>::iterator it = m_length.begin(), end = m_length.end();
for (; it != end; ++it) {
expr* e = *it;
for (expr* e : m_length) {
rational lo(-1), hi(-1);
lower_bound(e, lo);
upper_bound(e, hi);
@ -2635,6 +2627,12 @@ void theory_seq::collect_statistics(::statistics & st) const {
st.update("seq int.to.str", m_stats.m_int_string);
}
void theory_seq::init_search_eh() {
m_re2aut.reset();
m_res.reset();
m_automata.reset();
}
void theory_seq::init_model(expr_ref_vector const& es) {
expr_ref new_s(m);
for (expr* e : es) {
@ -3391,15 +3389,21 @@ void theory_seq::propagate_in_re(expr* n, bool is_true) {
return;
}
eautomaton* a = get_automaton(e2);
expr_ref e3(e2, m);
context& ctx = get_context();
literal lit = ctx.get_literal(n);
if (!is_true) {
e3 = m_util.re.mk_complement(e2);
lit.neg();
}
eautomaton* a = get_automaton(e3);
if (!a) return;
context& ctx = get_context();
expr_ref len(m_util.str.mk_length(e1), m);
for (unsigned i = 0; i < a->num_states(); ++i) {
literal acc = mk_accept(e1, len, e2, i);
literal rej = mk_reject(e1, len, e2, i);
literal acc = mk_accept(e1, len, e3, i);
literal rej = mk_reject(e1, len, e3, i);
add_axiom(a->is_final_state(i)?acc:~acc);
add_axiom(a->is_final_state(i)?~rej:rej);
}
@ -3408,27 +3412,17 @@ void theory_seq::propagate_in_re(expr* n, bool is_true) {
unsigned_vector states;
a->get_epsilon_closure(a->init(), states);
literal_vector lits;
literal lit = ctx.get_literal(n);
if (is_true) {
lits.push_back(~lit);
}
lits.push_back(~lit);
for (unsigned i = 0; i < states.size(); ++i) {
if (is_true) {
lits.push_back(mk_accept(e1, zero, e2, states[i]));
}
else {
literal nlit = ~lit;
propagate_lit(0, 1, &nlit, mk_reject(e1, zero, e2, states[i]));
}
lits.push_back(mk_accept(e1, zero, e3, states[i]));
}
if (is_true) {
if (lits.size() == 2) {
propagate_lit(0, 1, &lit, lits[1]);
}
else {
TRACE("seq", ctx.display_literals_verbose(tout, lits); tout << "\n";);
ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr());
}
if (lits.size() == 2) {
propagate_lit(0, 1, &lit, lits[1]);
}
else {
TRACE("seq", ctx.display_literals_verbose(tout, lits); tout << "\n";);
ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr());
}
}
@ -4173,10 +4167,8 @@ eautomaton* theory_seq::get_automaton(expr* re) {
TRACE("seq", result->display(tout, disp););
}
m_automata.push_back(result);
m_trail_stack.push(push_back_vector<theory_seq, scoped_ptr_vector<eautomaton> >(m_automata));
m_re2aut.insert(re, result);
m_trail_stack.push(insert_obj_map<theory_seq, expr, eautomaton*>(m_re2aut, re));
m_res.push_back(re);
return result;
}
@ -4257,6 +4249,10 @@ void theory_seq::propagate_acc_rej_length(literal lit, expr* e) {
if (m_util.str.is_length(idx)) return;
SASSERT(m_autil.is_numeral(idx));
SASSERT(get_context().get_assignment(lit) == l_true);
if (aut->is_sink_state(src)) {
propagate_lit(0, 1, &lit, false_literal);
return;
}
bool is_final = aut->is_final_state(src);
if (is_final == is_acc) {
propagate_lit(0, 1, &lit, mk_literal(m_autil.mk_ge(m_util.str.mk_length(s), idx)));

View file

@ -328,6 +328,7 @@ namespace smt {
// maintain automata with regular expressions.
scoped_ptr_vector<eautomaton> m_automata;
obj_map<expr, eautomaton*> m_re2aut;
expr_ref_vector m_res;
// queue of asserted atoms
ptr_vector<expr> m_atoms;
@ -361,6 +362,7 @@ namespace smt {
virtual void collect_statistics(::statistics & st) const;
virtual model_value_proc * mk_value(enode * n, model_generator & mg);
virtual void init_model(model_generator & mg);
virtual void init_search_eh();
void init_model(expr_ref_vector const& es);
// final check