mirror of
https://github.com/Z3Prover/z3
synced 2025-08-09 20:50:50 +00:00
Merge branch 'master' into polysat
This commit is contained in:
commit
1df749ad33
368 changed files with 12363 additions and 6152 deletions
|
@ -37,8 +37,7 @@ namespace smt {
|
|||
m_context(ctx) {
|
||||
}
|
||||
|
||||
virtual ~mam() {
|
||||
}
|
||||
virtual ~mam() = default;
|
||||
|
||||
virtual void add_pattern(quantifier * q, app * mp) = 0;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ Revision History:
|
|||
#include "smt/params/smt_params.h"
|
||||
#include "smt/params/smt_params_helper.hpp"
|
||||
#include "util/gparams.h"
|
||||
#include "params/solver_params.hpp"
|
||||
|
||||
void smt_params::updt_local_params(params_ref const & _p) {
|
||||
smt_params_helper p(_p);
|
||||
|
@ -59,6 +60,10 @@ void smt_params::updt_local_params(params_ref const & _p) {
|
|||
m_dump_benchmarks = false;
|
||||
m_dump_min_time = 0.5;
|
||||
m_dump_recheck = false;
|
||||
solver_params sp(_p);
|
||||
m_axioms2files = sp.axioms2files();
|
||||
m_lemmas2console = sp.lemmas2console();
|
||||
m_instantiations2console = sp.instantiations2console();
|
||||
}
|
||||
|
||||
void smt_params::updt_params(params_ref const & p) {
|
||||
|
@ -150,7 +155,8 @@ void smt_params::display(std::ostream & out) const {
|
|||
DISPLAY_PARAM(m_old_clause_relevancy);
|
||||
DISPLAY_PARAM(m_inv_clause_decay);
|
||||
|
||||
DISPLAY_PARAM(m_smtlib_dump_lemmas);
|
||||
DISPLAY_PARAM(m_axioms2files);
|
||||
DISPLAY_PARAM(m_lemmas2console);
|
||||
DISPLAY_PARAM(m_logic);
|
||||
DISPLAY_PARAM(m_string_solver);
|
||||
|
||||
|
|
|
@ -82,144 +82,146 @@ struct smt_params : public preprocessor_params,
|
|||
public theory_seq_params,
|
||||
public theory_pb_params,
|
||||
public theory_datatype_params {
|
||||
bool m_display_proof;
|
||||
bool m_display_dot_proof;
|
||||
bool m_display_unsat_core;
|
||||
bool m_check_proof;
|
||||
bool m_eq_propagation;
|
||||
bool m_binary_clause_opt;
|
||||
unsigned m_relevancy_lvl;
|
||||
bool m_relevancy_lemma;
|
||||
unsigned m_random_seed;
|
||||
double m_random_var_freq;
|
||||
double m_inv_decay;
|
||||
unsigned m_clause_decay;
|
||||
initial_activity m_random_initial_activity;
|
||||
phase_selection m_phase_selection;
|
||||
unsigned m_phase_caching_on;
|
||||
unsigned m_phase_caching_off;
|
||||
bool m_minimize_lemmas;
|
||||
unsigned m_max_conflicts;
|
||||
bool m_display_proof = false;
|
||||
bool m_display_dot_proof = false;
|
||||
bool m_display_unsat_core = false;
|
||||
bool m_check_proof = false;
|
||||
bool m_eq_propagation = true;
|
||||
bool m_binary_clause_opt = true;
|
||||
unsigned m_relevancy_lvl = 2;
|
||||
bool m_relevancy_lemma = false;
|
||||
unsigned m_random_seed = 0;
|
||||
double m_random_var_freq = 0.01;
|
||||
double m_inv_decay = 1.052;
|
||||
unsigned m_clause_decay = 1;
|
||||
initial_activity m_random_initial_activity = initial_activity::IA_RANDOM_WHEN_SEARCHING;
|
||||
phase_selection m_phase_selection = phase_selection::PS_CACHING_CONSERVATIVE;
|
||||
unsigned m_phase_caching_on = 700;
|
||||
unsigned m_phase_caching_off = 100;
|
||||
bool m_minimize_lemmas = true;
|
||||
unsigned m_max_conflicts = UINT_MAX;
|
||||
unsigned m_restart_max;
|
||||
unsigned m_cube_depth;
|
||||
unsigned m_threads;
|
||||
unsigned m_threads_max_conflicts;
|
||||
unsigned m_threads_cube_frequency;
|
||||
bool m_simplify_clauses;
|
||||
unsigned m_tick;
|
||||
bool m_display_features;
|
||||
bool m_new_core2th_eq;
|
||||
bool m_ematching;
|
||||
bool m_induction;
|
||||
bool m_clause_proof;
|
||||
unsigned m_cube_depth = 1;
|
||||
unsigned m_threads = 1;
|
||||
unsigned m_threads_max_conflicts = UINT_MAX;
|
||||
unsigned m_threads_cube_frequency = 2;
|
||||
bool m_simplify_clauses = true;
|
||||
unsigned m_tick = 1000;
|
||||
bool m_display_features = false;
|
||||
bool m_new_core2th_eq = true;
|
||||
bool m_ematching = true;
|
||||
bool m_induction = false;
|
||||
bool m_clause_proof = false;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Case split strategy
|
||||
//
|
||||
// -----------------------------------
|
||||
case_split_strategy m_case_split_strategy;
|
||||
unsigned m_rel_case_split_order;
|
||||
bool m_lookahead_diseq;
|
||||
bool m_theory_case_split;
|
||||
bool m_theory_aware_branching;
|
||||
case_split_strategy m_case_split_strategy = case_split_strategy::CS_ACTIVITY_DELAY_NEW;
|
||||
unsigned m_rel_case_split_order = 0;
|
||||
bool m_lookahead_diseq = false;
|
||||
bool m_theory_case_split = false;
|
||||
bool m_theory_aware_branching = false;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Delay units...
|
||||
//
|
||||
// -----------------------------------
|
||||
bool m_delay_units;
|
||||
unsigned m_delay_units_threshold;
|
||||
bool m_delay_units = false;
|
||||
unsigned m_delay_units_threshold = 32;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Conflict resolution
|
||||
//
|
||||
// -----------------------------------
|
||||
bool m_theory_resolve;
|
||||
bool m_theory_resolve = false;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Restart
|
||||
//
|
||||
// -----------------------------------
|
||||
restart_strategy m_restart_strategy;
|
||||
unsigned m_restart_initial;
|
||||
double m_restart_factor;
|
||||
bool m_restart_adaptive;
|
||||
double m_agility_factor;
|
||||
double m_restart_agility_threshold;
|
||||
restart_strategy m_restart_strategy = restart_strategy::RS_IN_OUT_GEOMETRIC;
|
||||
unsigned m_restart_initial = 100;
|
||||
double m_restart_factor = 1.1;
|
||||
bool m_restart_adaptive = true;
|
||||
double m_agility_factor = 0.9999;
|
||||
double m_restart_agility_threshold = 0.18;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Lemma garbage collection
|
||||
//
|
||||
// -----------------------------------
|
||||
lemma_gc_strategy m_lemma_gc_strategy;
|
||||
bool m_lemma_gc_half;
|
||||
unsigned m_recent_lemmas_size;
|
||||
unsigned m_lemma_gc_initial;
|
||||
double m_lemma_gc_factor;
|
||||
unsigned m_new_old_ratio; //!< the ratio of new and old clauses.
|
||||
unsigned m_new_clause_activity;
|
||||
unsigned m_old_clause_activity;
|
||||
unsigned m_new_clause_relevancy; //!< Max. number of unassigned literals to be considered relevant.
|
||||
unsigned m_old_clause_relevancy; //!< Max. number of unassigned literals to be considered relevant.
|
||||
double m_inv_clause_decay; //!< clause activity decay
|
||||
lemma_gc_strategy m_lemma_gc_strategy = lemma_gc_strategy::LGC_FIXED;
|
||||
bool m_lemma_gc_half = false;
|
||||
unsigned m_recent_lemmas_size = 100;
|
||||
unsigned m_lemma_gc_initial = 5000;
|
||||
double m_lemma_gc_factor = 1.1;
|
||||
unsigned m_new_old_ratio = 16; //!< the ratio of new and old clauses.
|
||||
unsigned m_new_clause_activity = 10;
|
||||
unsigned m_old_clause_activity = 500;
|
||||
unsigned m_new_clause_relevancy = 45; //!< Max. number of unassigned literals to be considered relevant.
|
||||
unsigned m_old_clause_relevancy = 6; //!< Max. number of unassigned literals to be considered relevant.
|
||||
double m_inv_clause_decay = 1; //!< clause activity decay
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// SMT-LIB (debug) pretty printer
|
||||
//
|
||||
// -----------------------------------
|
||||
bool m_smtlib_dump_lemmas;
|
||||
symbol m_logic;
|
||||
bool m_axioms2files = false;
|
||||
bool m_lemmas2console = false;
|
||||
bool m_instantiations2console = false;
|
||||
symbol m_logic = symbol::null;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Statistics for Profiling
|
||||
//
|
||||
// -----------------------------------
|
||||
bool m_profile_res_sub;
|
||||
bool m_display_bool_var2expr;
|
||||
bool m_display_ll_bool_var2expr;
|
||||
bool m_profile_res_sub = false;
|
||||
bool m_display_bool_var2expr = false;
|
||||
bool m_display_ll_bool_var2expr = false;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Model generation
|
||||
//
|
||||
// -----------------------------------
|
||||
bool m_model;
|
||||
bool m_model_on_timeout;
|
||||
bool m_model_on_final_check;
|
||||
bool m_model = true;
|
||||
bool m_model_on_timeout = false;
|
||||
bool m_model_on_final_check = false;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Progress sampling
|
||||
//
|
||||
// -----------------------------------
|
||||
unsigned m_progress_sampling_freq;
|
||||
unsigned m_progress_sampling_freq = 0;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Debugging goodies
|
||||
//
|
||||
// -----------------------------------
|
||||
bool m_core_validate;
|
||||
bool m_core_validate = false;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// From front_end_params
|
||||
//
|
||||
// -----------------------------------
|
||||
bool m_preprocess; // temporary hack for disabling all preprocessing..
|
||||
bool m_user_theory_preprocess_axioms;
|
||||
bool m_user_theory_persist_axioms;
|
||||
bool m_at_labels_cex; // only use labels which contains the @ symbol when building multiple counterexamples.
|
||||
bool m_check_at_labels; // check that @ labels are inserted to generate unique counter-examples.
|
||||
bool m_dump_goal_as_smt;
|
||||
bool m_auto_config;
|
||||
bool m_preprocess = true; // temporary hack for disabling all preprocessing..
|
||||
bool m_user_theory_preprocess_axioms = false;
|
||||
bool m_user_theory_persist_axioms = false;
|
||||
bool m_at_labels_cex = false; // only use labels which contains the @ symbol when building multiple counterexamples.
|
||||
bool m_check_at_labels = false; // check that @ labels are inserted to generate unique counter-examples.
|
||||
bool m_dump_goal_as_smt = false;
|
||||
bool m_auto_config = true;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
@ -238,77 +240,6 @@ struct smt_params : public preprocessor_params,
|
|||
symbol m_string_solver;
|
||||
|
||||
smt_params(params_ref const & p = params_ref()):
|
||||
m_display_proof(false),
|
||||
m_display_dot_proof(false),
|
||||
m_display_unsat_core(false),
|
||||
m_check_proof(false),
|
||||
m_eq_propagation(true),
|
||||
m_binary_clause_opt(true),
|
||||
m_relevancy_lvl(2),
|
||||
m_relevancy_lemma(false),
|
||||
m_random_seed(0),
|
||||
m_random_var_freq(0.01),
|
||||
m_inv_decay(1.052),
|
||||
m_clause_decay(1),
|
||||
m_random_initial_activity(initial_activity::IA_RANDOM_WHEN_SEARCHING),
|
||||
m_phase_selection(phase_selection::PS_CACHING_CONSERVATIVE),
|
||||
m_phase_caching_on(700),
|
||||
m_phase_caching_off(100),
|
||||
m_minimize_lemmas(true),
|
||||
m_max_conflicts(UINT_MAX),
|
||||
m_cube_depth(1),
|
||||
m_threads(1),
|
||||
m_threads_max_conflicts(UINT_MAX),
|
||||
m_threads_cube_frequency(2),
|
||||
m_simplify_clauses(true),
|
||||
m_tick(1000),
|
||||
m_display_features(false),
|
||||
m_new_core2th_eq(true),
|
||||
m_ematching(true),
|
||||
m_induction(false),
|
||||
m_clause_proof(false),
|
||||
m_case_split_strategy(case_split_strategy::CS_ACTIVITY_DELAY_NEW),
|
||||
m_rel_case_split_order(0),
|
||||
m_lookahead_diseq(false),
|
||||
m_theory_case_split(false),
|
||||
m_theory_aware_branching(false),
|
||||
m_delay_units(false),
|
||||
m_delay_units_threshold(32),
|
||||
m_theory_resolve(false),
|
||||
m_restart_strategy(restart_strategy::RS_IN_OUT_GEOMETRIC),
|
||||
m_restart_initial(100),
|
||||
m_restart_factor(1.1),
|
||||
m_restart_adaptive(true),
|
||||
m_agility_factor(0.9999),
|
||||
m_restart_agility_threshold(0.18),
|
||||
m_lemma_gc_strategy(lemma_gc_strategy::LGC_FIXED),
|
||||
m_lemma_gc_half(false),
|
||||
m_recent_lemmas_size(100),
|
||||
m_lemma_gc_initial(5000),
|
||||
m_lemma_gc_factor(1.1),
|
||||
m_new_old_ratio(16),
|
||||
m_new_clause_activity(10),
|
||||
m_old_clause_activity(500),
|
||||
m_new_clause_relevancy(45),
|
||||
m_old_clause_relevancy(6),
|
||||
m_inv_clause_decay(1),
|
||||
m_smtlib_dump_lemmas(false),
|
||||
m_logic(symbol::null),
|
||||
m_profile_res_sub(false),
|
||||
m_display_bool_var2expr(false),
|
||||
m_display_ll_bool_var2expr(false),
|
||||
m_model(true),
|
||||
m_model_on_timeout(false),
|
||||
m_model_on_final_check(false),
|
||||
m_progress_sampling_freq(0),
|
||||
m_core_validate(false),
|
||||
m_preprocess(true), // temporary hack for disabling all preprocessing..
|
||||
m_user_theory_preprocess_axioms(false),
|
||||
m_user_theory_persist_axioms(false),
|
||||
m_at_labels_cex(false),
|
||||
m_check_at_labels(false),
|
||||
m_dump_goal_as_smt(false),
|
||||
m_auto_config(true),
|
||||
m_string_solver(symbol("auto")){
|
||||
updt_local_params(p);
|
||||
}
|
||||
|
|
|
@ -48,9 +48,10 @@ def_module_params(module_name='smt',
|
|||
('bv.reflect', BOOL, True, 'create enode for every bit-vector term'),
|
||||
('bv.enable_int2bv', BOOL, True, 'enable support for int2bv and bv2int operators'),
|
||||
('bv.watch_diseq', BOOL, False, 'use watch lists instead of eager axioms for bit-vectors'),
|
||||
('bv.delay', BOOL, True, 'delay internalize expensive bit-vector operations'),
|
||||
('bv.delay', BOOL, False, 'delay internalize expensive bit-vector operations'),
|
||||
('bv.polysat', BOOL, False, 'use polysat bit-vector solver'),
|
||||
('bv.eq_axioms', BOOL, True, 'enable redundant equality axioms for bit-vectors'),
|
||||
('bv.size_reduce', BOOL, False, 'turn assertions that set the upper bits of a bit-vector to constants into a substitution that replaces the bit-vector with constant bits. Useful for minimizing circuits as many input bits to circuits are constant'),
|
||||
('arith.random_initial_value', BOOL, False, 'use random initial values in the simplex-based procedure for linear arithmetic'),
|
||||
('arith.solver', UINT, 6, 'arithmetic solver: 0 - no solver, 1 - bellman-ford based solver (diff. logic only), 2 - simplex based solver, 3 - floyd-warshall based solver (diff. logic only) and no theory combination 4 - utvpi, 5 - infinitary lra, 6 - lra solver'),
|
||||
('arith.nl', BOOL, True, '(incomplete) nonlinear arithmetic support based on Groebner basis and interval propagation, relevant only if smt.arith.solver=2'),
|
||||
|
@ -106,6 +107,8 @@ def_module_params(module_name='smt',
|
|||
('core.validate', BOOL, False, '[internal] validate unsat core produced by SMT context. This option is intended for debugging'),
|
||||
('seq.split_w_len', BOOL, True, 'enable splitting guided by length constraints'),
|
||||
('seq.validate', BOOL, False, 'enable self-validation of theory axioms created by seq theory'),
|
||||
('seq.max_unfolding', UINT, 1000000000, 'maximal unfolding depth for checking string equations and regular expressions'),
|
||||
('seq.min_unfolding', UINT, 1, 'initial bound for strings whose lengths are bounded by iterative deepening. Set this to a higher value if there are only models with larger string lengths'),
|
||||
('str.strong_arrangements', BOOL, True, 'assert equivalences instead of implications when generating string arrangement axioms'),
|
||||
('str.aggressive_length_testing', BOOL, False, 'prioritize testing concrete length values over generating more options'),
|
||||
('str.aggressive_value_testing', BOOL, False, 'prioritize testing concrete string constant values over generating more options'),
|
||||
|
|
|
@ -34,7 +34,6 @@ void theory_arith_params::updt_params(params_ref const & _p) {
|
|||
m_arith_int_eq_branching = p.arith_int_eq_branch();
|
||||
m_arith_ignore_int = p.arith_ignore_int();
|
||||
m_arith_bound_prop = static_cast<bound_prop_mode>(p.arith_propagation_mode());
|
||||
m_arith_dump_lemmas = p.arith_dump_lemmas();
|
||||
m_arith_eager_eq_axioms = p.arith_eager_eq_axioms();
|
||||
m_arith_auto_config_simplex = p.arith_auto_config_simplex();
|
||||
|
||||
|
@ -67,7 +66,6 @@ void theory_arith_params::display(std::ostream & out) const {
|
|||
DISPLAY_PARAM(m_arith_adaptive);
|
||||
DISPLAY_PARAM(m_arith_adaptive_assertion_threshold);
|
||||
DISPLAY_PARAM(m_arith_adaptive_propagation_threshold);
|
||||
DISPLAY_PARAM(m_arith_dump_lemmas);
|
||||
DISPLAY_PARAM(m_arith_eager_eq_axioms);
|
||||
DISPLAY_PARAM(m_arith_branch_cut_ratio);
|
||||
DISPLAY_PARAM(m_arith_int_eq_branching);
|
||||
|
|
|
@ -72,7 +72,6 @@ struct theory_arith_params {
|
|||
bool m_arith_adaptive = false;
|
||||
double m_arith_adaptive_assertion_threshold = 0.2;
|
||||
double m_arith_adaptive_propagation_threshold = 0.4;
|
||||
bool m_arith_dump_lemmas = false;
|
||||
bool m_arith_eager_eq_axioms = true;
|
||||
unsigned m_arith_branch_cut_ratio = 2;
|
||||
bool m_arith_int_eq_branching = false;
|
||||
|
|
|
@ -29,6 +29,7 @@ void theory_bv_params::updt_params(params_ref const & _p) {
|
|||
m_bv_delay = p.bv_delay();
|
||||
m_bv_polysat = p.bv_polysat();
|
||||
m_bv_eq_axioms = p.bv_eq_axioms();
|
||||
m_bv_size_reduce = p.bv_size_reduce();
|
||||
}
|
||||
|
||||
#define DISPLAY_PARAM(X) out << #X"=" << X << std::endl;
|
||||
|
@ -44,4 +45,5 @@ void theory_bv_params::display(std::ostream & out) const {
|
|||
DISPLAY_PARAM(m_bv_enable_int2bv2int);
|
||||
DISPLAY_PARAM(m_bv_delay);
|
||||
DISPLAY_PARAM(m_bv_polysat);
|
||||
DISPLAY_PARAM(m_bv_size_reduce);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ struct theory_bv_params {
|
|||
bool m_bv_watch_diseq = false;
|
||||
bool m_bv_delay = true;
|
||||
bool m_bv_polysat = false;
|
||||
bool m_bv_size_reduce = false;
|
||||
theory_bv_params(params_ref const & p = params_ref()) {
|
||||
updt_params(p);
|
||||
}
|
||||
|
|
|
@ -21,4 +21,6 @@ void theory_seq_params::updt_params(params_ref const & _p) {
|
|||
smt_params_helper p(_p);
|
||||
m_split_w_len = p.seq_split_w_len();
|
||||
m_seq_validate = p.seq_validate();
|
||||
m_seq_max_unfolding = p.seq_max_unfolding();
|
||||
m_seq_min_unfolding = p.seq_min_unfolding();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ struct theory_seq_params {
|
|||
*/
|
||||
bool m_split_w_len = false;
|
||||
bool m_seq_validate = false;
|
||||
unsigned m_seq_max_unfolding = UINT_MAX/4;
|
||||
unsigned m_seq_min_unfolding = 1;
|
||||
|
||||
theory_seq_params(params_ref const & p = params_ref()) {
|
||||
updt_params(p);
|
||||
|
|
|
@ -23,6 +23,7 @@ Revision History:
|
|||
#include "ast/rewriter/var_subst.h"
|
||||
#include "smt/smt_context.h"
|
||||
#include "smt/qi_queue.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace smt {
|
||||
|
||||
|
@ -228,15 +229,12 @@ namespace smt {
|
|||
|
||||
|
||||
TRACE("qi_queue", tout << "new instance:\n" << mk_pp(instance, m) << "\n";);
|
||||
TRACE("qi_queue_instance", tout << "new instance:\n" << mk_pp(instance, m) << "\n";);
|
||||
expr_ref s_instance(m);
|
||||
proof_ref pr(m);
|
||||
m_context.get_rewriter()(instance, s_instance, pr);
|
||||
|
||||
TRACE("qi_queue_bug", tout << "new instance after simplification:\n" << s_instance << "\n";);
|
||||
if (m.is_true(s_instance)) {
|
||||
TRACE("checker", tout << "reduced to true, before:\n" << mk_ll_pp(instance, m););
|
||||
|
||||
STRACE("instance", tout << "Instance reduced to true\n";);
|
||||
stat -> inc_num_instances_simplify_true();
|
||||
if (m.has_trace_stream()) {
|
||||
|
@ -250,9 +248,11 @@ namespace smt {
|
|||
std::cout << "instantiate\n";
|
||||
enode_vector _bindings(num_bindings, bindings);
|
||||
for (auto * b : _bindings)
|
||||
std::cout << enode_pp(b, m_context) << " ";
|
||||
std::cout << mk_pp(b->get_expr(), m) << " ";
|
||||
std::cout << "\n";
|
||||
std::cout << mk_pp(q, m) << "\n";
|
||||
std::cout << "instance\n";
|
||||
std::cout << instance << "\n";
|
||||
#endif
|
||||
|
||||
TRACE("qi_queue", tout << "simplified instance:\n" << s_instance << "\n";);
|
||||
|
|
|
@ -86,7 +86,7 @@ void seq_axioms::add_clause(expr_ref_vector const& clause) {
|
|||
justification* js =
|
||||
ctx().mk_justification(
|
||||
ext_theory_eq_propagation_justification(
|
||||
th.get_id(), ctx().get_region(), 0, nullptr, 0, nullptr, n1, n2));
|
||||
th.get_id(), ctx(), 0, nullptr, 0, nullptr, n1, n2));
|
||||
ctx().assign_eq(n1, n2, eq_justification(js));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace smt {
|
|||
virtual void pop_scope(unsigned num_scopes) = 0;
|
||||
virtual void next_case_split(bool_var & next, lbool & phase) = 0;
|
||||
virtual void display(std::ostream & out) = 0;
|
||||
virtual ~case_split_queue() {}
|
||||
virtual ~case_split_queue() = default;
|
||||
|
||||
// theory-aware branching hint
|
||||
virtual void add_theory_aware_branching_info(bool_var v, double priority, lbool phase) {}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace smt {
|
|||
*/
|
||||
class clause_del_eh {
|
||||
public:
|
||||
virtual ~clause_del_eh() {}
|
||||
virtual ~clause_del_eh() = default;
|
||||
virtual void operator()(ast_manager & m, clause * cls) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -80,7 +80,8 @@ namespace smt {
|
|||
m_unsat_core(m),
|
||||
m_mk_bool_var_trail(*this),
|
||||
m_mk_enode_trail(*this),
|
||||
m_mk_lambda_trail(*this) {
|
||||
m_mk_lambda_trail(*this),
|
||||
m_lemma_visitor(m) {
|
||||
|
||||
SASSERT(m_scope_lvl == 0);
|
||||
SASSERT(m_base_lvl == 0);
|
||||
|
@ -2560,7 +2561,7 @@ namespace smt {
|
|||
justification * js = cls.get_justification();
|
||||
justification * new_js = nullptr;
|
||||
if (js->in_region())
|
||||
new_js = mk_justification(unit_resolution_justification(m_region,
|
||||
new_js = mk_justification(unit_resolution_justification(*this,
|
||||
js,
|
||||
simp_lits.size(),
|
||||
simp_lits.data()));
|
||||
|
@ -2618,7 +2619,7 @@ namespace smt {
|
|||
if (!cls_js || cls_js->in_region()) {
|
||||
// If cls_js is 0 or is allocated in a region, then
|
||||
// we can allocate the new justification in a region too.
|
||||
js = mk_justification(unit_resolution_justification(m_region,
|
||||
js = mk_justification(unit_resolution_justification(*this,
|
||||
cls_js,
|
||||
simp_lits.size(),
|
||||
simp_lits.data()));
|
||||
|
@ -3197,13 +3198,22 @@ namespace smt {
|
|||
|
||||
void context::internalize_assertions() {
|
||||
if (get_cancel_flag()) return;
|
||||
if (m_internalizing_assertions) return;
|
||||
flet<bool> _internalizing(m_internalizing_assertions, true);
|
||||
TRACE("internalize_assertions", tout << "internalize_assertions()...\n";);
|
||||
timeit tt(get_verbosity_level() >= 100, "smt.preprocessing");
|
||||
reduce_assertions();
|
||||
if (get_cancel_flag()) return;
|
||||
if (!m_asserted_formulas.inconsistent()) {
|
||||
unsigned sz = m_asserted_formulas.get_num_formulas();
|
||||
unsigned qhead = m_asserted_formulas.get_qhead();
|
||||
unsigned qhead = 0;
|
||||
do {
|
||||
reduce_assertions();
|
||||
if (get_cancel_flag())
|
||||
return;
|
||||
if (m_asserted_formulas.inconsistent()) {
|
||||
if (!inconsistent())
|
||||
asserted_inconsistent();
|
||||
break;
|
||||
}
|
||||
qhead = m_asserted_formulas.get_qhead();
|
||||
unsigned sz = m_asserted_formulas.get_num_formulas();
|
||||
while (qhead < sz) {
|
||||
if (get_cancel_flag()) {
|
||||
m_asserted_formulas.commit(qhead);
|
||||
|
@ -3213,13 +3223,12 @@ namespace smt {
|
|||
proof * pr = m_asserted_formulas.get_formula_proof(qhead);
|
||||
SASSERT(!pr || f == m.get_fact(pr));
|
||||
internalize_assertion(f, pr, 0);
|
||||
qhead++;
|
||||
++qhead;
|
||||
}
|
||||
m_asserted_formulas.commit();
|
||||
}
|
||||
if (m_asserted_formulas.inconsistent() && !inconsistent()) {
|
||||
asserted_inconsistent();
|
||||
}
|
||||
while (qhead < m_asserted_formulas.get_num_formulas());
|
||||
|
||||
TRACE("internalize_assertions", tout << "after internalize_assertions()...\n";
|
||||
tout << "inconsistent: " << inconsistent() << "\n";);
|
||||
TRACE("after_internalize_assertions", display(tout););
|
||||
|
|
|
@ -107,11 +107,12 @@ namespace smt {
|
|||
|
||||
ptr_vector<justification> m_justifications;
|
||||
|
||||
unsigned m_final_check_idx; // circular counter used for implementing fairness
|
||||
unsigned m_final_check_idx = 0; // circular counter used for implementing fairness
|
||||
|
||||
bool m_is_auxiliary { false }; // used to prevent unwanted information from being logged.
|
||||
class parallel* m_par { nullptr };
|
||||
unsigned m_par_index { 0 };
|
||||
bool m_is_auxiliary = false; // used to prevent unwanted information from being logged.
|
||||
class parallel* m_par = nullptr;
|
||||
unsigned m_par_index = 0;
|
||||
bool m_internalizing_assertions = false;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
@ -777,8 +778,6 @@ namespace smt {
|
|||
|
||||
bool has_lambda();
|
||||
|
||||
bool is_beta_redex(enode* p, enode* n) const;
|
||||
|
||||
void internalize_lambda(quantifier * q);
|
||||
|
||||
void internalize_formula_core(app * n, bool gate_ctx);
|
||||
|
@ -892,6 +891,10 @@ namespace smt {
|
|||
void remove_lit_occs(clause const& cls, unsigned num_bool_vars);
|
||||
|
||||
void add_lit_occs(clause const& cls);
|
||||
|
||||
ast_pp_util m_lemma_visitor;
|
||||
void dump_lemma(unsigned n, literal const* lits);
|
||||
void dump_axiom(unsigned n, literal const* lits);
|
||||
public:
|
||||
|
||||
void ensure_internalized(expr* e);
|
||||
|
@ -1031,6 +1034,8 @@ namespace smt {
|
|||
|
||||
bool is_shared(enode * n) const;
|
||||
|
||||
bool is_beta_redex(enode* p, enode* n) const;
|
||||
|
||||
void assign_eq(enode * lhs, enode * rhs, eq_justification const & js) {
|
||||
push_eq(lhs, rhs, js);
|
||||
}
|
||||
|
|
|
@ -766,11 +766,11 @@ namespace smt {
|
|||
for (; p2 + 2 < str.size(); ++p2) l2 << " ";
|
||||
l1 << ")\n";
|
||||
l2 << ")\n";
|
||||
IF_VERBOSE(1, verbose_stream() << l1.str() << l2.str());
|
||||
IF_VERBOSE(2, verbose_stream() << l1.str() << l2.str());
|
||||
m_last_positions.reset();
|
||||
m_last_positions.append(offsets);
|
||||
}
|
||||
IF_VERBOSE(1, verbose_stream() << str);
|
||||
IF_VERBOSE(2, verbose_stream() << str);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace smt {
|
|||
|
||||
public:
|
||||
for_each_relevant_expr(context & ctx);
|
||||
virtual ~for_each_relevant_expr() {}
|
||||
virtual ~for_each_relevant_expr() = default;
|
||||
/**
|
||||
\brief Visit the relevant sub-expressions of n.
|
||||
That is, only subexpressions m of n, such that m_context.is_relevant(m).
|
||||
|
|
|
@ -24,6 +24,8 @@ Revision History:
|
|||
#include "smt/smt_model_finder.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace smt {
|
||||
|
||||
/**
|
||||
|
@ -613,11 +615,15 @@ namespace smt {
|
|||
|
||||
bool context::has_lambda() {
|
||||
for (auto const & [n, q] : m_lambdas) {
|
||||
if (n->get_class_size() != 1)
|
||||
if (n->get_class_size() != 1) {
|
||||
TRACE("context", tout << "class size " << n->get_class_size() << " " << enode_pp(n, *this) << "\n");
|
||||
return true;
|
||||
}
|
||||
for (enode* p : enode::parents(n))
|
||||
if (!is_beta_redex(p, n))
|
||||
if (!is_beta_redex(p, n)) {
|
||||
TRACE("context", tout << "not a beta redex " << enode_pp(p, *this) << "\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1372,8 +1378,10 @@ namespace smt {
|
|||
TRACE("mk_clause", display_literals_verbose(tout << "creating clause: " << literal_vector(num_lits, lits) << "\n", num_lits, lits) << "\n";);
|
||||
m_clause_proof.add(num_lits, lits, k, j);
|
||||
switch (k) {
|
||||
case CLS_AUX:
|
||||
case CLS_TH_AXIOM: {
|
||||
case CLS_TH_AXIOM:
|
||||
dump_axiom(num_lits, lits);
|
||||
Z3_fallthrough;
|
||||
case CLS_AUX: {
|
||||
literal_buffer simp_lits;
|
||||
if (!simplify_aux_clause_literals(num_lits, lits, simp_lits)) {
|
||||
if (j && !j->in_region()) {
|
||||
|
@ -1384,11 +1392,12 @@ namespace smt {
|
|||
}
|
||||
DEBUG_CODE(for (literal lit : simp_lits) SASSERT(get_assignment(lit) == l_true););
|
||||
if (!simp_lits.empty()) {
|
||||
j = mk_justification(unit_resolution_justification(m_region, j, simp_lits.size(), simp_lits.data()));
|
||||
j = mk_justification(unit_resolution_justification(*this, j, simp_lits.size(), simp_lits.data()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLS_TH_LEMMA:
|
||||
case CLS_TH_LEMMA:
|
||||
dump_lemma(num_lits, lits);
|
||||
if (!simplify_aux_lemma_literals(num_lits, lits)) {
|
||||
if (j && !j->in_region()) {
|
||||
j->del_eh(m);
|
||||
|
@ -1398,7 +1407,10 @@ namespace smt {
|
|||
}
|
||||
// simplify_aux_lemma_literals does not delete literals assigned to false, so
|
||||
// it is not necessary to create a unit_resolution_justification
|
||||
break;
|
||||
break;
|
||||
case CLS_LEARNED:
|
||||
dump_lemma(num_lits, lits);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1503,6 +1515,30 @@ namespace smt {
|
|||
}}
|
||||
}
|
||||
|
||||
void context::dump_axiom(unsigned n, literal const* lits) {
|
||||
if (m_fparams.m_axioms2files) {
|
||||
literal_buffer tmp;
|
||||
neg_literals(n, lits, tmp);
|
||||
SASSERT(tmp.size() == n);
|
||||
display_lemma_as_smt_problem(tmp.size(), tmp.data(), false_literal, m_fparams.m_logic);
|
||||
}
|
||||
}
|
||||
|
||||
void context::dump_lemma(unsigned n, literal const* lits) {
|
||||
|
||||
if (m_fparams.m_lemmas2console) {
|
||||
expr_ref fml(m);
|
||||
expr_ref_vector fmls(m);
|
||||
for (unsigned i = 0; i < n; ++i)
|
||||
fmls.push_back(literal2expr(lits[i]));
|
||||
fml = mk_or(fmls);
|
||||
m_lemma_visitor.collect(fml);
|
||||
m_lemma_visitor.display_skolem_decls(std::cout);
|
||||
m_lemma_visitor.display_assert(std::cout, fml.get(), true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void context::mk_clause(literal l1, literal l2, justification * j) {
|
||||
literal ls[2] = { l1, l2 };
|
||||
mk_clause(2, ls, j);
|
||||
|
@ -1518,13 +1554,7 @@ namespace smt {
|
|||
TRACE("mk_th_axiom", display_literals_verbose(tout, num_lits, lits) << "\n";);
|
||||
|
||||
if (m.proofs_enabled()) {
|
||||
js = mk_justification(theory_axiom_justification(tid, m_region, num_lits, lits, num_params, params));
|
||||
}
|
||||
if (m_fparams.m_smtlib_dump_lemmas) {
|
||||
literal_buffer tmp;
|
||||
neg_literals(num_lits, lits, tmp);
|
||||
SASSERT(tmp.size() == num_lits);
|
||||
display_lemma_as_smt_problem(tmp.size(), tmp.data(), false_literal, m_fparams.m_logic);
|
||||
js = mk_justification(theory_axiom_justification(tid, *this, num_lits, lits, num_params, params));
|
||||
}
|
||||
mk_clause(num_lits, lits, js, k);
|
||||
}
|
||||
|
|
|
@ -40,13 +40,14 @@ namespace smt {
|
|||
return m_proof;
|
||||
}
|
||||
|
||||
unit_resolution_justification::unit_resolution_justification(region & r,
|
||||
unit_resolution_justification::unit_resolution_justification(context& ctx,
|
||||
justification * js,
|
||||
unsigned num_lits,
|
||||
literal const * lits):
|
||||
m_antecedent(js),
|
||||
m_num_literals(num_lits) {
|
||||
SASSERT(!js || js->in_region());
|
||||
auto& r = ctx.get_region();
|
||||
m_literals = new (r) literal[num_lits];
|
||||
memcpy(m_literals, lits, sizeof(literal) * num_lits);
|
||||
TRACE("unit_resolution_justification_bug", tout << literal_vector(num_lits, lits) << "\n";);
|
||||
|
@ -101,6 +102,7 @@ namespace smt {
|
|||
return m.mk_unit_resolution(prs.size(), prs.data());
|
||||
}
|
||||
|
||||
|
||||
void eq_conflict_justification::get_antecedents(conflict_resolution & cr) {
|
||||
SASSERT(m_node1->get_root()->is_interpreted());
|
||||
SASSERT(m_node2->get_root()->is_interpreted());
|
||||
|
@ -235,8 +237,9 @@ namespace smt {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
simple_justification::simple_justification(region & r, unsigned num_lits, literal const * lits):
|
||||
simple_justification::simple_justification(context& ctx, unsigned num_lits, literal const * lits):
|
||||
m_num_literals(num_lits) {
|
||||
region& r = ctx.get_region();
|
||||
if (num_lits != 0) {
|
||||
m_literals = new (r) literal[num_lits];
|
||||
memcpy(m_literals, lits, sizeof(literal) * num_lits);
|
||||
|
@ -291,6 +294,12 @@ namespace smt {
|
|||
return m.mk_th_lemma(m_th_id, fact, prs.size(), prs.data(), m_params.size(), m_params.data());
|
||||
}
|
||||
|
||||
void theory_propagation_justification::log(context& ctx) {
|
||||
if (ctx.get_fparams().m_axioms2files)
|
||||
ctx.display_lemma_as_smt_problem(m_num_literals, m_literals, m_consequent);
|
||||
}
|
||||
|
||||
|
||||
proof * theory_conflict_justification::mk_proof(conflict_resolution & cr) {
|
||||
ptr_buffer<proof> prs;
|
||||
if (!antecedent2proof(cr, prs))
|
||||
|
@ -299,9 +308,16 @@ namespace smt {
|
|||
return m.mk_th_lemma(m_th_id, m.mk_false(), prs.size(), prs.data(), m_params.size(), m_params.data());
|
||||
}
|
||||
|
||||
ext_simple_justification::ext_simple_justification(region & r, unsigned num_lits, literal const * lits, unsigned num_eqs, enode_pair const * eqs):
|
||||
simple_justification(r, num_lits, lits),
|
||||
void theory_conflict_justification::log(context& ctx) {
|
||||
if (ctx.get_fparams().m_axioms2files)
|
||||
ctx.display_lemma_as_smt_problem(m_num_literals, m_literals);
|
||||
}
|
||||
|
||||
|
||||
ext_simple_justification::ext_simple_justification(context& ctx, unsigned num_lits, literal const * lits, unsigned num_eqs, enode_pair const * eqs):
|
||||
simple_justification(ctx, num_lits, lits),
|
||||
m_num_eqs(num_eqs) {
|
||||
region& r = ctx.get_region();
|
||||
m_eqs = new (r) enode_pair[num_eqs];
|
||||
std::uninitialized_copy(eqs, eqs + num_eqs, m_eqs);
|
||||
DEBUG_CODE({
|
||||
|
@ -342,6 +358,13 @@ namespace smt {
|
|||
ctx.literal2expr(m_consequent, fact);
|
||||
return m.mk_th_lemma(m_th_id, fact, prs.size(), prs.data(), m_params.size(), m_params.data());
|
||||
}
|
||||
|
||||
void ext_theory_propagation_justification::log(context& ctx) {
|
||||
if (ctx.get_fparams().m_axioms2files)
|
||||
ctx.display_lemma_as_smt_problem(m_num_literals, m_literals, m_num_eqs, m_eqs, m_consequent);
|
||||
|
||||
}
|
||||
|
||||
|
||||
proof * ext_theory_conflict_justification::mk_proof(conflict_resolution & cr) {
|
||||
ptr_buffer<proof> prs;
|
||||
|
@ -351,6 +374,12 @@ namespace smt {
|
|||
return m.mk_th_lemma(m_th_id, m.mk_false(), prs.size(), prs.data(), m_params.size(), m_params.data());
|
||||
}
|
||||
|
||||
void ext_theory_conflict_justification::log(context& ctx) {
|
||||
if (ctx.get_fparams().m_axioms2files)
|
||||
ctx.display_lemma_as_smt_problem(m_num_literals, m_literals);
|
||||
}
|
||||
|
||||
|
||||
proof * ext_theory_eq_propagation_justification::mk_proof(conflict_resolution & cr) {
|
||||
ptr_buffer<proof> prs;
|
||||
if (!antecedent2proof(cr, prs))
|
||||
|
@ -361,6 +390,9 @@ namespace smt {
|
|||
return m.mk_th_lemma(m_th_id, fact, prs.size(), prs.data(), m_params.size(), m_params.data());
|
||||
}
|
||||
|
||||
void ext_theory_eq_propagation_justification::log(context& ctx) {
|
||||
}
|
||||
|
||||
|
||||
theory_lemma_justification::theory_lemma_justification(family_id fid, context & ctx, unsigned num_lits, literal const * lits,
|
||||
unsigned num_params, parameter* params):
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace smt {
|
|||
unsigned m_in_region:1; // true if the object was allocated in a region.
|
||||
public:
|
||||
justification(bool in_region = true):m_mark(false), m_in_region(in_region) {}
|
||||
virtual ~justification() {}
|
||||
virtual ~justification() = default;
|
||||
|
||||
/**
|
||||
\brief This method should return true if the method del_eh needs to be invoked
|
||||
|
@ -95,6 +95,7 @@ namespace smt {
|
|||
virtual char const * get_name() const { return "unknown"; }
|
||||
|
||||
virtual void display_debug_info(conflict_resolution & cr, std::ostream & out) { /* do nothing */ }
|
||||
|
||||
};
|
||||
|
||||
class justification_proof_wrapper : public justification {
|
||||
|
@ -118,7 +119,7 @@ namespace smt {
|
|||
unsigned m_num_literals;
|
||||
literal * m_literals;
|
||||
public:
|
||||
unit_resolution_justification(region & r, justification * js, unsigned num_lits, literal const * lits);
|
||||
unit_resolution_justification(context& ctx, justification * js, unsigned num_lits, literal const * lits);
|
||||
|
||||
unit_resolution_justification(justification * js, unsigned num_lits, literal const * lits);
|
||||
|
||||
|
@ -137,6 +138,7 @@ namespace smt {
|
|||
proof * mk_proof(conflict_resolution & cr) override;
|
||||
|
||||
char const * get_name() const override { return "unit-resolution"; }
|
||||
|
||||
};
|
||||
|
||||
class eq_conflict_justification : public justification {
|
||||
|
@ -218,7 +220,7 @@ namespace smt {
|
|||
bool antecedent2proof(conflict_resolution & cr, ptr_buffer<proof> & result);
|
||||
|
||||
public:
|
||||
simple_justification(region & r, unsigned num_lits, literal const * lits);
|
||||
simple_justification(context& ctx, unsigned num_lits, literal const * lits);
|
||||
|
||||
void get_antecedents(conflict_resolution & cr) override;
|
||||
|
||||
|
@ -234,10 +236,10 @@ namespace smt {
|
|||
vector<parameter> m_params;
|
||||
public:
|
||||
simple_theory_justification(
|
||||
family_id fid, region & r,
|
||||
family_id fid, context& ctx,
|
||||
unsigned num_lits, literal const * lits,
|
||||
unsigned num_params, parameter* params):
|
||||
simple_justification(r, num_lits, lits),
|
||||
simple_justification(ctx, num_lits, lits),
|
||||
m_th_id(fid), m_params(num_params, params) {}
|
||||
|
||||
bool has_del_eh() const override { return !m_params.empty(); }
|
||||
|
@ -251,10 +253,10 @@ namespace smt {
|
|||
class theory_axiom_justification : public simple_theory_justification {
|
||||
public:
|
||||
|
||||
theory_axiom_justification(family_id fid, region & r,
|
||||
theory_axiom_justification(family_id fid, context& ctx,
|
||||
unsigned num_lits, literal const * lits,
|
||||
unsigned num_params = 0, parameter* params = nullptr):
|
||||
simple_theory_justification(fid, r, num_lits, lits, num_params, params) {}
|
||||
simple_theory_justification(fid, ctx, num_lits, lits, num_params, params) {}
|
||||
|
||||
void get_antecedents(conflict_resolution & cr) override {}
|
||||
|
||||
|
@ -265,10 +267,11 @@ namespace smt {
|
|||
|
||||
class theory_propagation_justification : public simple_theory_justification {
|
||||
literal m_consequent;
|
||||
void log(context& ctx);
|
||||
public:
|
||||
theory_propagation_justification(family_id fid, region & r, unsigned num_lits, literal const * lits, literal consequent,
|
||||
theory_propagation_justification(family_id fid, context& ctx, unsigned num_lits, literal const * lits, literal consequent,
|
||||
unsigned num_params = 0, parameter* params = nullptr):
|
||||
simple_theory_justification(fid, r, num_lits, lits, num_params, params), m_consequent(consequent) {}
|
||||
simple_theory_justification(fid, ctx, num_lits, lits, num_params, params), m_consequent(consequent) { log(ctx); }
|
||||
|
||||
proof * mk_proof(conflict_resolution & cr) override;
|
||||
|
||||
|
@ -278,10 +281,11 @@ namespace smt {
|
|||
};
|
||||
|
||||
class theory_conflict_justification : public simple_theory_justification {
|
||||
void log(context& ctx);
|
||||
public:
|
||||
theory_conflict_justification(family_id fid, region & r, unsigned num_lits, literal const * lits,
|
||||
theory_conflict_justification(family_id fid, context& ctx, unsigned num_lits, literal const * lits,
|
||||
unsigned num_params = 0, parameter* params = nullptr):
|
||||
simple_theory_justification(fid, r, num_lits, lits, num_params, params) {}
|
||||
simple_theory_justification(fid, ctx, num_lits, lits, num_params, params) { log(ctx); }
|
||||
|
||||
proof * mk_proof(conflict_resolution & cr) override;
|
||||
|
||||
|
@ -299,7 +303,7 @@ namespace smt {
|
|||
bool antecedent2proof(conflict_resolution & cr, ptr_buffer<proof> & result);
|
||||
|
||||
public:
|
||||
ext_simple_justification(region & r, unsigned num_lits, literal const * lits,
|
||||
ext_simple_justification(context& ctx, unsigned num_lits, literal const * lits,
|
||||
unsigned num_eqs, enode_pair const * eqs);
|
||||
|
||||
void get_antecedents(conflict_resolution & cr) override;
|
||||
|
@ -318,10 +322,10 @@ namespace smt {
|
|||
vector<parameter> m_params;
|
||||
|
||||
public:
|
||||
ext_theory_simple_justification(family_id fid, region & r, unsigned num_lits, literal const * lits,
|
||||
ext_theory_simple_justification(family_id fid, context& ctx, unsigned num_lits, literal const * lits,
|
||||
unsigned num_eqs, enode_pair const * eqs,
|
||||
unsigned num_params = 0, parameter* params = nullptr):
|
||||
ext_simple_justification(r, num_lits, lits, num_eqs, eqs), m_th_id(fid), m_params(num_params, params) {}
|
||||
ext_simple_justification(ctx, num_lits, lits, num_eqs, eqs), m_th_id(fid), m_params(num_params, params) {}
|
||||
|
||||
bool has_del_eh() const override { return !m_params.empty(); }
|
||||
|
||||
|
@ -332,26 +336,33 @@ namespace smt {
|
|||
|
||||
class ext_theory_propagation_justification : public ext_theory_simple_justification {
|
||||
literal m_consequent;
|
||||
void log(context& ctx);
|
||||
public:
|
||||
ext_theory_propagation_justification(family_id fid, region & r,
|
||||
ext_theory_propagation_justification(family_id fid, context & ctx,
|
||||
unsigned num_lits, literal const * lits,
|
||||
unsigned num_eqs, enode_pair const * eqs,
|
||||
literal consequent,
|
||||
unsigned num_params = 0, parameter* params = nullptr):
|
||||
ext_theory_simple_justification(fid, r, num_lits, lits, num_eqs, eqs, num_params, params),
|
||||
m_consequent(consequent) {}
|
||||
ext_theory_simple_justification(fid, ctx, num_lits, lits, num_eqs, eqs, num_params, params),
|
||||
m_consequent(consequent) {
|
||||
log(ctx);
|
||||
}
|
||||
|
||||
proof * mk_proof(conflict_resolution & cr) override;
|
||||
|
||||
char const * get_name() const override { return "ext-theory-propagation"; }
|
||||
|
||||
};
|
||||
|
||||
class ext_theory_conflict_justification : public ext_theory_simple_justification {
|
||||
void log(context& ctx);
|
||||
public:
|
||||
ext_theory_conflict_justification(family_id fid, region & r, unsigned num_lits, literal const * lits,
|
||||
ext_theory_conflict_justification(family_id fid, context& ctx, unsigned num_lits, literal const * lits,
|
||||
unsigned num_eqs, enode_pair const * eqs,
|
||||
unsigned num_params = 0, parameter* params = nullptr):
|
||||
ext_theory_simple_justification(fid, r, num_lits, lits, num_eqs, eqs, num_params, params) {}
|
||||
ext_theory_simple_justification(fid, ctx, num_lits, lits, num_eqs, eqs, num_params, params) {
|
||||
log(ctx);
|
||||
}
|
||||
|
||||
proof * mk_proof(conflict_resolution & cr) override;
|
||||
|
||||
|
@ -361,19 +372,20 @@ namespace smt {
|
|||
class ext_theory_eq_propagation_justification : public ext_theory_simple_justification {
|
||||
enode * m_lhs;
|
||||
enode * m_rhs;
|
||||
void log(context& ctx);
|
||||
public:
|
||||
ext_theory_eq_propagation_justification(
|
||||
family_id fid, region & r,
|
||||
family_id fid, context& ctx,
|
||||
unsigned num_lits, literal const * lits,
|
||||
unsigned num_eqs, enode_pair const * eqs,
|
||||
enode * lhs, enode * rhs,
|
||||
unsigned num_params = 0, parameter* params = nullptr):
|
||||
ext_theory_simple_justification(fid, r, num_lits, lits, num_eqs, eqs, num_params, params), m_lhs(lhs), m_rhs(rhs) {}
|
||||
ext_theory_simple_justification(fid, ctx, num_lits, lits, num_eqs, eqs, num_params, params), m_lhs(lhs), m_rhs(rhs) { log(ctx); }
|
||||
|
||||
ext_theory_eq_propagation_justification(
|
||||
family_id fid, region & r,
|
||||
family_id fid, context& ctx,
|
||||
enode * lhs, enode * rhs):
|
||||
ext_theory_simple_justification(fid, r, 0, nullptr, 0, nullptr, 0, nullptr), m_lhs(lhs), m_rhs(rhs) {}
|
||||
ext_theory_simple_justification(fid, ctx, 0, nullptr, 0, nullptr, 0, nullptr), m_lhs(lhs), m_rhs(rhs) { log(ctx); }
|
||||
|
||||
|
||||
proof * mk_proof(conflict_resolution & cr) override;
|
||||
|
|
|
@ -218,7 +218,7 @@ namespace smt {
|
|||
TRACE("model_checker", tout << "Got some value " << sk_value << "\n";);
|
||||
|
||||
if (use_inv) {
|
||||
unsigned sk_term_gen = 0;
|
||||
unsigned sk_term_gen = 0;
|
||||
expr * sk_term = m_model_finder.get_inv(q, i, sk_value, sk_term_gen);
|
||||
if (sk_term != nullptr) {
|
||||
TRACE("model_checker", tout << "Found inverse " << mk_pp(sk_term, m) << "\n";);
|
||||
|
@ -233,21 +233,30 @@ namespace smt {
|
|||
}
|
||||
else {
|
||||
expr * sk_term = get_term_from_ctx(sk_value);
|
||||
func_decl * f = nullptr;
|
||||
if (sk_term != nullptr) {
|
||||
TRACE("model_checker", tout << "sk term " << mk_pp(sk_term, m) << "\n");
|
||||
sk_value = sk_term;
|
||||
}
|
||||
// last ditch: am I an array?
|
||||
else if (false && autil.is_as_array(sk_value, f) && cex->get_func_interp(f) && cex->get_func_interp(f)->get_array_interp(f)) {
|
||||
sk_value = cex->get_func_interp(f)->get_array_interp(f);
|
||||
}
|
||||
|
||||
}
|
||||
if (contains_model_value(sk_value)) {
|
||||
TRACE("model_checker", tout << "type compatible term " << mk_pp(sk_value, m) << "\n");
|
||||
sk_value = get_type_compatible_term(sk_value);
|
||||
}
|
||||
func_decl * f = nullptr;
|
||||
if (autil.is_as_array(sk_value, f) && cex->get_func_interp(f) && cex->get_func_interp(f)->get_interp()) {
|
||||
expr_ref body(cex->get_func_interp(f)->get_interp(), m);
|
||||
if (contains_model_value(body))
|
||||
return false;
|
||||
ptr_vector<sort> sorts(f->get_arity(), f->get_domain());
|
||||
svector<symbol> names;
|
||||
for (unsigned i = 0; i < f->get_arity(); ++i) {
|
||||
for (unsigned i = 0; i < f->get_arity(); ++i)
|
||||
names.push_back(symbol(i));
|
||||
}
|
||||
defined_names dn(m);
|
||||
body = replace_value_from_ctx(body);
|
||||
body = m.mk_lambda(sorts.size(), sorts.data(), names.data(), body);
|
||||
|
@ -395,12 +404,14 @@ namespace smt {
|
|||
m_fparams = alloc(smt_params, m_context->get_fparams());
|
||||
m_fparams->m_relevancy_lvl = 0; // no relevancy since the model checking problems are quantifier free
|
||||
m_fparams->m_case_split_strategy = CS_ACTIVITY; // avoid warning messages about smt.case_split >= 3.
|
||||
m_fparams->m_arith_dump_lemmas = false;
|
||||
m_fparams->m_axioms2files = false;
|
||||
m_fparams->m_lemmas2console = false;
|
||||
}
|
||||
if (!m_aux_context) {
|
||||
symbol logic;
|
||||
params_ref p;
|
||||
p.set_bool("arith.dump_lemmas", false);
|
||||
p.set_bool("solver.axioms2files", false);
|
||||
p.set_bool("solver.lemmas2console", false);
|
||||
m_aux_context = m_context->mk_fresh(&logic, m_fparams.get(), p);
|
||||
}
|
||||
}
|
||||
|
@ -563,16 +574,16 @@ namespace smt {
|
|||
for (unsigned i = 0; i < n; ++i) {
|
||||
proof* pr = nullptr;
|
||||
expr* arg = args[i];
|
||||
if (m.proofs_enabled()) {
|
||||
if (m.proofs_enabled())
|
||||
pr = m.mk_def_intro(arg);
|
||||
}
|
||||
m_context->internalize_assertion(arg, pr, gen);
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("model_checker_bug_detail", tout << "instantiating... q:\n" << mk_pp(q, m) << "\n";
|
||||
tout << "inconsistent: " << m_context->inconsistent() << "\n";
|
||||
tout << "bindings:\n" << expr_ref_vector(m, num_decls, m_pinned_exprs.data() + offset) << "\n";);
|
||||
tout << "bindings:\n" << expr_ref_vector(m, num_decls, m_pinned_exprs.data() + offset) << "\n";
|
||||
tout << "def " << mk_pp(inst.m_def, m) << "\n";);
|
||||
m_context->add_instance(q, nullptr, num_decls, bindings.data(), inst.m_def, gen, gen, gen, dummy);
|
||||
TRACE("model_checker_bug_detail", tout << "after instantiating, inconsistent: " << m_context->inconsistent() << "\n";);
|
||||
}
|
||||
|
|
|
@ -1157,7 +1157,7 @@ namespace smt {
|
|||
ast_manager& m;
|
||||
public:
|
||||
qinfo(ast_manager& m) :m(m) {}
|
||||
virtual ~qinfo() {}
|
||||
virtual ~qinfo() = default;
|
||||
virtual char const* get_kind() const = 0;
|
||||
virtual bool is_equal(qinfo const* qi) const = 0;
|
||||
virtual void display(std::ostream& out) const { out << "[" << get_kind() << "]"; }
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace smt {
|
|||
*/
|
||||
class model_value_proc {
|
||||
public:
|
||||
virtual ~model_value_proc() {}
|
||||
virtual ~model_value_proc() = default;
|
||||
/**
|
||||
\brief Fill result with the dependencies of this functor.
|
||||
That is, to invoke mk_value, the dependencies in result must be constructed.
|
||||
|
|
|
@ -106,7 +106,7 @@ namespace smt {
|
|||
|
||||
class quantifier_manager_plugin {
|
||||
public:
|
||||
virtual ~quantifier_manager_plugin() {}
|
||||
virtual ~quantifier_manager_plugin() = default;
|
||||
|
||||
virtual void set_manager(quantifier_manager & qm) = 0;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace smt {
|
|||
void mark_as_relevant(relevancy_propagator & rp, expr * n);
|
||||
void mark_args_as_relevant(relevancy_propagator & rp, app * n);
|
||||
public:
|
||||
virtual ~relevancy_eh() {}
|
||||
virtual ~relevancy_eh() = default;
|
||||
/**
|
||||
\brief This method is invoked when n is marked as relevant.
|
||||
*/
|
||||
|
@ -87,7 +87,7 @@ namespace smt {
|
|||
context & m_context;
|
||||
public:
|
||||
relevancy_propagator(context & ctx);
|
||||
virtual ~relevancy_propagator() {}
|
||||
virtual ~relevancy_propagator() = default;
|
||||
|
||||
context & get_context() { return m_context; }
|
||||
|
||||
|
|
|
@ -294,7 +294,7 @@ namespace smt {
|
|||
m_bound_kind(k),
|
||||
m_atom(a) {
|
||||
}
|
||||
virtual ~bound() {}
|
||||
virtual ~bound() = default;
|
||||
theory_var get_var() const { return m_var; }
|
||||
bound_kind get_bound_kind() const { return static_cast<bound_kind>(m_bound_kind); }
|
||||
bool is_atom() const { return m_atom; }
|
||||
|
@ -544,9 +544,6 @@ namespace smt {
|
|||
unsigned small_lemma_size() const { return m_params.m_arith_small_lemma_size; }
|
||||
bool relax_bounds() const { return m_params.m_arith_stronger_lemmas; }
|
||||
bool skip_big_coeffs() const { return m_params.m_arith_skip_rows_with_big_coeffs; }
|
||||
bool dump_lemmas() const { return m_params.m_arith_dump_lemmas; }
|
||||
void dump_lemmas(literal l, antecedents const& ante);
|
||||
void dump_lemmas(literal l, derived_bound const& ante);
|
||||
bool process_atoms() const;
|
||||
unsigned get_num_conflicts() const { return m_num_conflicts; }
|
||||
var_kind get_var_kind(theory_var v) const { return m_data[v].kind(); }
|
||||
|
|
|
@ -563,7 +563,7 @@ namespace smt {
|
|||
if (!m_util.is_zero(divisor)) {
|
||||
// if divisor is zero, then idiv and mod are uninterpreted functions.
|
||||
expr_ref div(m), mod(m), zero(m), abs_divisor(m), one(m);
|
||||
expr_ref eqz(m), eq(m), lower(m), upper(m), qr(m);
|
||||
expr_ref eqz(m), eq(m), lower(m), upper(m), qr(m), qr1(m), le(m), ge(m);
|
||||
div = m_util.mk_idiv(dividend, divisor);
|
||||
mod = m_util.mk_mod(dividend, divisor);
|
||||
zero = m_util.mk_int(0);
|
||||
|
@ -584,9 +584,24 @@ namespace smt {
|
|||
mk_axiom(eqz, eq, false);
|
||||
mk_axiom(eqz, lower, false);
|
||||
mk_axiom(eqz, upper, !m_util.is_numeral(abs_divisor));
|
||||
|
||||
rational k;
|
||||
|
||||
m_arith_eq_adapter.mk_axioms(ensure_enode(qr), ensure_enode(mod));
|
||||
m_arith_eq_adapter.mk_axioms(ensure_enode(qr), ensure_enode(dividend));
|
||||
|
||||
// non-linear divisors/mod have to be flattened for the non-linear solver to understand the terms.
|
||||
// to ensure this use the rewriter. This is a hack required to fix a latent bug that affects the
|
||||
// legacy arithmetic solver broadly. It is not something that the newer arithmetic solver suffers from.
|
||||
qr1 = qr;
|
||||
s(qr1);
|
||||
if (qr != qr1) {
|
||||
expr_ref eq(m.mk_eq(qr, qr1), m);
|
||||
ctx.internalize(eq, false);
|
||||
literal qeq = ctx.get_literal(eq);
|
||||
ctx.mark_as_relevant(qeq);
|
||||
ctx.mk_th_axiom(get_id(), 1, &qeq);
|
||||
m_arith_eq_adapter.mk_axioms(ensure_enode(qr), ensure_enode(qr1));
|
||||
}
|
||||
|
||||
if (m_util.is_zero(dividend)) {
|
||||
mk_axiom(eqz, m.mk_eq(div, zero));
|
||||
|
@ -1029,13 +1044,14 @@ namespace smt {
|
|||
inf_numeral const & k1(a1->get_k());
|
||||
atom_kind kind1 = a1->get_atom_kind();
|
||||
TRACE("mk_bound_axioms", display_atom(tout << "making bound axioms for " << a1 << " ", a1, true); tout << "\n";);
|
||||
|
||||
typename atoms::iterator it = occs.begin();
|
||||
typename atoms::iterator end = occs.end();
|
||||
|
||||
typename atoms::iterator lo_inf = end, lo_sup = end;
|
||||
typename atoms::iterator hi_inf = end, hi_sup = end;
|
||||
|
||||
for (; it != end; ++it) {
|
||||
atom * a2 = *it;
|
||||
atom* a2 = *it;
|
||||
inf_numeral const & k2(a2->get_k());
|
||||
atom_kind kind2 = a2->get_atom_kind();
|
||||
TRACE("mk_bound_axioms", display_atom(tout << "compare " << a2 << " ", a2, true); tout << "\n";);
|
||||
|
@ -2978,23 +2994,7 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
void theory_arith<Ext>::dump_lemmas(literal l, antecedents const& ante) {
|
||||
if (dump_lemmas()) {
|
||||
TRACE("arith", ante.display(tout) << " --> "; ctx.display_detailed_literal(tout, l); tout << "\n";);
|
||||
ctx.display_lemma_as_smt_problem(ante.lits().size(), ante.lits().data(),
|
||||
ante.eqs().size(), ante.eqs().data(), l);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
void theory_arith<Ext>::dump_lemmas(literal l, derived_bound const& ante) {
|
||||
if (dump_lemmas()) {
|
||||
ctx.display_lemma_as_smt_problem(ante.lits().size(), ante.lits().data(),
|
||||
ante.eqs().size(), ante.eqs().data(), l);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
void theory_arith<Ext>::assign_bound_literal(literal l, row const & r, unsigned idx, bool is_lower, inf_numeral & delta) {
|
||||
|
@ -3006,28 +3006,23 @@ namespace smt {
|
|||
ante.display(tout) << " --> ";
|
||||
ctx.display_detailed_literal(tout, l);
|
||||
tout << "\n";);
|
||||
dump_lemmas(l, ante);
|
||||
|
||||
if (ante.lits().size() < small_lemma_size() && ante.eqs().empty()) {
|
||||
literal_vector & lits = m_tmp_literal_vector2;
|
||||
lits.reset();
|
||||
lits.push_back(l);
|
||||
literal_vector::const_iterator it = ante.lits().begin();
|
||||
literal_vector::const_iterator end = ante.lits().end();
|
||||
for (; it != end; ++it)
|
||||
lits.push_back(~(*it));
|
||||
for (auto const& lit : ante.lits())
|
||||
lits.push_back(~lit);
|
||||
justification * js = nullptr;
|
||||
if (proofs_enabled()) {
|
||||
if (proofs_enabled())
|
||||
js = alloc(theory_lemma_justification, get_id(), ctx, lits.size(), lits.data(),
|
||||
ante.num_params(), ante.params("assign-bounds"));
|
||||
}
|
||||
ctx.mk_clause(lits.size(), lits.data(), js, CLS_TH_LEMMA, nullptr);
|
||||
}
|
||||
else {
|
||||
region & r = ctx.get_region();
|
||||
ctx.assign(l, ctx.mk_justification(
|
||||
ext_theory_propagation_justification(
|
||||
get_id(), r, ante.lits().size(), ante.lits().data(),
|
||||
get_id(), ctx, ante.lits().size(), ante.lits().data(),
|
||||
ante.eqs().size(), ante.eqs().data(), l,
|
||||
ante.num_params(), ante.params("assign-bounds"))));
|
||||
}
|
||||
|
@ -3048,19 +3043,15 @@ namespace smt {
|
|||
int upper_idx;
|
||||
is_row_useful_for_bound_prop(r, lower_idx, upper_idx);
|
||||
|
||||
if (lower_idx >= 0) {
|
||||
if (lower_idx >= 0)
|
||||
imply_bound_for_monomial(r, lower_idx, true);
|
||||
}
|
||||
else if (lower_idx == -1) {
|
||||
else if (lower_idx == -1)
|
||||
imply_bound_for_all_monomials(r, true);
|
||||
}
|
||||
|
||||
if (upper_idx >= 0) {
|
||||
if (upper_idx >= 0)
|
||||
imply_bound_for_monomial(r, upper_idx, false);
|
||||
}
|
||||
else if (upper_idx == -1) {
|
||||
else if (upper_idx == -1)
|
||||
imply_bound_for_all_monomials(r, false);
|
||||
}
|
||||
|
||||
// sneaking cheap eq detection in this loop
|
||||
propagate_cheap_eq(r_idx);
|
||||
|
@ -3090,13 +3081,11 @@ namespace smt {
|
|||
template<typename Ext>
|
||||
void theory_arith<Ext>::set_conflict(antecedents const& ante, antecedents& bounds, char const* proof_rule) {
|
||||
set_conflict(ante.lits().size(), ante.lits().data(), ante.eqs().size(), ante.eqs().data(), bounds, proof_rule);
|
||||
dump_lemmas(false_literal, ante);
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
void theory_arith<Ext>::set_conflict(derived_bound const& ante, antecedents& bounds, char const* proof_rule) {
|
||||
set_conflict(ante.lits().size(), ante.lits().data(), ante.eqs().size(), ante.eqs().data(), bounds, proof_rule);
|
||||
dump_lemmas(false_literal, ante);
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
|
@ -3130,7 +3119,7 @@ namespace smt {
|
|||
record_conflict(num_literals, lits, num_eqs, eqs, bounds.num_params(), bounds.params(proof_rule));
|
||||
ctx.set_conflict(
|
||||
ctx.mk_justification(
|
||||
ext_theory_conflict_justification(get_id(), ctx.get_region(), num_literals, lits, num_eqs, eqs,
|
||||
ext_theory_conflict_justification(get_id(), ctx, num_literals, lits, num_eqs, eqs,
|
||||
bounds.num_params(), bounds.params(proof_rule))));
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace smt {
|
|||
return;
|
||||
|
||||
SASSERT(is_fixed(v));
|
||||
// WARNINING: it is not safe to use get_value(v) here, since
|
||||
// WARNING: it is not safe to use get_value(v) here, since
|
||||
// get_value(v) may not satisfy v bounds at this point.
|
||||
if (!lower_bound(v).is_rational())
|
||||
return;
|
||||
|
@ -328,7 +328,6 @@ namespace smt {
|
|||
return;
|
||||
}
|
||||
context & ctx = get_context();
|
||||
region & r = ctx.get_region();
|
||||
enode * _x = get_enode(x);
|
||||
enode * _y = get_enode(y);
|
||||
eq_vector const& eqs = antecedents.eqs();
|
||||
|
@ -336,7 +335,7 @@ namespace smt {
|
|||
justification * js =
|
||||
ctx.mk_justification(
|
||||
ext_theory_eq_propagation_justification(
|
||||
get_id(), r,
|
||||
get_id(), ctx,
|
||||
lits.size(), lits.data(),
|
||||
eqs.size(), eqs.data(),
|
||||
_x, _y,
|
||||
|
|
|
@ -487,13 +487,13 @@ namespace smt {
|
|||
template<typename Ext>
|
||||
class theory_arith<Ext>::gomory_cut_justification : public ext_theory_propagation_justification {
|
||||
public:
|
||||
gomory_cut_justification(family_id fid, region & r,
|
||||
gomory_cut_justification(family_id fid, context& ctx,
|
||||
unsigned num_lits, literal const * lits,
|
||||
unsigned num_eqs, enode_pair const * eqs,
|
||||
antecedents& bounds,
|
||||
literal consequent):
|
||||
ext_theory_propagation_justification(fid, r, num_lits, lits, num_eqs, eqs, consequent,
|
||||
bounds.num_params(), bounds.params("gomory-cut")) {
|
||||
ext_theory_propagation_justification(fid, ctx, num_lits, lits, num_eqs, eqs, consequent,
|
||||
bounds.num_params(), bounds.params("gomory-cut")) {
|
||||
}
|
||||
// Remark: the assignment must be propagated back to arith
|
||||
theory_id get_from_theory() const override { return null_theory_id; }
|
||||
|
@ -676,19 +676,16 @@ namespace smt {
|
|||
l = ctx.get_literal(bound);
|
||||
IF_VERBOSE(10, verbose_stream() << "cut " << bound << "\n");
|
||||
ctx.mark_as_relevant(l);
|
||||
dump_lemmas(l, ante);
|
||||
auto js = ctx.mk_justification(
|
||||
gomory_cut_justification(
|
||||
get_id(), ctx.get_region(),
|
||||
get_id(), ctx,
|
||||
ante.lits().size(), ante.lits().data(),
|
||||
ante.eqs().size(), ante.eqs().data(), ante, l));
|
||||
|
||||
if (l == false_literal) {
|
||||
if (l == false_literal)
|
||||
ctx.mk_clause(0, nullptr, js, CLS_TH_LEMMA, nullptr);
|
||||
}
|
||||
else {
|
||||
else
|
||||
ctx.assign(l, js);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -714,7 +711,7 @@ namespace smt {
|
|||
for (; it != end; ++it) {
|
||||
if (!it->is_dead()) {
|
||||
if (is_fixed(it->m_var)) {
|
||||
// WARNINING: it is not safe to use get_value(it->m_var) here, since
|
||||
// WARNING: it is not safe to use get_value(it->m_var) here, since
|
||||
// get_value(it->m_var) may not satisfy it->m_var bounds at this point.
|
||||
numeral aux = lcm_den * it->m_coeff;
|
||||
consts += aux * lower_bound(it->m_var).get_rational();
|
||||
|
@ -760,7 +757,7 @@ namespace smt {
|
|||
ctx.set_conflict(
|
||||
ctx.mk_justification(
|
||||
ext_theory_conflict_justification(
|
||||
get_id(), ctx.get_region(), ante.lits().size(), ante.lits().data(),
|
||||
get_id(), ctx, ante.lits().size(), ante.lits().data(),
|
||||
ante.eqs().size(), ante.eqs().data(),
|
||||
ante.num_params(), ante.params("gcd-test"))));
|
||||
return false;
|
||||
|
@ -840,7 +837,7 @@ namespace smt {
|
|||
ctx.set_conflict(
|
||||
ctx.mk_justification(
|
||||
ext_theory_conflict_justification(
|
||||
get_id(), ctx.get_region(),
|
||||
get_id(), ctx,
|
||||
ante.lits().size(), ante.lits().data(), ante.eqs().size(), ante.eqs().data(),
|
||||
ante.num_params(), ante.params("gcd-test"))));
|
||||
return false;
|
||||
|
@ -858,11 +855,9 @@ namespace smt {
|
|||
return true;
|
||||
if (m_eager_gcd)
|
||||
return true;
|
||||
typename vector<row>::const_iterator it = m_rows.begin();
|
||||
typename vector<row>::const_iterator end = m_rows.end();
|
||||
for (; it != end; ++it) {
|
||||
theory_var v = it->get_base_var();
|
||||
if (v != null_theory_var && is_int(v) && !get_value(v).is_int() && !gcd_test(*it)) {
|
||||
for (auto const& e : m_rows) {
|
||||
theory_var v = e.get_base_var();
|
||||
if (v != null_theory_var && is_int(v) && !get_value(v).is_int() && !gcd_test(e)) {
|
||||
if (m_params.m_arith_adaptive_gcd)
|
||||
m_eager_gcd = true;
|
||||
return false;
|
||||
|
@ -883,10 +878,8 @@ namespace smt {
|
|||
for (;;) {
|
||||
vars.reset();
|
||||
// Collect infeasible integer variables.
|
||||
typename vector<row>::const_iterator it = m_rows.begin();
|
||||
typename vector<row>::const_iterator end = m_rows.end();
|
||||
for (; it != end; ++it) {
|
||||
theory_var v = it->get_base_var();
|
||||
for (auto const& e : m_rows) {
|
||||
theory_var v = e.get_base_var();
|
||||
if (v != null_theory_var && is_int(v) && !get_value(v).is_int() && !is_bounded(v) && !already_processed.contains(v)) {
|
||||
vars.push_back(v);
|
||||
already_processed.insert(v);
|
||||
|
@ -1056,15 +1049,13 @@ namespace smt {
|
|||
|
||||
TRACE("arith_int_rows",
|
||||
unsigned num = 0;
|
||||
typename vector<row>::const_iterator it = m_rows.begin();
|
||||
typename vector<row>::const_iterator end = m_rows.end();
|
||||
for (; it != end; ++it) {
|
||||
theory_var v = it->get_base_var();
|
||||
for (auto const& e : m_rows) {
|
||||
theory_var v = e.get_base_var();
|
||||
if (v == null_theory_var)
|
||||
continue;
|
||||
if (is_int(v) && !get_value(v).is_int()) {
|
||||
num++;
|
||||
display_simplified_row(tout, *it);
|
||||
display_simplified_row(tout, e);
|
||||
tout << "\n";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,20 @@ namespace smt {
|
|||
return r;
|
||||
}
|
||||
|
||||
app * theory_array_base::mk_select_reduce(unsigned num_args, expr * * args) {
|
||||
array_util util(m);
|
||||
while (util.is_store(args[0])) {
|
||||
bool are_distinct = false;
|
||||
for (unsigned i = 1; i < num_args && !are_distinct; ++i)
|
||||
are_distinct |= m.are_distinct(args[i], to_app(args[0])->get_arg(i));
|
||||
if (!are_distinct)
|
||||
break;
|
||||
args[0] = to_app(to_app(args[0])->get_arg(0));
|
||||
}
|
||||
return mk_select(num_args, args);
|
||||
}
|
||||
|
||||
|
||||
app * theory_array_base::mk_store(unsigned num_args, expr * const * args) {
|
||||
return m.mk_app(get_family_id(), OP_STORE, 0, nullptr, num_args, args);
|
||||
}
|
||||
|
@ -484,6 +498,8 @@ namespace smt {
|
|||
return p->get_arg(0)->get_root() == n->get_root();
|
||||
if (is_map(p))
|
||||
return true;
|
||||
if (is_store(p))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace smt {
|
|||
bool is_select_arg(enode* r);
|
||||
|
||||
app * mk_select(unsigned num_args, expr * const * args);
|
||||
app * mk_select_reduce(unsigned num_args, expr * * args);
|
||||
app * mk_select(expr_ref_vector const& args) { return mk_select(args.size(), args.data()); }
|
||||
app * mk_store(unsigned num_args, expr * const * args);
|
||||
app * mk_default(expr* a);
|
||||
|
|
|
@ -330,7 +330,8 @@ namespace smt {
|
|||
// Even if there was, as-array on interpreted
|
||||
// functions will be incomplete.
|
||||
// The instantiation operations are still sound to include.
|
||||
found_unsupported_op(n);
|
||||
m_as_array.push_back(node);
|
||||
ctx.push_trail(push_back_vector(m_as_array));
|
||||
instantiate_default_as_array_axiom(node);
|
||||
}
|
||||
else if (is_array_ext(n)) {
|
||||
|
@ -604,6 +605,14 @@ namespace smt {
|
|||
for (unsigned i = 0; i < lam->get_num_decls(); ++i)
|
||||
args.push_back(mk_epsilon(lam->get_decl_sort(i)).first);
|
||||
expr_ref val(mk_select(args), m);
|
||||
ctx.get_rewriter()(val);
|
||||
if (has_quantifiers(val)) {
|
||||
expr_ref fn(m.mk_fresh_const("lambda-body", val->get_sort()), m);
|
||||
expr_ref eq(m.mk_eq(fn, val), m);
|
||||
ctx.assert_expr(eq);
|
||||
ctx.internalize_assertions();
|
||||
val = fn;
|
||||
}
|
||||
ctx.internalize(def, false);
|
||||
ctx.internalize(val.get(), false);
|
||||
return try_assign_eq(val.get(), def);
|
||||
|
@ -807,12 +816,24 @@ namespace smt {
|
|||
if (r == FC_DONE && m_bapa) {
|
||||
r = m_bapa->final_check();
|
||||
}
|
||||
bool should_giveup = m_found_unsupported_op || has_propagate_up_trail();
|
||||
bool should_giveup = m_found_unsupported_op || has_propagate_up_trail() || has_non_beta_as_array();
|
||||
if (r == FC_DONE && should_giveup)
|
||||
r = FC_GIVEUP;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool theory_array_full::has_non_beta_as_array() {
|
||||
for (enode* n : m_as_array) {
|
||||
for (enode* p : n->get_parents())
|
||||
if (!ctx.is_beta_redex(p, n)) {
|
||||
TRACE("array", tout << "not a beta redex " << enode_pp(p, ctx) << "\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool theory_array_full::instantiate_parent_stores_default(theory_var v) {
|
||||
SASSERT(v != null_theory_var);
|
||||
TRACE("array", tout << "v" << v << "\n";);
|
||||
|
|
|
@ -85,6 +85,8 @@ namespace smt {
|
|||
bool has_large_domain(app* array_term);
|
||||
bool has_unitary_domain(app* array_term);
|
||||
std::pair<app*,func_decl*> mk_epsilon(sort* s);
|
||||
enode_vector m_as_array;
|
||||
bool has_non_beta_as_array();
|
||||
|
||||
bool instantiate_select_const_axiom(enode* select, enode* cnst);
|
||||
bool instantiate_select_as_array_axiom(enode* select, enode* arr);
|
||||
|
|
|
@ -294,8 +294,7 @@ namespace smt {
|
|||
m_trail_stack.push(add_var_pos_trail(b));
|
||||
b->m_occs = new (get_region()) var_pos_occ(v, idx, b->m_occs);
|
||||
}
|
||||
else {
|
||||
SASSERT(th_id == null_theory_id);
|
||||
else if (th_id == null_theory_id) {
|
||||
ctx.set_var_theory(l.var(), get_id());
|
||||
SASSERT(ctx.get_var_theory(l.var()) == get_id());
|
||||
bit_atom * b = new (get_region()) bit_atom();
|
||||
|
@ -600,6 +599,8 @@ namespace smt {
|
|||
TRACE("bv", tout << mk_bounded_pp(n, m) << "\n";);
|
||||
process_args(n);
|
||||
mk_enode(n);
|
||||
m_bv2int.push_back(ctx.get_enode(n));
|
||||
ctx.push_trail(push_back_vector<enode_vector>(m_bv2int));
|
||||
if (!ctx.relevancy())
|
||||
assert_bv2int_axiom(n);
|
||||
}
|
||||
|
@ -1497,24 +1498,34 @@ namespace smt {
|
|||
unsigned sz = m_bits[v1].size();
|
||||
bool changed = true;
|
||||
TRACE("bv", tout << "bits size: " << sz << "\n";);
|
||||
if (sz == 0) {
|
||||
if (sz == 0 && !m_bv2int.empty()) {
|
||||
// int2bv(bv2int(x)) = x when int2bv(bv2int(x)) has same sort as x
|
||||
enode* n1 = get_enode(r1);
|
||||
for (enode* bv2int : *n1) {
|
||||
if (!m_util.is_bv2int(bv2int->get_expr()))
|
||||
continue;
|
||||
enode* bv2int_arg = bv2int->get_arg(0);
|
||||
auto propagate_bv2int = [&](enode* bv2int) {
|
||||
enode* bv2int_arg = get_arg(bv2int, 0);
|
||||
for (enode* p : enode::parents(n1->get_root())) {
|
||||
if (m_util.is_int2bv(p->get_expr()) && p->get_root() != bv2int_arg->get_root() && p->get_sort() == bv2int_arg->get_sort()) {
|
||||
enode_pair_vector eqs;
|
||||
eqs.push_back({n1, p->get_arg(0) });
|
||||
eqs.push_back({n1, get_arg(p, 0) });
|
||||
eqs.push_back({n1, bv2int});
|
||||
justification * js = ctx.mk_justification(
|
||||
ext_theory_eq_propagation_justification(get_id(), ctx.get_region(), 0, nullptr, eqs.size(), eqs.data(), p, bv2int_arg));
|
||||
ext_theory_eq_propagation_justification(get_id(), ctx, 0, nullptr, eqs.size(), eqs.data(), p, bv2int_arg));
|
||||
ctx.assign_eq(p, bv2int_arg, eq_justification(js));
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (m_bv2int.size() < n1->get_class_size()) {
|
||||
for (enode* bv2int : m_bv2int)
|
||||
if (bv2int->get_root() == n1->get_root())
|
||||
propagate_bv2int(bv2int);
|
||||
}
|
||||
else {
|
||||
for (enode* bv2int : *n1) {
|
||||
if (m_util.is_bv2int(bv2int->get_expr()))
|
||||
propagate_bv2int(bv2int);
|
||||
}
|
||||
}
|
||||
}
|
||||
do {
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace smt {
|
|||
|
||||
class atom {
|
||||
public:
|
||||
virtual ~atom() {}
|
||||
virtual ~atom() = default;
|
||||
virtual bool is_bit() const = 0;
|
||||
};
|
||||
|
||||
|
@ -112,6 +112,7 @@ namespace smt {
|
|||
svector<unsigned> m_wpos; // per var, watch position for fixed variable detection.
|
||||
vector<zero_one_bits> m_zero_one_bits; // per var, see comment in the struct zero_one_bit
|
||||
bool_var2atom m_bool_var2atom;
|
||||
enode_vector m_bv2int;
|
||||
typedef svector<theory_var> vars;
|
||||
|
||||
typedef std::pair<numeral, unsigned> value_sort_pair;
|
||||
|
|
|
@ -138,7 +138,7 @@ namespace smt {
|
|||
enode* n2 = ensure_enode(bits2char);
|
||||
justification* j =
|
||||
ctx.mk_justification(
|
||||
ext_theory_eq_propagation_justification(get_id(), ctx.get_region(), n1, n2));
|
||||
ext_theory_eq_propagation_justification(get_id(), ctx, n1, n2));
|
||||
ctx.assign_eq(n1, n2, eq_justification(j));
|
||||
}
|
||||
++m_stats.m_num_blast;
|
||||
|
@ -267,7 +267,7 @@ namespace smt {
|
|||
enode* n2 = ensure_enode(sum_bits);
|
||||
justification* j =
|
||||
ctx.mk_justification(
|
||||
ext_theory_eq_propagation_justification(get_id(), ctx.get_region(), n1, n2));
|
||||
ext_theory_eq_propagation_justification(get_id(), ctx, n1, n2));
|
||||
ctx.assign_eq(n1, n2, eq_justification(j));
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ namespace smt {
|
|||
|
||||
class dt_eq_justification : public ext_theory_eq_propagation_justification {
|
||||
public:
|
||||
dt_eq_justification(family_id fid, region & r, literal antecedent, enode * lhs, enode * rhs):
|
||||
ext_theory_eq_propagation_justification(fid, r, 1, &antecedent, 0, nullptr, lhs, rhs) {
|
||||
dt_eq_justification(family_id fid, context& ctx, literal antecedent, enode * lhs, enode * rhs):
|
||||
ext_theory_eq_propagation_justification(fid, ctx, 1, &antecedent, 0, nullptr, lhs, rhs) {
|
||||
}
|
||||
// Remark: the assignment must be propagated back to the datatype theory.
|
||||
theory_id get_from_theory() const override { return null_theory_id; }
|
||||
|
@ -122,9 +122,8 @@ namespace smt {
|
|||
}
|
||||
else {
|
||||
SASSERT(ctx.get_assignment(antecedent) == l_true);
|
||||
region & r = ctx.get_region();
|
||||
enode * _rhs = ctx.get_enode(rhs);
|
||||
justification * js = ctx.mk_justification(dt_eq_justification(get_id(), r, antecedent, lhs, _rhs));
|
||||
justification * js = ctx.mk_justification(dt_eq_justification(get_id(), ctx, antecedent, lhs, _rhs));
|
||||
TRACE("datatype", tout << "assigning... #" << lhs->get_owner_id() << " #" << _rhs->get_owner_id() << "\n";
|
||||
tout << "v" << lhs->get_th_var(get_id()) << " v" << _rhs->get_th_var(get_id()) << "\n";);
|
||||
TRACE("datatype_detail", display(tout););
|
||||
|
@ -209,9 +208,8 @@ namespace smt {
|
|||
l.neg();
|
||||
SASSERT(ctx.get_assignment(l) == l_true);
|
||||
enode_pair p(c, r->get_arg(0));
|
||||
region & reg = ctx.get_region();
|
||||
clear_mark();
|
||||
ctx.set_conflict(ctx.mk_justification(ext_theory_conflict_justification(get_id(), reg, 1, &l, 1, &p)));
|
||||
ctx.set_conflict(ctx.mk_justification(ext_theory_conflict_justification(get_id(), ctx, 1, &l, 1, &p)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -732,9 +730,8 @@ namespace smt {
|
|||
|
||||
if (res) {
|
||||
// m_used_eqs should contain conflict
|
||||
region & r = ctx.get_region();
|
||||
clear_mark();
|
||||
ctx.set_conflict(ctx.mk_justification(ext_theory_conflict_justification(get_id(), r, 0, nullptr, m_used_eqs.size(), m_used_eqs.data())));
|
||||
ctx.set_conflict(ctx.mk_justification(ext_theory_conflict_justification(get_id(), ctx, 0, nullptr, m_used_eqs.size(), m_used_eqs.data())));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -859,10 +856,9 @@ namespace smt {
|
|||
var_data * d2 = m_var_data[v2];
|
||||
if (d2->m_constructor != nullptr) {
|
||||
if (d1->m_constructor != nullptr && d1->m_constructor->get_decl() != d2->m_constructor->get_decl()) {
|
||||
region & r = ctx.get_region();
|
||||
enode_pair p(d1->m_constructor, d2->m_constructor);
|
||||
SASSERT(d1->m_constructor->get_root() == d2->m_constructor->get_root());
|
||||
ctx.set_conflict(ctx.mk_justification(ext_theory_conflict_justification(get_id(), r, 0, nullptr, 1, &p)));
|
||||
ctx.set_conflict(ctx.mk_justification(ext_theory_conflict_justification(get_id(), ctx, 0, nullptr, 1, &p)));
|
||||
}
|
||||
if (d1->m_constructor == nullptr) {
|
||||
m_trail_stack.push(set_ptr_trail<enode>(d1->m_constructor));
|
||||
|
@ -972,14 +968,13 @@ namespace smt {
|
|||
if (num_unassigned == 0) {
|
||||
// conflict
|
||||
SASSERT(!lits.empty());
|
||||
region & reg = ctx.get_region();
|
||||
TRACE("datatype_conflict", tout << mk_ismt2_pp(recognizer->get_expr(), m) << "\n";
|
||||
for (literal l : lits)
|
||||
ctx.display_detailed_literal(tout, l) << "\n";
|
||||
for (auto const& p : eqs)
|
||||
tout << enode_eq_pp(p, ctx);
|
||||
);
|
||||
ctx.set_conflict(ctx.mk_justification(ext_theory_conflict_justification(get_id(), reg, lits.size(), lits.data(), eqs.size(), eqs.data())));
|
||||
ctx.set_conflict(ctx.mk_justification(ext_theory_conflict_justification(get_id(), ctx, lits.size(), lits.data(), eqs.size(), eqs.data())));
|
||||
}
|
||||
else if (num_unassigned == 1) {
|
||||
// propagate remaining recognizer
|
||||
|
@ -997,9 +992,8 @@ namespace smt {
|
|||
consequent = literal(ctx.enode2bool_var(r));
|
||||
}
|
||||
ctx.mark_as_relevant(consequent);
|
||||
region & reg = ctx.get_region();
|
||||
ctx.assign(consequent,
|
||||
ctx.mk_justification(ext_theory_propagation_justification(get_id(), reg, lits.size(), lits.data(),
|
||||
ctx.mk_justification(ext_theory_propagation_justification(get_id(), ctx, lits.size(), lits.data(),
|
||||
eqs.size(), eqs.data(), consequent)));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -238,7 +238,6 @@ namespace smt {
|
|||
void flush_eh() override;
|
||||
void reset_eh() override;
|
||||
|
||||
bool dump_lemmas() const { return m_params.m_arith_dump_lemmas; }
|
||||
|
||||
void display(std::ostream & out) const override;
|
||||
virtual void display_atom(std::ostream & out, atom * a) const;
|
||||
|
|
|
@ -539,7 +539,7 @@ namespace smt {
|
|||
literal_vector & antecedents = m_tmp_literals;
|
||||
antecedents.reset();
|
||||
get_antecedents(source, target, antecedents);
|
||||
ctx.assign(l, ctx.mk_justification(theory_propagation_justification(get_id(), ctx.get_region(), antecedents.size(), antecedents.data(), l)));
|
||||
ctx.assign(l, ctx.mk_justification(theory_propagation_justification(get_id(), ctx, antecedents.size(), antecedents.data(), l)));
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
|
@ -591,12 +591,7 @@ namespace smt {
|
|||
get_antecedents(target, source, antecedents);
|
||||
if (l != null_literal)
|
||||
antecedents.push_back(l);
|
||||
region & r = ctx.get_region();
|
||||
ctx.set_conflict(ctx.mk_justification(theory_conflict_justification(get_id(), r, antecedents.size(), antecedents.data())));
|
||||
|
||||
if (dump_lemmas()) {
|
||||
ctx.display_lemma_as_smt_problem(antecedents.size(), antecedents.data(), false_literal);
|
||||
}
|
||||
ctx.set_conflict(ctx.mk_justification(theory_conflict_justification(get_id(), ctx, antecedents.size(), antecedents.data())));
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -350,8 +350,6 @@ namespace smt {
|
|||
|
||||
bool propagate_eqs() const { return m_params.m_arith_propagate_eqs; }
|
||||
|
||||
bool dump_lemmas() const { return m_params.m_arith_dump_lemmas; }
|
||||
|
||||
theory_var expand(bool pos, theory_var v, rational & k);
|
||||
|
||||
void new_eq_or_diseq(bool is_eq, theory_var v1, theory_var v2, justification& eq_just);
|
||||
|
|
|
@ -665,10 +665,6 @@ void theory_diff_logic<Ext>::new_edge(dl_var src, dl_var dst, unsigned num_edges
|
|||
params.size(), params.data());
|
||||
}
|
||||
ctx.mk_clause(lits.size(), lits.data(), js, CLS_TH_LEMMA, nullptr);
|
||||
if (dump_lemmas()) {
|
||||
symbol logic(m_lia_or_lra == is_lia ? "QF_LIA" : "QF_LRA");
|
||||
ctx.display_lemma_as_smt_problem(lits.size(), lits.data(), false_literal, logic);
|
||||
}
|
||||
|
||||
#if 0
|
||||
TRACE("arith",
|
||||
|
@ -707,11 +703,6 @@ void theory_diff_logic<Ext>::set_neg_cycle_conflict() {
|
|||
for (literal lit : lits) ctx.display_literal_info(tout, lit);
|
||||
tout << "\n";);
|
||||
|
||||
if (dump_lemmas()) {
|
||||
symbol logic(m_lia_or_lra == is_lia ? "QF_LIA" : "QF_LRA");
|
||||
ctx.display_lemma_as_smt_problem(lits.size(), lits.data(), false_literal, logic);
|
||||
}
|
||||
|
||||
vector<parameter> params;
|
||||
if (m.proofs_enabled()) {
|
||||
params.push_back(parameter(symbol("farkas")));
|
||||
|
@ -723,7 +714,7 @@ void theory_diff_logic<Ext>::set_neg_cycle_conflict() {
|
|||
ctx.set_conflict(
|
||||
ctx.mk_justification(
|
||||
ext_theory_conflict_justification(
|
||||
get_id(), ctx.get_region(),
|
||||
get_id(), ctx,
|
||||
lits.size(), lits.data(), 0, nullptr, params.size(), params.data())));
|
||||
|
||||
}
|
||||
|
|
|
@ -607,7 +607,7 @@ class theory_lra::imp {
|
|||
return v;
|
||||
}
|
||||
|
||||
bool const has_int() const { return lp().has_int_var(); }
|
||||
bool has_int() const { return lp().has_int_var(); }
|
||||
|
||||
lpvar register_theory_var_in_lar_solver(theory_var v) {
|
||||
lpvar lpv = lp().external_to_local(v);
|
||||
|
@ -1241,6 +1241,7 @@ public:
|
|||
context& c = ctx();
|
||||
if (!k.is_zero()) {
|
||||
mk_axiom(eq);
|
||||
m_arith_eq_adapter.mk_axioms(th.ensure_enode(mod_r), th.ensure_enode(p));
|
||||
mk_axiom(mk_literal(a.mk_ge(mod, zero)));
|
||||
mk_axiom(mk_literal(a.mk_le(mod, upper)));
|
||||
|
||||
|
@ -2331,7 +2332,6 @@ public:
|
|||
literal_vector m_core2;
|
||||
|
||||
void assign(literal lit, literal_vector const& core, svector<enode_pair> const& eqs, vector<parameter> const& params) {
|
||||
dump_assign(lit, core, eqs);
|
||||
if (core.size() < small_lemma_size() && eqs.empty()) {
|
||||
m_core2.reset();
|
||||
for (auto const& c : core) {
|
||||
|
@ -2349,7 +2349,7 @@ public:
|
|||
ctx().assign(
|
||||
lit, ctx().mk_justification(
|
||||
ext_theory_propagation_justification(
|
||||
get_id(), ctx().get_region(), core.size(), core.data(),
|
||||
get_id(), ctx(), core.size(), core.data(),
|
||||
eqs.size(), eqs.data(), lit, params.size(), params.data())));
|
||||
}
|
||||
}
|
||||
|
@ -2942,8 +2942,6 @@ public:
|
|||
}
|
||||
|
||||
|
||||
bool dump_lemmas() const { return params().m_arith_dump_lemmas; }
|
||||
|
||||
bool propagate_eqs() const { return params().m_arith_propagate_eqs && m_num_conflicts < params().m_arith_propagation_threshold; }
|
||||
|
||||
bound_prop_mode propagation_mode() const { return m_num_conflicts < params().m_arith_propagation_threshold ? params().m_arith_bound_prop : bound_prop_mode::BP_NONE; }
|
||||
|
@ -3079,7 +3077,7 @@ public:
|
|||
justification* js =
|
||||
ctx().mk_justification(
|
||||
ext_theory_eq_propagation_justification(
|
||||
get_id(), ctx().get_region(), m_core.size(), m_core.data(), m_eqs.size(), m_eqs.data(), x, y));
|
||||
get_id(), ctx(), m_core.size(), m_core.data(), m_eqs.size(), m_eqs.data(), x, y));
|
||||
|
||||
TRACE("arith",
|
||||
for (auto c : m_core)
|
||||
|
@ -3203,12 +3201,11 @@ public:
|
|||
set_evidence(ev.ci(), m_core, m_eqs);
|
||||
|
||||
// SASSERT(validate_conflict(m_core, m_eqs));
|
||||
dump_conflict(m_core, m_eqs);
|
||||
if (is_conflict) {
|
||||
ctx().set_conflict(
|
||||
ctx().mk_justification(
|
||||
ext_theory_conflict_justification(
|
||||
get_id(), ctx().get_region(),
|
||||
get_id(), ctx(),
|
||||
m_core.size(), m_core.data(),
|
||||
m_eqs.size(), m_eqs.data(), m_params.size(), m_params.data())));
|
||||
}
|
||||
|
@ -3414,11 +3411,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void dump_conflict(literal_vector const& core, svector<enode_pair> const& eqs) {
|
||||
if (dump_lemmas()) {
|
||||
ctx().display_lemma_as_smt_problem(core.size(), core.data(), eqs.size(), eqs.data(), false_literal);
|
||||
}
|
||||
}
|
||||
|
||||
bool validate_conflict(literal_vector const& core, svector<enode_pair> const& eqs) {
|
||||
if (params().m_arith_mode != arith_solver_id::AS_NEW_ARITH) return true;
|
||||
|
@ -3432,13 +3424,6 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
void dump_assign(literal lit, literal_vector const& core, svector<enode_pair> const& eqs) {
|
||||
if (dump_lemmas()) {
|
||||
unsigned id = ctx().display_lemma_as_smt_problem(core.size(), core.data(), eqs.size(), eqs.data(), lit);
|
||||
(void)id;
|
||||
}
|
||||
}
|
||||
|
||||
bool validate_assign(literal lit, literal_vector const& core, svector<enode_pair> const& eqs) {
|
||||
if (params().m_arith_mode != arith_solver_id::AS_NEW_ARITH) return true;
|
||||
scoped_arith_mode _sa(ctx().get_fparams());
|
||||
|
@ -3523,16 +3508,15 @@ public:
|
|||
case lp::lp_status::OPTIMAL: {
|
||||
init_variable_values();
|
||||
TRACE("arith", display(tout << st << " v" << v << " vi: " << vi << "\n"););
|
||||
inf_rational val = get_value(v);
|
||||
// inf_rational val(term_max.x, term_max.y);
|
||||
auto val = value(v);
|
||||
blocker = mk_gt(v);
|
||||
return inf_eps(rational::zero(), val);
|
||||
return val;
|
||||
}
|
||||
case lp::lp_status::FEASIBLE: {
|
||||
inf_rational val = get_value(v);
|
||||
auto val = value(v);
|
||||
TRACE("arith", display(tout << st << " v" << v << " vi: " << vi << "\n"););
|
||||
blocker = mk_gt(v);
|
||||
return inf_eps(rational::zero(), val);
|
||||
return val;
|
||||
}
|
||||
default:
|
||||
SASSERT(st == lp::lp_status::UNBOUNDED);
|
||||
|
@ -3549,23 +3533,19 @@ public:
|
|||
rational r = val.x;
|
||||
expr_ref e(m);
|
||||
if (a.is_int(obj->get_sort())) {
|
||||
if (r.is_int()) {
|
||||
if (r.is_int())
|
||||
r += rational::one();
|
||||
}
|
||||
else {
|
||||
else
|
||||
r = ceil(r);
|
||||
}
|
||||
e = a.mk_numeral(r, obj->get_sort());
|
||||
e = a.mk_ge(obj, e);
|
||||
}
|
||||
else {
|
||||
e = a.mk_numeral(r, obj->get_sort());
|
||||
if (val.y.is_neg()) {
|
||||
if (val.y.is_neg())
|
||||
e = a.mk_ge(obj, e);
|
||||
}
|
||||
else {
|
||||
else
|
||||
e = a.mk_gt(obj, e);
|
||||
}
|
||||
}
|
||||
TRACE("opt", tout << "v" << v << " " << val << " " << r << " " << e << "\n";);
|
||||
return e;
|
||||
|
|
|
@ -1106,7 +1106,7 @@ namespace smt {
|
|||
\brief propagate assignment to inequality.
|
||||
This is a basic, non-optimized implementation based
|
||||
on the assumption that inequalities are mostly units
|
||||
and/or relatively few compared to number of argumets.
|
||||
and/or relatively few compared to number of arguments.
|
||||
*/
|
||||
void theory_pb::assign_ineq(ineq& c, bool is_true) {
|
||||
m_mpz_trail.push_back(c.m_max_sum);
|
||||
|
@ -1486,9 +1486,9 @@ namespace smt {
|
|||
class theory_pb::pb_justification : public theory_propagation_justification {
|
||||
ineq& m_ineq;
|
||||
public:
|
||||
pb_justification(ineq& c, family_id fid, region & r,
|
||||
pb_justification(ineq& c, family_id fid, context& ctx,
|
||||
unsigned num_lits, literal const * lits, literal consequent):
|
||||
theory_propagation_justification(fid, r, num_lits, lits, consequent),
|
||||
theory_propagation_justification(fid, ctx, num_lits, lits, consequent),
|
||||
m_ineq(c)
|
||||
{}
|
||||
ineq& get_ineq() { return m_ineq; }
|
||||
|
@ -1504,7 +1504,7 @@ namespace smt {
|
|||
SASSERT(validate_antecedents(lits));
|
||||
ctx.assign(l, ctx.mk_justification(
|
||||
pb_justification(
|
||||
c, get_id(), ctx.get_region(), lits.size(), lits.data(), l)));
|
||||
c, get_id(), ctx, lits.size(), lits.data(), l)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2008,7 +2008,7 @@ namespace smt {
|
|||
|
||||
SASSERT(validate_antecedents(m_antecedents));
|
||||
TRACE("pb", tout << "assign " << m_antecedents << " ==> " << alit << "\n";);
|
||||
ctx.assign(alit, ctx.mk_justification(theory_propagation_justification(get_id(), ctx.get_region(), m_antecedents.size(), m_antecedents.data(), alit, 0, nullptr)));
|
||||
ctx.assign(alit, ctx.mk_justification(theory_propagation_justification(get_id(), ctx, m_antecedents.size(), m_antecedents.data(), alit, 0, nullptr)));
|
||||
|
||||
DEBUG_CODE(
|
||||
m_antecedents.push_back(~alit);
|
||||
|
@ -2029,7 +2029,7 @@ namespace smt {
|
|||
literal lits[2] = { l1, l2 };
|
||||
justification* js = nullptr;
|
||||
if (proofs_enabled()) {
|
||||
js = ctx.mk_justification(theory_axiom_justification(get_id(), ctx.get_region(), 2, lits));
|
||||
js = ctx.mk_justification(theory_axiom_justification(get_id(), ctx, 2, lits));
|
||||
}
|
||||
return js;
|
||||
}
|
||||
|
@ -2037,7 +2037,7 @@ namespace smt {
|
|||
justification* theory_pb::justify(literal_vector const& lits) {
|
||||
justification* js = nullptr;
|
||||
if (proofs_enabled()) {
|
||||
js = ctx.mk_justification(theory_axiom_justification(get_id(), ctx.get_region(), lits.size(), lits.data()));
|
||||
js = ctx.mk_justification(theory_axiom_justification(get_id(), ctx, lits.size(), lits.data()));
|
||||
}
|
||||
return js;
|
||||
}
|
||||
|
|
|
@ -304,6 +304,7 @@ void theory_seq::init() {
|
|||
m_ax.add_axiom5 = add_ax;
|
||||
m_ax.mk_eq_empty2 = mk_eq_emp;
|
||||
m_arith_value.init(&ctx);
|
||||
m_max_unfolding_depth = ctx.get_fparams().m_seq_min_unfolding;
|
||||
}
|
||||
|
||||
#define TRACEFIN(s) { TRACE("seq", tout << ">>" << s << "\n";); IF_VERBOSE(20, verbose_stream() << s << "\n"); }
|
||||
|
@ -418,6 +419,10 @@ final_check_status theory_seq::final_check_eh() {
|
|||
TRACEFIN("fixed_length");
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (solve_recfuns()) {
|
||||
TRACEFIN("solve_recfun");
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (m_unhandled_expr) {
|
||||
TRACEFIN("give_up");
|
||||
TRACE("seq", tout << "unhandled: " << mk_pp(m_unhandled_expr, m) << "\n";);
|
||||
|
@ -642,11 +647,9 @@ bool theory_seq::check_extensionality() {
|
|||
\brief check negated contains constraints.
|
||||
*/
|
||||
bool theory_seq::check_contains() {
|
||||
for (unsigned i = 0; !ctx.inconsistent() && i < m_ncs.size(); ++i) {
|
||||
if (solve_nc(i)) {
|
||||
for (unsigned i = 0; !ctx.inconsistent() && i < m_ncs.size(); ++i)
|
||||
if (solve_nc(i))
|
||||
m_ncs.erase_and_swap(i--);
|
||||
}
|
||||
}
|
||||
return m_new_propagation || ctx.inconsistent();
|
||||
}
|
||||
|
||||
|
@ -783,7 +786,7 @@ bool theory_seq::propagate_lit(dependency* dep, unsigned n, literal const* _lits
|
|||
justification* js =
|
||||
ctx.mk_justification(
|
||||
ext_theory_propagation_justification(
|
||||
get_id(), ctx.get_region(), lits.size(), lits.data(), eqs.size(), eqs.data(), lit));
|
||||
get_id(), ctx, lits.size(), lits.data(), eqs.size(), eqs.data(), lit));
|
||||
|
||||
m_new_propagation = true;
|
||||
ctx.assign(lit, js);
|
||||
|
@ -804,14 +807,14 @@ void theory_seq::set_conflict(enode_pair_vector const& eqs, literal_vector const
|
|||
ctx.set_conflict(
|
||||
ctx.mk_justification(
|
||||
ext_theory_conflict_justification(
|
||||
get_id(), ctx.get_region(), lits.size(), lits.data(), eqs.size(), eqs.data(), 0, nullptr)));
|
||||
get_id(), ctx, lits.size(), lits.data(), eqs.size(), eqs.data(), 0, nullptr)));
|
||||
validate_conflict(eqs, lits);
|
||||
}
|
||||
|
||||
bool theory_seq::propagate_eq(dependency* dep, enode* n1, enode* n2) {
|
||||
if (n1->get_root() == n2->get_root()) {
|
||||
if (n1->get_root() == n2->get_root())
|
||||
return false;
|
||||
}
|
||||
|
||||
literal_vector lits;
|
||||
enode_pair_vector eqs;
|
||||
linearize(dep, eqs, lits);
|
||||
|
@ -829,7 +832,7 @@ bool theory_seq::propagate_eq(dependency* dep, enode* n1, enode* n2) {
|
|||
|
||||
justification* js = ctx.mk_justification(
|
||||
ext_theory_eq_propagation_justification(
|
||||
get_id(), ctx.get_region(), lits.size(), lits.data(), eqs.size(), eqs.data(), n1, n2));
|
||||
get_id(), ctx, lits.size(), lits.data(), eqs.size(), eqs.data(), n1, n2));
|
||||
|
||||
{
|
||||
std::function<expr*(void)> fn = [&]() { return m.mk_eq(n1->get_expr(), n2->get_expr()); };
|
||||
|
@ -985,9 +988,8 @@ bool theory_seq::is_var(expr* a) const {
|
|||
|
||||
|
||||
bool theory_seq::add_solution(expr* l, expr* r, dependency* deps) {
|
||||
if (l == r) {
|
||||
if (l == r)
|
||||
return false;
|
||||
}
|
||||
m_new_solution = true;
|
||||
m_rep.update(l, r, deps);
|
||||
enode* n1 = ensure_enode(l);
|
||||
|
@ -1000,11 +1002,11 @@ bool theory_seq::add_solution(expr* l, expr* r, dependency* deps) {
|
|||
}
|
||||
|
||||
bool theory_seq::propagate_max_length(expr* l, expr* r, dependency* deps) {
|
||||
unsigned idx;
|
||||
expr* s;
|
||||
if (m_util.str.is_empty(l)) {
|
||||
if (m_util.str.is_empty(l))
|
||||
std::swap(l, r);
|
||||
}
|
||||
|
||||
unsigned idx;
|
||||
expr* s = nullptr;
|
||||
rational hi;
|
||||
if (m_sk.is_tail_u(l, s, idx) && has_length(s) && m_util.str.is_empty(r) && !upper_bound(s, hi)) {
|
||||
propagate_lit(deps, 0, nullptr, m_ax.mk_le(mk_len(s), idx+1));
|
||||
|
@ -1240,12 +1242,31 @@ bool theory_seq::get_length(expr* e, expr_ref& len, literal_vector& lits) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* solve for fold/map (recursive function that depends on a sequence)
|
||||
* Assumption: the Seq argument of fold/map expands into a concatentation of units
|
||||
* The assumption is enforced by tracking the length of the seq argument.
|
||||
* This is ensured in relevant_eh.
|
||||
* Under the assumption, evern occurrence of fold/map gets simplified by expanding
|
||||
* arguments.
|
||||
*/
|
||||
bool theory_seq::solve_recfuns() {
|
||||
for (unsigned i = 0; i < m_recfuns.size() && !ctx.inconsistent(); ++i) {
|
||||
expr* t = m_recfuns[i];
|
||||
dependency* dep = nullptr;
|
||||
expr_ref r(m);
|
||||
if (canonize(t, dep, r) && r != t) {
|
||||
add_solution(t, r, dep);
|
||||
m_recfuns.erase_and_swap(i--);
|
||||
}
|
||||
}
|
||||
return m_new_propagation || ctx.inconsistent();
|
||||
}
|
||||
|
||||
|
||||
bool theory_seq::solve_nc(unsigned idx) {
|
||||
nc const& n = m_ncs[idx];
|
||||
literal len_gt = n.len_gt();
|
||||
literal len_gt = n.len_gt();
|
||||
expr_ref c(m);
|
||||
expr* a = nullptr, *b = nullptr;
|
||||
VERIFY(m_util.str.is_contains(n.contains(), a, b));
|
||||
|
@ -1263,10 +1284,12 @@ bool theory_seq::solve_nc(unsigned idx) {
|
|||
m_new_propagation = true;
|
||||
return false;
|
||||
case l_false:
|
||||
break;
|
||||
if (!m_sk.is_tail(a))
|
||||
add_length_limit(a, m_max_unfolding_depth, true);
|
||||
m_ax.unroll_not_contains(n.contains());
|
||||
return true;
|
||||
}
|
||||
m_ax.unroll_not_contains(n.contains());
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
theory_seq::cell* theory_seq::mk_cell(cell* p, expr* e, dependency* d) {
|
||||
|
@ -1456,7 +1479,7 @@ bool theory_seq::internalize_term(app* term) {
|
|||
mk_var(ctx.get_enode(term));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (m.is_bool(term) &&
|
||||
(m_util.str.is_in_re(term) || m_sk.is_skolem(term))) {
|
||||
bool_var bv = ctx.mk_bool_var(term);
|
||||
|
@ -1515,10 +1538,23 @@ void theory_seq::add_length(expr* l) {
|
|||
Add length limit restrictions to sequence s.
|
||||
*/
|
||||
void theory_seq::add_length_limit(expr* s, unsigned k, bool is_searching) {
|
||||
if (m_sk.is_indexof_left(s))
|
||||
if (m_util.str.is_concat(s)) {
|
||||
for (expr* e : *to_app(s))
|
||||
add_length_limit(e, k, is_searching);
|
||||
return;
|
||||
if (m_sk.is_indexof_right(s))
|
||||
}
|
||||
if (m_util.str.is_unit(s))
|
||||
return;
|
||||
if (m_util.str.is_empty(s))
|
||||
return;
|
||||
|
||||
if (m_sk.is_skolem(s)) {
|
||||
for (expr* e : *to_app(s))
|
||||
if (m_util.is_seq(e) || m_sk.is_skolem(e))
|
||||
add_length_limit(e, k, is_searching);
|
||||
return;
|
||||
}
|
||||
|
||||
expr_ref lim_e = m_ax.add_length_limit(s, k);
|
||||
unsigned k0 = 0;
|
||||
if (m_length_limit_map.find(s, k0)) {
|
||||
|
@ -2500,8 +2536,8 @@ bool theory_seq::expand1(expr* e0, dependency*& eqs, expr_ref& result) {
|
|||
dependency* deps = nullptr;
|
||||
expr* e = m_rep.find(e0, deps);
|
||||
|
||||
expr* e1, *e2, *e3;
|
||||
expr_ref arg1(m), arg2(m);
|
||||
expr* e1, *e2, *e3, *e4;
|
||||
expr_ref arg1(m), arg2(m), arg3(m), arg4(m);
|
||||
if (m_util.str.is_concat(e, e1, e2)) {
|
||||
arg1 = try_expand(e1, deps);
|
||||
arg2 = try_expand(e2, deps);
|
||||
|
@ -2546,6 +2582,30 @@ bool theory_seq::expand1(expr* e0, dependency*& eqs, expr_ref& result) {
|
|||
if (!arg1 || !arg2) return true;
|
||||
result = m_util.str.mk_index(arg1, arg2, e3);
|
||||
}
|
||||
else if (m_util.str.is_map(e, e1, e2)) {
|
||||
arg2 = try_expand(e2, deps);
|
||||
if (!arg2) return true;
|
||||
result = m_util.str.mk_map(e1, arg2);
|
||||
ctx.get_rewriter()(result);
|
||||
}
|
||||
else if (m_util.str.is_mapi(e, e1, e2, e3)) {
|
||||
arg3 = try_expand(e3, deps);
|
||||
if (!arg3) return true;
|
||||
result = m_util.str.mk_mapi(e1, e2, arg3);
|
||||
ctx.get_rewriter()(result);
|
||||
}
|
||||
else if (m_util.str.is_foldl(e, e1, e2, e3)) {
|
||||
arg3 = try_expand(e3, deps);
|
||||
if (!arg3) return true;
|
||||
result = m_util.str.mk_foldl(e1, e2, arg3);
|
||||
ctx.get_rewriter()(result);
|
||||
}
|
||||
else if (m_util.str.is_foldli(e, e1, e2, e3, e4)) {
|
||||
arg4 = try_expand(e4, deps);
|
||||
if (!arg4) return true;
|
||||
result = m_util.str.mk_foldli(e1, e2, e3, arg4);
|
||||
ctx.get_rewriter()(result);
|
||||
}
|
||||
#if 0
|
||||
else if (m_util.str.is_nth_i(e, e1, e2)) {
|
||||
arg1 = try_expand(e1, deps);
|
||||
|
@ -2889,7 +2949,12 @@ void theory_seq::add_axiom(literal l1, literal l2, literal l3, literal l4, liter
|
|||
}
|
||||
|
||||
void theory_seq::add_axiom(literal_vector & lits) {
|
||||
TRACE("seq", ctx.display_literals_smt2(tout << "assert:", lits) << "\n";);
|
||||
TRACE("seq", ctx.display_literals_verbose(tout << "assert " << lits << " :", lits) << "\n";);
|
||||
|
||||
for (literal lit : lits)
|
||||
if (ctx.get_assignment(lit) == l_true)
|
||||
return;
|
||||
|
||||
for (literal lit : lits)
|
||||
ctx.mark_as_relevant(lit);
|
||||
|
||||
|
@ -2954,7 +3019,7 @@ bool theory_seq::propagate_eq(dependency* deps, literal_vector const& _lits, exp
|
|||
justification* js =
|
||||
ctx.mk_justification(
|
||||
ext_theory_eq_propagation_justification(
|
||||
get_id(), ctx.get_region(), lits.size(), lits.data(), eqs.size(), eqs.data(), n1, n2));
|
||||
get_id(), ctx, lits.size(), lits.data(), eqs.size(), eqs.data(), n1, n2));
|
||||
|
||||
m_new_propagation = true;
|
||||
|
||||
|
@ -3164,6 +3229,7 @@ void theory_seq::push_scope_eh() {
|
|||
m_nqs.push_scope();
|
||||
m_ncs.push_scope();
|
||||
m_lts.push_scope();
|
||||
m_recfuns.push_scope();
|
||||
m_regex.push_scope();
|
||||
}
|
||||
|
||||
|
@ -3177,6 +3243,7 @@ void theory_seq::pop_scope_eh(unsigned num_scopes) {
|
|||
m_nqs.pop_scope(num_scopes);
|
||||
m_ncs.pop_scope(num_scopes);
|
||||
m_lts.pop_scope(num_scopes);
|
||||
m_recfuns.pop_scope(num_scopes);
|
||||
m_regex.pop_scope(num_scopes);
|
||||
m_rewrite.reset();
|
||||
if (ctx.get_base_level() > ctx.get_scope_level() - num_scopes) {
|
||||
|
@ -3203,6 +3270,7 @@ void theory_seq::relevant_eh(app* n) {
|
|||
m_util.str.is_from_code(n) ||
|
||||
m_util.str.is_to_code(n) ||
|
||||
m_util.str.is_unit(n) ||
|
||||
m_util.str.is_last_index(n) ||
|
||||
m_util.str.is_length(n) ||
|
||||
/* m_util.str.is_replace_all(n) || uncomment to enable axiomatization */
|
||||
m_util.str.is_le(n)) {
|
||||
|
@ -3214,6 +3282,15 @@ void theory_seq::relevant_eh(app* n) {
|
|||
add_int_string(n);
|
||||
}
|
||||
|
||||
expr* fn, *acc, *i, *s;
|
||||
if (m_util.str.is_foldl(n, fn, acc, s) ||
|
||||
m_util.str.is_foldli(n, fn, i, acc, s) ||
|
||||
m_util.str.is_map(n, fn, s) ||
|
||||
m_util.str.is_mapi(n, fn, i, s)) {
|
||||
add_length_to_eqc(s);
|
||||
m_recfuns.push_back(n);
|
||||
}
|
||||
|
||||
if (m_util.str.is_ubv2s(n))
|
||||
add_ubv_string(n);
|
||||
|
||||
|
@ -3276,7 +3353,7 @@ bool theory_seq::should_research(expr_ref_vector & unsat_core) {
|
|||
}
|
||||
}
|
||||
|
||||
if (k_min < UINT_MAX/4) {
|
||||
if (k_min < get_fparams().m_seq_max_unfolding) {
|
||||
m_max_unfolding_depth++;
|
||||
k_min *= 2;
|
||||
if (m_util.is_seq(s_min))
|
||||
|
@ -3290,7 +3367,7 @@ bool theory_seq::should_research(expr_ref_vector & unsat_core) {
|
|||
IF_VERBOSE(1, verbose_stream() << "(smt.seq :increase-depth " << m_max_unfolding_depth << ")\n");
|
||||
return true;
|
||||
}
|
||||
else if (k_min != UINT_MAX && k_min >= UINT_MAX/4) {
|
||||
else if (k_min != UINT_MAX && k_min >= get_fparams().m_seq_max_unfolding) {
|
||||
throw default_exception("reached max unfolding");
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ namespace smt {
|
|||
|
||||
class apply {
|
||||
public:
|
||||
virtual ~apply() {}
|
||||
virtual ~apply() = default;
|
||||
virtual void operator()(theory_seq& th) = 0;
|
||||
};
|
||||
|
||||
|
@ -328,6 +328,7 @@ namespace smt {
|
|||
scoped_vector<ne> m_nqs; // set of current disequalities.
|
||||
scoped_vector<nc> m_ncs; // set of non-contains constraints.
|
||||
scoped_vector<expr*> m_lts; // set of asserted str.<, str.<= literals
|
||||
scoped_vector<expr*> m_recfuns; // set of recursive functions that are defined by unfolding seq argument (map/fold)
|
||||
bool m_lts_checked;
|
||||
unsigned m_eq_id;
|
||||
th_union_find m_find;
|
||||
|
@ -484,6 +485,7 @@ namespace smt {
|
|||
bool solve_nqs(unsigned i);
|
||||
bool solve_ne(unsigned i);
|
||||
bool solve_nc(unsigned i);
|
||||
bool solve_recfuns();
|
||||
bool check_ne_literals(unsigned idx, unsigned& num_undef_lits);
|
||||
bool propagate_ne2lit(unsigned idx);
|
||||
bool propagate_ne2eq(unsigned idx);
|
||||
|
|
|
@ -279,7 +279,7 @@ namespace smt {
|
|||
enode* tcn = ensure_enode(tc_app);
|
||||
if (ctx.get_assignment(tcn) != l_true) {
|
||||
literal consequent = ctx.get_literal(tc_app);
|
||||
justification* j = ctx.mk_justification(theory_propagation_justification(get_id(), ctx.get_region(), 1, &lit, consequent));
|
||||
justification* j = ctx.mk_justification(theory_propagation_justification(get_id(), ctx, 1, &lit, consequent));
|
||||
TRACE("special_relations", tout << "propagate: " << tc_app << "\n";);
|
||||
ctx.assign(consequent, j);
|
||||
new_assertion = true;
|
||||
|
@ -469,7 +469,7 @@ namespace smt {
|
|||
ctx.set_conflict(
|
||||
ctx.mk_justification(
|
||||
ext_theory_conflict_justification(
|
||||
get_id(), ctx.get_region(),
|
||||
get_id(), ctx,
|
||||
lits.size(), lits.data(), 0, nullptr, params.size(), params.data())));
|
||||
}
|
||||
|
||||
|
@ -532,7 +532,7 @@ namespace smt {
|
|||
literal_vector const& lits = r.m_explanation;
|
||||
TRACE("special_relations", ctx.display_literals_verbose(tout << mk_pp(x->get_expr(), m) << " = " << mk_pp(y->get_expr(), m) << "\n", lits) << "\n";);
|
||||
IF_VERBOSE(20, ctx.display_literals_verbose(verbose_stream() << mk_pp(x->get_expr(), m) << " = " << mk_pp(y->get_expr(), m) << "\n", lits) << "\n";);
|
||||
eq_justification js(ctx.mk_justification(ext_theory_eq_propagation_justification(get_id(), ctx.get_region(), lits.size(), lits.data(), 0, nullptr,
|
||||
eq_justification js(ctx.mk_justification(ext_theory_eq_propagation_justification(get_id(), ctx, lits.size(), lits.data(), 0, nullptr,
|
||||
x, y)));
|
||||
ctx.assign_eq(x, y, js);
|
||||
}
|
||||
|
@ -1149,8 +1149,8 @@ namespace smt {
|
|||
|
||||
|
||||
void theory_special_relations::get_specrels(func_decl_set& rels) const {
|
||||
for (auto [f, r] : m_relations)
|
||||
rels.insert(m_util.get_relation(r->m_decl));
|
||||
for (auto [f, r] : m_relations)
|
||||
rels.insert(r->m_decl);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8436,6 +8436,14 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
|
||||
bool existNegativeContains = false;
|
||||
expr_ref_vector assignments(m);
|
||||
ctx.get_assignments(assignments);
|
||||
for (expr * a : assignments) {
|
||||
expr * subterm;
|
||||
if (m.is_not(a, subterm) && u.str.is_contains(subterm)) existNegativeContains = true;
|
||||
}
|
||||
|
||||
if (!needToAssignFreeVars) {
|
||||
|
||||
// check string-int terms
|
||||
|
@ -8506,9 +8514,11 @@ namespace smt {
|
|||
// we're not done if some variable in a regex membership predicate was unassigned
|
||||
if (regexOK) {
|
||||
if (unused_internal_variables.empty()) {
|
||||
TRACE("str", tout << "All variables are assigned. Done!" << std::endl;);
|
||||
m_stats.m_solved_by = 2;
|
||||
return FC_DONE;
|
||||
if (!existNegativeContains) {
|
||||
TRACE("str", tout << "All variables are assigned. Done!" << std::endl;);
|
||||
m_stats.m_solved_by = 2;
|
||||
return FC_DONE;
|
||||
}
|
||||
} else {
|
||||
TRACE("str", tout << "Assigning decoy values to free internal variables." << std::endl;);
|
||||
for (auto const &var : unused_internal_variables) {
|
||||
|
@ -8561,9 +8571,6 @@ namespace smt {
|
|||
}
|
||||
TRACE("str", tout << "arithmetic solver done in final check" << std::endl;);
|
||||
|
||||
expr_ref_vector assignments(m);
|
||||
ctx.get_assignments(assignments);
|
||||
|
||||
expr_ref_vector precondition(m);
|
||||
expr_ref_vector cex(m);
|
||||
lbool model_status = fixed_length_model_construction(assignments, precondition, free_variables, candidate_model, cex);
|
||||
|
|
|
@ -315,7 +315,7 @@ void theory_user_propagator::propagate_consequence(prop_info const& prop) {
|
|||
if (m.is_false(prop.m_conseq)) {
|
||||
js = ctx.mk_justification(
|
||||
ext_theory_conflict_justification(
|
||||
get_id(), ctx.get_region(), m_lits.size(), m_lits.data(), m_eqs.size(), m_eqs.data(), 0, nullptr));
|
||||
get_id(), ctx, m_lits.size(), m_lits.data(), m_eqs.size(), m_eqs.data(), 0, nullptr));
|
||||
ctx.set_conflict(js);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -143,8 +143,8 @@ namespace smt {
|
|||
char const* get_name() const override { return "user_propagate"; }
|
||||
bool internalize_atom(app* atom, bool gate_ctx) override;
|
||||
bool internalize_term(app* term) override;
|
||||
void new_eq_eh(theory_var v1, theory_var v2) override { force_push(); if (m_eq_eh) m_eq_eh(m_user_context, this, var2expr(v1), var2expr(v2)); }
|
||||
void new_diseq_eh(theory_var v1, theory_var v2) override { force_push(); if (m_diseq_eh) m_diseq_eh(m_user_context, this, var2expr(v1), var2expr(v2)); }
|
||||
void new_eq_eh(theory_var v1, theory_var v2) override { if (m_eq_eh) force_push(), m_eq_eh(m_user_context, this, var2expr(v1), var2expr(v2)); }
|
||||
void new_diseq_eh(theory_var v1, theory_var v2) override { if (m_diseq_eh) force_push(), m_diseq_eh(m_user_context, this, var2expr(v1), var2expr(v2)); }
|
||||
bool use_diseqs() const override { return ((bool)m_diseq_eh); }
|
||||
bool build_models() const override { return false; }
|
||||
final_check_status final_check_eh() override;
|
||||
|
|
|
@ -204,12 +204,7 @@ namespace smt {
|
|||
inc_conflicts();
|
||||
literal_vector const& lits = m_nc_functor.get_lits();
|
||||
IF_VERBOSE(20, ctx.display_literals_smt2(verbose_stream() << "conflict:\n", lits));
|
||||
TRACE("utvpi", ctx.display_literals_smt2(tout << "conflict:\n", lits););
|
||||
|
||||
if (m_params.m_arith_dump_lemmas) {
|
||||
symbol logic(m_lra ? (m_lia?"QF_LIRA":"QF_LRA") : "QF_LIA");
|
||||
ctx.display_lemma_as_smt_problem(lits.size(), lits.data(), false_literal, logic);
|
||||
}
|
||||
TRACE("utvpi", ctx.display_literals_smt2(tout << "conflict:\n", lits););
|
||||
|
||||
vector<parameter> params;
|
||||
if (m.proofs_enabled()) {
|
||||
|
@ -222,7 +217,7 @@ namespace smt {
|
|||
ctx.set_conflict(
|
||||
ctx.mk_justification(
|
||||
ext_theory_conflict_justification(
|
||||
get_id(), ctx.get_region(),
|
||||
get_id(), ctx,
|
||||
lits.size(), lits.data(), 0, nullptr, params.size(), params.data())));
|
||||
|
||||
m_nc_functor.reset();
|
||||
|
|
|
@ -283,7 +283,7 @@ namespace smt {
|
|||
|
||||
ctx.set_conflict(
|
||||
ctx.mk_justification(
|
||||
ext_theory_conflict_justification(get_id(), ctx.get_region(), lits.size(), lits.data(), 0, nullptr, 0, nullptr)));
|
||||
ext_theory_conflict_justification(get_id(), ctx, lits.size(), lits.data(), 0, nullptr, 0, nullptr)));
|
||||
}
|
||||
|
||||
bool theory_wmaxsat::max_unassigned_is_blocked() {
|
||||
|
@ -328,10 +328,9 @@ namespace smt {
|
|||
ctx.display_literals_verbose(tout, lits.size(), lits.data());
|
||||
ctx.display_literal_verbose(tout << " --> ", lit););
|
||||
|
||||
region& r = ctx.get_region();
|
||||
ctx.assign(lit, ctx.mk_justification(
|
||||
ext_theory_propagation_justification(
|
||||
get_id(), r, lits.size(), lits.data(), 0, nullptr, lit, 0, nullptr)));
|
||||
get_id(), ctx, lits.size(), lits.data(), 0, nullptr, lit, 0, nullptr)));
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue