mirror of
https://github.com/Z3Prover/z3
synced 2025-04-29 11:55:51 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
984de9f98f
15 changed files with 1954 additions and 25 deletions
|
@ -2680,6 +2680,12 @@ namespace z3 {
|
|||
inline func_decl function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & d4, sort const & d5, sort const & range) {
|
||||
return range.ctx().function(name, d1, d2, d3, d4, d5, range);
|
||||
}
|
||||
inline func_decl function(char const* name, sort_vector const& domain, sort const& range) {
|
||||
return range.ctx().function(name, domain, range);
|
||||
}
|
||||
inline func_decl function(std::string const& name, sort_vector const& domain, sort const& range) {
|
||||
return range.ctx().function(name.c_str(), domain, range);
|
||||
}
|
||||
|
||||
inline expr select(expr const & a, expr const & i) {
|
||||
check_context(a, i);
|
||||
|
|
|
@ -1919,7 +1919,7 @@ void fpa2bv_converter::mk_round_to_integral(sort * s, expr_ref & rm, expr_ref &
|
|||
|
||||
expr_ref pow_2_sbitsm1(m), m1(m);
|
||||
pow_2_sbitsm1 = m_bv_util.mk_numeral(fu().fm().m_powers2(sbits - 1), sbits);
|
||||
m1 = m_bv_util.mk_numeral(-1, ebits);
|
||||
m1 = m_bv_util.mk_bv_neg(m_bv_util.mk_numeral(1, ebits));
|
||||
m_simp.mk_eq(a_sig, pow_2_sbitsm1, t1);
|
||||
m_simp.mk_eq(a_exp, m1, t2);
|
||||
m_simp.mk_and(t1, t2, tie);
|
||||
|
@ -1927,7 +1927,7 @@ void fpa2bv_converter::mk_round_to_integral(sort * s, expr_ref & rm, expr_ref &
|
|||
|
||||
m_simp.mk_and(tie, rm_is_rte, c421);
|
||||
m_simp.mk_and(tie, rm_is_rta, c422);
|
||||
c423 = m_bv_util.mk_sle(a_exp, m_bv_util.mk_numeral(-2, ebits));
|
||||
c423 = m_bv_util.mk_sle(a_exp, m_bv_util.mk_bv_neg(m_bv_util.mk_numeral(2, ebits)));
|
||||
|
||||
dbg_decouple("fpa2bv_r2i_c421", c421);
|
||||
dbg_decouple("fpa2bv_r2i_c422", c422);
|
||||
|
@ -2452,7 +2452,7 @@ void fpa2bv_converter::mk_to_fp_float(sort * to_srt, expr * rm, expr * x, expr_r
|
|||
const mpz & ovft = m_mpf_manager.m_powers2.m1(to_ebits+1, false);
|
||||
first_ovf_exp = m_bv_util.mk_numeral(ovft, from_ebits+2);
|
||||
first_udf_exp = m_bv_util.mk_concat(
|
||||
m_bv_util.mk_numeral(-1, ebits_diff + 3),
|
||||
m_bv_util.mk_bv_neg(m_bv_util.mk_numeral(1, ebits_diff + 3)),
|
||||
m_bv_util.mk_numeral(1, to_ebits + 1));
|
||||
dbg_decouple("fpa2bv_to_float_first_ovf_exp", first_ovf_exp);
|
||||
dbg_decouple("fpa2bv_to_float_first_udf_exp", first_udf_exp);
|
||||
|
@ -3107,7 +3107,7 @@ void fpa2bv_converter::mk_to_ieee_bv_unspecified(func_decl * f, unsigned num, ex
|
|||
|
||||
expr_ref exp_bv(m), exp_all_ones(m);
|
||||
exp_bv = m_bv_util.mk_extract(ebits+sbits-2, sbits-1, result);
|
||||
exp_all_ones = m.mk_eq(exp_bv, m_bv_util.mk_numeral(-1, ebits));
|
||||
exp_all_ones = m.mk_eq(exp_bv, m_bv_util.mk_bv_neg(m_bv_util.mk_numeral(1, ebits)));
|
||||
m_extra_assertions.push_back(exp_all_ones);
|
||||
|
||||
expr_ref sig_bv(m), sig_is_non_zero(m);
|
||||
|
@ -3246,18 +3246,20 @@ void fpa2bv_converter::mk_to_bv(func_decl * f, unsigned num, expr * const * args
|
|||
incd = m.mk_eq(rounding_decision, bv1);
|
||||
pr_is_zero = m.mk_eq(pre_rounded, m_bv_util.mk_numeral(0, bv_sz + 3));
|
||||
ovfl = m.mk_and(incd, pr_is_zero);
|
||||
dbg_decouple("fpa2bv_to_bv_incd", incd);
|
||||
dbg_decouple("fpa2bv_to_bv_ovfl", ovfl);
|
||||
|
||||
expr_ref ul(m), in_range(m);
|
||||
if (!is_signed) {
|
||||
ul = m_bv_util.mk_zero_extend(3, m_bv_util.mk_numeral(-1, bv_sz));
|
||||
ul = m_bv_util.mk_zero_extend(3, m_bv_util.mk_bv_neg(m_bv_util.mk_numeral(1, bv_sz)));
|
||||
in_range = m.mk_and(m.mk_not(x_is_neg), m.mk_not(ovfl),
|
||||
m_bv_util.mk_ule(pre_rounded, ul));
|
||||
}
|
||||
else {
|
||||
expr_ref ll(m);
|
||||
ll = m_bv_util.mk_sign_extend(3, m_bv_util.mk_concat(bv1, m_bv_util.mk_numeral(0, bv_sz-1)));
|
||||
ul = m_bv_util.mk_zero_extend(4, m_bv_util.mk_numeral(-1, bv_sz-1));
|
||||
ovfl = m.mk_or(ovfl, m_bv_util.mk_sle(pre_rounded, m_bv_util.mk_numeral(-1, bv_sz + 3)));
|
||||
ul = m_bv_util.mk_zero_extend(4, m_bv_util.mk_bv_neg(m_bv_util.mk_numeral(1, bv_sz-1)));
|
||||
ovfl = m.mk_or(ovfl, m_bv_util.mk_sle(pre_rounded, m_bv_util.mk_bv_neg(m_bv_util.mk_numeral(1, bv_sz + 3))));
|
||||
in_range = m.mk_and(m.mk_not(ovfl),
|
||||
m_bv_util.mk_sle(ll, pre_rounded),
|
||||
m_bv_util.mk_sle(pre_rounded, ul));
|
||||
|
|
|
@ -773,7 +773,7 @@ br_status fpa_rewriter::mk_to_ieee_bv(func_decl * f, expr * arg, expr_ref & resu
|
|||
if (m_fm.is_nan(v)) {
|
||||
if (m_hi_fp_unspecified) {
|
||||
expr * args[4] = { bu.mk_numeral(0, 1),
|
||||
bu.mk_numeral(-1, x.get_ebits()),
|
||||
bu.mk_bv_neg(bu.mk_numeral(1, x.get_ebits())),
|
||||
bu.mk_numeral(0, x.get_sbits() - 2),
|
||||
bu.mk_numeral(1, 1) };
|
||||
result = bu.mk_concat(4, args);
|
||||
|
|
|
@ -200,6 +200,9 @@ void re2automaton::set_solver(expr_solver* solver) {
|
|||
m_sa = alloc(symbolic_automata_t, sm, *m_ba.get());
|
||||
}
|
||||
|
||||
eautomaton* re2automaton::mk_product(eautomaton* a1, eautomaton* a2) {
|
||||
return m_sa->mk_product(*a1, *a2);
|
||||
}
|
||||
|
||||
eautomaton* re2automaton::operator()(expr* e) {
|
||||
eautomaton* r = re2aut(e);
|
||||
|
|
|
@ -53,7 +53,9 @@ public:
|
|||
bool is_range() const { return m_ty == t_range; }
|
||||
sort* get_sort() const { return m_sort; }
|
||||
expr* get_char() const { SASSERT(is_char()); return m_t; }
|
||||
|
||||
expr* get_pred() const { SASSERT(is_pred()); return m_t; }
|
||||
expr* get_lo() const { SASSERT(is_range()); return m_t; }
|
||||
expr* get_hi() const { SASSERT(is_range()); return m_s; }
|
||||
};
|
||||
|
||||
class sym_expr_manager {
|
||||
|
@ -87,6 +89,7 @@ public:
|
|||
~re2automaton();
|
||||
eautomaton* operator()(expr* e);
|
||||
void set_solver(expr_solver* solver);
|
||||
eautomaton* mk_product(eautomaton *a1, eautomaton *a2);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -213,6 +213,9 @@ std::string zstring::encode() const {
|
|||
else if (ch == '\\') {
|
||||
strm << "\\\\";
|
||||
}
|
||||
else if (ch >= 128) {
|
||||
strm << "\\x" << std::hex << (unsigned)ch << std::dec;
|
||||
}
|
||||
else {
|
||||
strm << (char)(ch);
|
||||
}
|
||||
|
|
|
@ -454,6 +454,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
|
||||
func_decl* f = m_ar.get_as_array_func_decl(to_app(a));
|
||||
func_interp* g = m_model.get_func_interp(f);
|
||||
if (!g) return false;
|
||||
unsigned sz = g->num_entries();
|
||||
unsigned arity = f->get_arity();
|
||||
unsigned base_sz = stores.size();
|
||||
|
|
|
@ -625,7 +625,7 @@ namespace datalog {
|
|||
#if _WINDOWS
|
||||
int converted = sscanf_s(s, "%I64u", &res);
|
||||
#else
|
||||
int converted = sscanf(s, "%llu", &res);
|
||||
int converted = sscanf(s, "%I64u", &res);
|
||||
#endif
|
||||
if(converted==0) {
|
||||
return false;
|
||||
|
|
|
@ -79,6 +79,12 @@ def_module_params(module_name='smt',
|
|||
('theory_aware_branching', BOOL, False, 'Allow the context to use extra information from theory solvers regarding literal branching prioritization.'),
|
||||
('str.finite_overlap_models', BOOL, False, 'attempt a finite model search for overlapping variables instead of completely giving up on the arrangement'),
|
||||
('str.overlap_priority', DOUBLE, -0.1, 'theory-aware priority for overlapping variable cases; use smt.theory_aware_branching=true'),
|
||||
('str.regex_automata', BOOL, True, 'use automata-based reasoning for regular expressions (Z3str3 only)'),
|
||||
('str.regex_automata_difficulty_threshold', UINT, 1000, 'difficulty threshold for regex automata heuristics'),
|
||||
('str.regex_automata_intersection_difficulty_threshold', UINT, 1000, 'difficulty threshold for regex intersection heuristics'),
|
||||
('str.regex_automata_failed_automaton_threshold', UINT, 10, 'number of failed automaton construction attempts after which a full automaton is automatically built'),
|
||||
('str.regex_automata_failed_intersection_threshold', UINT, 10, 'number of failed automaton intersection attempts after which intersection is always computed'),
|
||||
('str.regex_automata_length_attempt_threshold', UINT, 10, 'number of length/path constraint attempts before checking unsatisfiability of regex terms'),
|
||||
('core.minimize', BOOL, False, 'minimize unsat core produced by SMT context'),
|
||||
('core.extend_patterns', BOOL, False, 'extend unsat core with literals that trigger (potential) quantifier instances'),
|
||||
('core.extend_patterns.max_distance', UINT, UINT_MAX, 'limits the distance of a pattern-extended unsat core'),
|
||||
|
|
|
@ -31,4 +31,10 @@ void theory_str_params::updt_params(params_ref const & _p) {
|
|||
m_UseBinarySearch = p.str_use_binary_search();
|
||||
m_BinarySearchInitialUpperBound = p.str_binary_search_start();
|
||||
m_OverlapTheoryAwarePriority = p.str_overlap_priority();
|
||||
m_RegexAutomata = p.str_regex_automata();
|
||||
m_RegexAutomata_DifficultyThreshold = p.str_regex_automata_difficulty_threshold();
|
||||
m_RegexAutomata_IntersectionDifficultyThreshold = p.str_regex_automata_intersection_difficulty_threshold();
|
||||
m_RegexAutomata_FailedAutomatonThreshold = p.str_regex_automata_failed_automaton_threshold();
|
||||
m_RegexAutomata_FailedIntersectionThreshold = p.str_regex_automata_failed_intersection_threshold();
|
||||
m_RegexAutomata_LengthAttemptThreshold = p.str_regex_automata_length_attempt_threshold();
|
||||
}
|
||||
|
|
|
@ -80,6 +80,43 @@ struct theory_str_params {
|
|||
|
||||
double m_OverlapTheoryAwarePriority;
|
||||
|
||||
/*
|
||||
* If RegexAutomata is set to true,
|
||||
* Z3str3 will use automata-based methods to reason about
|
||||
* regular expression constraints.
|
||||
*/
|
||||
bool m_RegexAutomata;
|
||||
|
||||
/*
|
||||
* RegexAutomata_DifficultyThreshold is the lowest difficulty above which Z3str3
|
||||
* will not eagerly construct an automaton for a regular expression term.
|
||||
*/
|
||||
unsigned m_RegexAutomata_DifficultyThreshold;
|
||||
|
||||
/*
|
||||
* RegexAutomata_IntersectionDifficultyThreshold is the lowest difficulty above which Z3str3
|
||||
* will not eagerly intersect automata to check unsatisfiability.
|
||||
*/
|
||||
unsigned m_RegexAutomata_IntersectionDifficultyThreshold;
|
||||
|
||||
/*
|
||||
* RegexAutomata_FailedAutomatonThreshold is the number of failed attempts to build an automaton
|
||||
* after which a full automaton (i.e. with no length information) will be built regardless of difficulty.
|
||||
*/
|
||||
unsigned m_RegexAutomata_FailedAutomatonThreshold;
|
||||
|
||||
/*
|
||||
* RegexAutomaton_FailedIntersectionThreshold is the number of failed attempts to perform automaton
|
||||
* intersection after which intersection will always be performed regardless of difficulty.
|
||||
*/
|
||||
unsigned m_RegexAutomata_FailedIntersectionThreshold;
|
||||
|
||||
/*
|
||||
* RegexAutomaton_LengthAttemptThreshold is the number of attempts to satisfy length/path constraints
|
||||
* before which we begin checking unsatisfiability of a regex term.
|
||||
*/
|
||||
unsigned m_RegexAutomata_LengthAttemptThreshold;
|
||||
|
||||
theory_str_params(params_ref const & p = params_ref()):
|
||||
m_StrongArrangements(true),
|
||||
m_AggressiveLengthTesting(false),
|
||||
|
@ -91,7 +128,13 @@ struct theory_str_params {
|
|||
m_FiniteOverlapModels(false),
|
||||
m_UseBinarySearch(false),
|
||||
m_BinarySearchInitialUpperBound(64),
|
||||
m_OverlapTheoryAwarePriority(-0.1)
|
||||
m_OverlapTheoryAwarePriority(-0.1),
|
||||
m_RegexAutomata(true),
|
||||
m_RegexAutomata_DifficultyThreshold(1000),
|
||||
m_RegexAutomata_IntersectionDifficultyThreshold(1000),
|
||||
m_RegexAutomata_FailedAutomatonThreshold(10),
|
||||
m_RegexAutomata_FailedIntersectionThreshold(10),
|
||||
m_RegexAutomata_LengthAttemptThreshold(10)
|
||||
{
|
||||
updt_params(p);
|
||||
}
|
||||
|
|
|
@ -446,7 +446,16 @@ namespace smt {
|
|||
expr* arg = atom->get_arg(i);
|
||||
literal l = compile_arg(arg);
|
||||
numeral c = m_util.get_coeff(atom, i);
|
||||
args.push_back(std::make_pair(l, c));
|
||||
switch (ctx.get_assignment(l)) {
|
||||
case l_true:
|
||||
k -= c;
|
||||
break;
|
||||
case l_false:
|
||||
break;
|
||||
default:
|
||||
args.push_back(std::make_pair(l, c));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_util.is_at_most_k(atom) || m_util.is_le(atom)) {
|
||||
// turn W <= k into -W >= -k
|
||||
|
@ -458,7 +467,7 @@ namespace smt {
|
|||
else {
|
||||
SASSERT(m_util.is_at_least_k(atom) || m_util.is_ge(atom) || m_util.is_eq(atom));
|
||||
}
|
||||
TRACE("pb", display(tout, *c););
|
||||
TRACE("pb", display(tout, *c, true););
|
||||
//app_ref fml1(m), fml2(m);
|
||||
//fml1 = c->to_expr(ctx, m);
|
||||
c->unique();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -20,9 +20,11 @@
|
|||
#include "util/trail.h"
|
||||
#include "util/union_find.h"
|
||||
#include "util/scoped_ptr_vector.h"
|
||||
#include "util/hashtable.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/rewriter/seq_rewriter.h"
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
#include "smt/smt_theory.h"
|
||||
#include "smt/params/theory_str_params.h"
|
||||
|
@ -36,6 +38,7 @@
|
|||
namespace smt {
|
||||
|
||||
typedef hashtable<symbol, symbol_hash_proc, symbol_eq_proc> symbol_set;
|
||||
typedef int_hashtable<int_hash, default_eq<int> > integer_set;
|
||||
|
||||
class str_value_factory : public value_factory {
|
||||
seq_util u;
|
||||
|
@ -148,6 +151,70 @@ public:
|
|||
bool matches(zstring input);
|
||||
};
|
||||
|
||||
class regex_automaton_under_assumptions {
|
||||
protected:
|
||||
expr * re_term;
|
||||
eautomaton * aut;
|
||||
bool polarity;
|
||||
|
||||
bool assume_lower_bound;
|
||||
rational lower_bound;
|
||||
|
||||
bool assume_upper_bound;
|
||||
rational upper_bound;
|
||||
public:
|
||||
regex_automaton_under_assumptions() :
|
||||
re_term(NULL), aut(NULL), polarity(false),
|
||||
assume_lower_bound(false), assume_upper_bound(false) {}
|
||||
|
||||
regex_automaton_under_assumptions(expr * re_term, eautomaton * aut, bool polarity) :
|
||||
re_term(re_term), aut(aut), polarity(polarity),
|
||||
assume_lower_bound(false), assume_upper_bound(false) {}
|
||||
|
||||
void set_lower_bound(rational & lb) {
|
||||
lower_bound = lb;
|
||||
assume_lower_bound = true;
|
||||
}
|
||||
void unset_lower_bound() {
|
||||
assume_lower_bound = false;
|
||||
}
|
||||
|
||||
void set_upper_bound(rational & ub) {
|
||||
upper_bound = ub;
|
||||
assume_upper_bound = true;
|
||||
}
|
||||
void unset_upper_bound() {
|
||||
assume_upper_bound = false;
|
||||
}
|
||||
|
||||
bool get_lower_bound(rational & lb) const {
|
||||
if (assume_lower_bound) {
|
||||
lb = lower_bound;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool get_upper_bound(rational & ub) const {
|
||||
if (assume_upper_bound) {
|
||||
ub = upper_bound;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
eautomaton * get_automaton() const { return aut; }
|
||||
expr * get_regex_term() const { return re_term; }
|
||||
bool get_polarity() const { return polarity; }
|
||||
|
||||
virtual ~regex_automaton_under_assumptions() {
|
||||
// don't free str_in_re or aut;
|
||||
// they are managed separately
|
||||
}
|
||||
};
|
||||
|
||||
class theory_str : public theory {
|
||||
struct T_cut
|
||||
{
|
||||
|
@ -250,6 +317,8 @@ protected:
|
|||
|
||||
str_value_factory * m_factory;
|
||||
|
||||
re2automaton m_mk_aut;
|
||||
|
||||
// Unique identifier appended to unused variables to ensure that model construction
|
||||
// does not introduce equalities when they weren't enforced.
|
||||
unsigned m_unused_id;
|
||||
|
@ -267,6 +336,10 @@ protected:
|
|||
// enode lists for library-aware/high-level string terms (e.g. substr, contains)
|
||||
ptr_vector<enode> m_library_aware_axiom_todo;
|
||||
|
||||
// list of axioms that are re-asserted every time the scope is popped
|
||||
expr_ref_vector m_persisted_axioms;
|
||||
expr_ref_vector m_persisted_axiom_todo;
|
||||
|
||||
// hashtable of all exprs for which we've already set up term-specific axioms --
|
||||
// this prevents infinite recursive descent with respect to axioms that
|
||||
// include an occurrence of the term for which axioms are being generated
|
||||
|
@ -320,7 +393,31 @@ protected:
|
|||
// TBD: do a curried map for determinism.
|
||||
std::map<std::pair<expr*, zstring>, expr*> regex_in_bool_map;
|
||||
obj_map<expr, std::set<zstring> > regex_in_var_reg_str_map;
|
||||
|
||||
// regex automata
|
||||
scoped_ptr_vector<eautomaton> m_automata;
|
||||
ptr_vector<eautomaton> regex_automata;
|
||||
obj_hashtable<expr> regex_terms;
|
||||
obj_map<expr, ptr_vector<expr> > regex_terms_by_string; // S --> [ (str.in.re S *) ]
|
||||
obj_map<expr, svector<regex_automaton_under_assumptions> > regex_automaton_assumptions; // RegEx --> [ aut+assumptions ]
|
||||
obj_map<expr, nfa> regex_nfa_cache; // Regex term --> NFA
|
||||
obj_hashtable<expr> regex_terms_with_path_constraints; // set of string terms which have had path constraints asserted in the current scope
|
||||
obj_hashtable<expr> regex_terms_with_length_constraints; // set of regex terms which had had length constraints asserted in the current scope
|
||||
obj_map<expr, expr*> regex_term_to_length_constraint; // (str.in.re S R) -> (length constraint over S wrt. R)
|
||||
obj_map<expr, ptr_vector<expr> > regex_term_to_extra_length_vars; // extra length vars used in regex_term_to_length_constraint entries
|
||||
|
||||
// keep track of the last lower/upper bound we saw for each string term
|
||||
// so we don't perform duplicate work
|
||||
obj_map<expr, rational> regex_last_lower_bound;
|
||||
obj_map<expr, rational> regex_last_upper_bound;
|
||||
|
||||
// each counter maps a (str.in.re) expression to an integer.
|
||||
// use helper functions regex_inc_counter() and regex_get_counter() to access
|
||||
obj_map<expr, unsigned> regex_length_attempt_count;
|
||||
obj_map<expr, unsigned> regex_fail_count;
|
||||
obj_map<expr, unsigned> regex_intersection_fail_count;
|
||||
|
||||
obj_map<expr, ptr_vector<expr> > string_chars; // S --> [S_0, S_1, ...] for character terms S_i
|
||||
|
||||
svector<char> char_set;
|
||||
std::map<char, int> charSetLookupTable;
|
||||
|
@ -439,14 +536,32 @@ protected:
|
|||
void instantiate_axiom_str_to_int(enode * e);
|
||||
void instantiate_axiom_int_to_str(enode * e);
|
||||
|
||||
void add_persisted_axiom(expr * a);
|
||||
|
||||
expr * mk_RegexIn(expr * str, expr * regexp);
|
||||
void instantiate_axiom_RegexIn(enode * e);
|
||||
app * mk_unroll(expr * n, expr * bound);
|
||||
|
||||
void process_unroll_eq_const_str(expr * unrollFunc, expr * constStr);
|
||||
void unroll_str2reg_constStr(expr * unrollFunc, expr * eqConstStr);
|
||||
void process_concat_eq_unroll(expr * concat, expr * unroll);
|
||||
|
||||
// regex automata and length-aware regex
|
||||
unsigned estimate_regex_complexity(expr * re);
|
||||
unsigned estimate_regex_complexity_under_complement(expr * re);
|
||||
unsigned estimate_automata_intersection_difficulty(eautomaton * aut1, eautomaton * aut2);
|
||||
bool check_regex_length_linearity(expr * re);
|
||||
bool check_regex_length_linearity_helper(expr * re, bool already_star);
|
||||
expr_ref infer_all_regex_lengths(expr * lenVar, expr * re, expr_ref_vector & freeVariables);
|
||||
void check_subterm_lengths(expr * re, integer_set & lens);
|
||||
void find_automaton_initial_bounds(expr * str_in_re, eautomaton * aut);
|
||||
bool refine_automaton_lower_bound(eautomaton * aut, rational current_lower_bound, rational & refined_lower_bound);
|
||||
bool refine_automaton_upper_bound(eautomaton * aut, rational current_upper_bound, rational & refined_upper_bound);
|
||||
expr_ref generate_regex_path_constraints(expr * stringTerm, eautomaton * aut, rational lenVal, expr_ref & characterConstraints);
|
||||
void aut_path_add_next(u_map<expr*>& next, expr_ref_vector& trail, unsigned idx, expr* cond);
|
||||
expr_ref aut_path_rewrite_constraint(expr * cond, expr * ch_var);
|
||||
void regex_inc_counter(obj_map<expr, unsigned> & counter_map, expr * key);
|
||||
unsigned regex_get_counter(obj_map<expr, unsigned> & counter_map, expr * key);
|
||||
|
||||
void set_up_axioms(expr * ex);
|
||||
void handle_equality(expr * lhs, expr * rhs);
|
||||
|
||||
|
@ -535,6 +650,7 @@ protected:
|
|||
std::map<expr*, std::map<expr*, int> > & concat_eq_concat_map,
|
||||
std::map<expr*, std::set<expr*> > & unrollGroupMap);
|
||||
|
||||
bool term_appears_as_subterm(expr * needle, expr * haystack);
|
||||
void classify_ast_by_type(expr * node, std::map<expr*, int> & varMap,
|
||||
std::map<expr*, int> & concatMap, std::map<expr*, int> & unrollMap);
|
||||
void classify_ast_by_type_in_positive_context(std::map<expr*, int> & varMap,
|
||||
|
@ -623,6 +739,7 @@ protected:
|
|||
void new_diseq_eh(theory_var, theory_var) override;
|
||||
|
||||
theory* mk_fresh(context*) override { return alloc(theory_str, get_manager(), m_params); }
|
||||
void init(context * ctx) override;
|
||||
void init_search_eh() override;
|
||||
void add_theory_assumptions(expr_ref_vector & assumptions) override;
|
||||
lbool validate_unsat_core(expr_ref_vector & unsat_core) override;
|
||||
|
|
|
@ -93,7 +93,7 @@ class fpa2bv_tactic : public tactic {
|
|||
expr * sgn, *sig, *exp;
|
||||
m_conv.split_fp(new_curr, sgn, exp, sig);
|
||||
result.back()->assert_expr(m.mk_eq(sgn, m_conv.bu().mk_numeral(0, 1)));
|
||||
result.back()->assert_expr(m.mk_eq(exp, m_conv.bu().mk_numeral(-1, m_conv.bu().get_bv_size(exp))));
|
||||
result.back()->assert_expr(m.mk_eq(exp, m_conv.bu().mk_bv_neg(m_conv.bu().mk_numeral(1, m_conv.bu().get_bv_size(exp)))));
|
||||
result.back()->assert_expr(m.mk_eq(sig, m_conv.bu().mk_numeral(1, m_conv.bu().get_bv_size(sig))));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue