#ifndef _congruenc_hpp_INCLUDED
#define _congruenc_hpp_INCLUDED
#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <queue>
#include <string>
#include <sys/types.h>
#include <unordered_set>
#include <vector>
#include "clause.hpp"
#include "inttypes.hpp"
#include "util.hpp"
#include "watch.hpp"
namespace CaDiCaL {
typedef int64_t LRAT_ID;
struct Internal;
#define LD_MAX_ARITY 26
#define MAX_ARITY ((1 << LD_MAX_ARITY) - 1)
enum class Gate_Type : int8_t { And_Gate, XOr_Gate, ITE_Gate };
struct lit_implication {
int first;
int second;
Clause *clause;
lit_implication (int f, int s, Clause *_id)
: first (f), second (s), clause (_id) {}
lit_implication (int f, int s) : first (f), second (s), clause (0) {}
lit_implication () : first (0), second (0), clause (nullptr) {}
void swap () { std::swap (first, second); }
};
struct lit_equivalence {
int first;
int second;
Clause *first_clause;
Clause *second_clause;
void check_invariant () const {
assert (second_clause);
assert (first_clause);
assert (std::find (begin (*first_clause), end (*first_clause), first) !=
end (*first_clause));
assert (std::find (begin (*second_clause), end (*second_clause),
second) != end (*second_clause));
assert (std::find (begin (*first_clause), end (*first_clause),
-second) != end (*first_clause));
assert (std::find (begin (*second_clause), end (*second_clause),
-first) != end (*second_clause));
}
lit_equivalence (int f, Clause *f_id, int s, Clause *s_id)
: first (f), second (s), first_clause (f_id), second_clause (s_id) {}
lit_equivalence (int f, int s)
: first (f), second (s), first_clause (nullptr),
second_clause (nullptr) {}
lit_equivalence ()
: first (0), second (0), first_clause (nullptr),
second_clause (nullptr) {}
lit_equivalence swap () {
std::swap (first, second);
std::swap (first_clause, second_clause);
return *this;
}
lit_equivalence negate_both () {
first = -first;
second = -second;
std::swap (first_clause, second_clause);
return *this;
}
};
typedef std::vector<lit_implication> lit_implications;
typedef std::vector<lit_equivalence> lit_equivalences;
std::string string_of_gate (Gate_Type t);
struct LitClausePair {
int current_lit; Clause *clause;
LitClausePair (int lit, Clause *cl) : current_lit (lit), clause (cl) {}
LitClausePair () : current_lit (0), clause (nullptr) {}
};
struct LitIdPair {
int lit; LRAT_ID id;
LitIdPair (int l, LRAT_ID i) : lit (l), id (i) {}
LitIdPair () : lit (0), id (0) {}
};
struct ClauseSize {
size_t size;
Clause *clause;
ClauseSize (int s, Clause *c) : size (s), clause (c) {}
ClauseSize (Clause *c) : size (c->size), clause (c) {}
ClauseSize () {}
};
struct smaller_clause_size_rank {
typedef size_t Type;
Type operator() (const ClauseSize &a) { return a.size; }
};
enum Special_Gate {
NORMAL = 0,
NO_PLUS_THEN = (1 << 0),
NO_NEG_THEN = (1 << 1),
NO_THEN = NO_PLUS_THEN + NO_NEG_THEN,
NO_PLUS_ELSE = (1 << 2),
NO_NEG_ELSE = (1 << 3),
DEGENERATED_AND = (1 << 4), DEGENERATED_AND_LHS_FALSE = (1 << 5), NO_ELSE = NO_PLUS_ELSE + NO_NEG_ELSE,
COND_LHS = NO_NEG_THEN + NO_PLUS_ELSE,
UCOND_LHS = NO_PLUS_THEN + NO_NEG_ELSE,
};
std::string special_gate_str (int8_t f);
inline bool ite_flags_no_then_clauses (int8_t flag) {
return (flag & NO_THEN) == NO_THEN;
}
inline bool ite_flags_no_else_clauses (int8_t flag) {
return (flag & NO_ELSE) == NO_ELSE;
}
inline bool ite_flags_neg_cond_lhs (int8_t flag) {
return (flag & UCOND_LHS) == UCOND_LHS;
}
inline bool ite_flags_cond_lhs (int8_t flag) {
return (flag & COND_LHS) == COND_LHS;
}
struct my_dummy_optional {
LitClausePair content;
my_dummy_optional () : content (0, 0) {}
bool operator() () const { return content.current_lit; }
my_dummy_optional operator= (LitClausePair p) {
content = p;
return *this;
}
void reset () { content = LitClausePair (0, 0); }
};
struct Gate {
#ifdef LOGGING
uint64_t id;
#endif
int lhs;
Gate_Type tag;
bool garbage : 1;
bool indexed : 1;
bool marked : 1;
bool shrunken : 1;
vector<LitClausePair> pos_lhs_ids;
my_dummy_optional neg_lhs_ids;
int8_t degenerated_gate = Special_Gate::NORMAL;
vector<int> rhs;
size_t arity () const { return rhs.size (); }
bool operator== (Gate const &lhs) {
return tag == lhs.tag && rhs == lhs.rhs;
}
Gate ()
: lhs (0), garbage (false), indexed (false), marked (false),
shrunken (false), neg_lhs_ids () {}
};
typedef vector<Gate *> GOccs;
struct GateEqualTo {
bool operator() (const Gate *const lhs, const Gate *const rhs) const {
return lhs->rhs == rhs->rhs && lhs->tag == rhs->tag;
}
};
struct CompactBinary {
Clause *clause;
LRAT_ID id;
int lit1, lit2;
CompactBinary (Clause *c, LRAT_ID i, int l1, int l2)
: clause (c), id (i), lit1 (l1), lit2 (l2) {}
CompactBinary () : clause (nullptr), id (0), lit1 (0), lit2 (0) {}
};
struct Hash {
Hash (std::array<uint64_t, 16> &ncs) : nonces (ncs) {}
const std::array<uint64_t, 16> &nonces;
inline size_t operator() (const Gate *const g) const;
};
struct Rewrite {
int src, dst;
LRAT_ID id1;
LRAT_ID id2;
Rewrite (int _src, int _dst, LRAT_ID _id1, LRAT_ID _id2)
: src (_src), dst (_dst), id1 (_id1), id2 (_id2) {}
Rewrite () : src (0), dst (0), id1 (0), id2 (0) {}
};
struct Closure {
Closure (Internal *i);
~Closure () { delete dummy_search_gate; }
Gate *dummy_search_gate = nullptr;
Internal *const internal;
vector<Clause *> extra_clauses;
vector<CompactBinary> binaries;
std::vector<std::pair<size_t, size_t>> offsetsize;
bool full_watching = false;
std::array<uint64_t, 16> nonces;
typedef unordered_set<Gate *, Hash, GateEqualTo> GatesTable;
vector<bool> scheduled;
vector<signed char> marks;
vector<LitClausePair> mu1_ids, mu2_ids,
mu4_ids;
vector<int> lits; vector<int> rhs; vector<int> unsimplified; vector<int> chain; vector<int> clause; vector<uint64_t>
glargecounts; vector<uint64_t> gnew_largecounts; GatesTable table;
std::array<lit_implications, 2> condbin;
std::array<lit_equivalences, 2> condeq;
std::vector<Clause *> new_unwatched_binary_clauses;
vector<int> resolvent_analyzed;
mutable vector<LRAT_ID> lrat_chain;
#ifdef LOGGING
uint64_t fresh_id;
#endif
uint64_t &new_largecounts (int lit);
uint64_t &largecounts (int lit);
void unmark_all ();
vector<int> representant; vector<int> eager_representant; vector<LRAT_ID> representant_id; vector<LRAT_ID> eager_representant_id; int &representative (int lit);
int representative (int lit) const;
LRAT_ID &representative_id (int lit);
LRAT_ID representative_id (int lit) const;
int &eager_representative (int lit);
int eager_representative (int lit) const;
LRAT_ID &eager_representative_id (int lit);
LRAT_ID eager_representative_id (int lit) const;
std::vector<char> lazy_propagated_idx;
char &lazy_propagated (int lit);
int find_lrat_representative_with_marks (int lit);
int find_representative (int lit);
int find_representative_and_compress_no_proofs (int lit);
int find_representative_already_compressed (int lit);
int find_representative_and_compress (int, bool update_eager = true);
void find_representative_and_compress_both (int);
int find_eager_representative (int);
int find_eager_representative_and_compress (int);
void import_lazy_and_find_eager_representative_and_compress_both (
int);
LRAT_ID find_representative_lrat (int lit);
LRAT_ID find_eager_representative_lrat (int lit);
void produce_eager_representative_lrat (int lit);
void produce_representative_lrat (int lit);
Clause *maybe_add_binary_clause (int a, int b);
Clause *add_binary_clause (int a, int b);
Clause *add_tmp_binary_clause (int a, int b);
Clause *learn_binary_tmp_or_full_clause (int a, int b);
void promote_clause (Clause *);
bool merge_literals_equivalence (int lit, int other, Clause *c1,
Clause *c2);
bool merge_literals (Gate *g, Gate *h, int lit, int other,
const std::vector<LRAT_ID> & = {},
const std::vector<LRAT_ID> & = {});
bool merge_literals (int lit, int other,
const std::vector<LRAT_ID> & = {},
const std::vector<LRAT_ID> & = {});
bool really_merge_literals (int lit, int other, int repr_lit,
int repr_other,
const std::vector<LRAT_ID> & = {},
const std::vector<LRAT_ID> & = {});
vector<LitClausePair> lrat_chain_and_gate;
void push_lrat_id (const Clause *const c, int lit);
void push_lrat_unit (int lit);
void push_id_and_rewriting_lrat_unit (Clause *c, Rewrite rewrite1,
std::vector<LRAT_ID> &chain,
bool = true,
Rewrite rewrite2 = Rewrite (),
int execept_lhs = 0,
int except_lhs2 = 0);
void push_id_and_rewriting_lrat_full (Clause *c, Rewrite rewrite1,
std::vector<LRAT_ID> &chain,
bool = true,
Rewrite rewrite2 = Rewrite (),
int execept_lhs = 0,
int except_lhs2 = 0);
void push_id_on_chain (std::vector<LRAT_ID> &chain, Clause *c);
void push_id_on_chain (std::vector<LRAT_ID> &chain,
const std::vector<LitClausePair> &c);
void push_id_on_chain (std::vector<LRAT_ID> &chain,
const my_dummy_optional &c);
void push_id_on_chain (std::vector<LRAT_ID> &chain, Rewrite rewrite, int);
void update_and_gate_build_lrat_chain (
Gate *g, Gate *h, std::vector<LRAT_ID> &extra_reasons_lit,
std::vector<LRAT_ID> &extra_reasons_ulit, bool remove_units = true);
void update_and_gate_unit_build_lrat_chain (
Gate *g, int src, LRAT_ID id1, LRAT_ID id2, int dst,
std::vector<LRAT_ID> &extra_reasons_lit,
std::vector<LRAT_ID> &extra_reasons_ulit);
vector<GOccs> gtab;
GOccs &goccs (int lit);
void connect_goccs (Gate *g, int lit);
vector<Gate *> garbage;
void mark_garbage (Gate *);
bool remove_gate (Gate *);
bool remove_gate (GatesTable::iterator git);
void index_gate (Gate *);
uint64_t &largecount (int lit);
bool skip_and_gate (Gate *g);
bool skip_xor_gate (Gate *g);
void update_and_gate (Gate *g, GatesTable::iterator, int src, int dst,
LRAT_ID id1, LRAT_ID id2, int falsified = 0,
int clashing = 0);
void update_xor_gate (Gate *g, GatesTable::iterator);
void shrink_and_gate (Gate *g, int falsified = 0, int clashing = 0);
bool simplify_gate (Gate *g);
void simplify_and_gate (Gate *g);
void simplify_ite_gate (Gate *g);
Clause *simplify_xor_clause (int lhs, Clause *);
void simplify_xor_gate (Gate *g);
bool simplify_gates (int lit);
void simplify_and_sort_xor_lrat_clauses (const vector<LitClausePair> &,
vector<LitClausePair> &, int,
int except2 = 0, bool flip = 0);
void simplify_unit_xor_lrat_clauses (const vector<LitClausePair> &, int);
bool rewriting_lhs (Gate *g, int dst);
bool rewrite_gates (int dst, int src, LRAT_ID id1, LRAT_ID id2);
bool rewrite_gate (Gate *g, int dst, int src, LRAT_ID id1, LRAT_ID id2);
void rewrite_xor_gate (Gate *g, int dst, int src);
void rewrite_and_gate (Gate *g, int dst, int src, LRAT_ID id1,
LRAT_ID id2);
void rewrite_ite_gate (Gate *g, int dst, int src);
size_t units; bool propagate_unit (int lit);
bool propagate_units ();
size_t propagate_units_and_equivalences ();
bool propagate_equivalence (int lit);
void init_closure ();
void reset_closure ();
void reset_extraction ();
void reset_and_gate_extraction ();
void extract_and_gates (Closure &);
void extract_gates ();
void extract_and_gates_with_base_clause (Clause *c);
void init_and_gate_extraction ();
Gate *find_first_and_gate (Clause *base_clause, int lhs);
Gate *find_remaining_and_gate (Clause *base_clause, int lhs);
void extract_and_gates ();
Gate *find_and_lits (vector<int> &rhs, Gate *except = nullptr);
Gate *
find_gate_lits (vector<int> &rhs,
Gate_Type typ, Gate *except = nullptr);
Gate *find_xor_lits (vector<int> &rhs);
Gate *find_ite_gate (Gate *, bool &);
Gate *find_xor_gate (Gate *);
void reset_xor_gate_extraction ();
void init_xor_gate_extraction (std::vector<Clause *> &candidates);
LRAT_ID check_and_add_to_proof_chain (vector<int> &clause);
void add_xor_matching_proof_chain (Gate *g, int lhs1,
const vector<LitClausePair> &,
int lhs2, vector<LRAT_ID> &,
vector<LRAT_ID> &);
void add_xor_shrinking_proof_chain (Gate *g, int src);
void extract_xor_gates ();
void extract_xor_gates_with_base_clause (Clause *c);
Clause *find_large_xor_side_clause (std::vector<int> &lits);
void merge_condeq (int cond, lit_equivalences &condeq,
lit_equivalences ¬_condeq);
void find_conditional_equivalences (int lit, lit_implications &condbin,
lit_equivalences &condeq);
void copy_conditional_equivalences (int lit, lit_implications &condbin);
void check_ite_implied (int lhs, int cond, int then_lit, int else_lit);
void check_ite_gate_implied (Gate *g);
void check_and_gate_implied (Gate *g);
void check_ite_lrat_reasons (Gate *g);
void check_contained_module_rewriting (Clause *c, int lit, bool,
int except);
void delete_proof_chain ();
void extract_ite_gates_of_literal (int);
void extract_ite_gates_of_variable (int idx);
void extract_condeq_pairs (int lit, lit_implications &condbin,
lit_equivalences &condeq);
void init_ite_gate_extraction (std::vector<ClauseSize> &candidates);
lit_implications::const_iterator find_lit_implication_second_literal (
int lit, lit_implications::const_iterator begin,
lit_implications::const_iterator end);
void search_condeq (int lit, int pos_lit,
lit_implications::const_iterator pos_begin,
lit_implications::const_iterator pos_end, int neg_lit,
lit_implications::const_iterator neg_begin,
lit_implications::const_iterator neg_end,
lit_equivalences &condeq);
void reset_ite_gate_extraction ();
void extract_ite_gates ();
void forward_subsume_matching_clauses ();
void extract_congruence ();
void add_ite_matching_proof_chain (Gate *g, Gate *h, int lhs1, int lhs2,
std::vector<LRAT_ID> &reasons1,
std::vector<LRAT_ID> &reasons2);
void add_ite_turned_and_binary_clauses (Gate *g);
Gate *new_and_gate (Clause *, int);
Gate *new_ite_gate (int lhs, int cond, int then_lit, int else_lit,
std::vector<LitClausePair> &&clauses);
Gate *new_xor_gate (const vector<LitClausePair> &, int);
void check_xor_gate_implied (Gate const *const);
void check_ternary (int a, int b, int c);
void check_binary_implied (int a, int b);
void check_implied ();
bool learn_congruence_unit (int unit, bool = false, bool = false);
bool fully_propagate ();
void learn_congruence_unit_falsifies_lrat_chain (Gate *g, int src,
int dst, int clashing,
int falsified, int unit);
void learn_congruence_unit_when_lhs_set (Gate *g, int src, LRAT_ID id1,
LRAT_ID id2, int dst);
void find_units ();
void find_equivalences ();
void subsume_clause (Clause *subsuming, Clause *subsumed);
bool find_subsuming_clause (Clause *c);
void produce_rewritten_clause_lrat_and_clean (vector<LitClausePair> &,
int execept_lhs = 0,
bool = true, bool = false);
void produce_rewritten_clause_lrat_and_clean (my_dummy_optional &,
int execept_lhs = 0,
bool = true);
Clause *produce_rewritten_clause_lrat (Clause *c, int execept_lhs = 0,
bool remove_units = true,
bool = false);
void produce_rewritten_clause_lrat (vector<LitClausePair> &,
int execept_lhs = 0, bool = true);
void compute_rewritten_clause_lrat_simple (Clause *c, int except);
void produce_rewritten_clause_lrat_and_clean (
std::vector<LitClausePair> &litIds, int except_lhs,
size_t &old_position1, size_t &old_position2,
bool remove_units = true);
void extract_binaries ();
bool find_binary (int, int) const;
Clause *new_tmp_clause (std::vector<int> &clause);
Clause *maybe_promote_tmp_binary_clause (Clause *);
void check_not_tmp_binary_clause (Clause *c);
Clause *new_clause ();
void sort_literals_by_var (vector<int> &rhs);
void sort_literals_by_var_except (vector<int> &rhs, int, int except2 = 0);
queue<int> schedule;
void schedule_literal (int lit);
void add_clause_to_chain (std::vector<int>, LRAT_ID);
LRAT_ID simplify_and_add_to_proof_chain (vector<int> &unsimplified,
LRAT_ID delete_id = 0);
signed char &marked (int lit);
void set_mu1_reason (int lit, Clause *c);
void set_mu2_reason (int lit, Clause *c);
void set_mu4_reason (int lit, Clause *c);
LitClausePair marked_mu1 (int lit);
LitClausePair marked_mu2 (int lit);
LitClausePair marked_mu4 (int lit);
uint32_t number_from_xor_reason_reversed (const std::vector<int> &rhs);
uint32_t number_from_xor_reason (const std::vector<int> &rhs, int,
int except2 = 0, bool flip = 0);
void gate_sort_lrat_reasons (std::vector<LitClausePair> &, int,
int except2 = 0, bool flip = 0);
void gate_sort_lrat_reasons (LitClausePair &, int, int except2 = 0,
bool flip = 0);
bool rewrite_ite_gate_to_and (Gate *g, int dst, int src, size_t c,
size_t d,
int cond_lit_to_learn_if_degenerated);
void produce_ite_merge_then_else_reasons (
Gate *g, int dst, int src, std::vector<LRAT_ID> &reasons_implication,
std::vector<LRAT_ID> &reasons_back);
void produce_ite_merge_lhs_then_else_reasons (
Gate *g, std::vector<LRAT_ID> &reasons_implication,
std::vector<LRAT_ID> &reasons_back,
std::vector<LRAT_ID> &reasons_unit, bool, bool &);
void produce_ite_merge_rhs_cond (Gate *g, int, int);
void rewrite_ite_gate_update_lrat_reasons (Gate *g, int src, int dst);
void simplify_ite_gate_produce_unit_lrat (Gate *g, int lit, size_t idx1,
size_t idx2);
void merge_and_gate_lrat_produce_lrat (
Gate *g, Gate *h, std::vector<LRAT_ID> &reasons_lrat,
std::vector<LRAT_ID> &reasons_lrat_back, bool remove_units = true);
bool simplify_ite_gate_to_and (Gate *g, size_t idx1, size_t idx2,
int removed);
void merge_ite_gate_same_then_else_lrat (
std::vector<LitClausePair> &clauses,
std::vector<LRAT_ID> &reasons_implication,
std::vector<LRAT_ID> &reasons_back);
void simplify_ite_gate_then_else_set (
Gate *g, std::vector<LRAT_ID> &reasons_implication,
std::vector<LRAT_ID> &reasons_back, size_t idx1, size_t idx2);
void simplify_ite_gate_condition_set (
Gate *g, std::vector<LRAT_ID> &reasons_lrat,
std::vector<LRAT_ID> &reasons_back_lrat, size_t idx1, size_t idx2);
bool normalize_ite_lits_gate (Gate *rhs);
};
}
#endif