mirror of
https://github.com/Z3Prover/z3
synced 2025-05-09 00:35:47 +00:00
Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
3f9edad676
commit
e9eab22e5c
1186 changed files with 381859 additions and 0 deletions
265
lib/bound_propagator.h
Normal file
265
lib/bound_propagator.h
Normal file
|
@ -0,0 +1,265 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
bound_propagator.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Bound propagators for arithmetic.
|
||||
Support class for implementing strategies and search procedures
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-06-18.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _BOUND_PROPAGATOR_H_
|
||||
#define _BOUND_PROPAGATOR_H_
|
||||
|
||||
#include"mpq.h"
|
||||
#include"vector.h"
|
||||
#include"params.h"
|
||||
#include"statistics.h"
|
||||
#include"numeral_buffer.h"
|
||||
#include"linear_equation.h"
|
||||
|
||||
class bound_propagator {
|
||||
public:
|
||||
typedef unsigned var;
|
||||
typedef unsigned assumption;
|
||||
typedef unsynch_mpq_manager numeral_manager;
|
||||
typedef unsigned_vector assumption_vector;
|
||||
typedef unsigned constraint_id;
|
||||
typedef numeral_buffer<mpz, numeral_manager> mpz_buffer;
|
||||
typedef svector<double> double_vector;
|
||||
static const assumption null_assumption = UINT_MAX;
|
||||
static const var null_var = UINT_MAX;
|
||||
static const unsigned null_constraint_idx = UINT_MAX;
|
||||
class trail_info {
|
||||
unsigned m_x_lower;
|
||||
public:
|
||||
trail_info(var x, bool is_lower):m_x_lower((x << 1) + static_cast<unsigned>(is_lower)) {}
|
||||
trail_info():m_x_lower(UINT_MAX) {}
|
||||
var x() const { return m_x_lower >> 1; }
|
||||
bool is_lower() const { return (m_x_lower & 1) != 0; }
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
enum ckind { LINEAR // only linear equalities so far.
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Constraints don't need justification.
|
||||
*/
|
||||
class constraint {
|
||||
friend class bound_propagator;
|
||||
unsigned m_kind:2;
|
||||
unsigned m_dead:1;
|
||||
unsigned m_timestamp; // Constraint tried to propagate new bounds using bounds with timestamp < m_timestamp.
|
||||
unsigned m_act; // activity
|
||||
unsigned m_counter; // number of times the constraint propagated
|
||||
union {
|
||||
linear_equation * m_eq;
|
||||
};
|
||||
};
|
||||
|
||||
enum bkind { AXIOM, // doesn't need justification
|
||||
ASSUMPTION, // aka external case-split, it is used to connect with external search engine.
|
||||
DERIVED, // implied
|
||||
DECISION // internal case-split
|
||||
};
|
||||
|
||||
struct bound {
|
||||
mpq m_k;
|
||||
double m_approx_k;
|
||||
unsigned m_lower:1;
|
||||
unsigned m_strict:1;
|
||||
unsigned m_mark:1;
|
||||
unsigned m_kind:2;
|
||||
unsigned m_level:27;
|
||||
unsigned m_timestamp;
|
||||
union {
|
||||
assumption m_assumption;
|
||||
unsigned m_constraint_idx;
|
||||
};
|
||||
bound * m_prev;
|
||||
bound(numeral_manager & m, mpq const & k, double approx_k, bool lower, bool strict, unsigned lvl, unsigned ts, bkind bk,
|
||||
unsigned c_idx, assumption a, bound * prev);
|
||||
|
||||
bound * at(unsigned timestamp);
|
||||
bkind kind() const { return static_cast<bkind>(m_kind); }
|
||||
bool is_lower() const { return m_lower != 0; }
|
||||
};
|
||||
|
||||
typedef ptr_vector<bound> var2bound;
|
||||
typedef svector<var> var_vector;
|
||||
typedef svector<constraint> constraint_vector;
|
||||
typedef unsigned_vector c_idx_vector;
|
||||
typedef c_idx_vector wlist;
|
||||
typedef small_object_allocator allocator;
|
||||
typedef linear_equation_manager lin_eq_manager;
|
||||
|
||||
numeral_manager & m;
|
||||
allocator & m_allocator;
|
||||
lin_eq_manager m_eq_manager;
|
||||
constraint_vector m_constraints;
|
||||
char_vector m_is_int;
|
||||
char_vector m_dead;
|
||||
var2bound m_lowers;
|
||||
var2bound m_uppers;
|
||||
vector<wlist> m_watches;
|
||||
svector<trail_info> m_trail;
|
||||
unsigned m_qhead;
|
||||
c_idx_vector m_reinit_stack;
|
||||
unsigned_vector m_lower_refinements; // number of times a lower bound was propagated for each variable (loop prevention)
|
||||
unsigned_vector m_upper_refinements; // number of times a upper bound was propagated for each variable (loop prevention)
|
||||
unsigned m_timestamp;
|
||||
var m_conflict;
|
||||
mpq m_tmp;
|
||||
|
||||
struct scope {
|
||||
unsigned m_trail_limit;
|
||||
unsigned m_qhead_old;
|
||||
unsigned m_reinit_stack_limit;
|
||||
unsigned m_timestamp_old:31;
|
||||
unsigned m_in_conflict:1;
|
||||
};
|
||||
|
||||
svector<scope> m_scopes;
|
||||
|
||||
unsigned_vector m_to_reset_ts; // temp field: ids of the constraints we must reset the field m_timestamp
|
||||
|
||||
// config
|
||||
unsigned m_max_refinements; // maximum number of refinements per round
|
||||
double m_small_interval;
|
||||
double m_threshold; // improvement threshold
|
||||
double m_strict2double;
|
||||
|
||||
// statistics
|
||||
unsigned m_conflicts;
|
||||
unsigned m_propagations;
|
||||
unsigned m_false_alarms;
|
||||
|
||||
void del_constraint(constraint & cnstr);
|
||||
void del_constraints_core();
|
||||
|
||||
template<bool LOWER>
|
||||
bool relevant_bound(var x, double approx_k) const;
|
||||
bool relevant_lower(var x, double approx_k) const;
|
||||
bool relevant_upper(var x, double approx_k) const;
|
||||
bool get_interval_size(var x, double & r) const;
|
||||
void check_feasibility(var x);
|
||||
|
||||
bool assert_lower_core(var x, mpq & k, bool strict, bkind bk, unsigned c_idx, assumption a);
|
||||
bool assert_upper_core(var x, mpq & k, bool strict, bkind bk, unsigned c_idx, assumption a);
|
||||
|
||||
bool propagate(unsigned c_idx);
|
||||
bool propagate_eq(unsigned c_idx);
|
||||
bool propagate_lower(unsigned c_idx, unsigned i);
|
||||
bool propagate_upper(unsigned c_idx, unsigned i);
|
||||
void undo_trail(unsigned old_sz);
|
||||
|
||||
typedef std::pair<var, bound *> var_bound;
|
||||
svector<var_bound> m_todo;
|
||||
void explain(var x, bound * b, unsigned ts, assumption_vector & ex) const;
|
||||
bool is_a_i_pos(linear_equation const & eq, var x) const;
|
||||
|
||||
template<bool LOWER, typename Numeral>
|
||||
bool get_bound(unsigned sz, Numeral const * as, var const * xs, mpq & r, bool & st) const;
|
||||
|
||||
void init_eq(linear_equation * eq);
|
||||
|
||||
public:
|
||||
bound_propagator(numeral_manager & m, allocator & a, params_ref const & p);
|
||||
~bound_propagator();
|
||||
|
||||
void updt_params(params_ref const & p);
|
||||
static void get_param_descrs(param_descrs & r);
|
||||
|
||||
void collect_statistics(statistics & st) const;
|
||||
void reset_statistics();
|
||||
|
||||
double strict2double() const { return m_strict2double; }
|
||||
|
||||
bool is_int(var x) const { return m_is_int[x] != 0; }
|
||||
|
||||
unsigned scope_lvl() const { return m_scopes.size(); }
|
||||
void mk_var(var x, bool is_int);
|
||||
void del_var(var x);
|
||||
bool is_dead(var x) const { return m_dead[x] != 0; }
|
||||
void mk_eq(unsigned sz, mpq * as, var * xs);
|
||||
void mk_eq(unsigned sz, mpz * as, var * xs);
|
||||
void del_constraints();
|
||||
void assert_lower(var x, mpq const & k, bool strict, assumption a = null_assumption) {
|
||||
m.set(m_tmp, k);
|
||||
assert_lower_core(x, m_tmp, strict, a == null_assumption ? AXIOM : ASSUMPTION, 0, a);
|
||||
}
|
||||
void assert_upper(var x, mpq const & k, bool strict, assumption a = null_assumption) {
|
||||
m.set(m_tmp, k);
|
||||
assert_upper_core(x, m_tmp, strict, a == null_assumption ? AXIOM : ASSUMPTION, 0, a);
|
||||
}
|
||||
void assert_decided_lower(var x, mpq const & k) {
|
||||
m.set(m_tmp, k);
|
||||
assert_lower_core(x, m_tmp, false, DECISION, 0, null_assumption);
|
||||
}
|
||||
void assert_decided_upper(var x, mpq const & k) {
|
||||
m.set(m_tmp, k);
|
||||
assert_upper_core(x, m_tmp, false, DECISION, 0, null_assumption);
|
||||
}
|
||||
void propagate();
|
||||
void push();
|
||||
void pop(unsigned num_scopes);
|
||||
void reset();
|
||||
bool has_lower(var x) const { return m_lowers[x] != 0; }
|
||||
bool has_upper(var x) const { return m_uppers[x] != 0; }
|
||||
bool lower(var x, mpq & k, bool & strict, unsigned & ts) const;
|
||||
bool upper(var x, mpq & k, bool & strict, unsigned & ts) const;
|
||||
bool is_fixed(var x) const { return has_lower(x) && has_upper(x) && m.eq(m_lowers[x]->m_k, m_uppers[x]->m_k) && !inconsistent(); }
|
||||
mpq const & lower(var x, bool & strict) const { SASSERT(has_lower(x)); bound * b = m_lowers[x]; strict = b->m_strict; return b->m_k; }
|
||||
mpq const & upper(var x, bool & strict) const { SASSERT(has_upper(x)); bound * b = m_uppers[x]; strict = b->m_strict; return b->m_k; }
|
||||
mpq const & lower(var x) const { SASSERT(has_lower(x)); return m_lowers[x]->m_k; }
|
||||
mpq const & upper(var x) const { SASSERT(has_upper(x)); return m_uppers[x]->m_k; }
|
||||
double approx_lower(var x) const {
|
||||
SASSERT(has_lower(x));
|
||||
return m_lowers[x]->m_strict ? m_lowers[x]->m_approx_k + m_strict2double : m_lowers[x]->m_approx_k;
|
||||
}
|
||||
double approx_upper(var x) const {
|
||||
SASSERT(has_upper(x));
|
||||
return m_uppers[x]->m_strict ? m_uppers[x]->m_approx_k - m_strict2double : m_uppers[x]->m_approx_k;
|
||||
}
|
||||
bool is_zero(var x) const { return has_lower(x) && has_upper(x) && m.is_zero(lower(x)) && m.is_zero(upper(x)); }
|
||||
void explain_lower(var x, unsigned ts, assumption_vector & ex) const { explain(x, m_lowers[x], ts, ex); }
|
||||
void explain_upper(var x, unsigned ts, assumption_vector & ex) const { explain(x, m_uppers[x], ts, ex); }
|
||||
void explain_lower(var x, assumption_vector & ex) const { explain_lower(x, m_timestamp, ex); }
|
||||
void explain_upper(var x, assumption_vector & ex) const { explain_upper(x, m_timestamp, ex); }
|
||||
var conflict_var() const { return m_conflict; }
|
||||
bool inconsistent() const { return m_conflict != null_var; }
|
||||
|
||||
unsigned trail_size() const { return m_trail.size(); }
|
||||
unsigned qhead() const { return m_qhead; }
|
||||
|
||||
typedef svector<trail_info>::const_iterator trail_iterator;
|
||||
|
||||
trail_iterator begin_trail() const { return m_trail.begin(); }
|
||||
trail_iterator end_trail() const { return m_trail.end(); }
|
||||
|
||||
bool lower(unsigned sz, mpq const * as, var const * xs, mpq & r, bool & st) const;
|
||||
bool upper(unsigned sz, mpq const * as, var const * xs, mpq & r, bool & st) const;
|
||||
void display(std::ostream & out) const;
|
||||
void display_var_bounds(std::ostream & out, var x, bool approx = true, bool precise = true) const;
|
||||
void display_bounds(std::ostream & out, bool approx = true, bool precise = true) const;
|
||||
void display_precise_bounds(std::ostream & out) const { display_bounds(out, false, true); }
|
||||
void display_approx_bounds(std::ostream & out) const { display_bounds(out, true, false); }
|
||||
void display_constraints(std::ostream & out) const;
|
||||
void display_bounds_of(std::ostream & out, linear_equation const & eq) const;
|
||||
|
||||
unsigned get_num_false_alarms() const { return m_false_alarms; }
|
||||
unsigned get_num_propagations() const { return m_propagations; }
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue