#ifndef _internal_hpp_INCLUDED
#define _internal_hpp_INCLUDED
#include "inttypes.hpp"
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <variant>
extern "C" {
#include <unistd.h>
}
#include <algorithm>
#include <queue>
#include <string>
#include <unordered_set>
#include <vector>
#include "arena.hpp"
#include "averages.hpp"
#include "bins.hpp"
#include "block.hpp"
#include "cadical.hpp"
#include "checker.hpp"
#include "clause.hpp"
#include "config.hpp"
#include "congruence.hpp"
#include "contract.hpp"
#include "cover.hpp"
#include "decompose.hpp"
#include "drattracer.hpp"
#include "elim.hpp"
#include "ema.hpp"
#include "external.hpp"
#include "factor.hpp"
#include "file.hpp"
#include "flags.hpp"
#include "format.hpp"
#include "frattracer.hpp"
#include "heap.hpp"
#include "idruptracer.hpp"
#include "instantiate.hpp"
#include "internal.hpp"
#include "level.hpp"
#include "lidruptracer.hpp"
#include "limit.hpp"
#include "logging.hpp"
#include "lratchecker.hpp"
#include "lrattracer.hpp"
#include "message.hpp"
#include "occs.hpp"
#include "options.hpp"
#include "parse.hpp"
#include "phases.hpp"
#include "profile.hpp"
#include "proof.hpp"
#include "queue.hpp"
#include "radix.hpp"
#include "random.hpp"
#include "range.hpp"
#include "reap.hpp"
#include "reluctant.hpp"
#include "resources.hpp"
#include "score.hpp"
#include "stats.hpp"
#include "sweep.hpp"
#include "terminal.hpp"
#include "tracer.hpp"
#include "util.hpp"
#include "var.hpp"
#include "veripbtracer.hpp"
#include "version.hpp"
#include "vivify.hpp"
#include "walk.hpp"
#include "watch.hpp"
extern "C" {
#include "kitten.h"
}
namespace CaDiCaL {
using namespace std;
struct Coveror;
struct External;
struct WalkerFO;
struct Walker;
class Tracer;
class FileTracer;
class StatTracer;
struct CubesWithStatus {
int status = 0;
std::vector<std::vector<int>> cubes;
};
struct Internal {
enum Mode {
BLOCK = (1 << 0),
CONDITION = (1 << 1),
CONGRUENCE = (1 << 2),
COVER = (1 << 3),
DECOMP = (1 << 4),
DEDUP = (1 << 5),
ELIM = (1 << 6),
FACTOR = (1 << 7),
LUCKY = (1 << 8),
PROBE = (1 << 9),
SEARCH = (1 << 10),
SIMPLIFY = (1 << 11),
SUBSUME = (1 << 12),
SWEEP = (1 << 13),
TERNARY = (1 << 14),
TRANSRED = (1 << 15),
VIVIFY = (1 << 16),
WALK = (1 << 17),
BACKBONE = (1 << 18),
};
bool in_mode (Mode m) const { return (mode & m) != 0; }
void set_mode (Mode m) {
assert (!(mode & m));
mode |= m;
}
void reset_mode (Mode m) {
assert (mode & m);
mode &= ~m;
}
void require_mode (Mode m) const { assert (mode & m), (void) m; }
int mode; int tier1[2] = {
2, 2}; int tier2[2] = {
6, 6}; bool unsat; bool iterating; bool localsearching; bool lookingahead; bool preprocessing; bool protected_reasons; bool force_saved_phase; bool searching_lucky_phases; bool stable; bool reported; bool external_prop; bool did_external_prop; bool external_prop_is_lazy; bool forced_backt_allowed; bool private_steps; char rephased; Reluctant reluctant; size_t vsize; int max_var; int64_t clause_id; int64_t original_id; int64_t reserved_ids; int64_t conflict_id; int64_t saved_decisions; bool concluded; vector<int64_t> conclusion; vector<int64_t>
unit_clauses_idx; vector<int64_t> lrat_chain; vector<int64_t> mini_chain; vector<int64_t> minimize_chain; vector<int64_t> unit_chain; vector<Clause *> inst_chain; vector<vector<vector<int64_t>>>
probehbr_chains; bool lrat; bool frat; int level; Phases phases; signed char *vals; vector<signed char> marks; vector<unsigned> frozentab; vector<int> i2e; vector<unsigned> relevanttab; Queue queue; Links links; double score_inc; ScoreSchedule scores; vector<double> stab; vector<Var> vtab; vector<int> parents; vector<Flags> ftab; vector<int64_t> btab; vector<int64_t> gtab; vector<Occs> otab; vector<Occs> rtab; vector<int> ptab; vector<int64_t> ntab; vector<Bins> big; vector<Watches> wtab; Clause *conflict; Clause *ignore; Clause *dummy_binary; Clause *external_reason; Clause *newest_clause; bool force_no_backtrack; bool from_propagator; bool ext_clause_forgettable; int changed_val; size_t notified; Clause *probe_reason; size_t propagated; size_t propagated2; size_t propergated; size_t best_assigned; size_t target_assigned; size_t no_conflict_until; vector<int> trail; vector<int> clause; vector<int> assumptions; vector<int> constraint; bool unsat_constraint; bool marked_failed; vector<int> original; vector<int> levels; vector<int> analyzed; vector<int> unit_analyzed; vector<int> sign_marked; vector<int> minimized; vector<int> shrinkable; Reap reap; bool factorcheckdone =
0;
vector<int> sweep_schedule; bool sweep_incomplete; uint64_t randomized_deciding;
kitten *citten;
size_t num_assigned;
vector<int> probes; vector<Level> control; vector<Clause *> clauses; Averages averages; Delay delay[2]; Delay congruence_delay; Limit lim; Last last; Inc inc;
Delay delaying_vivify_irredundant;
Delay delaying_sweep;
Proof *proof; vector<Tracer *>
tracers; vector<FileTracer *>
file_tracers; vector<StatTracer *> stat_tracers;
Options opts; Stats stats; #ifndef QUIET
Profiles profiles; bool force_phase_messages; #endif
Arena arena; Format error_message; string prefix;
Internal *internal; External *external;
static constexpr unsigned max_used =
31;
volatile bool termination_forced;
const Range vars; const Sange lits;
Internal ();
~Internal ();
void init_vars (int new_max_var);
void init_enqueue (int idx);
void init_queue (int old_max_var, int new_max_var);
void init_scores (int old_max_var, int new_max_var);
void add_original_lit (int lit);
void finish_added_clause_with_id (int64_t id, bool restore = false);
void reserve_ids (int number);
void enlarge_vals (size_t new_vsize);
void enlarge (int new_max_var);
bool active (int lit) { return flags (lit).active (); }
int active () const {
int res = stats.active;
#ifndef NDEBUG
int tmp = max_var;
tmp -= stats.unused;
tmp -= stats.now.fixed;
tmp -= stats.now.eliminated;
tmp -= stats.now.substituted;
tmp -= stats.now.pure;
assert (tmp >= 0);
assert (tmp == res);
#endif
return res;
}
void reactivate (int lit);
int64_t redundant () const { return stats.current.redundant; }
int64_t irredundant () const { return stats.current.irredundant; }
double clause_variable_ratio () const {
return relative (irredundant (), active ());
}
double scale (double v) const;
int vidx (int lit) const {
int idx;
assert (lit);
assert (lit != INT_MIN);
idx = abs (lit);
assert (idx <= max_var);
return idx;
}
unsigned vlit (int lit) const {
return (lit < 0) + 2u * (unsigned) vidx (lit);
}
int u2i (unsigned u) {
assert (u > 1);
int res = u / 2;
assert (res <= max_var);
if (u & 1)
res = -res;
return res;
}
int citten2lit (unsigned ulit) {
int res = (ulit / 2) + 1;
assert (res <= max_var);
if (ulit & 1)
res = -res;
return res;
}
unsigned lit2citten (int lit) {
int idx = vidx (lit) - 1;
return (lit < 0) + 2u * (unsigned) idx;
}
int64_t unit_id (int lit) const {
assert (lrat || frat);
assert (val (lit) > 0);
const unsigned uidx = vlit (lit);
int64_t id = unit_clauses_idx[uidx];
assert (id);
return id;
}
inline int64_t &unit_clauses (int uidx) {
assert (lrat || frat);
assert (uidx > 0);
assert ((size_t) uidx < unit_clauses_idx.size ());
return unit_clauses_idx[uidx];
}
Var &var (int lit) { return vtab[vidx (lit)]; }
Link &link (int lit) { return links[vidx (lit)]; }
Flags &flags (int lit) { return ftab[vidx (lit)]; }
int64_t &bumped (int lit) { return btab[vidx (lit)]; }
int &propfixed (int lit) { return ptab[vlit (lit)]; }
double &score (int lit) { return stab[vidx (lit)]; }
const Flags &flags (int lit) const { return ftab[vidx (lit)]; }
bool occurring () const { return !otab.empty (); }
bool watching () const { return !wtab.empty (); }
Bins &bins (int lit) { return big[vlit (lit)]; }
Occs &occs (int lit) { return otab[vlit (lit)]; }
int64_t &noccs (int lit) { return ntab[vlit (lit)]; }
Watches &watches (int lit) { return wtab[vlit (lit)]; }
bool use_scores () const { return opts.score && stable; }
void bump_variable_score (int lit);
void bump_variable_score_inc ();
void rescale_variable_scores ();
signed char marked (int lit) const {
signed char res = marks[vidx (lit)];
if (lit < 0)
res = -res;
return res;
}
void mark (int lit) {
assert (!marked (lit));
marks[vidx (lit)] = sign (lit);
assert (marked (lit) > 0);
assert (marked (-lit) < 0);
}
void unmark (int lit) {
marks[vidx (lit)] = 0;
assert (!marked (lit));
}
signed char marked67 (int lit) const {
signed char res = marks[vidx (lit)] >> 6;
if (lit < 0)
res = -res;
return res;
}
void mark67 (int lit) {
signed char &m = marks[vidx (lit)];
const signed char mask = 0x3f;
#ifndef NDEBUG
const signed char bits = m & mask;
#endif
m = (m & mask) | (sign (lit) << 6);
assert (marked (lit) > 0);
assert (marked (-lit) < 0);
assert ((m & mask) == bits);
assert (marked67 (lit) > 0);
assert (marked67 (-lit) < 0);
}
void unmark67 (int lit) {
signed char &m = marks[vidx (lit)];
const signed char mask = 0x3f;
#ifndef NDEBUG
const signed bits = m & mask;
#endif
m &= mask;
assert ((m & mask) == bits);
}
void unmark (vector<int> &lits) {
for (const auto &lit : lits)
unmark (lit);
}
bool getbit (int lit, int bit) const {
assert (0 <= bit), assert (bit < 6);
return marks[vidx (lit)] & (1 << bit);
}
void setbit (int lit, int bit) {
assert (0 <= bit), assert (bit < 6);
assert (!getbit (lit, bit));
marks[vidx (lit)] |= (1 << bit);
assert (getbit (lit, bit));
}
void unsetbit (int lit, int bit) {
assert (0 <= bit), assert (bit < 6);
assert (getbit (lit, bit));
marks[vidx (lit)] &= ~(1 << bit);
assert (!getbit (lit, bit));
}
bool marked2 (int lit) const {
unsigned res = marks[vidx (lit)];
assert (res <= 3);
unsigned bit = bign (lit);
return (res & bit) != 0;
}
void mark2 (int lit) {
marks[vidx (lit)] |= bign (lit);
assert (marked2 (lit));
}
bool getfact (int lit, int fact) const {
assert (fact == 1 || fact == 2 || fact == 4);
int res = marks[vidx (lit)];
if (lit < 0) {
res >>= 3;
} else {
res &= 7;
}
return res & fact;
}
void markfact (int lit, int fact) {
assert (fact == 1 || fact == 2 || fact == 4);
assert (!getfact (lit, fact));
#ifndef NDEBUG
int before = getfact (-lit, fact);
#endif
int res = marks[vidx (lit)];
if (lit < 0) {
res |= fact << 3;
} else {
res |= fact;
}
marks[vidx (lit)] = res;
assert (getfact (lit, fact));
#ifndef NDEBUG
assert (getfact (-lit, fact) == before);
#endif
}
void unmarkfact (int lit, int fact) {
assert (fact == 1 || fact == 2 || fact == 4);
assert (getfact (lit, fact));
int res = marks[vidx (lit)];
if (lit < 0) {
res &= ~(fact << 3);
} else {
res &= ~fact;
}
marks[vidx (lit)] = res;
assert (!getfact (lit, fact));
}
void mark_clause (); void mark (Clause *);
void mark2 (Clause *);
void unmark_clause (); void unmark (Clause *);
inline void watch_literal (int lit, int blit, Clause *c) {
assert (lit != blit);
Watches &ws = watches (lit);
ws.push_back (Watch (blit, c));
assert (c->literals[0] == lit || c->literals[1] == lit);
LOG (c, "watch %d blit %d in", lit, blit);
}
inline void watch_binary_literal (int lit, int blit, Clause *c) {
assert (lit != blit);
Watches &ws = watches (lit);
ws.push_back (Watch (true, blit, c));
LOG (c, "watch binary %d blit %d in", lit, blit);
}
inline void watch_clause (Clause *c) {
const int l0 = c->literals[0];
const int l1 = c->literals[1];
watch_literal (l0, l1, c);
watch_literal (l1, l0, c);
}
inline void unwatch_clause (Clause *c) {
const int l0 = c->literals[0];
const int l1 = c->literals[1];
remove_watch (watches (l0), c);
remove_watch (watches (l1), c);
}
inline void update_queue_unassigned (int idx) {
assert (0 < idx);
assert (idx <= max_var);
queue.unassigned = idx;
queue.bumped = btab[idx];
LOG ("queue unassigned now %d bumped %" PRId64 "", idx, btab[idx]);
}
void bump_queue (int idx);
void mark_eliminated (int);
void mark_substituted (int);
void mark_active (int);
void mark_fixed (int);
void mark_pure (int);
Clause *new_clause (bool red, int glue = 0);
void promote_clause (Clause *, int new_glue);
void promote_clause_glue_only (Clause *, int new_glue);
size_t shrink_clause (Clause *, int new_size);
void minimize_sort_clause ();
void shrink_and_minimize_clause ();
void reset_shrinkable ();
void mark_shrinkable_as_removable (int, std::vector<int>::size_type);
int shrink_literal (int, int, unsigned);
unsigned shrunken_block_uip (int, int,
std::vector<int>::reverse_iterator &,
std::vector<int>::reverse_iterator &,
std::vector<int>::size_type, const int);
void shrunken_block_no_uip (const std::vector<int>::reverse_iterator &,
const std::vector<int>::reverse_iterator &,
unsigned &, const int);
void push_literals_of_block (const std::vector<int>::reverse_iterator &,
const std::vector<int>::reverse_iterator &,
int, unsigned);
unsigned shrink_next (int, unsigned &, unsigned &);
std::vector<int>::reverse_iterator
minimize_and_shrink_block (std::vector<int>::reverse_iterator &,
unsigned int &, unsigned int &, const int);
unsigned shrink_block (std::vector<int>::reverse_iterator &,
std::vector<int>::reverse_iterator &, int,
unsigned &, unsigned &, const int, unsigned);
unsigned shrink_along_reason (int, int, bool, bool &, unsigned);
void deallocate_clause (Clause *);
void delete_clause (Clause *);
void mark_garbage (Clause *);
void assign_original_unit (int64_t, int);
void add_new_original_clause (int64_t);
Clause *new_learned_redundant_clause (int glue);
Clause *new_hyper_binary_resolved_clause (bool red, int glue);
Clause *new_clause_as (const Clause *orig);
Clause *new_resolved_irredundant_clause ();
int assignment_level (int lit, Clause *);
void build_chain_for_units (int lit, Clause *reason, bool forced);
void build_chain_for_empty ();
void search_assign (int lit, Clause *);
void search_assign_driving (int lit, Clause *reason);
void search_assign_external (int lit);
void search_assume_decision (int decision);
static Clause *decision_reason;
void assign_unit (int lit);
int64_t cache_lines (size_t bytes) { return (bytes + 127) / 128; }
int64_t cache_lines (size_t n, size_t bytes) {
return cache_lines (n * bytes);
}
bool propagate ();
#ifdef PROFILE_MODE
bool propagate_wrapper ();
bool propagate_unstable ();
bool propagate_stable ();
void analyze_wrapper ();
void analyze_unstable ();
void analyze_stable ();
int decide_wrapper ();
int decide_stable ();
int decide_unstable ();
#else
#define propagate_wrapper propagate
#define analyze_wrapper analyze
#define decide_wrapper decide
#endif
void propergate ();
void unassign (int lit);
void update_target_and_best ();
void backtrack (int target_level = 0);
void backtrack_without_updating_phases (int target_level = 0);
bool minimize_literal (int lit, int depth = 0);
void minimize_clause ();
void calculate_minimize_chain (int lit, std::vector<int> &stack);
void learn_empty_clause ();
void learn_unit_clause (int lit);
void bump_variable (int lit);
void bump_variables ();
int recompute_glue (Clause *);
void bump_clause (Clause *);
void bump_clause2 (Clause *);
void clear_unit_analyzed_literals ();
void clear_analyzed_literals ();
void clear_analyzed_levels ();
void clear_minimized_literals ();
bool bump_also_reason_literal (int lit);
void bump_also_reason_literals (int lit, int depth_limit,
size_t size_limit);
void bump_also_all_reason_literals ();
void analyze_literal (int lit, int &open, int &resolvent_size,
int &antecedent_size);
void analyze_reason (int lit, Clause *, int &open, int &resolvent_size,
int &antecedent_size);
Clause *new_driving_clause (const int glue, int &jump);
int find_conflict_level (int &forced);
int determine_actual_backtrack_level (int jump);
void otfs_strengthen_clause (Clause *, int, int,
const std::vector<int> &);
void otfs_subsume_clause (Clause *subsuming, Clause *subsumed);
int otfs_find_backtrack_level (int &forced);
Clause *on_the_fly_strengthen (Clause *conflict, int lit);
void update_decision_rate_average ();
void lazy_external_propagator_out_of_order_clause (int &);
void analyze ();
void iterate ();
bool external_propagate ();
bool external_check_solution ();
void add_external_clause (int propagated_lit = 0,
bool no_backtrack = false);
Clause *learn_external_reason_clause (int lit, int falsified_elit = 0,
bool no_backtrack = false);
Clause *wrapped_learn_external_reason_clause (int lit);
void explain_external_propagations ();
void explain_reason (int lit, Clause *, int &open);
void move_literals_to_watch ();
void handle_external_clause (Clause *);
void notify_assignments ();
void notify_decision ();
void notify_backtrack (size_t new_level);
void force_backtrack (int new_level);
int ask_decision ();
bool ask_external_clause ();
void add_observed_var (int ilit);
void remove_observed_var (int ilit);
bool observed (int ilit) const;
bool is_decision (int ilit);
void check_watched_literal_invariants ();
void set_changed_val ();
void renotify_trail_after_ilb ();
void renotify_trail_after_local_search ();
void renotify_full_trail ();
void renotify_full_trail_between_trail_pos (int start_level,
int end_level,
int propagator_level,
std::vector<int> &assigned,
bool start_new_level);
void connect_propagator ();
void mark_garbage_external_forgettable (int64_t id);
bool is_external_forgettable (int64_t id);
#ifndef NDEBUG
bool get_merged_literals (std::vector<int> &);
void get_all_fixed_literals (std::vector<int> &);
#endif
void recompute_tier ();
void decay_clauses_upon_incremental_clauses ();
void print_tier_usage_statistics ();
void eagerly_subsume_recently_learned_clauses (Clause *);
bool stabilizing ();
bool restarting ();
int reuse_trail ();
void restart ();
void clear_phases (vector<signed char> &); void copy_phases (vector<signed char> &); void save_assigned_phases (
vector<signed char> &);
bool rephasing ();
char rephase_best ();
char rephase_flipping ();
char rephase_inverted ();
char rephase_original ();
char rephase_random ();
char rephase_walk ();
void shuffle_scores ();
void shuffle_queue ();
void rephase ();
int unlucky (int res);
int lucky_decide_assumptions ();
bool lucky_propagate_discrepency (int);
int trivially_false_satisfiable ();
int trivially_true_satisfiable ();
int forward_false_satisfiable ();
int forward_true_satisfiable ();
int backward_false_satisfiable ();
int backward_true_satisfiable ();
int positive_horn_satisfiable ();
int negative_horn_satisfiable ();
bool terminated_asynchronously (int factor = 1);
bool search_limits_hit ();
void terminate () {
LOG ("forcing asynchronous termination");
termination_forced = true;
}
bool flushing ();
bool reducing ();
void protect_reasons ();
void mark_clauses_to_be_flushed ();
void mark_useless_redundant_clauses_as_garbage ();
bool propagate_out_of_order_units ();
void unprotect_reasons ();
void reduce ();
int clause_contains_fixed_literal (Clause *);
void remove_falsified_literals (Clause *);
void mark_satisfied_clauses_as_garbage ();
void copy_clause (Clause *);
void flush_watches (int lit, Watches &);
size_t flush_occs (int lit);
void flush_all_occs_and_watches ();
void update_reason_references ();
void copy_non_garbage_clauses ();
void delete_garbage_clauses ();
void check_clause_stats ();
void check_var_stats ();
bool arenaing ();
void garbage_collection ();
void remove_garbage_binaries ();
void init_occs ();
void init_bins ();
void init_noccs ();
void clear_noccs ();
void clear_occs ();
void reset_occs ();
void reset_bins ();
void reset_noccs ();
void init_watches ();
void connect_watches (bool irredundant_only = false);
void connect_binary_watches ();
void sort_watches ();
void clear_watches ();
void reset_watches ();
void strengthen_clause (Clause *, int);
void subsume_clause (Clause *subsuming, Clause *subsumed);
int subsume_check (Clause *subsuming, Clause *subsumed);
int try_to_subsume_clause (Clause *, vector<Clause *> &shrunken);
void reset_subsume_bits ();
bool subsume_round ();
void subsume ();
void covered_literal_addition (int lit, Coveror &);
void asymmetric_literal_addition (int lit, Coveror &);
void cover_push_extension (int lit, Coveror &);
bool cover_propagate_asymmetric (int lit, Clause *ignore, Coveror &);
bool cover_propagate_covered (int lit, Coveror &);
bool cover_clause (Clause *c, Coveror &);
int64_t cover_round ();
bool cover ();
void demote_clause (Clause *);
void flush_vivification_schedule (std::vector<Clause *> &, int64_t &);
void vivify_increment_stats (const Vivifier &vivifier);
void vivify_subsume_clause (Clause *subsuming, Clause *subsumed);
void compute_tier_limits (Vivifier &);
void vivify_initialize (Vivifier &vivifier, int64_t &ticks);
inline void vivify_prioritize_leftovers (char, size_t prioritized,
std::vector<Clause *> &schedule);
bool consider_to_vivify_clause (Clause *candidate);
void vivify_sort_watched (Clause *c);
bool vivify_instantiate (
const std::vector<int> &, Clause *,
std::vector<std::tuple<int, Clause *, bool>> &lrat_stack,
int64_t &ticks);
void vivify_analyze_redundant (Vivifier &, Clause *start, bool &);
void vivify_build_lrat (int, Clause *,
std::vector<std::tuple<int, Clause *, bool>> &);
void vivify_chain_for_units (int lit, Clause *reason);
void vivify_strengthen (Clause *candidate, int64_t &);
void vivify_assign (int lit, Clause *);
void vivify_assume (int lit);
bool vivify_propagate (int64_t &);
void vivify_deduce (Clause *candidate, Clause *conflct, int implied,
Clause **, bool &);
bool vivify_clause (Vivifier &, Clause *candidate);
void vivify_analyze (Clause *start, bool &, Clause **,
const Clause *const, int implied, bool &);
bool vivify_shrinkable (const std::vector<int> &sorted, Clause *c);
void vivify_round (Vivifier &, int64_t delta);
bool vivify ();
void deduplicate_all_clauses ();
bool compacting ();
void compact ();
void transred ();
void backbone_decision (int lit);
bool backbone_propagate (int64_t &);
void backbone_propagate2 (int64_t &);
unsigned compute_backbone ();
void backbone_unit_reassign (
int lit); void backbone_unit_assign (
int lit); void backbone_assign_any (int lit, Clause *reason);
void backbone_assign (int lit, Clause *reason);
void backbone_lrat_for_units (int lit, Clause *c);
unsigned compute_backbone_round (std::vector<int> &candidates,
std::vector<int> &units,
const int64_t ticks_limit,
int64_t &ticks, unsigned inconsistent);
void schedule_backbone_cands (std::vector<int> &candidates);
void keep_backbone_candidates (const std::vector<int> &candidates);
int backbone_analyze (Clause *, int64_t &);
void binary_clauses_backbone ();
bool likely_to_be_kept_clause (Clause *c) {
if (!c->redundant)
return true;
if (c->glue <= tier2[false])
return true;
if (c->glue > lim.keptglue)
return false;
if (c->size > lim.keptsize)
return false;
return true;
}
void mark_subsume (int lit) {
Flags &f = flags (lit);
if (f.subsume)
return;
LOG ("marking %d as subsuming literal candidate", abs (lit));
stats.mark.subsume++;
f.subsume = true;
}
void mark_ternary (int lit) {
Flags &f = flags (lit);
if (f.ternary)
return;
LOG ("marking %d as ternary resolution literal candidate", abs (lit));
stats.mark.ternary++;
f.ternary = true;
}
void mark_factor (int lit) {
Flags &f = flags (lit);
const unsigned bit = bign (lit);
if (f.factor & bit)
return;
LOG ("marking %d as factor literal candidate", lit);
stats.mark.factor++;
f.factor |= bit;
}
void mark_added (int lit, int size, bool redundant);
void mark_added (Clause *);
bool marked_subsume (int lit) const { return flags (lit).subsume; }
void mark_elim (int lit) {
Flags &f = flags (lit);
if (f.elim)
return;
LOG ("marking %d as elimination literal candidate", lit);
stats.mark.elim++;
f.elim = true;
}
void mark_block (int lit) {
Flags &f = flags (lit);
const unsigned bit = bign (lit);
if (f.block & bit)
return;
LOG ("marking %d as blocking literal candidate", lit);
stats.mark.block++;
f.block |= bit;
}
void mark_removed (int lit) {
mark_elim (lit);
mark_block (-lit);
}
void mark_removed (Clause *, int except = 0);
bool marked_block (int lit) const {
const Flags &f = flags (lit);
const unsigned bit = bign (lit);
return (f.block & bit) != 0;
}
void unmark_block (int lit) {
Flags &f = flags (lit);
const unsigned bit = bign (lit);
f.block &= ~bit;
}
void mark_skip (int lit) {
Flags &f = flags (lit);
const unsigned bit = bign (lit);
if (f.skip & bit)
return;
LOG ("marking %d to be skipped as blocking literal", lit);
f.skip |= bit;
}
bool marked_skip (int lit) {
const Flags &f = flags (lit);
const unsigned bit = bign (lit);
return (f.skip & bit) != 0;
}
void mark_decomposed (int lit) {
Flags &f = flags (lit);
const unsigned bit = bign (lit);
assert ((f.marked_signed & bit) == 0);
sign_marked.push_back (lit);
f.marked_signed |= bit;
}
void unmark_decomposed (int lit) {
Flags &f = flags (lit);
const unsigned bit = bign (lit);
f.marked_signed &= ~bit;
}
bool marked_decomposed (int lit) {
const Flags &f = flags (lit);
const unsigned bit = bign (lit);
return (f.marked_signed & bit) != 0;
}
void clear_sign_marked_literals ();
bool is_blocked_clause (Clause *c, int pivot);
void block_schedule (Blocker &);
size_t block_candidates (Blocker &, int lit);
Clause *block_impossible (Blocker &, int lit);
void block_literal_with_at_least_two_negative_occs (Blocker &, int lit);
void block_literal_with_one_negative_occ (Blocker &, int lit);
void block_pure_literal (Blocker &, int lit);
void block_reschedule_clause (Blocker &, int lit, Clause *);
void block_reschedule (Blocker &, int lit);
void block_literal (Blocker &, int lit);
bool block ();
int second_literal_in_binary_clause_lrat (Clause *, int first);
int second_literal_in_binary_clause (Eliminator &, Clause *, int first);
void mark_binary_literals (Eliminator &, int pivot);
void find_and_gate (Eliminator &, int pivot);
void find_equivalence (Eliminator &, int pivot);
bool get_ternary_clause (Clause *, int &, int &, int &);
bool match_ternary_clause (Clause *, int, int, int);
Clause *find_ternary_clause (int, int, int);
bool get_clause (Clause *, vector<int> &);
bool is_clause (Clause *, const vector<int> &);
Clause *find_clause (const vector<int> &);
void find_xor_gate (Eliminator &, int pivot);
void find_if_then_else (Eliminator &, int pivot);
Clause *find_binary_clause (int, int);
void find_gate_clauses (Eliminator &, int pivot);
void unmark_gate_clauses (Eliminator &);
void find_definition (Eliminator &, int);
void init_citten ();
void reset_citten ();
void citten_clear_track_log_terminate ();
bool ineliminating ();
double compute_elim_score (unsigned lit);
void mark_redundant_clauses_with_eliminated_variables_as_garbage ();
void unmark_binary_literals (Eliminator &);
bool resolve_clauses (Eliminator &, Clause *, int pivot, Clause *, bool);
void mark_eliminated_clauses_as_garbage (Eliminator &, int pivot, bool &);
bool elim_resolvents_are_bounded (Eliminator &, int pivot);
void elim_update_removed_lit (Eliminator &, int lit);
void elim_update_removed_clause (Eliminator &, Clause *, int except = 0);
void elim_update_added_clause (Eliminator &, Clause *);
void elim_add_resolvents (Eliminator &, int pivot);
void elim_backward_clause (Eliminator &, Clause *);
void elim_backward_clauses (Eliminator &);
void elim_propagate (Eliminator &, int unit);
void elim_on_the_fly_self_subsumption (Eliminator &, Clause *, int);
void try_to_eliminate_variable (Eliminator &, int pivot, bool &);
void increase_elimination_bound ();
int elim_round (bool &completed, bool &);
void elim (bool update_limits = true);
int64_t flush_elimfast_occs (int lit);
void elimfast_add_resolvents (Eliminator &, int pivot);
bool elimfast_resolvents_are_bounded (Eliminator &, int pivot);
void try_to_fasteliminate_variable (Eliminator &, int pivot, bool &);
int elimfast_round (bool &completed, bool &);
void elimfast ();
int sweep_solve ();
void sweep_set_kitten_ticks_limit (Sweeper &sweeper);
bool kitten_ticks_limit_hit (Sweeper &sweeper, const char *when);
void init_sweeper (Sweeper &sweeper);
void release_sweeper (Sweeper &sweeper);
void clear_sweeper (Sweeper &sweeper);
int sweep_repr (Sweeper &sweeper, int lit);
void add_literal_to_environment (Sweeper &sweeper, unsigned depth, int);
void sweep_clause (Sweeper &sweeper, unsigned depth, Clause *);
void sweep_add_clause (Sweeper &sweeper, unsigned depth);
void add_core (Sweeper &sweeper, unsigned core_idx);
void save_core (Sweeper &sweeper, unsigned core);
void clear_core (Sweeper &sweeper, unsigned core_idx);
void save_add_clear_core (Sweeper &sweeper);
void init_backbone_and_partition (Sweeper &sweeper);
void sweep_empty_clause (Sweeper &sweeper);
void sweep_refine_partition (Sweeper &sweeper);
void sweep_refine_backbone (Sweeper &sweeper);
void sweep_refine (Sweeper &sweeper);
void flip_backbone_literals (struct Sweeper &sweeper);
bool sweep_backbone_candidate (Sweeper &sweeper, int lit);
int64_t add_sweep_binary (sweep_proof_clause, int lit, int other);
bool scheduled_variable (Sweeper &sweeper, int idx);
void schedule_inner (Sweeper &sweeper, int idx);
void schedule_outer (Sweeper &sweeper, int idx);
int next_scheduled (Sweeper &sweeper);
void substitute_connected_clauses (Sweeper &sweeper, int lit, int other,
int64_t id);
void sweep_remove (Sweeper &sweeper, int lit);
void flip_partition_literals (struct Sweeper &sweeper);
const char *sweep_variable (Sweeper &sweeper, int idx);
bool scheduable_variable (Sweeper &sweeper, int idx, size_t *occ_ptr);
unsigned schedule_all_other_not_scheduled_yet (Sweeper &sweeper);
bool sweep_equivalence_candidates (Sweeper &sweeper, int lit, int other);
unsigned reschedule_previously_remaining (Sweeper &sweeper);
unsigned incomplete_variables ();
void mark_incomplete (Sweeper &sweeper);
unsigned schedule_sweeping (Sweeper &sweeper);
void unschedule_sweeping (Sweeper &sweeper, unsigned swept,
unsigned scheduled);
bool sweep ();
void sweep_dense_propagate (Sweeper &sweeper);
void sweep_sparse_mode ();
void sweep_dense_mode_and_watch_irredundant ();
void sweep_substitute_lrat (Clause *c, int64_t id);
void sweep_substitute_new_equivalences (Sweeper &sweeper);
void sweep_update_noccs (Clause *c);
void delete_sweep_binary (const sweep_binary &sb);
bool can_sweep_clause (Clause *c);
bool sweep_flip (int);
int sweep_flip_and_implicant (int);
bool sweep_extract_fixed (Sweeper &sweeper, int lit);
void factor_mode ();
void reset_factor_mode ();
double tied_next_factor_score (int);
Quotient *new_quotient (Factoring &, int);
void release_quotients (Factoring &);
size_t first_factor (Factoring &, int);
void clear_nounted (vector<int> &);
void clear_flauses (vector<Clause *> &);
Quotient *best_quotient (Factoring &, size_t *);
int next_factor (Factoring &, unsigned *);
void factorize_next (Factoring &, int, unsigned);
void resize_factoring (Factoring &factoring, int lit);
void flush_unmatched_clauses (Quotient *);
void add_self_subsuming_factor (Quotient *, Quotient *);
bool self_subsuming_factor (Quotient *);
void add_factored_divider (Quotient *, int);
void blocked_clause (Quotient *q, int);
void add_factored_quotient (Quotient *, int not_fresh);
void eagerly_remove_from_occurences (Clause *c);
void delete_unfactored (Quotient *q);
void update_factored (Factoring &factoring, Quotient *q);
bool apply_factoring (Factoring &factoring, Quotient *q);
void update_factor_candidate (Factoring &, int);
void schedule_factorization (Factoring &);
bool run_factorization (int64_t limit);
bool factor ();
int get_new_extension_variable ();
Clause *new_factor_clause (int);
void adjust_scores_and_phases_of_fresh_variables (Factoring &);
void inst_assign (int lit);
bool inst_propagate ();
void collect_instantiation_candidates (Instantiator &);
bool instantiate_candidate (int lit, Clause *);
void instantiate (Instantiator &);
void new_trail_level (int lit);
bool ternary_find_binary_clause (int, int);
bool ternary_find_ternary_clause (int, int, int);
Clause *new_hyper_ternary_resolved_clause (bool red);
Clause *new_hyper_ternary_resolved_clause_and_watch (bool red, bool);
bool hyper_ternary_resolve (Clause *, int, Clause *);
void ternary_lit (int pivot, int64_t &steps, int64_t &htrs);
void ternary_idx (int idx, int64_t &steps, int64_t &htrs);
bool ternary_round (int64_t &steps, int64_t &htrs);
bool ternary ();
bool inprobing ();
void failed_literal (int lit);
void probe_lrat_for_units (int lit);
void probe_assign_unit (int lit);
void probe_assign_decision (int lit);
void probe_assign (int lit, int parent);
void mark_duplicated_binary_clauses_as_garbage ();
int get_parent_reason_literal (int lit);
void set_parent_reason_literal (int lit, int reason);
void clean_probehbr_lrat ();
void init_probehbr_lrat ();
void get_probehbr_lrat (int lit, int uip);
void set_probehbr_lrat (int lit, int uip);
void probe_post_dominator_lrat (vector<Clause *> &, int, int);
void probe_dominator_lrat (int dom, Clause *reason);
int probe_dominator (int a, int b);
int hyper_binary_resolve (Clause *);
void probe_propagate2 ();
bool probe_propagate ();
bool is_binary_clause (Clause *c, int &, int &);
void generate_probes ();
void flush_probes ();
int next_probe ();
bool probe ();
void inprobe (bool update_limits = true);
void walk_save_minimum (Walker &);
ClauseOrBinary walk_pick_clause (Walker &);
unsigned walk_break_value (int lit, int64_t &ticks);
int walk_pick_lit (Walker &walker, ClauseOrBinary);
int walk_pick_lit (Walker &, Clause *);
bool walk_flip_lit (Walker &, int lit);
int walk_pick_lit (Walker &walker, TaggedBinary c);
int walk_round (int64_t limit, bool prev);
void walk ();
int walk_full_occs_round (int64_t limit, bool prev);
void walk_full_occs ();
void walk_full_occs_save_minimum (WalkerFO &);
void make_clauses_along_occurrences (WalkerFO &walker, int lit);
void make_clauses_along_unsatisfied (WalkerFO &walker, int lit);
inline void warmup_assign (int lit, Clause *reason);
void warmup_propagate_beyond_conflict ();
int warmup_decide ();
int warmup ();
void decompose_conflicting_scc_lrat (DFS *dfs, vector<int> &);
void build_lrat_for_clause (const vector<vector<Clause *>> &dfs_chains,
bool invert = false);
vector<Clause *> decompose_analyze_binary_clauses (DFS *dfs, int from);
void decompose_analyze_binary_chain (DFS *dfs, int);
bool decompose_round ();
void decompose ();
void reset_limits ();
bool flip (int lit);
bool flippable (int lit);
void assume_analyze_literal (int lit);
void assume_analyze_reason (int lit, Clause *reason);
void assume (int); bool failed (int lit); void reset_assumptions (); void sort_and_reuse_assumptions (); void failing ();
bool assumed (int lit) { Flags &f = flags (lit);
const unsigned bit = bign (lit);
return (f.assumed & bit) != 0;
}
void constrain (int); bool
failed_constraint (); void reset_constraint ();
int propagate_assumptions ();
void implied (std::vector<int> &entrailed);
void phase (int lit);
void unphase (int lit);
bool is_autarky_literal (int lit) const;
bool is_conditional_literal (int lit) const;
void mark_as_conditional_literal (int lit);
void unmark_as_conditional_literal (int lit);
bool is_in_candidate_clause (int lit) const;
void mark_in_candidate_clause (int lit);
void unmark_in_candidate_clause (int lit);
void condition_assign (int lit);
void condition_unassign (int lit);
bool conditioning ();
long condition_round (long unassigned_literal_propagation_limit);
void condition (bool update_limits = true);
bool satisfied ();
void start_random_sequence ();
int next_random_decision ();
int next_decision_variable_on_queue ();
int next_decision_variable_with_best_score ();
int next_decision_variable ();
int decide_phase (int idx, bool target);
int likely_phase (int idx);
bool better_decision (int lit, int other);
int decide ();
void limit_terminate (int);
void limit_decisions (int); void limit_conflicts (int); void limit_preprocessing (int); void limit_local_search (int); void limit_ticks (int64_t);
static bool is_valid_limit (const char *name);
bool limit (const char *name, int);
void init_report_limits ();
void init_preprocessing_limits ();
void init_search_limits ();
void init_averages ();
void swap_averages ();
int try_to_satisfy_formula_by_saved_phases ();
void produce_failed_assumptions ();
int already_solved ();
int restore_clauses ();
bool preprocess_round (int round);
void preprocess_quickly (bool always);
int preprocess (bool always);
int local_search_round (int round);
int local_search ();
int lucky_phases ();
int cdcl_loop_with_inprocessing ();
void reset_solving ();
int solve (bool preprocess_only = false);
void finalize (int);
int lookahead ();
CubesWithStatus generate_cubes (int, int);
int most_occurring_literal ();
int lookahead_probing ();
int lookahead_next_probe ();
void lookahead_flush_probes ();
void lookahead_generate_probes ();
std::vector<int> lookahead_populate_locc ();
int lookahead_locc (const std::vector<int> &);
bool terminating_asked ();
#ifndef QUIET
void start_profiling (Profile &p, double);
void stop_profiling (Profile &p, double);
double update_profiles (); void print_profile ();
#endif
signed char val (int lit) const {
assert (-max_var <= lit);
assert (lit);
assert (lit <= max_var);
return vals[lit];
}
void set_val (int lit, signed char val) {
assert (-1 <= val);
assert (val <= 1);
assert (-max_var <= lit);
assert (lit);
assert (lit <= max_var);
vals[lit] = val;
vals[-lit] = -val;
}
int fixed (int lit) {
assert (-max_var <= lit);
assert (lit);
assert (lit <= max_var);
const int idx = vidx (lit);
int res = vals[idx];
if (res && vtab[idx].level)
res = 0;
if (lit < 0)
res = -res;
return res;
}
int externalize (int lit) {
assert (lit != INT_MIN);
const int idx = abs (lit);
assert (idx);
assert (idx <= max_var);
int res = i2e[idx];
if (lit < 0)
res = -res;
return res;
}
void freeze (int lit) {
int idx = vidx (lit);
if ((size_t) idx >= frozentab.size ()) {
size_t new_vsize = vsize ? 2 * vsize : 1 + (size_t) max_var;
while (new_vsize <= (size_t) max_var)
new_vsize *= 2;
frozentab.resize (new_vsize);
}
unsigned &ref = frozentab[idx];
if (ref < UINT_MAX) {
ref++;
LOG ("variable %d frozen %u times", idx, ref);
} else
LOG ("variable %d remains frozen forever", idx);
}
void melt (int lit) {
int idx = vidx (lit);
unsigned &ref = frozentab[idx];
if (ref < UINT_MAX) {
if (!--ref) {
if (relevanttab[idx]) {
LOG ("variable %d is observed, can not be completely molten",
idx);
ref++;
} else
LOG ("variable %d completely molten", idx);
} else
LOG ("variable %d melted once but remains frozen %u times", lit,
ref);
} else
LOG ("variable %d remains frozen forever", idx);
}
bool frozen (int lit) {
return (size_t) vidx (lit) < frozentab.size () &&
frozentab[vidx (lit)] > 0;
}
bool extract_gates (bool remove_units_before_run = false);
const char *parse_dimacs (FILE *);
const char *parse_dimacs (const char *);
const char *parse_solution (const char *);
void new_proof_on_demand ();
void force_lrat (); void resize_unit_clauses_idx (); void close_trace (bool stats = false); void flush_trace (bool stats = false); void trace (File *); void check ();
void connect_proof_tracer (Tracer *tracer, bool antecedents,
bool finalize_clauses = false);
void connect_proof_tracer (InternalTracer *tracer, bool antecedents,
bool finalize_clauses = false);
void connect_proof_tracer (StatTracer *tracer, bool antecedents,
bool finalize_clauses = false);
void connect_proof_tracer (FileTracer *tracer, bool antecedents,
bool finalize_clauses = false);
bool disconnect_proof_tracer (Tracer *tracer);
bool disconnect_proof_tracer (StatTracer *tracer);
bool disconnect_proof_tracer (FileTracer *tracer);
void conclude_unsat ();
void reset_concluded ();
void dump (Clause *);
void dump ();
bool traverse_clauses (ClauseIterator &);
bool traverse_constraint (ClauseIterator &);
double solve_time ();
double process_time () const; double real_time () const;
double time () { return opts.realtime ? real_time () : process_time (); }
void report (char type, int verbose_level = 0);
void report_solving (int);
void print_statistics ();
void print_resource_usage ();
#ifndef QUIET
void print_prefix ();
void vmessage (const char *, va_list &);
void message (const char *, ...) CADICAL_ATTRIBUTE_FORMAT (2, 3);
void message ();
void vverbose (int level, const char *fmt, va_list &);
void verbose (int level, const char *fmt, ...)
CADICAL_ATTRIBUTE_FORMAT (3, 4);
void verbose (int level);
void section (const char *title);
void phase (const char *phase, const char *, ...)
CADICAL_ATTRIBUTE_FORMAT (3, 4);
void phase (const char *phase, int64_t count, const char *, ...)
CADICAL_ATTRIBUTE_FORMAT (4, 5);
#endif
void error_message_end ();
void verror (const char *, va_list &);
void error (const char *, ...) CADICAL_ATTRIBUTE_FORMAT (2, 3);
void error_message_start ();
void warning (const char *, ...) CADICAL_ATTRIBUTE_FORMAT (2, 3);
};
void fatal_message_start ();
void fatal_message_end ();
void fatal (const char *, ...) CADICAL_ATTRIBUTE_FORMAT (1, 2);
inline bool score_smaller::operator() (unsigned a, unsigned b) {
assert (1 <= a);
assert (a <= (unsigned) internal->max_var);
assert (1 <= b);
assert (b <= (unsigned) internal->max_var);
double s = internal->stab[a];
double t = internal->stab[b];
if (s < t)
return true;
if (s > t)
return false;
return a > b;
}
inline int External::fixed (int elit) const {
assert (elit);
assert (elit != INT_MIN);
int eidx = abs (elit);
if (eidx > max_var)
return 0;
int ilit = e2i[eidx];
if (!ilit)
return 0;
if (elit < 0)
ilit = -ilit;
return internal->fixed (ilit);
}
inline bool Internal::terminated_asynchronously (int factor) {
if (termination_forced) {
LOG ("termination asynchronously forced");
return true;
}
if (lim.terminate.forced) {
assert (lim.terminate.forced > 0);
if (lim.terminate.forced-- == 1) {
LOG ("internally forcing termination");
termination_forced = true;
return true;
}
LOG ("decremented internal forced termination limit to %d",
lim.terminate.forced);
}
if (external->terminator && !lim.terminate.check--) {
assert (factor > 0);
assert (INT_MAX / factor > opts.terminateint);
lim.terminate.check = factor * opts.terminateint;
if (external->terminator->terminate ()) {
termination_forced = true; LOG ("connected terminator forces termination");
return true;
}
}
return false;
}
inline bool Internal::search_limits_hit () {
assert (!preprocessing);
assert (!localsearching);
if (lim.conflicts >= 0 && stats.conflicts >= lim.conflicts) {
LOG ("conflict limit %" PRId64 " reached", lim.conflicts);
return true;
}
if (lim.decisions >= 0 && stats.decisions >= lim.decisions) {
LOG ("decision limit %" PRId64 " reached", lim.decisions);
return true;
}
if (lim.ticks >= 0 &&
stats.ticks.search[0] + stats.ticks.search[1] >= lim.ticks) {
LOG ("ticks limit %" PRId64 " reached", lim.ticks);
return true;
}
return false;
}
}
#endif