mirror of
https://github.com/Z3Prover/z3
synced 2025-07-19 10:52:02 +00:00
add xor parity solver feature
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
cb050998e5
commit
98c5a779b4
6 changed files with 665 additions and 108 deletions
|
@ -32,9 +32,7 @@ namespace sat {
|
|||
void reset() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// class card_allocator;
|
||||
class card {
|
||||
//friend class card_allocator;
|
||||
unsigned m_index;
|
||||
literal m_lit;
|
||||
unsigned m_k;
|
||||
|
@ -53,6 +51,22 @@ namespace sat {
|
|||
void negate();
|
||||
};
|
||||
|
||||
class xor {
|
||||
unsigned m_index;
|
||||
literal m_lit;
|
||||
unsigned m_size;
|
||||
literal m_lits[0];
|
||||
public:
|
||||
static size_t get_obj_size(unsigned num_lits) { return sizeof(xor) + num_lits * sizeof(literal); }
|
||||
xor(unsigned index, literal lit, literal_vector const& lits);
|
||||
unsigned index() const { return m_index; }
|
||||
literal lit() const { return m_lit; }
|
||||
literal operator[](unsigned i) const { return m_lits[i]; }
|
||||
unsigned size() const { return m_size; }
|
||||
void swap(unsigned i, unsigned j) { std::swap(m_lits[i], m_lits[j]); }
|
||||
void negate() { m_lits[0].neg(); }
|
||||
};
|
||||
|
||||
struct ineq {
|
||||
literal_vector m_lits;
|
||||
unsigned_vector m_coeffs;
|
||||
|
@ -61,29 +75,48 @@ namespace sat {
|
|||
void push(literal l, unsigned c) { m_lits.push_back(l); m_coeffs.push_back(c); }
|
||||
};
|
||||
|
||||
typedef ptr_vector<card> watch;
|
||||
typedef ptr_vector<card> card_watch;
|
||||
typedef ptr_vector<xor> xor_watch;
|
||||
struct var_info {
|
||||
watch* m_lit_watch[2];
|
||||
card* m_card;
|
||||
var_info(): m_card(0) {
|
||||
m_lit_watch[0] = 0;
|
||||
m_lit_watch[1] = 0;
|
||||
card_watch* m_card_watch[2];
|
||||
xor_watch* m_xor_watch;
|
||||
card* m_card;
|
||||
xor* m_xor;
|
||||
var_info(): m_xor_watch(0), m_card(0), m_xor(0) {
|
||||
m_card_watch[0] = 0;
|
||||
m_card_watch[1] = 0;
|
||||
}
|
||||
void reset() {
|
||||
dealloc(m_card);
|
||||
dealloc(card_extension::set_tag_non_empty(m_lit_watch[0]));
|
||||
dealloc(card_extension::set_tag_non_empty(m_lit_watch[1]));
|
||||
dealloc(m_xor);
|
||||
dealloc(card_extension::set_tag_non_empty(m_card_watch[0]));
|
||||
dealloc(card_extension::set_tag_non_empty(m_card_watch[1]));
|
||||
dealloc(card_extension::set_tag_non_empty(m_xor_watch));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static ptr_vector<T>* set_tag_empty(ptr_vector<T>* c) {
|
||||
return TAG(ptr_vector<T>*, c, 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool is_tag_empty(ptr_vector<T> const* c) {
|
||||
return !c || GET_TAG(c) == 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static ptr_vector<T>* set_tag_non_empty(ptr_vector<T>* c) {
|
||||
return UNTAG(ptr_vector<T>*, c);
|
||||
}
|
||||
|
||||
|
||||
static ptr_vector<card>* set_tag_empty(ptr_vector<card>* c);
|
||||
static bool is_tag_empty(ptr_vector<card> const* c);
|
||||
static ptr_vector<card>* set_tag_non_empty(ptr_vector<card>* c);
|
||||
|
||||
solver* m_solver;
|
||||
stats m_stats;
|
||||
|
||||
ptr_vector<card> m_constraints;
|
||||
ptr_vector<card> m_cards;
|
||||
ptr_vector<xor> m_xors;
|
||||
|
||||
// watch literals
|
||||
svector<var_info> m_var_infos;
|
||||
|
@ -98,8 +131,14 @@ namespace sat {
|
|||
int m_bound;
|
||||
tracked_uint_set m_active_var_set;
|
||||
literal_vector m_lemma;
|
||||
// literal_vector m_literals;
|
||||
unsigned m_num_propagations_since_pop;
|
||||
bool m_has_xor;
|
||||
unsigned_vector m_parity_marks;
|
||||
literal_vector m_parity_trail;
|
||||
void ensure_parity_size(bool_var v);
|
||||
unsigned get_parity(bool_var v);
|
||||
void inc_parity(bool_var v);
|
||||
void reset_parity(bool_var v);
|
||||
|
||||
solver& s() const { return *m_solver; }
|
||||
void init_watch(card& c, bool is_true);
|
||||
|
@ -111,13 +150,44 @@ namespace sat {
|
|||
void clear_watch(card& c);
|
||||
void reset_coeffs();
|
||||
void reset_marked_literals();
|
||||
void unwatch_literal(literal w, card* c);
|
||||
|
||||
// xor specific functionality
|
||||
void clear_watch(xor& x);
|
||||
void watch_literal(xor& x, literal lit);
|
||||
void unwatch_literal(literal w, xor* x);
|
||||
void init_watch(xor& x, bool is_true);
|
||||
void assign(xor& x, literal lit);
|
||||
void set_conflict(xor& x, literal lit);
|
||||
bool parity(xor const& x, unsigned offset) const;
|
||||
lbool add_assign(xor& x, literal alit);
|
||||
void asserted_xor(literal l, ptr_vector<xor>* xors, xor* x);
|
||||
|
||||
bool is_card_index(unsigned idx) const { return 0 == (idx & 0x1); }
|
||||
card& index2card(unsigned idx) const { SASSERT(is_card_index(idx)); return *m_cards[idx >> 1]; }
|
||||
xor& index2xor(unsigned idx) const { SASSERT(!is_card_index(idx)); return *m_xors[idx >> 1]; }
|
||||
void get_xor_antecedents(unsigned index, literal_vector& r);
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool remove(ptr_vector<T>& ts, T* t) {
|
||||
unsigned sz = ts.size();
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
if (ts[j] == t) {
|
||||
std::swap(ts[j], ts[sz-1]);
|
||||
ts.pop_back();
|
||||
return sz == 1;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline lbool value(literal lit) const { return m_solver->value(lit); }
|
||||
inline unsigned lvl(literal lit) const { return m_solver->lvl(lit); }
|
||||
inline unsigned lvl(bool_var v) const { return m_solver->lvl(v); }
|
||||
|
||||
void unwatch_literal(literal w, card* c);
|
||||
bool remove(ptr_vector<card>& cards, card* c);
|
||||
|
||||
void normalize_active_coeffs();
|
||||
void inc_coeff(literal l, int offset);
|
||||
|
@ -131,6 +201,7 @@ namespace sat {
|
|||
|
||||
// validation utilities
|
||||
bool validate_conflict(card& c);
|
||||
bool validate_conflict(xor& x);
|
||||
bool validate_assign(literal_vector const& lits, literal lit);
|
||||
bool validate_lemma();
|
||||
bool validate_unit_propagation(card const& c);
|
||||
|
@ -143,12 +214,16 @@ namespace sat {
|
|||
|
||||
void display(std::ostream& out, ineq& p) const;
|
||||
void display(std::ostream& out, card& c, bool values) const;
|
||||
void display(std::ostream& out, xor& c, bool values) const;
|
||||
void display_watch(std::ostream& out, bool_var v) const;
|
||||
void display_watch(std::ostream& out, bool_var v, bool sign) const;
|
||||
|
||||
public:
|
||||
card_extension();
|
||||
virtual ~card_extension();
|
||||
virtual void set_solver(solver* s) { m_solver = s; }
|
||||
void add_at_least(bool_var v, literal_vector const& lits, unsigned k);
|
||||
void add_xor(bool_var v, literal_vector const& lits);
|
||||
virtual void propagate(literal l, ext_constraint_idx idx, bool & keep);
|
||||
virtual bool resolve_conflict();
|
||||
virtual void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue