3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 18:31:49 +00:00
z3/lib/sat_clause.h
Leonardo de Moura e9eab22e5c Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:35:25 -07:00

180 lines
6.8 KiB
C++

/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
sat_clause.h
Abstract:
Clauses
Author:
Leonardo de Moura (leonardo) 2011-05-21.
Revision History:
--*/
#ifndef _SAT_CLAUSE_H_
#define _SAT_CLAUSE_H_
#include"sat_types.h"
#include"small_object_allocator.h"
#include"id_gen.h"
#ifdef _MSC_VER
#pragma warning(disable : 4200)
#pragma warning(disable : 4355)
#endif
namespace sat {
class clause_allocator;
class clause {
friend class clause_allocator;
friend class tmp_clause;
unsigned m_id;
unsigned m_size;
unsigned m_capacity;
var_approx_set m_approx;
unsigned m_strengthened:1;
unsigned m_removed:1;
unsigned m_learned:1;
unsigned m_used:1;
unsigned m_frozen:1;
unsigned m_reinit_stack:1;
unsigned m_inact_rounds:8;
unsigned m_glue:8;
unsigned m_psm:8; // transient field used during gc
literal m_lits[0];
static size_t get_obj_size(unsigned num_lits) { return sizeof(clause) + num_lits * sizeof(literal); }
size_t get_size() const { return get_obj_size(m_capacity); }
clause(unsigned id, unsigned sz, literal const * lits, bool learned);
public:
unsigned id() const { return m_id; }
unsigned size() const { return m_size; }
literal & operator[](unsigned idx) { SASSERT(idx < m_size); return m_lits[idx]; }
literal const & operator[](unsigned idx) const { SASSERT(idx < m_size); return m_lits[idx]; }
bool is_learned() const { return m_learned; }
void unset_learned() { SASSERT(is_learned()); m_learned = false; }
void shrink(unsigned num_lits) { SASSERT(num_lits <= m_size); if (num_lits < m_size) { m_size = num_lits; mark_strengthened(); } }
bool strengthened() const { return m_strengthened; }
void mark_strengthened() { m_strengthened = true; update_approx(); }
void unmark_strengthened() { m_strengthened = false; }
void elim(literal l);
bool was_removed() const { return m_removed; }
void set_removed(bool f) { m_removed = f; }
var_approx_set approx() const { return m_approx; }
void update_approx();
bool check_approx() const; // for debugging
literal * begin() { return m_lits; }
literal * end() { return m_lits + m_size; }
bool contains(literal l) const;
bool contains(bool_var v) const;
bool satisfied_by(model const & m) const;
void mark_used() { m_used = true; }
void unmark_used() { m_used = false; }
bool was_used() const { return m_used; }
void inc_inact_rounds() { m_inact_rounds++; }
void reset_inact_rounds() { m_inact_rounds = 0; }
unsigned inact_rounds() const { return m_inact_rounds; }
bool frozen() const { return m_frozen; }
void freeze() { SASSERT(is_learned()); SASSERT(!frozen()); m_frozen = true; }
void unfreeze() { SASSERT(is_learned()); SASSERT(frozen()); m_frozen = false; }
static var_approx_set approx(unsigned num, literal const * lits);
void set_glue(unsigned glue) { m_glue = glue > 255 ? 255 : glue; }
unsigned glue() const { return m_glue; }
void set_psm(unsigned psm) { m_psm = psm > 255 ? 255 : psm; }
unsigned psm() const { return m_psm; }
bool on_reinit_stack() const { return m_reinit_stack; }
void set_reinit_stack(bool f) { m_reinit_stack = f; }
};
std::ostream & operator<<(std::ostream & out, clause const & c);
std::ostream & operator<<(std::ostream & out, clause_vector const & cs);
class bin_clause {
unsigned m_val1;
unsigned m_val2;
public:
bin_clause(literal l1, literal l2, bool learned):m_val1(l1.to_uint()), m_val2((l2.to_uint() << 1) + static_cast<unsigned>(learned)) {}
literal get_literal1() const { return to_literal(m_val1); }
literal get_literal2() const { return to_literal(m_val2 >> 1); }
bool is_learned() const { return (m_val2 & 1) == 1; }
};
class tmp_clause {
clause * m_clause;
public:
tmp_clause():m_clause(0) {}
~tmp_clause() { if (m_clause) dealloc_svect(m_clause); }
clause * get() const { return m_clause; }
void set(unsigned num_lits, literal const * lits, bool learned);
void set(literal l1, literal l2, bool learned) { literal ls[2] = { l1, l2 }; set(2, ls, learned); }
void set(bin_clause const & c) { set(c.get_literal1(), c.get_literal2(), c.is_learned()); }
};
/**
\brief Simple clause allocator that allows uint (32bit integers) to be used to reference clauses (even in 64bit machines).
*/
class clause_allocator {
small_object_allocator m_allocator;
id_gen m_id_gen;
#ifdef _AMD64_
unsigned get_segment(size_t ptr);
static const unsigned c_cls_alignment = 3;
static const unsigned c_max_segments = 1 << c_cls_alignment;
static const size_t c_aligment_mask = (1ull << c_cls_alignment) - 1ull;
unsigned m_num_segments;
size_t m_segments[c_max_segments];
#endif
public:
clause_allocator();
clause * get_clause(clause_offset cls_off) const;
clause_offset get_offset(clause const * ptr) const;
clause * mk_clause(unsigned num_lits, literal const * lits, bool learned);
void del_clause(clause * cls);
};
/**
\brief Wrapper for clauses & binary clauses.
I do not create clause objects for binary clauses.
clause_ref wraps a clause object or a pair of literals (i.e., a binary clause).
*/
class clause_wrapper {
union {
clause * m_cls;
unsigned m_l1_idx;
};
unsigned m_l2_idx;
public:
clause_wrapper(literal l1, literal l2):m_l1_idx(l1.to_uint()), m_l2_idx(l2.to_uint()) {}
clause_wrapper(clause & c):m_cls(&c), m_l2_idx(null_literal.to_uint()) {}
bool is_binary() const { return m_l2_idx != null_literal.to_uint(); }
unsigned size() const { return is_binary() ? 2 : m_cls->size(); }
literal operator[](unsigned idx) const {
SASSERT(idx < size());
if (is_binary())
return idx == 0 ? to_literal(m_l1_idx) : to_literal(m_l2_idx);
else
return m_cls->operator[](idx);
}
bool contains(literal l) const;
bool contains(bool_var v) const;
clause * get_clause() const { SASSERT(!is_binary()); return m_cls; }
};
typedef svector<clause_wrapper> clause_wrapper_vector;
std::ostream & operator<<(std::ostream & out, clause_wrapper const & c);
};
#endif