ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
CaDiCaL::Internal Struct Reference

#include <internal.hpp>

Collaboration diagram for CaDiCaL::Internal:

Public Types

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)
}
 

Public Member Functions

bool in_mode (Mode m) const
 
void set_mode (Mode m)
 
void reset_mode (Mode m)
 
void require_mode (Mode m) const
 
 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)
 
int active () const
 
void reactivate (int lit)
 
int64_t redundant () const
 
int64_t irredundant () const
 
double clause_variable_ratio () const
 
double scale (double v) const
 
int vidx (int lit) const
 
unsigned vlit (int lit) const
 
int u2i (unsigned u)
 
int citten2lit (unsigned ulit)
 
unsigned lit2citten (int lit)
 
int64_t unit_id (int lit) const
 
int64_t & unit_clauses (int uidx)
 
Varvar (int lit)
 
Linklink (int lit)
 
Flagsflags (int lit)
 
int64_t & bumped (int lit)
 
int & propfixed (int lit)
 
double & score (int lit)
 
const Flagsflags (int lit) const
 
bool occurring () const
 
bool watching () const
 
Binsbins (int lit)
 
Occsoccs (int lit)
 
int64_t & noccs (int lit)
 
Watcheswatches (int lit)
 
bool use_scores () const
 
void bump_variable_score (int lit)
 
void bump_variable_score_inc ()
 
void rescale_variable_scores ()
 
signed char marked (int lit) const
 
void mark (int lit)
 
void unmark (int lit)
 
signed char marked67 (int lit) const
 
void mark67 (int lit)
 
void unmark67 (int lit)
 
void unmark (vector< int > &lits)
 
bool getbit (int lit, int bit) const
 
void setbit (int lit, int bit)
 
void unsetbit (int lit, int bit)
 
bool marked2 (int lit) const
 
void mark2 (int lit)
 
bool getfact (int lit, int fact) const
 
void markfact (int lit, int fact)
 
void unmarkfact (int lit, int fact)
 
void mark_clause ()
 
void mark (Clause *)
 
void mark2 (Clause *)
 
void unmark_clause ()
 
void unmark (Clause *)
 
void watch_literal (int lit, int blit, Clause *c)
 
void watch_clause (Clause *c)
 
void unwatch_clause (Clause *c)
 
void update_queue_unassigned (int 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)
 
Clausenew_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)
 
Clausenew_learned_redundant_clause (int glue)
 
Clausenew_hyper_binary_resolved_clause (bool red, int glue)
 
Clausenew_clause_as (const Clause *orig)
 
Clausenew_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)
 
void assign_unit (int lit)
 
int64_t cache_lines (size_t bytes)
 
int64_t cache_lines (size_t n, size_t bytes)
 
bool propagate ()
 
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)
 
Clausenew_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)
 
Clauseon_the_fly_strengthen (Clause *conflict, int lit)
 
void update_decision_rate_average ()
 
void analyze ()
 
void iterate ()
 
bool external_propagate ()
 
bool external_check_solution ()
 
void add_external_clause (int propagated_lit=0, bool no_backtrack=false)
 
Clauselearn_external_reason_clause (int lit, int falsified_elit=0, bool no_backtrack=false)
 
Clausewrapped_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 (size_t 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_tainted_literal ()
 
void renotify_trail_after_ilb ()
 
void renotify_trail_after_local_search ()
 
void renotify_full_trail ()
 
void connect_propagator ()
 
void mark_garbage_external_forgettable (int64_t id)
 
bool is_external_forgettable (int64_t id)
 
void recompute_tier ()
 
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 > &)
 
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)
 
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 ()
 
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)
 
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)
 
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 ()
 
bool compacting ()
 
void compact ()
 
void transred ()
 
bool likely_to_be_kept_clause (Clause *c)
 
void mark_subsume (int lit)
 
void mark_ternary (int lit)
 
void mark_factor (int lit)
 
void mark_added (int lit, int size, bool redundant)
 
void mark_added (Clause *)
 
bool marked_subsume (int lit) const
 
void mark_elim (int lit)
 
void mark_block (int lit)
 
void mark_removed (int lit)
 
void mark_removed (Clause *, int except=0)
 
bool marked_block (int lit) const
 
void unmark_block (int lit)
 
void mark_skip (int lit)
 
bool marked_skip (int lit)
 
void mark_decomposed (int lit)
 
void unmark_decomposed (int lit)
 
bool marked_decomposed (int lit)
 
void clear_sign_marked_literals ()
 
bool is_blocked_clause (Clause *c, int pivot)
 
void block_schedule (Blocker &)
 
size_t block_candidates (Blocker &, int lit)
 
Clauseblock_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)
 
Clausefind_ternary_clause (int, int, int)
 
bool get_clause (Clause *, vector< int > &)
 
bool is_clause (Clause *, const vector< int > &)
 
Clausefind_clause (const vector< int > &)
 
void find_xor_gate (Eliminator &, int pivot)
 
void find_if_then_else (Eliminator &, int pivot)
 
Clausefind_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_cadical_kitten_ticks_limit (Sweeper &sweeper)
 
bool cadical_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)
 
Quotientnew_quotient (Factoring &, int)
 
void release_quotients (Factoring &)
 
size_t first_factor (Factoring &, int)
 
void clear_nounted (vector< int > &)
 
void clear_flauses (vector< Clause * > &)
 
Quotientbest_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 ()
 
Clausenew_factor_clause ()
 
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)
 
Clausenew_hyper_ternary_resolved_clause (bool red)
 
Clausenew_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 &)
 
Clausewalk_pick_clause (Walker &)
 
unsigned walk_break_value (int lit)
 
int walk_pick_lit (Walker &, Clause *)
 
void walk_flip_lit (Walker &, int lit)
 
int walk_round (int64_t limit, bool prev)
 
void walk ()
 
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)
 
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 ()
 
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)
 
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 ()
 
int preprocess ()
 
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 ()
 
signed char val (int lit) const
 
void set_val (int lit, signed char val)
 
int fixed (int lit)
 
int externalize (int lit)
 
void freeze (int lit)
 
void melt (int lit)
 
bool frozen (int lit)
 
bool extract_gates ()
 
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 ()
 
void report (char type, int verbose_level=0)
 
void report_solving (int)
 
void print_statistics ()
 
void print_resource_usage ()
 
void error_message_end ()
 
void verror (const char *, va_list &)
 
void error (const char *,...) CADICAL_ATTRIBUTE_FORMAT(2
 
void void error_message_start ()
 
void warning (const char *,...) CADICAL_ATTRIBUTE_FORMAT(2
 

Static Public Member Functions

static bool is_valid_limit (const char *name)
 

Public Attributes

int mode
 
int tier1 [2]
 
int tier2 [2]
 
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< Varvtab
 
vector< int > parents
 
vector< Flagsftab
 
vector< int64_t > btab
 
vector< int64_t > gtab
 
vector< Occsotab
 
vector< Occsrtab
 
vector< int > ptab
 
vector< int64_t > ntab
 
vector< Binsbig
 
vector< Watcheswtab
 
Clauseconflict
 
Clauseignore
 
Clausedummy_binary
 
Clauseexternal_reason
 
Clausenewest_clause
 
bool force_no_backtrack
 
bool from_propagator
 
bool ext_clause_forgettable
 
int tainted_literal
 
size_t notified
 
Clauseprobe_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
 
vector< int > sweep_schedule
 
bool sweep_incomplete
 
cadical_kittencitten
 
size_t num_assigned
 
vector< int > probes
 
vector< Levelcontrol
 
vector< Clause * > clauses
 
Averages averages
 
Delay delay [2]
 
Delay congruence_delay
 
Limit lim
 
Last last
 
Inc inc
 
Delay delaying_vivify_irredundant
 
Delay delaying_sweep
 
Proofproof
 
vector< Tracer * > tracers
 
vector< FileTracer * > file_tracers
 
vector< StatTracer * > stat_tracers
 
Options opts
 
Stats stats
 
Arena arena
 
Format error_message
 
string prefix
 
Internalinternal
 
Externalexternal
 
const unsigned max_used = 255
 
volatile bool termination_forced
 
const Range vars
 
const Sange lits
 

Detailed Description

Definition at line 136 of file internal.hpp.

Member Enumeration Documentation

◆ Mode

Enumerator
BLOCK 
CONDITION 
CONGRUENCE 
COVER 
DECOMP 
DEDUP 
ELIM 
FACTOR 
LUCKY 
PROBE 
SEARCH 
SIMPLIFY 
SUBSUME 
SWEEP 
TERNARY 
TRANSRED 
VIVIFY 
WALK 

Definition at line 143 of file internal.hpp.

143 {
144 BLOCK = (1 << 0),
145 CONDITION = (1 << 1),
146 CONGRUENCE = (1 << 2),
147 COVER = (1 << 3),
148 DECOMP = (1 << 4),
149 DEDUP = (1 << 5),
150 ELIM = (1 << 6),
151 FACTOR = (1 << 7),
152 LUCKY = (1 << 8),
153 PROBE = (1 << 9),
154 SEARCH = (1 << 10),
155 SIMPLIFY = (1 << 11),
156 SUBSUME = (1 << 12),
157 SWEEP = (1 << 13),
158 TERNARY = (1 << 14),
159 TRANSRED = (1 << 15),
160 VIVIFY = (1 << 16),
161 WALK = (1 << 17),
162 };

Constructor & Destructor Documentation

◆ Internal()

CaDiCaL::Internal::Internal ( )

Definition at line 12 of file cadical_internal.cpp.

13 : mode (SEARCH), unsat (false), iterating (false),
14 localsearching (false), lookingahead (false), preprocessing (false),
15 protected_reasons (false), force_saved_phase (false),
16 searching_lucky_phases (false), stable (false), reported (false),
17 external_prop (false), did_external_prop (false),
19
20 private_steps (false), rephased (0), vsize (0), max_var (0),
22 saved_decisions (0), concluded (false), lrat (false), frat (false),
23 level (0), vals (0), score_inc (1.0), scores (this), conflict (0),
24 ignore (0), external_reason (&external_reason_clause),
30 marked_failed (true), sweep_incomplete (false), citten (0),
31 num_assigned (0), proof (0), opts (this),
32#ifndef CADICAL_QUIET
33 profiles (this), force_phase_messages (false),
34#endif
35 arena (this), prefix ("c "), internal (this), external (0),
36 termination_forced (false), vars (this->max_var),
37 lits (this->max_var) {
38 control.push_back (Level (0, 0));
39
40 // The 'dummy_binary' is used in 'try_to_subsume_clause' to fake a real
41 // clause, which then can be used to subsume or strengthen the given
42 // clause in one routine for both binary and non binary clauses. This
43 // fake binary clause is always kept non-redundant (and not-moved etc.)
44 // due to the following 'memset'. Only literals will be changed.
45
46 // In a previous version we used local automatic allocated 'Clause' on the
47 // stack, which became incompatible with several compilers (see the
48 // discussion on flexible array member in 'Clause.cpp').
49
50 size_t bytes = Clause::bytes (2);
51 dummy_binary = (Clause *) new char[bytes];
52 memset (dummy_binary, 0, bytes);
53 dummy_binary->size = 2;
54}
size_t bytes() const
Definition clause.hpp:157
External * external
Definition internal.hpp:312
bool ext_clause_forgettable
Definition internal.hpp:249
bool searching_lucky_phases
Definition internal.hpp:189
cadical_kitten * citten
Definition internal.hpp:277
const Sange lits
Definition internal.hpp:325
Clause * dummy_binary
Definition internal.hpp:244
int64_t saved_decisions
Definition internal.hpp:205
size_t no_conflict_until
Definition internal.hpp:258
Clause * newest_clause
Definition internal.hpp:246
signed char * vals
Definition internal.hpp:221
const Range vars
Definition internal.hpp:324
Clause * external_reason
Definition internal.hpp:245
vector< Level > control
Definition internal.hpp:282
Internal * internal
Definition internal.hpp:311
ScoreSchedule scores
Definition internal.hpp:229
Clause * probe_reason
Definition internal.hpp:252
volatile bool termination_forced
Definition internal.hpp:320
char * memset()
Here is the call graph for this function:

◆ ~Internal()

CaDiCaL::Internal::~Internal ( )

Definition at line 56 of file cadical_internal.cpp.

56 {
57 // If a memory exception ocurred a profile might still be active.
58#ifndef CADICAL_QUIET
59#define PROFILE(NAME, LEVEL) \
60 if (PROFILE_ACTIVE (NAME)) \
61 STOP (NAME);
62 PROFILES
63#undef PROFILE
64#endif
65 delete[] (char *) dummy_binary;
66 for (const auto &c : clauses)
67 delete_clause (c);
68 if (proof)
69 delete proof;
70 for (auto &tracer : tracers)
71 delete tracer;
72 for (auto &filetracer : file_tracers)
73 delete filetracer;
74 for (auto &stattracer : stat_tracers)
75 delete stattracer;
76 if (vals) {
77 vals -= vsize;
78 delete[] vals;
79 }
80}
vector< StatTracer * > stat_tracers
Definition internal.hpp:299
vector< Tracer * > tracers
Definition internal.hpp:296
vector< Clause * > clauses
Definition internal.hpp:283
vector< FileTracer * > file_tracers
Definition internal.hpp:298
void delete_clause(Clause *)
Here is the call graph for this function:

Member Function Documentation

◆ active() [1/2]

int CaDiCaL::Internal::active ( ) const
inline

Definition at line 362 of file internal.hpp.

362 {
363 int res = stats.active;
364#ifndef CADICAL_NDEBUG
365 int tmp = max_var;
366 tmp -= stats.unused;
367 tmp -= stats.now.fixed;
368 tmp -= stats.now.eliminated;
369 tmp -= stats.now.substituted;
370 tmp -= stats.now.pure;
371 CADICAL_assert (tmp >= 0);
372 CADICAL_assert (tmp == res);
373#endif
374 return res;
375 }
#define CADICAL_assert(ignore)
Definition global.h:14
Here is the caller graph for this function:

◆ active() [2/2]

bool CaDiCaL::Internal::active ( int lit)
inline

Definition at line 360 of file internal.hpp.

360{ return flags (lit).active (); }
const char * flags()
int lit
Definition satVec.h:130
Here is the call graph for this function:

◆ add_core()

void CaDiCaL::Internal::add_core ( Sweeper & sweeper,
unsigned core_idx )

Definition at line 494 of file cadical_sweep.cpp.

494 {
495 if (unsat)
496 return;
497 LOG ("check and add extracted core[%u] lemmas to proof", core_idx);
498 CADICAL_assert (core_idx == 0 || core_idx == 1);
499 vector<sweep_proof_clause> &core = sweeper.core[core_idx];
500
502
503 unsigned unsat_size = 0;
504 for (auto &pc : core) {
505 unsat_size++;
506
507 if (!pc.learned) {
508 LOG (pc.literals,
509 "not adding already present core[%u] cadical_kitten[%u] clause",
510 core_idx, pc.kit_id);
511 continue;
512 }
513
514 LOG (pc.literals, "adding extracted core[%u] cadical_kitten[%u] lemma",
515 core_idx, pc.kit_id);
516
517 const unsigned new_size = pc.literals.size ();
518
519 if (lrat) {
520 CADICAL_assert (pc.cad_id == INVALID64);
521 for (auto &cid : pc.chain) {
522 int64_t id = 0;
523 for (const auto &cpc : core) {
524 if (cpc.kit_id == cid) {
525 if (cpc.learned)
526 id = cpc.cad_id;
527 else {
528 id = cpc.cad_id;
529 CADICAL_assert (cpc.cad_id == sweeper.clauses[cpc.sweep_id]->id);
530 CADICAL_assert (!sweeper.clauses[cpc.sweep_id]->garbage);
531 // avoid duplicate ids of units with seen flags
532 for (const auto &lit : cpc.literals) {
533 if (val (lit) >= 0)
534 continue;
535 if (flags (lit).seen)
536 continue;
537 const int idx = abs (lit);
538 if (sweeper.prev_units[idx]) {
539 int64_t uid = unit_id (-lit);
540 lrat_chain.push_back (uid);
541 analyzed.push_back (lit);
542 flags (lit).seen = true;
543 }
544 }
545 }
546 break;
547 }
548 }
549 CADICAL_assert (id);
550 if (id != INVALID64)
551 lrat_chain.push_back (id);
552 }
554 }
555
556 if (!new_size) {
557 LOG ("sweeping produced empty clause");
559 core.resize (unsat_size);
560 return;
561 }
562
563 if (new_size == 1) {
564 int unit = pc.literals[0];
565 if (val (unit) > 0) {
566 LOG ("already assigned sweeping unit %d", unit);
567 lrat_chain.clear ();
568 } else if (val (unit) < 0) {
569 LOG ("falsified sweeping unit %d leads to empty clause", unit);
570 if (lrat) {
571 int64_t id = unit_id (-unit);
572 lrat_chain.push_back (id);
573 }
575 core.resize (unsat_size);
576 return;
577 } else {
578 LOG ("sweeping produced unit %d", unit);
579 assign_unit (unit);
580 stats.sweep_units++;
581 sweeper.propagate.push_back (unit);
582 }
583 if (proof && lrat)
584 pc.cad_id = unit_id (unit);
585 continue;
586 }
587
588 CADICAL_assert (new_size > 1);
589 CADICAL_assert (pc.learned);
590
591 if (proof) {
592 pc.cad_id = ++clause_id;
593 proof->add_derived_clause (pc.cad_id, true, pc.literals, lrat_chain);
594 lrat_chain.clear ();
595 }
596 }
597}
#define LOG(...)
#define INVALID64
vector< int > analyzed
Definition internal.hpp:267
vector< int64_t > lrat_chain
Definition internal.hpp:210
Flags & flags(int lit)
Definition internal.hpp:454
signed char val(int lit) const
int64_t unit_id(int lit) const
Definition internal.hpp:434
unsigneds core[2]
Definition sweep.c:33
unsigned clauses
Definition sweep.c:36
struct sweeper sweeper
Definition sweep.c:40
struct vector vector
Definition vector.h:24
Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_external_clause()

void CaDiCaL::Internal::add_external_clause ( int propagated_lit = 0,
bool no_backtrack = false )

Definition at line 478 of file cadical_external_propagate.cpp.

479 {
480 CADICAL_assert (original.empty ());
481 int elit = 0;
482
483 if (propagated_elit) {
484 // Propagation reason clauses are by default assumed to be forgettable
485 // irredundant. In case they would be unforgettably important, the
486 // propagator can add them as an explicit unforgettable external clause
487 // or set 'are_reasons_forgettable' to false.
488 ext_clause_forgettable = external->propagator->are_reasons_forgettable;
489#ifndef CADICAL_NDEBUG
490 LOG ("add external reason of propagated lit: %d", propagated_elit);
491#endif
492 elit = external->propagator->cb_add_reason_clause_lit (propagated_elit);
493 } else
494 elit = external->propagator->cb_add_external_clause_lit ();
495
496 // we need to be build a new LRAT chain if we are already in the middle of
497 // the analysis (like during failed assumptions)
498 LOG (lrat_chain, "lrat chain before");
499 std::vector<int64_t> lrat_chain_ext = std::move (lrat_chain);
500 lrat_chain.clear ();
501 clause.clear ();
502
503 // Read out the external lemma into original and simplify it into clause
504 CADICAL_assert (clause.empty ());
505 CADICAL_assert (original.empty ());
506
509 force_no_backtrack = no_backtrack;
510 from_propagator = true;
511 while (elit) {
512 CADICAL_assert (external->is_observed[abs (elit)]);
513 external->add (elit);
514 if (propagated_elit)
515 elit =
516 external->propagator->cb_add_reason_clause_lit (propagated_elit);
517 else
518 elit = external->propagator->cb_add_external_clause_lit ();
519 }
520 external->add (elit);
521 CADICAL_assert (original.empty ());
522 CADICAL_assert (clause.empty ());
523 force_no_backtrack = false;
524 from_propagator = false;
525 lrat_chain = std::move (lrat_chain_ext);
526 LOG (lrat_chain, "lrat chain after");
527}
vector< int > original
Definition internal.hpp:265
vector< int > clause
Definition internal.hpp:260
Here is the caller graph for this function:

◆ add_factored_divider()

void CaDiCaL::Internal::add_factored_divider ( Quotient * q,
int fresh )

Definition at line 599 of file cadical_factor.cpp.

599 {
600 const int factor = q->factor;
601 LOG ("factored %d divider %d", factor, fresh);
602 clause.push_back (factor);
603 clause.push_back (fresh);
605 clause.clear ();
606 if (lrat)
607 mini_chain.push_back (-clause_id);
608}
Clause * new_factor_clause()
vector< int64_t > mini_chain
Definition internal.hpp:211
Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_factored_quotient()

void CaDiCaL::Internal::add_factored_quotient ( Quotient * q,
int not_fresh )

Definition at line 631 of file cadical_factor.cpp.

631 {
632 LOG ("adding factored quotient[%zu] clauses", q->id);
633 const int factor = q->factor;
634 CADICAL_assert (lrat_chain.empty ());
635 auto qlauses = q->qlauses;
636 for (unsigned idx = 0; idx < qlauses.size (); idx++) {
637 const auto c = qlauses[idx];
638 CADICAL_assert (clause.empty ());
639 for (const auto &other : *c) {
640 if (other == factor) {
641 continue;
642 }
643 clause.push_back (other);
644 }
645 if (lrat) {
647 CADICAL_assert (q->bid);
648 unsigned idxtoo = idx;
649 for (Quotient *p = q; p; p = p->prev) {
650 lrat_chain.push_back (p->qlauses[idxtoo]->id);
651 if (p->prev)
652 idxtoo = p->matches[idx];
653 }
654 lrat_chain.push_back (q->bid);
655 }
656 clause.push_back (not_fresh);
658 clause.clear ();
659 lrat_chain.clear ();
660 }
661 if (proof) {
662 for (Quotient *p = q; p; p = p->prev) {
663 clause.push_back (-p->factor);
664 }
665 clause.push_back (not_fresh);
666 proof->delete_clause (q->bid, true, clause);
667 clause.clear ();
668 }
669}
Cube * p
Definition exorList.c:222
Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_literal_to_environment()

void CaDiCaL::Internal::add_literal_to_environment ( Sweeper & sweeper,
unsigned depth,
int lit )

Definition at line 343 of file cadical_sweep.cpp.

344 {
345 const int repr = sweep_repr (sweeper, lit);
346 if (repr != lit)
347 return;
348 const int idx = abs (lit);
349 if (sweeper.depths[idx])
350 return;
351 CADICAL_assert (depth < UINT_MAX);
352 sweeper.depths[idx] = depth + 1;
353 CADICAL_assert (idx);
354 sweeper.vars.push_back (idx);
355 LOG ("sweeping[%u] adding literal %d", depth, lit);
356}
int sweep_repr(Sweeper &sweeper, int lit)
unsigned * depths
Definition sweep.c:22
unsigneds vars
Definition sweep.c:28
Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_new_original_clause()

void CaDiCaL::Internal::add_new_original_clause ( int64_t id)

Definition at line 385 of file cadical_clause.cpp.

385 {
386
387 if (!from_propagator && level && !opts.ilb) {
388 backtrack ();
389 } else if (tainted_literal) {
391 int new_level = var (tainted_literal).level - 1;
392 CADICAL_assert (new_level >= 0);
393 backtrack (new_level);
394 }
396 LOG (original, "original clause");
397 CADICAL_assert (clause.empty ());
398 bool skip = false;
399 unordered_set<int> learned_levels;
400 size_t unassigned = 0;
401 newest_clause = 0;
402 if (unsat) {
403 LOG ("skipping clause since formula is already inconsistent");
404 skip = true;
405 } else {
406 CADICAL_assert (clause.empty ());
407 for (const auto &lit : original) {
408 int tmp = marked (lit);
409 if (tmp > 0) {
410 LOG ("removing duplicated literal %d", lit);
411 } else if (tmp < 0) {
412 LOG ("tautological since both %d and %d occur", -lit, lit);
413 skip = true;
414 } else {
415 mark (lit);
416 tmp = fixed (lit);
417 if (tmp < 0) {
418 LOG ("removing falsified literal %d", lit);
419 if (lrat) {
420 int elit = externalize (lit);
421 unsigned eidx = (elit > 0) + 2u * (unsigned) abs (elit);
422 if (!external->ext_units[eidx]) {
423 int64_t uid = unit_id (-lit);
424 lrat_chain.push_back (uid);
425 }
426 }
427 } else if (tmp > 0) {
428 LOG ("satisfied since literal %d true", lit);
429 skip = true;
430 } else {
431 clause.push_back (lit);
433 tmp = val (lit);
434 if (tmp)
435 learned_levels.insert (var (lit).level);
436 else
437 unassigned++;
438 }
439 }
440 }
441 for (const auto &lit : original)
442 unmark (lit);
443 }
444 if (skip) {
445 if (from_propagator) {
446 stats.ext_prop.elearn_conf++;
447
448 // In case it was a skipped external forgettable, we need to mark it
449 // immediately as removed
450
451 if (opts.check && is_external_forgettable (id))
453 }
454 if (proof) {
455 proof->delete_external_original_clause (id, false, external->eclause);
456 }
457 } else {
458 int64_t new_id = id;
459 const size_t size = clause.size ();
460 if (original.size () > size) {
461 new_id = ++clause_id;
462 if (proof) {
463 if (lrat)
464 lrat_chain.push_back (id);
465 proof->add_derived_clause (new_id, false, clause, lrat_chain);
466 proof->delete_external_original_clause (id, false,
467 external->eclause);
468 }
469 external->check_learned_clause ();
470
471 if (from_propagator) {
472 // The original form of the added clause is immediately forgotten
473 // TODO: shall we save and check the simplified form? (one with
474 // new_id)
475 if (opts.check && is_external_forgettable (id))
477 }
478 }
479 external->eclause.clear ();
480 lrat_chain.clear ();
481 if (!size) {
482 if (from_propagator)
483 stats.ext_prop.elearn_conf++;
485 if (!original.size ())
486 VERBOSE (1, "found empty original clause");
487 else
488 VERBOSE (1, "found falsified original clause");
489 unsat = true;
490 conflict_id = new_id;
491 marked_failed = true;
492 conclusion.push_back (new_id);
493 } else if (size == 1) {
494 if (force_no_backtrack) {
496 const int idx = vidx (clause[0]);
497 CADICAL_assert (val (clause[0]) >= 0);
498 CADICAL_assert (!flags (idx).eliminated ());
499 Var &v = var (idx);
501 v.level = 0;
502 v.reason = 0;
503 const unsigned uidx = vlit (clause[0]);
504 if (lrat || frat)
505 unit_clauses (uidx) = new_id;
506 mark_fixed (clause[0]);
507 } else {
508 const int lit = clause[0];
509 CADICAL_assert (!val (lit) || var (lit).level);
510 if (val (lit) < 0)
511 backtrack (var (lit).level - 1);
512 CADICAL_assert (val (lit) >= 0);
514 assign_original_unit (new_id, lit);
515 }
516 } else {
518#ifndef CADICAL_NDEBUG
520#endif
521 int glue = (int) (learned_levels.size () + unassigned);
522 CADICAL_assert (glue <= (int) clause.size ());
523 bool clause_redundancy = from_propagator && ext_clause_forgettable;
524 Clause *c = new_clause (clause_redundancy, glue);
525 c->id = new_id;
526 clause_id--;
527 watch_clause (c);
528 clause.clear ();
529 original.clear ();
531 newest_clause = c;
532 }
533 }
534 clause.clear ();
535 lrat_chain.clear ();
536}
int Var
Definition exorList.c:228
#define VERBOSE(...)
Definition message.hpp:58
unsigned long long size
Definition giaNewBdd.h:39
Var & var(int lit)
Definition internal.hpp:452
int vidx(int lit) const
Definition internal.hpp:395
void unmark(int lit)
Definition internal.hpp:490
int fixed(int lit)
int externalize(int lit)
void mark_garbage_external_forgettable(int64_t id)
void watch_clause(Clause *c)
Definition internal.hpp:633
vector< int64_t > conclusion
Definition internal.hpp:207
signed char marked(int lit) const
Definition internal.hpp:478
Clause * new_clause(bool red, int glue=0)
void backtrack(int target_level=0)
unsigned vlit(int lit) const
Definition internal.hpp:408
int64_t & unit_clauses(int uidx)
Definition internal.hpp:443
void assign_original_unit(int64_t, int)
int level
Definition var.hpp:19
signed char mark
Definition value.h:8
Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_observed_var()

void CaDiCaL::Internal::add_observed_var ( int ilit)

Definition at line 14 of file cadical_external_propagate.cpp.

14 {
15 int idx = vidx (ilit);
16 if (idx >= (int64_t) relevanttab.size ())
17 relevanttab.resize (1 + (size_t) idx, 0);
18 unsigned &ref = relevanttab[idx];
19 if (ref < UINT_MAX) {
20 ref++;
21 LOG ("variable %d is observed %u times", idx, ref);
22 } else
23 LOG ("variable %d remains observed forever", idx);
24 // TODO: instead of actually backtracking, it would be enough to notify
25 // backtrack and re-play again every levels' notification to the
26 // propagator
27 if (val (ilit) && level && !fixed (ilit)) {
28 // The variable is already assigned, but we can not send a notification
29 // about it because it happened on an earlier decision level.
30 // To not break the stack-like view of the trail, we simply backtrack to
31 // undo this unnotifiable assignment.
32 const int assignment_level = var (ilit).level;
34 } else if (level && fixed (ilit)) {
35 backtrack (0);
36 }
37}
unsigned short ref
Definition giaNewBdd.h:38
vector< unsigned > relevanttab
Definition internal.hpp:225
int assignment_level(int lit, Clause *)
Here is the call graph for this function:

◆ add_original_lit()

void CaDiCaL::Internal::add_original_lit ( int lit)

Definition at line 184 of file cadical_internal.cpp.

184 {
185 CADICAL_assert (abs (lit) <= max_var);
186 if (lit) {
187 original.push_back (lit);
188 } else {
189 const int64_t id =
191 if (proof) {
192 // Use the external form of the clause for printing in proof
193 // Externalize(internalized literal) != external literal
194 CADICAL_assert (!original.size () || !external->eclause.empty ());
195 proof->add_external_original_clause (id, false, external->eclause);
196 }
197 if (internal->opts.check &&
198 (internal->opts.checkwitness || internal->opts.checkfailed)) {
199 bool forgettable = from_propagator && ext_clause_forgettable;
200 if (forgettable && opts.check) {
201 CADICAL_assert (!original.size () || !external->eclause.empty ());
202
203 // First integer is the presence-flag (even if the clause is empty)
204 external->forgettable_original[id] = {1};
205
206 for (auto const &elit : external->eclause)
207 external->forgettable_original[id].push_back (elit);
208
209 LOG (external->eclause,
210 "clause added to external forgettable map:");
211 }
212 }
213
215 original.clear ();
216 }
217}
void add_new_original_clause(int64_t)
Here is the call graph for this function:

◆ add_self_subsuming_factor()

void CaDiCaL::Internal::add_self_subsuming_factor ( Quotient * q,
Quotient * p )

Definition at line 510 of file cadical_factor.cpp.

510 {
511 const int factor = q->factor;
512 const int not_factor = p->factor;
513 CADICAL_assert (-factor == not_factor);
514 LOG (
515 "adding self subsuming factor because blocked clause is a tautology");
516 for (auto c : q->qlauses) {
517 for (const auto &lit : *c) {
518 if (lit == factor)
519 continue;
520 clause.push_back (lit);
521 }
522 if (lrat) {
523 for (auto d : p->qlauses) {
524 bool match = true;
525 for (const auto &lit : *d) {
526 if (lit == not_factor)
527 continue;
528 if (std::find (clause.begin (), clause.end (), lit) ==
529 clause.end ()) {
530 match = false;
531 break;
532 }
533 }
534 if (match) {
535 lrat_chain.push_back (d->id);
536 break;
537 }
538 }
539 lrat_chain.push_back (c->id);
540 CADICAL_assert (lrat_chain.size () == 2);
541 }
542 if (clause.size () > 1) {
544 } else {
545 const int unit = clause[0];
546 const signed char tmp = val (unit);
547 if (!tmp)
548 assign_unit (unit);
549 else if (tmp < 0) {
550 if (lrat) {
551 int64_t id = unit_id (-unit);
552 lrat_chain.push_back (id);
553 std::reverse (lrat_chain.begin (), lrat_chain.end ());
554 }
556 clause.clear ();
557 lrat_chain.clear ();
558 break;
559 }
560 }
561 clause.clear ();
562 lrat_chain.clear ();
563 }
564}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_sweep_binary()

int64_t CaDiCaL::Internal::add_sweep_binary ( sweep_proof_clause pc,
int lit,
int other )

Definition at line 899 of file cadical_sweep.cpp.

900 {
902 if (unsat)
903 return 0; // sanity check, should be fuzzed
904
905 CADICAL_assert (!val (lit) && !val (other));
906 if (val (lit) || val (other))
907 return 0;
908
909 if (lrat) {
910 for (const auto &plit : pc.literals) {
911 if (val (plit)) {
912 int64_t id = unit_id (-plit);
913 lrat_chain.push_back (id);
914 }
915 }
916 lrat_chain.push_back (pc.cad_id);
917 }
918 clause.push_back (lit);
919 clause.push_back (other);
920 const int64_t id = ++clause_id;
921 if (proof) {
922 proof->add_derived_clause (id, false, clause, lrat_chain);
923 proof->weaken_minus (id, clause);
924 }
925 external->push_binary_clause_on_extension_stack (id, lit, other);
926 clause.clear ();
927 lrat_chain.clear ();
928 return id;
929}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ already_solved()

int CaDiCaL::Internal::already_solved ( )

Definition at line 941 of file cadical_internal.cpp.

941 {
942 int res = 0;
943 if (unsat || unsat_constraint) {
944 LOG ("already inconsistent");
945 res = 20;
946 } else {
947 if (level && !opts.ilb)
948 backtrack ();
949 if (!level && !propagate ()) {
950 LOG ("root level propagation produces conflict");
952 res = 20;
953 }
954 if (max_var == 0 && res == 0)
955 res = 10;
956 }
957 return res;
958}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ analyze()

void CaDiCaL::Internal::analyze ( )

Definition at line 943 of file cadical_analyze.cpp.

943 {
944
945 START (analyze);
946
948 CADICAL_assert (lrat_chain.empty ());
949 CADICAL_assert (unit_chain.empty ());
950 CADICAL_assert (unit_analyzed.empty ());
951 CADICAL_assert (clause.empty ());
952
953 // First update moving averages of trail height at conflict.
954 //
955 UPDATE_AVERAGE (averages.current.trail.fast, num_assigned);
956 UPDATE_AVERAGE (averages.current.trail.slow, num_assigned);
958
959 /*----------------------------------------------------------------------*/
960
961 if (external_prop && !external_prop_is_lazy && opts.exteagerreasons) {
963 }
964
965 if (opts.chrono || external_prop) {
966
967 int forced;
968
969 const int conflict_level = find_conflict_level (forced);
970
971 // In principle we can perform conflict analysis as in non-chronological
972 // backtracking except if there is only one literal with the maximum
973 // assignment level in the clause. Then standard conflict analysis is
974 // unnecessary and we can use the conflict as a driving clause. In the
975 // pseudo code of the SAT'18 paper on chronological backtracking this
976 // corresponds to the situation handled in line 4-6 in Alg. 1, except
977 // that the pseudo code in the paper only backtracks while we eagerly
978 // assign the single literal on the highest decision level.
979
980 if (forced) {
981
982 CADICAL_assert (forced);
983 CADICAL_assert (conflict_level > 0);
984 LOG ("single highest level literal %d", forced);
985
986 // The pseudo code in the SAT'18 paper actually backtracks to the
987 // 'second highest decision' level, while their code backtracks
988 // to 'conflict_level-1', which is more in the spirit of chronological
989 // backtracking anyhow and thus we also do the latter.
990 //
991 backtrack (conflict_level - 1);
992
993 // if we are on decision level 0 search assign will learn unit
994 // so we need a valid chain here (of course if we are not on decision
995 // level 0 this will not result in a valid chain).
996 // we can just use build_chain_for_units in propagate
997 //
998 build_chain_for_units (forced, conflict, 0);
999
1000 LOG ("forcing %d", forced);
1002
1003 conflict = 0;
1004 STOP (analyze);
1005 return;
1006 }
1007
1008 // Backtracking to the conflict level is in the pseudo code in the
1009 // SAT'18 chronological backtracking paper, but not in their actual
1010 // implementation. In principle we do not need to backtrack here.
1011 // However, as a side effect of backtracking to the conflict level we
1012 // set 'level' to the conflict level which then allows us to reuse the
1013 // old 'analyze' code as is. The alternative (which we also tried but
1014 // then abandoned) is to use 'conflict_level' instead of 'level' in the
1015 // analysis, which however requires to pass it to the 'analyze_reason'
1016 // and 'analyze_literal' functions.
1017 //
1018 backtrack (conflict_level);
1019 }
1020
1021 // Actual conflict on root level, thus formula unsatisfiable.
1022 //
1023 if (!level) {
1025 if (external->learner)
1026 external->export_learned_empty_clause ();
1027 STOP (analyze);
1028 return;
1029 }
1030
1031 /*----------------------------------------------------------------------*/
1032
1033 // First derive the 1st UIP clause by going over literals assigned on the
1034 // current decision level. Literals in the conflict are marked as 'seen'
1035 // as well as all literals in reason clauses of already 'seen' literals on
1036 // the current decision level. Thus the outer loop starts with the
1037 // conflict clause as 'reason' and then uses the 'reason' of the next
1038 // seen literal on the trail assigned on the current decision level.
1039 // During this process maintain the number 'open' of seen literals on the
1040 // current decision level with not yet processed 'reason'. As soon 'open'
1041 // drops to one, we have found the first unique implication point. This
1042 // is sound because the topological order in which literals are processed
1043 // follows the assignment order and a more complex algorithm to find
1044 // articulation points is not necessary.
1045 //
1046 Clause *reason = conflict;
1047 LOG (reason, "analyzing conflict");
1048
1049 CADICAL_assert (clause.empty ());
1050 CADICAL_assert (lrat_chain.empty ());
1051
1052 const auto &t = &trail;
1053 int i = t->size (); // Start at end-of-trail.
1054 int open = 0; // Seen but not processed on this level.
1055 int uip = 0; // The first UIP literal.
1056 int resolvent_size = 0; // without the uip
1057 int antecedent_size = 1; // with the uip and without unit literals
1058 int conflict_size = 0; // without the uip and without unit literals
1059 int resolved = 0; // number of resolution (0 = clause in CNF)
1060 const bool otfs = opts.otfs;
1061
1062 for (;;) {
1063 antecedent_size = 1; // for uip
1064 analyze_reason (uip, reason, open, resolvent_size, antecedent_size);
1065 if (resolved == 0)
1066 conflict_size = antecedent_size - 1;
1067 CADICAL_assert (resolvent_size == open + (int) clause.size ());
1068
1069 if (otfs && resolved > 0 && antecedent_size > 2 &&
1070 resolvent_size < antecedent_size) {
1071 CADICAL_assert (reason != conflict);
1072 LOG (analyzed, "found candidate for OTFS conflict");
1073 LOG (clause, "found candidate for OTFS conflict");
1074 LOG (reason, "found candidate (size %d) for OTFS resolvent",
1075 antecedent_size);
1076 const int other = reason->literals[0] ^ reason->literals[1] ^ uip;
1077 CADICAL_assert (other != uip);
1078 reason = on_the_fly_strengthen (reason, uip);
1079 if (opts.bump)
1080 bump_variables ();
1081
1082 CADICAL_assert (conflict_size);
1083 if (!reason) {
1084 uip = -other;
1085 CADICAL_assert (open == 1);
1086 LOG ("clause is actually unit %d, stopping", -uip);
1087 reverse (begin (mini_chain), end (mini_chain));
1088 for (auto id : mini_chain)
1089 lrat_chain.push_back (id);
1090 mini_chain.clear ();
1092 CADICAL_assert (!opts.exteagerreasons);
1093 clause.clear ();
1094 break;
1095 }
1096 CADICAL_assert (conflict_size >= 2);
1097
1098 if (resolved == 1 && resolvent_size < conflict_size) {
1099 // here both clauses are part of the CNF, so one subsumes the other
1100 otfs_subsume_clause (reason, conflict);
1101 LOG (reason, "changing conflict to");
1102 --conflict_size;
1103 CADICAL_assert (conflict_size == reason->size);
1104 ++stats.otfs.subsumed;
1105 ++stats.subsumed;
1106 }
1107
1108 LOG (reason, "changing conflict to");
1109 conflict = reason;
1110 if (open == 1) {
1111 int forced = 0;
1112 const int conflict_level = otfs_find_backtrack_level (forced);
1113 int new_level = determine_actual_backtrack_level (conflict_level);
1114 UPDATE_AVERAGE (averages.current.level, new_level);
1115 backtrack (new_level);
1116
1117 LOG ("forcing %d", forced);
1119
1120 // Clean up.
1121 //
1122 conflict = 0;
1125 clause.clear ();
1126 STOP (analyze);
1127 return;
1128 }
1129
1130 stats.conflicts++;
1131
1134 clause.clear ();
1135 resolvent_size = 0;
1136 antecedent_size = 1;
1137 resolved = 0;
1138 open = 0;
1139 analyze_reason (0, reason, open, resolvent_size, antecedent_size);
1140 conflict_size = antecedent_size - 1;
1141 CADICAL_assert (open > 1);
1142 }
1143
1144 ++resolved;
1145
1146 uip = 0;
1147 while (!uip) {
1148 CADICAL_assert (i > 0);
1149 const int lit = (*t)[--i];
1150 if (!flags (lit).seen)
1151 continue;
1152 if (var (lit).level == level)
1153 uip = lit;
1154 }
1155 if (!--open)
1156 break;
1157 reason = var (uip).reason;
1158 if (reason == external_reason) {
1159 CADICAL_assert (!opts.exteagerreasons);
1160 reason = learn_external_reason_clause (-uip, 0, true);
1161 var (uip).reason = reason;
1162 }
1163 CADICAL_assert (reason != external_reason);
1164 LOG (reason, "analyzing %d reason", uip);
1165 CADICAL_assert (resolvent_size);
1166 --resolvent_size;
1167 }
1168 LOG ("first UIP %d", uip);
1169 clause.push_back (-uip);
1170
1171 // Update glue and learned (1st UIP literals) statistics.
1172 //
1173 int size = (int) clause.size ();
1174 const int glue = (int) levels.size () - 1;
1175 LOG (clause, "1st UIP size %d and glue %d clause", size, glue);
1176 UPDATE_AVERAGE (averages.current.glue.fast, glue);
1177 UPDATE_AVERAGE (averages.current.glue.slow, glue);
1178 stats.learned.literals += size;
1179 stats.learned.clauses++;
1180 CADICAL_assert (glue < size);
1181
1182 // up to this point lrat_chain contains the proof for current clause in
1183 // reversed order. in minimize and shrink the clause is changed and
1184 // therefore lrat_chain has to be extended. Unfortunately we cannot create
1185 // the chain directly during minimization (or shrinking) but afterwards we
1186 // can calculate it pretty easily and even better the same algorithm works
1187 // for both shrinking and minimization.
1188
1189 // Minimize the 1st UIP clause as pioneered by Niklas Soerensson in
1190 // MiniSAT and described in our joint SAT'09 paper.
1191 //
1192 if (size > 1) {
1193 if (opts.shrink)
1195 else if (opts.minimize)
1196 minimize_clause ();
1197
1198 size = (int) clause.size ();
1199
1200 // Update decision heuristics.
1201 //
1202 if (opts.bump) {
1204 bump_variables ();
1205 }
1206
1207 if (external->learner)
1208 external->export_learned_large_clause (clause);
1209 } else if (external->learner)
1210 external->export_learned_unit_clause (-uip);
1211
1212 // Update actual size statistics.
1213 //
1214 stats.units += (size == 1);
1215 stats.binaries += (size == 2);
1216 UPDATE_AVERAGE (averages.current.size, size);
1217
1218 // reverse lrat_chain. We could probably work with reversed iterators
1219 // (views) to be more efficient but we would have to distinguish in proof
1220 //
1221 if (lrat) {
1222 LOG (unit_chain, "unit chain: ");
1223 for (auto id : unit_chain)
1224 lrat_chain.push_back (id);
1225 unit_chain.clear ();
1226 reverse (lrat_chain.begin (), lrat_chain.end ());
1227 }
1228
1229 // Determine back-jump level, learn driving clause, backtrack and assign
1230 // flipped 1st UIP literal.
1231 //
1232 int jump;
1233 Clause *driving_clause = new_driving_clause (glue, jump);
1234 UPDATE_AVERAGE (averages.current.jump, jump);
1235
1236 int new_level = determine_actual_backtrack_level (jump);
1237 UPDATE_AVERAGE (averages.current.level, new_level);
1238 backtrack (new_level);
1239
1240 // It should hold that (!level <=> size == 1)
1241 // and (!uip <=> size == 0)
1242 // this means either we have already learned a clause => size >= 2
1243 // in this case we will not learn empty clause or unit here
1244 // or we haven't actually learned a clause in new_driving_clause
1245 // then lrat_chain is still valid and we will learn a unit or empty clause
1246 //
1247 if (uip) {
1248 search_assign_driving (-uip, driving_clause);
1249 } else
1251
1252 if (stable)
1253 reluctant.tick (); // Reluctant has its own 'conflict' counter.
1254
1255 // Clean up.
1256 //
1260 clause.clear ();
1261 conflict = 0;
1262
1263 lrat_chain.clear ();
1264 STOP (analyze);
1265
1266 if (driving_clause && opts.eagersubsume)
1268
1269 if (lim.recompute_tier <= stats.conflicts)
1270 recompute_tier ();
1271}
#define UPDATE_AVERAGE(A, Y)
Definition ema.hpp:56
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
vector< int > trail
Definition internal.hpp:259
Clause * on_the_fly_strengthen(Clause *conflict, int lit)
Clause * learn_external_reason_clause(int lit, int falsified_elit=0, bool no_backtrack=false)
void eagerly_subsume_recently_learned_clauses(Clause *)
vector< int64_t > unit_chain
Definition internal.hpp:213
void otfs_subsume_clause(Clause *subsuming, Clause *subsumed)
int find_conflict_level(int &forced)
vector< int > unit_analyzed
Definition internal.hpp:268
Reluctant reluctant
Definition internal.hpp:198
Clause * new_driving_clause(const int glue, int &jump)
int otfs_find_backtrack_level(int &forced)
void analyze_reason(int lit, Clause *, int &open, int &resolvent_size, int &antecedent_size)
void search_assign_driving(int lit, Clause *reason)
int determine_actual_backtrack_level(int jump)
void build_chain_for_units(int lit, Clause *reason, bool forced)
vector< int > levels
Definition internal.hpp:266
Clause * reason
Definition var.hpp:21
Here is the call graph for this function:
Here is the caller graph for this function:

◆ analyze_literal()

void CaDiCaL::Internal::analyze_literal ( int lit,
int & open,
int & resolvent_size,
int & antecedent_size )
inline

Definition at line 256 of file cadical_analyze.cpp.

258 {
260 Var &v = var (lit);
261 Flags &f = flags (lit);
262
263 if (!v.level) {
264 if (f.seen || !lrat)
265 return;
266 f.seen = true;
267 unit_analyzed.push_back (lit);
268 CADICAL_assert (val (lit) < 0);
269 int64_t id = unit_id (-lit);
270 unit_chain.push_back (id);
271 return;
272 }
273 ++antecedent_size;
274 if (f.seen)
275 return;
276
277 // before marking as seen, get reason and check for missed unit
278
279 CADICAL_assert (val (lit) < 0);
280 CADICAL_assert (v.level <= level);
281 if (v.reason == external_reason) {
282 CADICAL_assert (!opts.exteagerreasons);
283 v.reason = learn_external_reason_clause (-lit, 0, true);
284 if (!v.reason) { // actually a unit
285 --antecedent_size;
286 LOG ("%d unit after explanation", -lit);
287 if (f.seen || !lrat)
288 return;
289 f.seen = true;
290 unit_analyzed.push_back (lit);
291 CADICAL_assert (val (lit) < 0);
292 const unsigned uidx = vlit (-lit);
293 int64_t id = unit_clauses (uidx);
294 CADICAL_assert (id);
295 unit_chain.push_back (id);
296 return;
297 }
298 }
299
300 f.seen = true;
301 analyzed.push_back (lit);
302
303 CADICAL_assert (v.reason != external_reason);
304 if (v.level < level)
305 clause.push_back (lit);
306 Level &l = control[v.level];
307 if (!l.seen.count++) {
308 LOG ("found new level %d contributing to conflict", v.level);
309 levels.push_back (v.level);
310 }
311 if (v.trail < l.seen.trail)
312 l.seen.trail = v.trail;
313 ++resolvent_size;
314 LOG ("analyzed literal %d assigned at level %d", lit, v.level);
315 if (v.level == level)
316 open++;
317}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ analyze_reason()

void CaDiCaL::Internal::analyze_reason ( int lit,
Clause * reason,
int & open,
int & resolvent_size,
int & antecedent_size )
inline

Definition at line 319 of file cadical_analyze.cpp.

321 {
322 CADICAL_assert (reason);
324 bump_clause (reason);
325 if (lrat)
326 lrat_chain.push_back (reason->id);
327 for (const auto &other : *reason)
328 if (other != lit)
329 analyze_literal (other, open, resolvent_size, antecedent_size);
330}
void bump_clause(Clause *)
void analyze_literal(int lit, int &open, int &resolvent_size, int &antecedent_size)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ apply_factoring()

bool CaDiCaL::Internal::apply_factoring ( Factoring & factoring,
Quotient * q )

Definition at line 713 of file cadical_factor.cpp.

713 {
714 for (Quotient *p = q; p->prev; p = p->prev)
716 if (self_subsuming_factor (q)) {
717 for (Quotient *p = q; p; p = p->prev)
719 for (Quotient *p = q; p; p = p->prev)
721 return true;
722 }
723 const int fresh = get_new_extension_variable ();
724 if (!fresh)
725 return false;
726 stats.factored++;
727 factoring.fresh.push_back (fresh);
728 for (Quotient *p = q; p; p = p->prev)
729 add_factored_divider (p, fresh);
730 const int not_fresh = -fresh;
731 blocked_clause (q, not_fresh);
732 add_factored_quotient (q, not_fresh);
733 for (Quotient *p = q; p; p = p->prev)
735 for (Quotient *p = q; p; p = p->prev)
737 CADICAL_assert (fresh > 0);
739 return true;
740}
struct factoring factoring
Definition factor.c:65
void update_factored(Factoring &factoring, Quotient *q)
bool self_subsuming_factor(Quotient *)
void resize_factoring(Factoring &factoring, int lit)
void add_factored_quotient(Quotient *, int not_fresh)
void flush_unmatched_clauses(Quotient *)
void blocked_clause(Quotient *q, int)
void add_factored_divider(Quotient *, int)
void delete_unfactored(Quotient *q)
unsigneds fresh
Definition factor.c:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ arenaing()

bool CaDiCaL::Internal::arenaing ( )

Definition at line 527 of file cadical_collect.cpp.

527{ return opts.arena && (stats.collections > 1); }
Here is the caller graph for this function:

◆ ask_decision()

int CaDiCaL::Internal::ask_decision ( )

Definition at line 998 of file cadical_external_propagate.cpp.

998 {
1000 return 0;
1001
1005 int level_before = level;
1006 forced_backt_allowed = true;
1007 int elit = external->propagator->cb_decide ();
1008 forced_backt_allowed = false;
1009 stats.ext_prop.ext_cb++;
1010
1011 if (level_before != level) {
1012
1013 propagate ();
1017
1018 // In case the external propagator forced to backtrack below the
1019 // pseduo decision levels, we must go back to the CDCL loop instead of
1020 // making a decision.
1021 if ((size_t) level < assumptions.size () ||
1022 ((size_t) level == assumptions.size () && constraint.size ())) {
1023 return 0;
1024 }
1025 }
1026
1027 if (!elit)
1028 return 0;
1029 LOG ("external propagator proposes decision: %d", elit);
1030 CADICAL_assert (external->is_observed[abs (elit)]);
1031 if (!external->is_observed[abs (elit)])
1032 return 0;
1033
1034 int ilit = external->e2i[abs (elit)];
1035 if (elit < 0)
1036 ilit = -ilit;
1037
1038 CADICAL_assert (fixed (ilit) || observed (ilit));
1039
1040 LOG ("Asking external propagator for decision returned: %d (internal: "
1041 "%d, fixed: %d, val: %d)",
1042 elit, ilit, fixed (ilit), val (ilit));
1043
1044 if (fixed (ilit) || val (ilit)) {
1045 LOG ("Proposed decision variable is already assigned, falling back to "
1046 "internal decision.");
1047 return 0;
1048 }
1049
1050 return ilit;
1051}
vector< int > constraint
Definition internal.hpp:262
vector< int > assumptions
Definition internal.hpp:261
bool observed(int ilit) const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ask_external_clause()

bool CaDiCaL::Internal::ask_external_clause ( )

Definition at line 392 of file cadical_external_propagate.cpp.

392 {
394 bool res =
395 external->propagator->cb_has_external_clause (ext_clause_forgettable);
396
397 return res;
398}
Here is the caller graph for this function:

◆ assign_original_unit()

void CaDiCaL::Internal::assign_original_unit ( int64_t id,
int lit )

Definition at line 347 of file cadical_clause.cpp.

347 {
348 CADICAL_assert (!level || opts.chrono);
350 const int idx = vidx (lit);
351 CADICAL_assert (!vals[idx]);
352 CADICAL_assert (!flags (idx).eliminated ());
353 Var &v = var (idx);
354 v.level = 0;
355 v.trail = (int) trail.size ();
356 v.reason = 0;
357 const signed char tmp = sign (lit);
358 set_val (idx, tmp);
359 trail.push_back (lit);
360 num_assigned++;
361 const unsigned uidx = vlit (lit);
362 if (lrat || frat)
363 unit_clauses (uidx) = id;
364 LOG ("original unit assign %d", lit);
365 CADICAL_assert (num_assigned == trail.size () || level);
366 mark_fixed (lit);
367 if (level)
368 return;
369 if (propagate ())
370 return;
372 LOG ("propagation of original unit results in conflict");
374}
int sign(int lit)
Definition util.hpp:22
void set_val(int lit, signed char val)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ assign_unit()

void CaDiCaL::Internal::assign_unit ( int lit)

Definition at line 184 of file cadical_propagate.cpp.

184 {
186 search_assign (lit, 0);
187}
void search_assign(int lit, Clause *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ assignment_level()

int CaDiCaL::Internal::assignment_level ( int lit,
Clause * reason )
inline

Definition at line 42 of file cadical_propagate.cpp.

42 {
43
45 if (!reason || reason == external_reason)
46 return level;
47
48 int res = 0;
49
50 for (const auto &other : *reason) {
51 if (other == lit)
52 continue;
53 CADICAL_assert (val (other));
54 int tmp = var (other).level;
55 if (tmp > res)
56 res = tmp;
57 }
58
59 return res;
60}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ assume()

void CaDiCaL::Internal::assume ( int lit)

Definition at line 13 of file cadical_assume.cpp.

13 {
14 if (level && !opts.ilbassumptions)
15 backtrack ();
16 else if (val (lit) < 0)
17 backtrack (max (0, var (lit).level - 1));
18 Flags &f = flags (lit);
19 const unsigned char bit = bign (lit);
20 if (f.assumed & bit) {
21 LOG ("ignoring already assumed %d", lit);
22 return;
23 }
24 LOG ("assume %d", lit);
25 f.assumed |= bit;
26 assumptions.push_back (lit);
27 freeze (lit);
28}
unsigned bign(int lit)
Definition util.hpp:23
void freeze(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ assume_analyze_literal()

void CaDiCaL::Internal::assume_analyze_literal ( int lit)

Definition at line 33 of file cadical_assume.cpp.

33 {
35 Flags &f = flags (lit);
36 if (f.seen)
37 return;
38 f.seen = true;
39 analyzed.push_back (lit);
40 Var &v = var (lit);
41 CADICAL_assert (val (lit) < 0);
42 if (v.reason == external_reason) {
44 CADICAL_assert (v.reason || !v.level);
45 }
46 CADICAL_assert (v.reason != external_reason);
47 if (!v.level) {
48 int64_t id = unit_id (-lit);
49 lrat_chain.push_back (id);
50 return;
51 }
52 if (v.reason) {
53 CADICAL_assert (v.level);
54 LOG (v.reason, "analyze reason");
55 for (const auto &other : *v.reason) {
57 }
58 lrat_chain.push_back (v.reason->id);
59 return;
60 }
62 LOG ("failed assumption %d", -lit);
63 clause.push_back (lit);
64}
void assume_analyze_literal(int lit)
Clause * wrapped_learn_external_reason_clause(int lit)
bool assumed(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ assume_analyze_reason()

void CaDiCaL::Internal::assume_analyze_reason ( int lit,
Clause * reason )

Definition at line 66 of file cadical_assume.cpp.

66 {
67 CADICAL_assert (reason);
68 CADICAL_assert (lrat_chain.empty ());
71 for (const auto &other : *reason)
72 if (other != lit)
74 lrat_chain.push_back (reason->id);
75}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ assumed()

bool CaDiCaL::Internal::assumed ( int lit)
inline

Definition at line 1384 of file internal.hpp.

1384 { // Marked as assumption.
1385 Flags &f = flags (lit);
1386 const unsigned bit = bign (lit);
1387 return (f.assumed & bit) != 0;
1388 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ asymmetric_literal_addition()

void CaDiCaL::Internal::asymmetric_literal_addition ( int lit,
Coveror & coveror )
inline

Definition at line 85 of file cadical_cover.cpp.

86 {
88 CADICAL_assert (level == 1);
89 LOG ("initial asymmetric literal addition %d", lit);
91 set_val (lit, -1);
92 coveror.added.push_back (lit);
93 coveror.alas++;
94 coveror.next.covered = 0;
95}
void require_mode(Mode m) const
Definition internal.hpp:173
Here is the call graph for this function:
Here is the caller graph for this function:

◆ backtrack()

void CaDiCaL::Internal::backtrack ( int target_level = 0)

Definition at line 80 of file cadical_backtrack.cpp.

80 {
81 CADICAL_assert (new_level <= level);
82 if (new_level == level)
83 return;
84
87}
void backtrack_without_updating_phases(int target_level=0)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ backtrack_without_updating_phases()

void CaDiCaL::Internal::backtrack_without_updating_phases ( int target_level = 0)

Definition at line 89 of file cadical_backtrack.cpp.

89 {
90
91 CADICAL_assert (new_level <= level);
92 if (new_level == level)
93 return;
94
95 stats.backtracks++;
96
98
99 const size_t assigned = control[new_level + 1].trail;
100
101 LOG ("backtracking to decision level %d with decision %d and trail %zd",
102 new_level, control[new_level].decision, assigned);
103
104 const size_t end_of_trail = trail.size ();
105 size_t i = assigned, j = i;
106
107#ifdef LOGGING
108 int unassigned = 0;
109#endif
110 int reassigned = 0;
111
112 notify_backtrack (new_level);
114 notified > assigned) {
115 LOG ("external propagator is notified about some unassignments (trail: "
116 "%zd, notified: %zd).",
117 trail.size (), notified);
119 }
120
121 while (i < end_of_trail) {
122 int lit = trail[i++];
123 Var &v = var (lit);
124 if (v.level > new_level) {
125 unassign (lit);
126#ifdef LOGGING
127 unassigned++;
128#endif
129 } else {
130 // This is the essence of the SAT'18 paper on chronological
131 // backtracking. It is possible to just keep out-of-order assigned
132 // literals on the trail without breaking the solver (after some
133 // modifications to 'analyze' - see 'opts.chrono' guarded code there).
135#ifdef LOGGING
136 if (!v.level)
137 LOG ("reassign %d @ 0 unit clause %d", lit, lit);
138 else
139 LOG (v.reason, "reassign %d @ %d", lit, v.level);
140#endif
141 trail[j] = lit;
142 v.trail = j++;
143 reassigned++;
144 }
145 }
146 trail.resize (j);
147 LOG ("unassigned %d literals %.0f%%", unassigned,
148 percent (unassigned, unassigned + reassigned));
149 LOG ("reassigned %d literals %.0f%%", reassigned,
150 percent (reassigned, unassigned + reassigned));
151
152 if (propagated > assigned)
154 if (propagated2 > assigned)
158
159 propergated = 0; // Always go back to root-level.
160
161 CADICAL_assert (notified <= assigned + reassigned);
162 if (reassigned) {
164 }
165
166 control.resize (new_level + 1);
167 level = new_level;
168 if (tainted_literal) {
169 CADICAL_assert (opts.ilb);
170 if (!val (tainted_literal)) {
171 tainted_literal = 0;
172 }
173 }
174 CADICAL_assert (num_assigned == trail.size ());
175}
struct assigned assigned
Definition assign.h:15
double percent(double a, double b)
Definition util.hpp:21
void notify_backtrack(size_t new_level)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ backward_false_satisfiable()

int CaDiCaL::Internal::backward_false_satisfiable ( )

Definition at line 206 of file cadical_lucky.cpp.

206 {
207 LOG ("checking decreasing variable index false assignment");
210 CADICAL_assert (assumptions.empty ());
211 for (int idx = max_var; idx > 0; idx--) {
212 START:
214 return unlucky (-1);
215 if (val (idx))
216 continue;
217 if (lucky_propagate_discrepency (-idx)) {
218 if (unsat)
219 return 20;
220 else
221 return unlucky (0);
222 } else
223 goto START;
224 }
225 VERBOSE (1, "backward assuming variables false satisfies formula");
227 stats.lucky.backward.zero++;
228 return 10;
229}
bool terminated_asynchronously(int factor=1)
bool lucky_propagate_discrepency(int)
int unlucky(int res)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ backward_true_satisfiable()

int CaDiCaL::Internal::backward_true_satisfiable ( )

Definition at line 231 of file cadical_lucky.cpp.

231 {
232 LOG ("checking decreasing variable index true assignment");
235 CADICAL_assert (assumptions.empty ());
236 for (int idx = max_var; idx > 0; idx--) {
237 START:
239 return unlucky (-1);
240 if (val (idx))
241 continue;
242 if (lucky_propagate_discrepency (idx)) {
243 if (unsat)
244 return 20;
245 else
246 return unlucky (0);
247 } else
248 goto START;
249 }
250 VERBOSE (1, "backward assuming variables true satisfies formula");
252 stats.lucky.backward.one++;
253 return 10;
254}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ best_quotient()

Quotient * CaDiCaL::Internal::best_quotient ( Factoring & factoring,
size_t * best_reduction_ptr )

Definition at line 217 of file cadical_factor.cpp.

218 {
219 size_t factors = 1, best_reduction = 0;
220 Quotient *best = 0;
221 for (Quotient *q = factoring.quotients.first; q; q = q->next) {
222 size_t quotients = q->qlauses.size ();
223 size_t before_factorization = quotients * factors;
224 size_t after_factorization = quotients + factors;
225 if (before_factorization == after_factorization)
226 LOG ("quotient[%zu] factors %zu clauses into %zu thus no change",
227 factors - 1, before_factorization, after_factorization);
228 else if (before_factorization < after_factorization)
229 LOG ("quotient[%zu] factors %zu clauses into %zu thus %zu more",
230 factors - 1, before_factorization, after_factorization,
231 after_factorization - before_factorization);
232 else {
233 size_t delta = before_factorization - after_factorization;
234 LOG ("quotient[%zu] factors %zu clauses into %zu thus %zu less",
235 factors - 1, before_factorization, after_factorization, delta);
236 if (!best || best_reduction < delta) {
237 best_reduction = delta;
238 best = q;
239 }
240 }
241 factors++;
242 }
243 if (!best) {
244 LOG ("no decreasing quotient found");
245 return 0;
246 }
247 LOG ("best decreasing quotient[%zu] with reduction %zu", best->id,
248 best_reduction);
249 *best_reduction_ptr = best_reduction;
250 return best;
251}
struct factoring::@160277325255143145147274163211332332056211107037 quotients
quotient * first
Definition factor.c:60
struct quotient * next
Definition factor.c:30
Here is the caller graph for this function:

◆ better_decision()

bool CaDiCaL::Internal::better_decision ( int lit,
int other )

Definition at line 114 of file cadical_decide.cpp.

114 {
115 int lit_idx = abs (lit);
116 int other_idx = abs (other);
117 if (stable)
118 return stab[lit_idx] > stab[other_idx];
119 else
120 return btab[lit_idx] > btab[other_idx];
121}
vector< int64_t > btab
Definition internal.hpp:234
vector< double > stab
Definition internal.hpp:230
Here is the caller graph for this function:

◆ bins()

Bins & CaDiCaL::Internal::bins ( int lit)
inline

Definition at line 464 of file internal.hpp.

464{ return big[vlit (lit)]; }
vector< Bins > big
Definition internal.hpp:240
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block()

bool CaDiCaL::Internal::block ( )

Definition at line 741 of file cadical_block.cpp.

741 {
742
743 if (!opts.block)
744 return false;
745 if (unsat)
746 return false;
747 if (!stats.current.irredundant)
748 return false;
750 return false;
751
752 if (propagated < trail.size ()) {
753 LOG ("need to propagate %zd units first", trail.size () - propagated);
754 init_watches ();
756 if (!propagate ()) {
757 LOG ("propagating units results in empty clause");
760 }
761 clear_watches ();
762 reset_watches ();
763 if (unsat)
764 return false;
765 }
766
768
769 stats.blockings++;
770
771 LOG ("block-%" PRId64 "", stats.blockings);
772
776
778
779 init_occs (); // Occurrence lists for all literals.
780 init_noccs (); // Number of occurrences to avoid flushing garbage clauses.
781
782 Blocker blocker (this);
783 block_schedule (blocker);
784
785 int64_t blocked = stats.blocked;
786 int64_t resolutions = stats.blockres;
787 int64_t purelits = stats.blockpurelits;
788 int64_t pured = stats.blockpured;
789
790 while (!terminated_asynchronously () && !blocker.schedule.empty ()) {
791 int lit = u2i (blocker.schedule.front ());
792 blocker.schedule.pop_front ();
793 block_literal (blocker, lit);
794 block_reschedule (blocker, lit);
795 }
796
797 blocker.erase ();
798 reset_noccs ();
799 reset_occs ();
800
801 resolutions = stats.blockres - resolutions;
802 blocked = stats.blocked - blocked;
803
804 PHASE ("block", stats.blockings,
805 "blocked %" PRId64 " clauses in %" PRId64 " resolutions", blocked,
806 resolutions);
807
808 pured = stats.blockpured - pured;
809 purelits = stats.blockpurelits - purelits;
810
811 if (pured)
813
814 if (purelits)
815 PHASE ("block", stats.blockings,
816 "found %" PRId64 " pure literals in %" PRId64 " clauses",
817 purelits, pured);
818 else
819 PHASE ("block", stats.blockings, "no pure literals found");
820
821 report ('b', !opts.reportall && !blocked);
822
824
825 return blocked;
826}
#define PHASE(...)
Definition message.hpp:52
#define START_SIMPLIFIER(S, M)
Definition profile.hpp:172
#define STOP_SIMPLIFIER(S, M)
Definition profile.hpp:197
void report(char type, int verbose_level=0)
void mark_redundant_clauses_with_eliminated_variables_as_garbage()
int u2i(unsigned u)
Definition internal.hpp:412
void block_literal(Blocker &, int lit)
void block_reschedule(Blocker &, int lit)
bool watching() const
Definition internal.hpp:462
void block_schedule(Blocker &)
bool occurring() const
Definition internal.hpp:461
void mark_satisfied_clauses_as_garbage()
void connect_watches(bool irredundant_only=false)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_candidates()

size_t CaDiCaL::Internal::block_candidates ( Blocker & blocker,
int lit )

Definition at line 439 of file cadical_block.cpp.

439 {
440
441 CADICAL_assert (blocker.candidates.empty ());
442
443 Occs &pos = occs (lit); // Positive occurrences of 'lit'.
444 Occs &nos = occs (-lit);
445
446 CADICAL_assert ((size_t) noccs (lit) <= pos.size ());
447 CADICAL_assert ((size_t) noccs (-lit) == nos.size ()); // Already flushed.
448
449 // Mark all literals in clauses with '-lit'. Note that 'mark2' uses
450 // separate bits for 'lit' and '-lit'.
451 //
452 for (const auto &c : nos)
453 mark2 (c);
454
455 const auto eop = pos.end ();
456 auto j = pos.begin (), i = j;
457
458 for (; i != eop; i++) {
459 Clause *c = *j++ = *i;
460 if (c->garbage) {
461 j--;
462 continue;
463 }
464 CADICAL_assert (!c->redundant);
465 if (c->size > opts.blockmaxclslim)
466 continue;
467 if (c->size < opts.blockminclslim)
468 continue;
469 const const_literal_iterator eoc = c->end ();
471 for (l = c->begin (); l != eoc; l++) {
472 const int other = *l;
473 if (other == lit)
474 continue;
475 CADICAL_assert (other != -lit);
476 CADICAL_assert (active (other));
477 CADICAL_assert (!val (other));
478 if (marked2 (-other))
479 break;
480 }
481 if (l != eoc)
482 blocker.candidates.push_back (c);
483 }
484 if (j == pos.begin ())
486 else
487 pos.resize (j - pos.begin ());
488
489 CADICAL_assert (pos.size () == (size_t) noccs (lit)); // Now also flushed.
490
491 for (const auto &c : nos)
492 unmark (c);
493
494 return blocker.candidates.size ();
495}
bool pos
Definition globals.c:30
vector< Clause * > Occs
Definition occs.hpp:18
const int * const_literal_iterator
Definition clause.hpp:18
void erase_vector(std::vector< T > &v)
Definition util.hpp:90
bool active(int lit)
Definition internal.hpp:360
int64_t & noccs(int lit)
Definition internal.hpp:466
void mark2(int lit)
Definition internal.hpp:561
Occs & occs(int lit)
Definition internal.hpp:465
bool marked2(int lit) const
Definition internal.hpp:555
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_impossible()

Clause * CaDiCaL::Internal::block_impossible ( Blocker & blocker,
int lit )

Definition at line 504 of file cadical_block.cpp.

504 {
505 CADICAL_assert (noccs (-lit) > 1);
506 CADICAL_assert (blocker.candidates.size () > 1);
507
508 for (const auto &c : blocker.candidates)
509 mark2 (c);
510
511 Occs &nos = occs (-lit);
512 Clause *res = 0;
513
514 for (const auto &c : nos) {
515 CADICAL_assert (!c->garbage);
516 CADICAL_assert (!c->redundant);
517 CADICAL_assert (c->size <= opts.blockmaxclslim);
518 const const_literal_iterator eoc = c->end ();
520 for (l = c->begin (); l != eoc; l++) {
521 const int other = *l;
522 if (other == -lit)
523 continue;
524 CADICAL_assert (other != lit);
525 CADICAL_assert (active (other));
526 CADICAL_assert (!val (other));
527 if (marked2 (-other))
528 break;
529 }
530 if (l == eoc)
531 res = c;
532 }
533
534 for (const auto &c : blocker.candidates)
535 unmark (c);
536
537 if (res) {
538 LOG (res, "common non-tautological resolvent producing");
539 blocker.candidates.clear ();
540 }
541
542 return res;
543}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_literal()

void CaDiCaL::Internal::block_literal ( Blocker & blocker,
int lit )

Definition at line 694 of file cadical_block.cpp.

694 {
696
697 if (!active (lit))
698 return; // Pure literal '-lit'.
699 if (frozen (lit))
700 return;
701
703
704 // If the maximum number of a negative clauses (with '-lit') exceeds the
705 // occurrence limit ignore this candidate literal.
706 //
707 if (noccs (-lit) > opts.blockocclim)
708 return;
709
710 LOG ("blocking literal candidate %d "
711 "with %" PRId64 " positive and %" PRId64 " negative occurrences",
712 lit, noccs (lit), noccs (-lit));
713
714 stats.blockcands++;
715
716 CADICAL_assert (blocker.reschedule.empty ());
717 CADICAL_assert (blocker.candidates.empty ());
718
719 if (!noccs (-lit))
720 block_pure_literal (blocker, lit);
721 else if (!noccs (lit)) {
722 // Rare situation, where the clause length limit was hit for 'lit' and
723 // '-lit' is skipped and then it becomes pure. Can be ignored. We also
724 // so it once happening for a 'elimboundmin=-1' and zero positive and
725 // one negative occurrence.
726 } else if (noccs (-lit) == 1)
728 else
730
731 // Done with blocked clause elimination on this literal and we do not
732 // have to try blocked clause elimination on it again until irredundant
733 // clauses with its negation are removed.
734 //
735 CADICAL_assert (!frozen (lit)); // just to be sure ...
737}
void block_literal_with_at_least_two_negative_occs(Blocker &, int lit)
bool frozen(int lit)
bool marked_skip(int lit)
void block_pure_literal(Blocker &, int lit)
void unmark_block(int lit)
void block_literal_with_one_negative_occ(Blocker &, int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_literal_with_at_least_two_negative_occs()

void CaDiCaL::Internal::block_literal_with_at_least_two_negative_occs ( Blocker & blocker,
int lit )

Definition at line 549 of file cadical_block.cpp.

550 {
553 CADICAL_assert (noccs (lit) > 0);
554 CADICAL_assert (noccs (-lit) > 1);
555
556 Occs &nos = occs (-lit);
557 CADICAL_assert ((size_t) noccs (-lit) <= nos.size ());
558
559 int max_size = 0;
560
561 // Flush all garbage clauses in occurrence list 'nos' of '-lit' and
562 // determine the maximum size of negative clauses (with '-lit').
563 //
564 const auto eon = nos.end ();
565 auto j = nos.begin (), i = j;
566 for (; i != eon; i++) {
567 Clause *c = *j++ = *i;
568 if (c->garbage)
569 j--;
570 else if (c->size > max_size)
571 max_size = c->size;
572 }
573 if (j == nos.begin ())
574 erase_vector (nos);
575 else
576 nos.resize (j - nos.begin ());
577
578 CADICAL_assert (nos.size () == (size_t) noccs (-lit));
579 CADICAL_assert (nos.size () > 1);
580
581 // If the maximum size of a negative clause (with '-lit') exceeds the
582 // maximum clause size limit ignore this candidate literal.
583 //
584 if (max_size > opts.blockmaxclslim) {
585 LOG ("maximum size %d of clauses with %d exceeds clause size limit %d",
586 max_size, -lit, opts.blockmaxclslim);
587 return;
588 }
589
590 LOG ("maximum size %d of clauses with %d", max_size, -lit);
591
592 // We filter candidate clauses with positive occurrence of 'lit' in
593 // 'blocker.candidates' and return if no candidate clause remains.
594 // Candidates should be small enough and should have at least one literal
595 // which occurs negated in one of the clauses with '-lit'.
596 //
597 size_t candidates = block_candidates (blocker, lit);
598 if (!candidates) {
599 LOG ("no candidate clauses found");
600 return;
601 }
602
603 LOG ("found %zd candidate clauses", candidates);
604
605 // We further search for a clause with '-lit' that has no literal
606 // negated in any of the candidate clauses (except 'lit'). If such a
607 // clause exists, we know that none of the candidates is blocked.
608 //
609 if (candidates > 1 && block_impossible (blocker, lit)) {
610 LOG ("impossible to block any candidate clause on %d", lit);
611 CADICAL_assert (blocker.candidates.empty ());
612 return;
613 }
614
615 LOG ("trying to block %zd clauses out of %" PRId64 " with literal %d",
616 candidates, noccs (lit), lit);
617
618 int64_t blocked = 0;
619
620 // Go over all remaining candidates and try to block them on 'lit'.
621 //
622 for (const auto &c : blocker.candidates) {
623 CADICAL_assert (!c->garbage);
624 CADICAL_assert (!c->redundant);
625 if (!is_blocked_clause (c, lit))
626 continue;
627 blocked++;
628 LOG (c, "blocked");
629 if (proof) {
630 proof->weaken_minus (c);
631 }
632 external->push_clause_on_extension_stack (c, lit);
633 blocker.reschedule.push_back (c);
634 mark_garbage (c);
635 }
636
637 LOG ("blocked %" PRId64
638 " clauses on %d out of %zd candidates in %zd occurrences",
639 blocked, lit, blocker.candidates.size (), occs (lit).size ());
640
641 blocker.candidates.clear ();
642 stats.blocked += blocked;
643 if (blocked)
644 flush_occs (lit);
645}
bool is_blocked_clause(Clause *c, int pivot)
void mark_garbage(Clause *)
Clause * block_impossible(Blocker &, int lit)
size_t block_candidates(Blocker &, int lit)
size_t flush_occs(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_literal_with_one_negative_occ()

void CaDiCaL::Internal::block_literal_with_one_negative_occ ( Blocker & blocker,
int lit )

Definition at line 302 of file cadical_block.cpp.

303 {
306 CADICAL_assert (noccs (lit) > 0);
307 CADICAL_assert (noccs (-lit) == 1);
308
309 Occs &nos = occs (-lit);
310 CADICAL_assert (nos.size () >= 1);
311
312 Clause *d = 0;
313 for (const auto &c : nos) {
314 if (c->garbage)
315 continue;
316 CADICAL_assert (!d);
317 d = c;
318#ifndef CADICAL_NDEBUG
319 break;
320#endif
321 }
322 CADICAL_assert (d);
323 nos.resize (1);
324 nos[0] = d;
325
326 if (d && d->size > opts.blockmaxclslim) {
327 LOG (d, "skipped common antecedent");
328 return;
329 }
330
331 CADICAL_assert (!d->garbage);
332 CADICAL_assert (!d->redundant);
333 CADICAL_assert (d->size <= opts.blockmaxclslim);
334
335 LOG (d, "common %d antecedent", lit);
336 mark (d);
337 int64_t blocked = 0;
338#ifdef LOGGING
339 int64_t skipped = 0;
340#endif
341 Occs &pos = occs (lit);
342
343 // Again no 'auto' since 'pos' is update during traversal.
344 //
345 const auto eop = pos.end ();
346 auto j = pos.begin (), i = j;
347
348 for (; i != eop; i++) {
349 Clause *c = *j++ = *i;
350
351 if (c->garbage) {
352 j--;
353 continue;
354 }
355 if (c->size > opts.blockmaxclslim) {
356#ifdef LOGGING
357 skipped++;
358#endif
359 continue;
360 }
361 if (c->size < opts.blockminclslim) {
362#ifdef LOGGING
363 skipped++;
364#endif
365 continue;
366 }
367
368 LOG (c, "trying to block on %d", lit);
369
370 // We use the same literal move-to-front strategy as in
371 // 'is_blocked_clause'. See there for more explanations.
372
373 int prev_other = 0; // Previous non-tautological literal.
374
375 // No 'auto' since literals of 'c' are updated during traversal.
376 //
377 const const_literal_iterator end_of_c = c->end ();
379
380 for (l = c->begin (); l != end_of_c; l++) {
381 const int other = *l;
382 *l = prev_other;
383 prev_other = other;
384 if (other == lit)
385 continue;
386 CADICAL_assert (other != -lit);
387 CADICAL_assert (active (other));
388 CADICAL_assert (!val (other));
389 if (marked (other) < 0) {
390 LOG ("found tautological literal %d", other);
391 c->literals[0] = other; // Move to front of 'c'.
392 break;
393 }
394 }
395
396 if (l == end_of_c) {
397 LOG ("no tautological literal found");
398
399 // Restore old literal order in the clause because.
400
401 const const_literal_iterator begin_of_c = c->begin ();
402 while (l-- != begin_of_c) {
403 const int other = *l;
404 *l = prev_other;
405 prev_other = other;
406 }
407
408 continue; // ... with next candidate 'c' in 'pos'.
409 }
410
411 blocked++;
412 LOG (c, "blocked");
413 if (proof) {
414 proof->weaken_minus (c);
415 }
416 external->push_clause_on_extension_stack (c, lit);
417 blocker.reschedule.push_back (c);
418 mark_garbage (c);
419 j--;
420 }
421 if (j == pos.begin ())
423 else
424 pos.resize (j - pos.begin ());
425
426 stats.blocked += blocked;
427 LOG ("blocked %" PRId64 " clauses on %d (skipped %" PRId64 ")", blocked,
428 lit, skipped);
429
430 unmark (d);
431}
int * literal_iterator
Definition clause.hpp:17
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_pure_literal()

void CaDiCaL::Internal::block_pure_literal ( Blocker & blocker,
int lit )

Definition at line 253 of file cadical_block.cpp.

253 {
254 if (frozen (lit))
255 return;
257
258 Occs &pos = occs (lit);
259 Occs &nos = occs (-lit);
260
262#ifndef CADICAL_NDEBUG
263 for (const auto &c : nos)
264 CADICAL_assert (c->garbage);
265#endif
266 stats.blockpurelits++;
267 LOG ("found pure literal %d", lit);
268#ifdef LOGGING
269 int64_t pured = 0;
270#endif
271 for (const auto &c : pos) {
272 if (c->garbage)
273 continue;
274 CADICAL_assert (!c->redundant);
275 LOG (c, "pure literal %d in", lit);
276 blocker.reschedule.push_back (c);
277 if (proof) {
278 proof->weaken_minus (c);
279 }
280 external->push_clause_on_extension_stack (c, lit);
281 stats.blockpured++;
282 mark_garbage (c);
283#ifdef LOGGING
284 pured++;
285#endif
286 }
287
289 erase_vector (nos);
290
291 mark_pure (lit);
292 stats.blockpured++;
293 LOG ("blocking %" PRId64 " clauses on pure literal %d", pured, lit);
294}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_reschedule()

void CaDiCaL::Internal::block_reschedule ( Blocker & blocker,
int lit )

Definition at line 684 of file cadical_block.cpp.

684 {
685 while (!blocker.reschedule.empty ()) {
686 Clause *c = blocker.reschedule.back ();
687 blocker.reschedule.pop_back ();
688 block_reschedule_clause (blocker, lit, c);
689 }
690}
void block_reschedule_clause(Blocker &, int lit, Clause *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_reschedule_clause()

void CaDiCaL::Internal::block_reschedule_clause ( Blocker & blocker,
int lit,
Clause * c )

Definition at line 651 of file cadical_block.cpp.

652 {
653#ifdef CADICAL_NDEBUG
654 (void) lit;
655#endif
656 CADICAL_assert (c->garbage);
657
658 for (const auto &other : *c) {
659
660 int64_t &n = noccs (other);
661 CADICAL_assert (n > 0);
662 n--;
663
664 LOG ("updating %d with %" PRId64 " positive and %" PRId64
665 " negative occurrences",
666 other, noccs (other), noccs (-other));
667
668 if (blocker.schedule.contains (vlit (-other)))
669 blocker.schedule.update (vlit (-other));
670 else if (active (other) && !frozen (other) && !marked_skip (-other)) {
671 LOG ("rescheduling to block clauses on %d", -other);
672 blocker.schedule.push_back (vlit (-other));
673 }
674
675 if (blocker.schedule.contains (vlit (other))) {
676 CADICAL_assert (other != lit);
677 blocker.schedule.update (vlit (other));
678 }
679 }
680}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_schedule()

void CaDiCaL::Internal::block_schedule ( Blocker & blocker)

Definition at line 153 of file cadical_block.cpp.

153 {
154 // Set skip flags for all literals in too large clauses.
155 //
156 for (const auto &c : clauses) {
157
158 if (c->garbage)
159 continue;
160 if (c->redundant)
161 continue;
162 if (c->size <= opts.blockmaxclslim)
163 continue;
164
165 for (const auto &lit : *c)
166 mark_skip (-lit);
167 }
168
169 // Connect all literal occurrences in irredundant clauses.
170 //
171 for (const auto &c : clauses) {
172
173 if (c->garbage)
174 continue;
175 if (c->redundant)
176 continue;
177
178 for (const auto &lit : *c) {
181 occs (lit).push_back (c);
182 }
183 }
184
185 // We establish the invariant that 'noccs' gives the number of actual
186 // occurrences of 'lit' in non-garbage clauses, while 'occs' might still
187 // refer to garbage clauses, thus 'noccs (lit) <= occs (lit).size ()'. It
188 // is expensive to remove references to garbage clauses from 'occs' during
189 // blocked clause elimination, but decrementing 'noccs' is cheap.
190
191 for (auto lit : lits) {
192 if (!active (lit))
193 continue;
195 Occs &os = occs (lit);
196 noccs (lit) = os.size ();
197 }
198
199 // Now we fill the schedule (priority queue) of candidate literals to be
200 // tried as blocking literals. It is probably slightly faster to do this
201 // in one go after all occurrences have been determined, instead of
202 // filling the priority queue during pushing occurrences. Filling the
203 // schedule can not be fused with the previous loop (easily) since we
204 // first have to initialize 'noccs' for both 'lit' and '-lit'.
205
206#ifndef CADICAL_QUIET
207 int skipped = 0;
208#endif
209
210 for (auto idx : vars) {
211 if (!active (idx))
212 continue;
213 if (frozen (idx)) {
214#ifndef CADICAL_QUIET
215 skipped += 2;
216#endif
217 continue;
218 }
219 CADICAL_assert (!val (idx));
220 for (int sign = -1; sign <= 1; sign += 2) {
221 const int lit = sign * idx;
222 if (marked_skip (lit)) {
223#ifndef CADICAL_QUIET
224 skipped++;
225#endif
226 continue;
227 }
228 if (!marked_block (lit))
229 continue;
231 LOG ("scheduling %d with %" PRId64 " positive and %" PRId64
232 " negative occurrences",
233 lit, noccs (lit), noccs (-lit));
234 blocker.schedule.push_back (vlit (lit));
235 }
236 }
237
238 PHASE ("block", stats.blockings,
239 "scheduled %zd candidate literals %.2f%% (%d skipped %.2f%%)",
240 blocker.schedule.size (),
241 percent (blocker.schedule.size (), 2.0 * active ()), skipped,
242 percent (skipped, 2.0 * active ()));
243}
bool marked_block(int lit) const
void mark_skip(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ blocked_clause()

void CaDiCaL::Internal::blocked_clause ( Quotient * q,
int not_fresh )

Definition at line 613 of file cadical_factor.cpp.

613 {
614 if (!proof)
615 return;
616 int64_t new_id = ++clause_id;
617 q->bid = new_id;
618 CADICAL_assert (clause.empty ());
619 for (Quotient *p = q; p; p = p->prev)
620 clause.push_back (-p->factor);
621 clause.push_back (not_fresh);
622 CADICAL_assert (!lrat || mini_chain.size ());
623 proof->add_derived_clause (new_id, true, clause, mini_chain);
624 mini_chain.clear ();
625 clause.clear ();
626}
Here is the caller graph for this function:

◆ build_chain_for_empty()

void CaDiCaL::Internal::build_chain_for_empty ( )

Definition at line 89 of file cadical_propagate.cpp.

89 {
90 if (!lrat || !lrat_chain.empty ())
91 return;
93 CADICAL_assert (lrat_chain.empty ());
95 LOG (conflict, "lrat for global empty clause with conflict");
96 for (auto &lit : *conflict) {
97 CADICAL_assert (val (lit) < 0);
98 int64_t id = unit_id (-lit);
99 lrat_chain.push_back (id);
100 }
101 lrat_chain.push_back (conflict->id);
102}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_chain_for_units()

void CaDiCaL::Internal::build_chain_for_units ( int lit,
Clause * reason,
bool forced )

Definition at line 64 of file cadical_propagate.cpp.

65 {
66 if (!lrat)
67 return;
68 if (opts.chrono && assignment_level (lit, reason) && !forced)
69 return;
70 else if (!opts.chrono && level && !forced)
71 return; // not decision level 0
72 CADICAL_assert (lrat_chain.empty ());
73 for (auto &reason_lit : *reason) {
74 if (lit == reason_lit)
75 continue;
76 CADICAL_assert (val (reason_lit));
77 if (!val (reason_lit))
78 continue;
79 const int signed_reason_lit = val (reason_lit) * reason_lit;
80 int64_t id = unit_id (signed_reason_lit);
81 lrat_chain.push_back (id);
82 }
83 lrat_chain.push_back (reason->id);
84}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_lrat_for_clause()

void CaDiCaL::Internal::build_lrat_for_clause ( const vector< vector< Clause * > > & dfs_chains,
bool invert = false )

Definition at line 72 of file cadical_decompose.cpp.

73 {
75 LOG ("building chain for not subsumed clause");
76 CADICAL_assert (lrat_chain.empty ());
77 CADICAL_assert (sign_marked.empty ());
78 // build chain for each replaced literal
79 for (const auto lit : clause) {
80 auto other = lit;
81 if (val (other) > 0) {
82 if (marked_decomposed (other))
83 continue;
84 mark_decomposed (other);
85 int64_t id = unit_id (other);
86 lrat_chain.push_back (id);
87 continue;
88 }
89 CADICAL_assert (mini_chain.empty ());
90 for (auto p : dfs_chains[vlit (other)]) {
91 if (marked_decomposed (other))
92 continue;
93 mark_decomposed (other);
94 int implied = p->literals[0];
95 implied = implied == other ? -p->literals[1] : -implied;
96 LOG ("ADDED %d -> %d (%" PRId64 ")", implied, other, p->id);
97 other = implied;
98 mini_chain.push_back (p->id);
99 if (val (implied) <= 0)
100 continue;
102 break;
104 int64_t id = unit_id (implied);
105 mini_chain.push_back (id);
106 break;
107 }
108 if (invert)
109 for (auto p = mini_chain.rbegin (); p != mini_chain.rend (); p++)
110 lrat_chain.push_back (*p);
111 else
112 for (auto p = mini_chain.begin (); p != mini_chain.end (); p++)
113 lrat_chain.push_back (*p);
114 mini_chain.clear ();
115 }
117 LOG (lrat_chain, "lrat_chain:");
118}
void mark_decomposed(int lit)
void implied(std::vector< int > &entrailed)
vector< int > sign_marked
Definition internal.hpp:269
bool marked_decomposed(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bump_also_all_reason_literals()

void CaDiCaL::Internal::bump_also_all_reason_literals ( )
inline

Definition at line 387 of file cadical_analyze.cpp.

387 {
388 CADICAL_assert (opts.bump);
389 if (!opts.bumpreason)
390 return;
391 if (averages.current.decisions > opts.bumpreasonrate) {
392 LOG ("decisions per conflict rate %g > limit %d",
393 (double) averages.current.decisions, opts.bumpreasonrate);
394 return;
395 }
396 if (delay[stable].bumpreasons.limit) {
397 LOG ("delaying reason bumping %" PRId64 " more times",
398 delay[stable].bumpreasons.limit);
399 delay[stable].bumpreasons.limit--;
400 return;
401 }
402 CADICAL_assert (opts.bumpreasondepth > 0);
403 const int depth_limit = opts.bumpreasondepth + stable;
404 size_t saved_analyzed = analyzed.size ();
405 size_t analyzed_limit = saved_analyzed * opts.bumpreasonlimit;
406 for (const auto &lit : clause)
407 if (analyzed.size () <= analyzed_limit)
408 bump_also_reason_literals (-lit, depth_limit, analyzed_limit);
409 else
410 break;
411 if (analyzed.size () > analyzed_limit) {
412 LOG ("not bumping reason side literals as limit exhausted");
413 for (size_t i = saved_analyzed; i != analyzed.size (); i++) {
414 const int lit = analyzed[i];
415 Flags &f = flags (lit);
416 CADICAL_assert (f.seen);
417 f.seen = false;
418 }
419 delay[stable].bumpreasons.interval++;
420 analyzed.resize (saved_analyzed);
421 } else {
422 LOG ("bumping reasons up to depth %d", opts.bumpreasondepth);
423 delay[stable].bumpreasons.interval /= 2;
424 }
425 LOG ("delay internal %" PRId64, delay[stable].bumpreasons.interval);
426 delay[stable].bumpreasons.limit = delay[stable].bumpreasons.interval;
427}
void bump_also_reason_literals(int lit, int depth_limit, size_t size_limit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bump_also_reason_literal()

bool CaDiCaL::Internal::bump_also_reason_literal ( int lit)
inline

Definition at line 345 of file cadical_analyze.cpp.

345 {
347 CADICAL_assert (val (lit) < 0);
348 Flags &f = flags (lit);
349 if (f.seen)
350 return false;
351 const Var &v = var (lit);
352 if (!v.level)
353 return false;
354 f.seen = true;
355 analyzed.push_back (lit);
356 LOG ("bumping also reason literal %d assigned at level %d", lit, v.level);
357 return true;
358}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bump_also_reason_literals()

void CaDiCaL::Internal::bump_also_reason_literals ( int lit,
int depth_limit,
size_t size_limit )
inline

Definition at line 362 of file cadical_analyze.cpp.

363 {
365 CADICAL_assert (depth_limit > 0);
366 const Var &v = var (lit);
368 if (!v.level)
369 return;
370 Clause *reason = v.reason;
371 if (!reason || reason == external_reason)
372 return;
373 stats.ticks.search[stable]++;
374 for (const auto &other : *reason) {
375 if (other == lit)
376 continue;
377 if (!bump_also_reason_literal (other))
378 continue;
379 if (depth_limit < 2)
380 continue;
381 bump_also_reason_literals (-other, depth_limit - 1, analyzed_limit);
382 if (analyzed.size () > analyzed_limit)
383 break;
384 }
385}
bool bump_also_reason_literal(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bump_clause()

void CaDiCaL::Internal::bump_clause ( Clause * c)
inline

Definition at line 228 of file cadical_analyze.cpp.

228 {
229 LOG (c, "bumping");
230 c->used = max_used;
231 if (c->hyper)
232 return;
233 if (!c->redundant)
234 return;
235 int new_glue = recompute_glue (c);
236 if (new_glue < c->glue)
237 promote_clause (c, new_glue);
238
239 const size_t glue =
240 std::min ((size_t) c->glue, stats.used[stable].size () - 1);
241 ++stats.used[stable][glue];
242 ++stats.bump_used[stable];
243}
const unsigned max_used
Definition internal.hpp:314
void promote_clause(Clause *, int new_glue)
int recompute_glue(Clause *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bump_clause2()

void CaDiCaL::Internal::bump_clause2 ( Clause * c)

Definition at line 245 of file cadical_analyze.cpp.

245{ bump_clause (c); }
Here is the call graph for this function:

◆ bump_queue()

void CaDiCaL::Internal::bump_queue ( int idx)

Definition at line 56 of file cadical_analyze.cpp.

56 {
57 CADICAL_assert (opts.bump);
58 const int idx = vidx (lit);
59 if (!links[idx].next)
60 return;
61 queue.dequeue (links, idx);
62 queue.enqueue (links, idx);
63 CADICAL_assert (stats.bumped != INT64_MAX);
64 btab[idx] = ++stats.bumped;
65 LOG ("moved to front variable %d and bumped to %" PRId64 "", idx,
66 btab[idx]);
67 if (!vals[idx])
69}
void update_queue_unassigned(int idx)
Definition internal.hpp:652
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bump_variable()

void CaDiCaL::Internal::bump_variable ( int lit)

Definition at line 131 of file cadical_analyze.cpp.

131 {
132 if (use_scores ())
134 else
135 bump_queue (lit);
136}
bool use_scores() const
Definition internal.hpp:471
void bump_queue(int idx)
void bump_variable_score(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bump_variable_score()

void CaDiCaL::Internal::bump_variable_score ( int lit)

Definition at line 109 of file cadical_analyze.cpp.

109 {
110 CADICAL_assert (opts.bump);
111 int idx = vidx (lit);
112 double old_score = score (idx);
113 CADICAL_assert (!evsids_limit_hit (old_score));
114 double new_score = old_score + score_inc;
115 if (evsids_limit_hit (new_score)) {
116 LOG ("bumping %g score of %d hits EVSIDS score limit", old_score, idx);
118 old_score = score (idx);
119 CADICAL_assert (!evsids_limit_hit (old_score));
120 new_score = old_score + score_inc;
121 }
122 CADICAL_assert (!evsids_limit_hit (new_score));
123 LOG ("new %g score of %d", new_score, idx);
124 score (idx) = new_score;
125 if (scores.contains (idx))
126 scores.update (idx);
127}
double & score(int lit)
Definition internal.hpp:457
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bump_variable_score_inc()

void CaDiCaL::Internal::bump_variable_score_inc ( )

Definition at line 141 of file cadical_analyze.cpp.

141 {
143 CADICAL_assert (!evsids_limit_hit (score_inc));
144 double f = 1e3 / opts.scorefactor;
145 double new_score_inc = score_inc * f;
146 if (evsids_limit_hit (new_score_inc)) {
147 LOG ("bumping %g increment by %g hits EVSIDS score limit", score_inc,
148 f);
150 new_score_inc = score_inc * f;
151 }
152 CADICAL_assert (!evsids_limit_hit (new_score_inc));
153 LOG ("bumped score increment from %g to %g with factor %g", score_inc,
154 new_score_inc, f);
155 score_inc = new_score_inc;
156}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bump_variables()

void CaDiCaL::Internal::bump_variables ( )

Definition at line 179 of file cadical_analyze.cpp.

179 {
180
181 CADICAL_assert (opts.bump);
182
183 START (bump);
184
185 if (!use_scores ()) {
186
187 // Variables are bumped in the order they are in the current decision
188 // queue. This maintains relative order between bumped variables in
189 // the queue and seems to work best. We also experimented with
190 // focusing on variables of the last decision level, but results were
191 // mixed.
192
193 MSORT (opts.radixsortlim, analyzed.begin (), analyzed.end (),
194 analyze_bumped_rank (this), analyze_bumped_smaller (this));
195 }
196
197 for (const auto &lit : analyzed)
199
200 if (use_scores ())
202
203 STOP (bump);
204}
#define MSORT(LIMIT, FIRST, LAST, RANK, LESS)
Definition radix.hpp:173
void bump_variable(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bumped()

int64_t & CaDiCaL::Internal::bumped ( int lit)
inline

Definition at line 455 of file internal.hpp.

455{ return btab[vidx (lit)]; }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cache_lines() [1/2]

int64_t CaDiCaL::Internal::cache_lines ( size_t bytes)
inline

Definition at line 722 of file internal.hpp.

722{ return (bytes + 127) / 128; }
Here is the caller graph for this function:

◆ cache_lines() [2/2]

int64_t CaDiCaL::Internal::cache_lines ( size_t n,
size_t bytes )
inline

Definition at line 723 of file internal.hpp.

723 {
724 return cache_lines (n * bytes);
725 }
int64_t cache_lines(size_t bytes)
Definition internal.hpp:722
Here is the call graph for this function:

◆ cadical_kitten_ticks_limit_hit()

bool CaDiCaL::Internal::cadical_kitten_ticks_limit_hit ( Sweeper & sweeper,
const char * when )

Definition at line 201 of file cadical_sweep.cpp.

201 {
202 const uint64_t current =
204 if (current >= sweeper.limit.ticks) {
205 LOG ("'cadical_kitten_ticks' limit of %" PRIu64 " ticks hit after %" PRIu64
206 " ticks during %s",
207 sweeper.limit.ticks, current, when);
208 return true;
209 }
210#ifndef LOGGING
211 (void) when;
212#endif
213 return false;
214}
uint64_t cadical_kitten_current_ticks(cadical_kitten *cadical_kitten)
struct sweeper::@220272220222261246232307276064033320167134062222 limit
uint64_t ticks
Definition sweep.c:35
Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_minimize_chain()

void CaDiCaL::Internal::calculate_minimize_chain ( int lit,
std::vector< int > & stack )

Definition at line 159 of file cadical_minimize.cpp.

159 {
160 CADICAL_assert (stack.empty ());
161 stack.push_back (vidx (lit));
162
163 while (!stack.empty ()) {
164 const int idx = stack.back ();
165 CADICAL_assert (idx);
166 stack.pop_back ();
167 if (idx < 0) {
168 Var &v = var (idx);
169 mini_chain.push_back (v.reason->id);
170 continue;
171 }
172 CADICAL_assert (idx);
173 Flags &f = flags (idx);
174 Var &v = var (idx);
175 if (f.keep || f.added || f.poison) {
176 continue;
177 }
178 if (!v.level) {
179 if (f.seen)
180 continue;
181 f.seen = true;
182 unit_analyzed.push_back (idx);
183 const int lit = val (idx) > 0 ? idx : -idx;
184 int64_t id = unit_id (lit);
185 unit_chain.push_back (id);
186 continue;
187 }
188 f.added = true;
189 CADICAL_assert (v.reason && f.removable);
190 const const_literal_iterator end = v.reason->end ();
192 LOG (v.reason, "LRAT chain for lit %d at depth %zd by going over", lit,
193 stack.size ());
194 stack.push_back (-idx);
195 for (i = v.reason->begin (); i != end; i++) {
196 const int other = *i;
197 if (other == idx)
198 continue;
199 stack.push_back (vidx (other));
200 }
201 }
202 CADICAL_assert (stack.empty ());
203}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ can_sweep_clause()

bool CaDiCaL::Internal::can_sweep_clause ( Clause * c)

Definition at line 68 of file cadical_sweep.cpp.

68 {
69 if (c->garbage)
70 return false;
71 if (!c->redundant)
72 return true;
73 return c->size == 2; // && !c->hyper; // could ignore hyper
74}
Here is the caller graph for this function:

◆ cdcl_loop_with_inprocessing()

int CaDiCaL::Internal::cdcl_loop_with_inprocessing ( )

Definition at line 276 of file cadical_internal.cpp.

276 {
277
278 int res = 0;
279
280 START (search);
281
282 if (stable) {
283 START (stable);
284 report ('[');
285 } else {
286 START (unstable);
287 report ('{');
288 }
289
290 while (!res) {
291 if (unsat)
292 res = 20;
293 else if (unsat_constraint)
294 res = 20;
295 else if (!propagate_wrapper ())
296 analyze_wrapper (); // propagate and analyze
297 else if (iterating)
298 iterate (); // report learned unit
299 else if (!external_propagate () || unsat) { // external propagation
300 if (unsat)
301 continue;
302 else
303 analyze ();
304 } else if (satisfied ()) { // found model
305 if (!external_check_solution () || unsat) {
306 if (unsat)
307 continue;
308 else
309 analyze ();
310 } else if (satisfied ())
311 res = 10;
312 } else if (search_limits_hit ())
313 break; // decision or conflict limit
314 else if (terminated_asynchronously ()) // externally terminated
315 break;
316 else if (restarting ())
317 restart (); // restart by backtracking
318 else if (rephasing ())
319 rephase (); // reset variable phases
320 else if (reducing ())
321 reduce (); // collect useless clauses
322 else if (inprobing ())
323 inprobe (); // schedule of inprocessing
324 else if (ineliminating ())
325 elim (); // variable elimination
326 else if (compacting ())
327 compact (); // collect variables
328 else if (conditioning ())
329 condition (); // globally blocked clauses
330 else
331 res = decide (); // next decision
332 }
333
334 if (stable) {
335 STOP (stable);
336 report (']');
337 } else {
338 STOP (unstable);
339 report ('}');
340 }
341
342 STOP (search);
343
344 return res;
345}
#define propagate_wrapper
Definition internal.hpp:739
#define analyze_wrapper
Definition internal.hpp:740
void inprobe(bool update_limits=true)
void condition(bool update_limits=true)
void elim(bool update_limits=true)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check()

void CaDiCaL::Internal::check ( )

Definition at line 162 of file cadical_proof.cpp.

162 {
164 if (opts.checkproof > 1) {
165 StatTracer *lratchecker = new LratChecker (this);
166 DeferDeletePtr<LratChecker> delete_lratchecker (
167 (LratChecker *) lratchecker);
168 LOG ("PROOF connecting LRAT proof checker");
169 force_lrat ();
170 frat = true;
172 proof->connect (lratchecker);
173 stat_tracers.push_back (lratchecker);
174 delete_lratchecker.release ();
175 }
176 if (opts.checkproof == 1 || opts.checkproof == 3) {
177 StatTracer *checker = new Checker (this);
178 DeferDeletePtr<Checker> delete_checker ((Checker *) checker);
179 LOG ("PROOF connecting proof checker");
180 proof->connect (checker);
181 stat_tracers.push_back (checker);
182 delete_checker.release ();
183 }
184}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_clause_stats()

void CaDiCaL::Internal::check_clause_stats ( )

Definition at line 452 of file cadical_collect.cpp.

452 {
453#ifndef CADICAL_NDEBUG
454 int64_t irredundant = 0, redundant = 0, total = 0, irrlits = 0;
455 for (const auto &c : clauses) {
456 if (c->garbage)
457 continue;
458 if (c->redundant)
459 redundant++;
460 else
461 irredundant++;
462 if (!c->redundant)
463 irrlits += c->size;
464 total++;
465 }
466 CADICAL_assert (stats.current.irredundant == irredundant);
467 CADICAL_assert (stats.current.redundant == redundant);
468 CADICAL_assert (stats.current.total == total);
469 CADICAL_assert (stats.irrlits == irrlits);
470#endif
471}
int64_t irredundant() const
Definition internal.hpp:383
int64_t redundant() const
Definition internal.hpp:381
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_var_stats()

void CaDiCaL::Internal::check_var_stats ( )

Definition at line 15 of file cadical_var.cpp.

15 {
16#ifndef CADICAL_NDEBUG
17 int64_t fixed = 0, eliminated = 0, substituted = 0, pure = 0, unused = 0;
18 for (auto idx : vars) {
19 Flags &f = flags (idx);
20 if (f.active ())
21 continue;
22 if (f.fixed ())
23 fixed++;
24 if (f.eliminated ())
25 eliminated++;
26 if (f.substituted ())
27 substituted++;
28 if (f.unused ())
29 unused++;
30 if (f.pure ())
31 pure++;
32 }
33 CADICAL_assert (stats.now.fixed == fixed);
34 CADICAL_assert (stats.now.eliminated == eliminated);
35 CADICAL_assert (stats.now.substituted == substituted);
36 CADICAL_assert (stats.now.pure == pure);
37 int64_t inactive = unused + fixed + eliminated + substituted + pure;
38 CADICAL_assert (stats.inactive == inactive);
39 CADICAL_assert (max_var == stats.active + stats.inactive);
40#endif
41}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_watched_literal_invariants()

void CaDiCaL::Internal::check_watched_literal_invariants ( )

Definition at line 1085 of file cadical_external_propagate.cpp.

1085 {
1086#ifndef CADICAL_NDEBUG
1087 int v0 = 0;
1088 int v1 = 0;
1089
1090 if (val (clause[0]) > 0)
1091 v0 = 1;
1092 else if (val (clause[0]) < 0)
1093 v0 = -1;
1094
1095 if (val (clause[1]) > 0)
1096 v1 = 1;
1097 else if (val (clause[1]) < 0)
1098 v1 = -1;
1099 CADICAL_assert (v0 >= v1);
1100#endif
1101 if (val (clause[0]) > 0) {
1102 if (val (clause[1]) > 0) { // Case 1: Both literals are satisfied
1103 // They are ordered by lower to higher decision level
1104 CADICAL_assert (var (clause[0]).level <= var (clause[1]).level);
1105
1106 // Every other literal of the clause is either
1107 // - satisfied at higher level
1108 // - unassigned
1109 // - falsified
1110 for (size_t i = 2; i < clause.size (); i++)
1111 CADICAL_assert (val (clause[i]) <= 0 ||
1112 (var (clause[1]).level <= var (clause[i]).level));
1113
1114 } else if (val (clause[1]) ==
1115 0) { // Case 2: First satisfied, next unassigned
1116
1117 // Every other literal of the clause is either
1118 // - unassigned
1119 // - falsified
1120 for (size_t i = 2; i < clause.size (); i++)
1121 CADICAL_assert (val (clause[i]) <= 0);
1122
1123 } else { // Case 3: First satisfied, next falsified -> could have been a
1124 // reason of a previous propagation
1125 // Every other literal of the clause is falsified but at a lower
1126 // decision level
1127 for (size_t i = 2; i < clause.size (); i++)
1128 CADICAL_assert (val (clause[i]) < 0 &&
1129 (var (clause[1]).level >= var (clause[i]).level));
1130 }
1131 } else if (val (clause[0]) == 0) {
1132 if (val (clause[1]) == 0) { // Case 4: Both literals are unassigned
1133
1134 // Every other literal of the clause is either
1135 // - unassigned
1136 // - falsified
1137 for (size_t i = 2; i < clause.size (); i++)
1138 CADICAL_assert (val (clause[i]) <= 0);
1139
1140 } else { // Case 5: First unassigned, next falsified -> PROPAGATE
1141 // Every other literal of the clause is falsified but at a lower
1142 // decision level
1143 for (size_t i = 2; i < clause.size (); i++)
1144 CADICAL_assert (val (clause[i]) < 0 &&
1145 (var (clause[1]).level >= var (clause[i]).level));
1146 }
1147 } else {
1148 CADICAL_assert (val (clause[0]) < 0 &&
1149 val (clause[1]) < 0); // Case 6: Both literals are falsified
1150
1151 // They are ordered by higher to lower decision level
1152 CADICAL_assert (var (clause[0]).level >= var (clause[1]).level);
1153
1154 // Every other literal of the clause is falsified, but at a lower level
1155 for (size_t i = 2; i < clause.size (); i++)
1156 CADICAL_assert (val (clause[i]) < 0 &&
1157 (var (clause[1]).level >= var (clause[i]).level));
1158 }
1159}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ citten2lit()

int CaDiCaL::Internal::citten2lit ( unsigned ulit)
inline

Definition at line 421 of file internal.hpp.

421 {
422 int res = (ulit / 2) + 1;
423 CADICAL_assert (res <= max_var);
424 if (ulit & 1)
425 res = -res;
426 return res;
427 }

◆ citten_clear_track_log_terminate()

void CaDiCaL::Internal::citten_clear_track_log_terminate ( )

Definition at line 482 of file cadical_sweep.cpp.

482 {
486 if (external->terminator)
487 cadical_kitten_set_terminator (citten, internal, citten_terminate);
488#ifdef LOGGING
489 if (opts.log)
490 cadical_kitten_set_logging (citten);
491#endif
492}
void cadical_kitten_set_terminator(cadical_kitten *cadical_kitten, void *data, int(*terminator)(void *))
void cadical_kitten_clear(cadical_kitten *cadical_kitten)
void cadical_kitten_track_antecedents(cadical_kitten *cadical_kitten)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clause_contains_fixed_literal()

int CaDiCaL::Internal::clause_contains_fixed_literal ( Clause * c)

Definition at line 16 of file cadical_collect.cpp.

16 {
17 int satisfied = 0, falsified = 0;
18 for (const auto &lit : *c) {
19 const int tmp = fixed (lit);
20 if (tmp > 0) {
21 LOG (c, "root level satisfied literal %d in", lit);
22 satisfied++;
23 }
24 if (tmp < 0) {
25 LOG (c, "root level falsified literal %d in", lit);
26 falsified++;
27 }
28 }
29 if (satisfied)
30 return 1;
31 else if (falsified)
32 return -1;
33 else
34 return 0;
35}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clause_variable_ratio()

double CaDiCaL::Internal::clause_variable_ratio ( ) const
inline

Definition at line 385 of file internal.hpp.

385 {
386 return relative (irredundant (), active ());
387 }
double relative(double a, double b)
Definition util.hpp:20
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clean_probehbr_lrat()

void CaDiCaL::Internal::clean_probehbr_lrat ( )

Definition at line 58 of file cadical_probe.cpp.

58 {
59 if (!lrat || opts.probehbr)
60 return;
61 for (auto &field : probehbr_chains) {
62 for (auto &chain : field) {
63 chain.clear ();
64 }
65 }
66}
vector< vector< vector< int64_t > > > probehbr_chains
Definition internal.hpp:216
Here is the caller graph for this function:

◆ clear_analyzed_levels()

void CaDiCaL::Internal::clear_analyzed_levels ( )

Definition at line 466 of file cadical_analyze.cpp.

466 {
467 LOG ("clearing %zd analyzed levels", levels.size ());
468 for (const auto &l : levels)
469 if (l < (int) control.size ())
470 control[l].reset ();
471 levels.clear ();
472}
Here is the caller graph for this function:

◆ clear_analyzed_literals()

void CaDiCaL::Internal::clear_analyzed_literals ( )

Definition at line 445 of file cadical_analyze.cpp.

445 {
446 LOG ("clearing %zd analyzed literals", analyzed.size ());
447 for (const auto &lit : analyzed) {
448 Flags &f = flags (lit);
449 CADICAL_assert (f.seen);
450 f.seen = false;
451 CADICAL_assert (!f.keep);
452 CADICAL_assert (!f.poison);
453 CADICAL_assert (!f.removable);
454 }
455 analyzed.clear ();
456#if 0 // to expensive, even for debugging mode
457 if (unit_analyzed.size ())
458 return;
459 for (auto idx : vars) {
460 Flags &f = flags (idx);
461 CADICAL_assert (!f.seen);
462 }
463#endif
464}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clear_core()

void CaDiCaL::Internal::clear_core ( Sweeper & sweeper,
unsigned core_idx )

Definition at line 612 of file cadical_sweep.cpp.

612 {
613 CADICAL_assert (core_idx == 0 || core_idx == 1);
614 LOG ("clearing core[%u] lemmas", core_idx);
615 vector<sweep_proof_clause> &core = sweeper.core[core_idx];
616 if (proof) {
617 LOG ("deleting sub-solver core clauses");
618 for (auto &pc : core) {
619 if (pc.learned && pc.literals.size () > 1)
620 proof->delete_clause (pc.cad_id, true, pc.literals);
621 }
622 }
623 core.clear ();
624}
Here is the caller graph for this function:

◆ clear_flauses()

void CaDiCaL::Internal::clear_flauses ( vector< Clause * > & flauses)

Definition at line 209 of file cadical_factor.cpp.

209 {
210 for (auto c : flauses) {
211 CADICAL_assert (c->swept);
212 c->swept = false;
213 }
214 flauses.clear ();
215}
Here is the caller graph for this function:

◆ clear_minimized_literals()

void CaDiCaL::Internal::clear_minimized_literals ( )

Definition at line 215 of file cadical_minimize.cpp.

215 {
216 LOG ("clearing %zd minimized literals", minimized.size ());
217 for (const auto &lit : minimized) {
218 Flags &f = flags (lit);
219 f.poison = f.removable = f.shrinkable = f.added = false;
220 }
221 for (const auto &lit : clause)
223 flags (lit).shrinkable =
224 flags (lit).added = false;
225 minimized.clear ();
226}
vector< int > shrinkable
Definition internal.hpp:271
vector< int > minimized
Definition internal.hpp:270
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clear_noccs()

void CaDiCaL::Internal::clear_noccs ( )

Definition at line 43 of file cadical_occs.cpp.

43 {
44 CADICAL_assert (!ntab.empty ());
45 for (auto &nt : ntab)
46 nt = 0;
47 LOG ("clear two-sided occurrence counters");
48}
vector< int64_t > ntab
Definition internal.hpp:239

◆ clear_nounted()

void CaDiCaL::Internal::clear_nounted ( vector< int > & nounted)

Definition at line 201 of file cadical_factor.cpp.

201 {
202 for (const auto &lit : nounted) {
205 }
206 nounted.clear ();
207}
#define NOUNTED
void unmarkfact(int lit, int fact)
Definition internal.hpp:599
bool getfact(int lit, int fact) const
Definition internal.hpp:568
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clear_occs()

void CaDiCaL::Internal::clear_occs ( )

Definition at line 25 of file cadical_occs.cpp.

25 {
27 for (auto &occ : otab)
28 occ.clear ();
29 LOG ("clear occurrence lists");
30}
vector< Occs > otab
Definition internal.hpp:236
Here is the call graph for this function:

◆ clear_phases()

void CaDiCaL::Internal::clear_phases ( vector< signed char > & dst)

Definition at line 16 of file cadical_phases.cpp.

16 {
17 START (copy);
18 for (auto i : vars)
19 dst[i] = 0;
20 STOP (copy);
21}
Here is the caller graph for this function:

◆ clear_sign_marked_literals()

void CaDiCaL::Internal::clear_sign_marked_literals ( )

Definition at line 120 of file cadical_decompose.cpp.

120 {
121 LOG ("clearing %zd marked literals", sign_marked.size ());
122 for (const auto &lit : sign_marked) {
123 // CADICAL_assert (marked_signed (lit)); violated on purpose in factor
125 }
126 sign_marked.clear ();
127}
void unmark_decomposed(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clear_sweeper()

void CaDiCaL::Internal::clear_sweeper ( Sweeper & sweeper)

Definition at line 298 of file cadical_sweep.cpp.

298 {
299 LOG ("clearing sweeping environment");
301
303 for (auto &idx : sweeper.vars) {
305 sweeper.depths[idx] = 0;
306 }
307 sweeper.vars.clear ();
308 for (auto c : sweeper.clauses) {
309 CADICAL_assert (c->swept);
310 c->swept = false;
311 }
312 sweeper.clauses.clear ();
313 sweeper.backbone.clear ();
314 sweeper.partition.clear ();
315 sweeper.encoded = 0;
317}
void citten_clear_track_log_terminate()
void sweep_set_cadical_kitten_ticks_limit(Sweeper &sweeper)
unsigneds backbone
Definition sweep.c:31
unsigneds partition
Definition sweep.c:32
unsigned encoded
Definition sweep.c:26
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clear_unit_analyzed_literals()

void CaDiCaL::Internal::clear_unit_analyzed_literals ( )

Definition at line 431 of file cadical_analyze.cpp.

431 {
432 LOG ("clearing %zd unit analyzed literals", unit_analyzed.size ());
433 for (const auto &lit : unit_analyzed) {
434 Flags &f = flags (lit);
435 CADICAL_assert (f.seen);
437 f.seen = false;
438 CADICAL_assert (!f.keep);
439 CADICAL_assert (!f.poison);
440 CADICAL_assert (!f.removable);
441 }
442 unit_analyzed.clear ();
443}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clear_watches()

void CaDiCaL::Internal::clear_watches ( )

Definition at line 16 of file cadical_watch.cpp.

16 {
17 for (auto lit : lits)
18 watches (lit).clear ();
19}
vector watches
Definition watch.h:49
Here is the caller graph for this function:

◆ close_trace()

void CaDiCaL::Internal::close_trace ( bool stats = false)

Definition at line 188 of file cadical_proof.cpp.

188 {
189 for (auto &tracer : file_tracers)
190 tracer->close (print);
191}

◆ collect_instantiation_candidates()

void CaDiCaL::Internal::collect_instantiation_candidates ( Instantiator & instantiator)

Definition at line 18 of file cadical_instantiate.cpp.

19 {
21 for (auto idx : vars) {
22 if (frozen (idx))
23 continue;
24 if (!active (idx))
25 continue;
26 if (flags (idx).elim)
27 continue; // BVE attempt pending
28 for (int sign = -1; sign <= 1; sign += 2) {
29 const int lit = sign * idx;
30 if (noccs (lit) > opts.instantiateocclim)
31 continue;
32 Occs &os = occs (lit);
33 for (const auto &c : os) {
34 if (c->garbage)
35 continue;
36 if (opts.instantiateonce && c->instantiated)
37 continue;
38 if (c->size < opts.instantiateclslim)
39 continue;
40 bool satisfied = false;
41 int unassigned = 0;
42 for (const auto &other : *c) {
43 const signed char tmp = val (other);
44 if (tmp > 0)
45 satisfied = true;
46 if (!tmp)
47 unassigned++;
48 }
49 if (satisfied)
50 continue;
51 if (unassigned < 3)
52 continue; // avoid learning units
53 size_t negoccs = occs (-lit).size ();
54 LOG (c,
55 "instantiation candidate literal %d "
56 "with %zu negative occurrences in",
57 lit, negoccs);
58 instantiator.candidate (lit, c, c->size, negoccs);
59 }
60 }
61 }
62}
unsigned size
Definition vector.h:35
Here is the call graph for this function:
Here is the caller graph for this function:

◆ compact()

void CaDiCaL::Internal::compact ( )

Definition at line 166 of file cadical_compact.cpp.

166 {
167
168 START (compact);
169
171
172 stats.compacts++;
173
177 CADICAL_assert (clause.empty ());
178 CADICAL_assert (levels.empty ());
179 CADICAL_assert (analyzed.empty ());
180 CADICAL_assert (minimized.empty ());
181 CADICAL_assert (control.size () == 1);
182 CADICAL_assert (propagated == trail.size ());
183
185
186 Mapper mapper (this);
187
188 if (mapper.first_fixed)
189 LOG ("found first fixed %d",
190 sign (mapper.first_fixed_val) * mapper.first_fixed);
191 else
192 LOG ("no variable fixed");
193
194 if (!assumptions.empty ()) {
195 CADICAL_assert (!external->assumptions.empty ());
196 LOG ("temporarily reset internal assumptions");
198 }
199
200 const bool is_constraint = !constraint.empty ();
201 if (is_constraint) {
202 CADICAL_assert (!external->constraint.empty ());
203 LOG ("temporarily reset internal constraint");
205 }
206
207 /*======================================================================*/
208 // In this first part we only map stuff without reallocation / shrinking.
209 /*======================================================================*/
210
211 // Flush the external indices. This has to occur before we map 'vals'.
212 // Also fixes external units.
213 //
214 for (auto eidx : external->vars) {
215 int src = external->e2i[eidx];
216 if (!src) {
217 continue;
218 }
219 if (lrat || frat) {
220 CADICAL_assert (eidx > 0);
221 CADICAL_assert (external->ext_units.size () >= (size_t) 2 * eidx + 1);
222 int64_t id1 = external->ext_units[2 * eidx];
223 int64_t id2 = external->ext_units[2 * eidx + 1];
224 CADICAL_assert (!id1 || !id2);
225 if (!id1 && !id2) {
226 int64_t new_id1 = unit_clauses (2 * src);
227 int64_t new_id2 = unit_clauses (2 * src + 1);
228 external->ext_units[2 * eidx] = new_id1;
229 external->ext_units[2 * eidx + 1] = new_id2;
230 }
231 }
232 int dst = mapper.map_lit (src);
233 LOG ("compact %" PRId64
234 " maps external %d to internal %d from internal %d",
235 stats.compacts, eidx, dst, src);
236 external->e2i[eidx] = dst;
237 }
238
239 // Delete garbage units. Needs to occur before resizing unit_clauses
240 //
241 if (lrat || frat) {
242 for (auto src : internal->vars) {
243 const int dst = mapper.map_idx (src);
244 CADICAL_assert (dst <= src);
245 const signed char tmp = internal->val (src);
246 if (!dst && !tmp) {
247 unit_clauses (2 * src) = 0;
248 unit_clauses (2 * src + 1) = 0;
249 continue;
250 }
251 if (!tmp || src == mapper.first_fixed) {
252 CADICAL_assert (0 < dst);
253 if (dst == src)
254 continue;
255 CADICAL_assert (!unit_clauses (2 * dst) && !unit_clauses (2 * dst + 1));
256 unit_clauses (2 * dst) = unit_clauses (2 * src);
257 unit_clauses (2 * dst + 1) = unit_clauses (2 * src + 1);
258 unit_clauses (2 * src) = 0;
259 unit_clauses (2 * src + 1) = 0;
260 continue;
261 }
262 int64_t id = unit_clauses (2 * src);
263 int lit = src;
264 if (!id) {
265 id = unit_clauses (2 * src + 1);
266 lit = -lit;
267 }
268 unit_clauses (2 * src) = 0;
269 unit_clauses (2 * src + 1) = 0;
270 CADICAL_assert (id);
271 }
272 unit_clauses_idx.resize (2 * mapper.new_vsize);
274 }
275 // Map the literals in all clauses.
276 //
277 for (const auto &c : clauses) {
278 CADICAL_assert (!c->garbage);
279 for (auto &src : *c) {
280 CADICAL_assert (!val (src));
281 int dst;
282 dst = mapper.map_lit (src);
283 CADICAL_assert (dst || c->garbage);
284 src = dst;
285 }
286 }
287
288 // Map the blocking literals in all watches.
289 //
290 if (!wtab.empty ())
291 for (auto lit : lits)
292 for (auto &w : watches (lit))
293 w.blit = mapper.map_lit (w.blit);
294
295 // We first flush inactive variables and map the links in the queue. This
296 // has to be done before we map the actual links data structure 'links'.
297 {
298 int prev = 0, mapped_prev = 0, next;
299 for (int idx = queue.first; idx; idx = next) {
300 next = links[idx].next;
301 if (idx == mapper.first_fixed)
302 continue;
303 const int dst = mapper.map_idx (idx);
304 if (!dst)
305 continue;
306 CADICAL_assert (active (idx));
307 if (prev)
308 links[prev].next = dst;
309 else
310 queue.first = dst;
311 links[idx].prev = mapped_prev;
312 mapped_prev = dst;
313 prev = idx;
314 }
315 if (prev)
316 links[prev].next = 0;
317 else
318 queue.first = 0;
319 queue.unassigned = queue.last = mapped_prev;
320 }
321
322 /*======================================================================*/
323 // In the second part we map, flush and shrink arrays.
324 /*======================================================================*/
325
326 CADICAL_assert (trail.size () == num_assigned);
327 mapper.map_flush_and_shrink_lits (trail);
328 propagated = trail.size ();
329 num_assigned = trail.size ();
330 if (mapper.first_fixed) {
331 CADICAL_assert (trail.size () == 1);
332 var (mapper.first_fixed).trail = 0; // before mapping 'vtab'
333 } else
334 CADICAL_assert (trail.empty ());
335
336 if (!probes.empty ())
337 mapper.map_flush_and_shrink_lits (probes);
338
339 if (!sweep_schedule.empty ())
340 mapper.map_flush_and_shrink_lits (sweep_schedule);
341
342 /*======================================================================*/
343 // In the third part we map stuff and also reallocate memory.
344 /*======================================================================*/
345
346 // Now we continue in reverse order of allocated bytes, e.g., see
347 // 'Internal::enlarge' which reallocates in order of allocated bytes.
348
349 mapper.map_vector (ftab);
350 mapper.map_vector (parents);
351 mapper.map_vector (marks);
352 mapper.map_vector (phases.saved);
353 mapper.map_vector (phases.forced);
354 mapper.map_vector (phases.target);
355 mapper.map_vector (phases.best);
356 mapper.map_vector (phases.prev);
357 mapper.map_vector (phases.min);
358
359 // Special code for 'frozentab'.
360 //
361 for (auto src : vars) {
362 const int dst = abs (mapper.map_lit (src));
363 if (!dst)
364 continue;
365 if (src == dst)
366 continue;
367 CADICAL_assert (dst < src);
368 if ((size_t) src >= frozentab.size ())
369 break;
370 if ((size_t) dst >= frozentab.size ())
371 break;
372 frozentab[dst] += frozentab[src];
373 frozentab[src] = 0;
374 }
375 frozentab.resize (min (frozentab.size (), mapper.new_vsize));
377
378 // Special code for 'relevanttab'.
379 //
380 if (external) {
381 for (auto src : vars) {
382 const int dst = abs (mapper.map_lit (src));
383 if (!dst)
384 continue;
385 if (src == dst)
386 continue;
387 CADICAL_assert (dst < src);
388
389 relevanttab[dst] += relevanttab[src];
390 relevanttab[src] = 0;
391 }
392 relevanttab.resize (mapper.new_vsize);
394 }
395
396 /*----------------------------------------------------------------------*/
397
398 if (!external->assumptions.empty ()) {
399
400 for (const auto &elit : external->assumptions) {
401 CADICAL_assert (elit);
402 CADICAL_assert (elit != INT_MIN);
403 int eidx = abs (elit);
404 CADICAL_assert (eidx <= external->max_var);
405 int ilit = external->e2i[eidx];
406 CADICAL_assert (ilit); // Because we froze all!!!
407 if (elit < 0)
408 ilit = -ilit;
409 assume (ilit);
410 }
411
412 PHASE ("compact", stats.compacts, "reassumed %zd external assumptions",
413 external->assumptions.size ());
414 }
415
416 // Special case for 'val' as for 'val' we trade branch less code for
417 // memory and always allocated an [-maxvar,...,maxvar] array.
418 {
419 signed char *new_vals = new signed char[2 * mapper.new_vsize];
420 ignore_clang_analyze_memory_leak_warning = new_vals;
421 new_vals += mapper.new_vsize;
422 for (auto src : vars)
423 new_vals[-mapper.map_idx (src)] = vals[-src];
424 for (auto src : vars)
425 new_vals[mapper.map_idx (src)] = vals[src];
426 new_vals[0] = 0;
427 vals -= vsize;
428 delete[] vals;
429 vals = new_vals;
430 vsize = mapper.new_vsize;
431 }
432
433 // 'constrain' uses 'val', so this code has to be after remapping that
434 if (is_constraint) {
436 CADICAL_assert (!external->constraint.back ());
437 for (auto elit : external->constraint) {
438 CADICAL_assert (elit != INT_MIN);
439 int eidx = abs (elit);
440 CADICAL_assert (eidx <= external->max_var);
441 int ilit = external->e2i[eidx];
442 CADICAL_assert (!ilit == !elit);
443 if (elit < 0)
444 ilit = -ilit;
445 LOG ("re adding lit external %d internal %d to constraint", elit,
446 ilit);
447 constrain (ilit);
448 }
449 PHASE ("compact", stats.compacts,
450 "added %zd external literals to constraint",
451 external->constraint.size () - 1);
452 }
453
454 mapper.map_vector (i2e);
455 mapper.map2_vector (ptab);
456 mapper.map_vector (btab);
457 mapper.map_vector (gtab);
458 mapper.map_vector (links);
459 mapper.map_vector (vtab);
460 if (!ntab.empty ())
461 mapper.map2_vector (ntab);
462 if (!wtab.empty ())
463 mapper.map2_vector (wtab);
464 if (!otab.empty ())
465 mapper.map2_vector (otab);
466 if (!rtab.empty ())
467 mapper.map2_vector (rtab);
468 if (!big.empty ())
469 mapper.map2_vector (big);
470
471 /*======================================================================*/
472 // In the fourth part we map the binary heap for scores.
473 /*======================================================================*/
474
475 // The simplest way to map a binary heap is to get all elements from the
476 // heap and reinsert them. This could be slightly improved in terms of
477 // speed if we add a 'flush (int * map)' function to 'Heap', but that is
478 // pretty complicated and would require that the 'Heap' knows that mapped
479 // elements with 'zero' destination should be flushed.
480
481 vector<int> saved;
482 CADICAL_assert (saved.empty ());
483 if (!scores.empty ()) {
484 while (!scores.empty ()) {
485 const int src = scores.front ();
486 scores.pop_front ();
487 const int dst = mapper.map_idx (src);
488 if (!dst)
489 continue;
490 if (src == mapper.first_fixed)
491 continue;
492 saved.push_back (dst);
493 }
494 scores.erase ();
495 }
496 mapper.map_vector (stab);
497 if (!saved.empty ()) {
498 for (const auto idx : saved)
499 scores.push_back (idx);
500 scores.shrink ();
501 }
502
503 /*----------------------------------------------------------------------*/
504
505 PHASE ("compact", stats.compacts,
506 "reducing internal variables from %d to %d", max_var,
507 mapper.new_max_var);
508
509 /*----------------------------------------------------------------------*/
510
511 // Need to adjust the target and best assigned counters too.
512
513 size_t new_target_assigned = 0, new_best_assigned = 0;
514
515 for (auto idx : Range (mapper.new_max_var)) {
516 if (phases.target[idx])
517 new_target_assigned++;
518 if (phases.best[idx])
519 new_best_assigned++;
520 }
521
522 LOG ("reset target assigned from %zd to %zd", target_assigned,
523 new_target_assigned);
524 LOG ("reset best assigned from %zd to %zd", best_assigned,
525 new_best_assigned);
526
527 target_assigned = new_target_assigned;
528 best_assigned = new_best_assigned;
530 notified = 0;
531
532 INIT_EMA (averages.current.trail.fast, opts.ematrailfast);
533 INIT_EMA (averages.current.trail.slow, opts.ematrailslow);
534
535 /*----------------------------------------------------------------------*/
536
537 max_var = mapper.new_max_var;
538
539 stats.unused = 0;
540 stats.inactive = stats.now.fixed = mapper.first_fixed ? 1 : 0;
541 stats.now.substituted = stats.now.eliminated = stats.now.pure = 0;
542
544
545 int64_t delta = opts.compactint * (stats.compacts + 1);
546 lim.compact = stats.conflicts + delta;
547
548 PHASE ("compact", stats.compacts,
549 "new compact limit %" PRId64 " after %" PRId64 " conflicts",
550 lim.compact, delta);
551
552 STOP (compact);
553}
#define INIT_EMA(E, WINDOW)
Definition ema.hpp:61
void shrink_vector(std::vector< T > &v)
Definition util.hpp:101
vector< int > ptab
Definition internal.hpp:238
vector< unsigned > frozentab
Definition internal.hpp:223
vector< int64_t > gtab
Definition internal.hpp:235
vector< int64_t > unit_clauses_idx
Definition internal.hpp:209
vector< Var > vtab
Definition internal.hpp:231
vector< int > i2e
Definition internal.hpp:224
vector< int > sweep_schedule
Definition internal.hpp:274
vector< Occs > rtab
Definition internal.hpp:237
vector< signed char > marks
Definition internal.hpp:222
vector< int > parents
Definition internal.hpp:232
vector< int > probes
Definition internal.hpp:281
Watches & watches(int lit)
Definition internal.hpp:467
vector< Watches > wtab
Definition internal.hpp:241
vector< Flags > ftab
Definition internal.hpp:233
int trail
Definition var.hpp:20
Here is the call graph for this function:
Here is the caller graph for this function:

◆ compacting()

bool CaDiCaL::Internal::compacting ( )

Definition at line 17 of file cadical_compact.cpp.

17 {
18 if (level)
19 return false;
20 if (!opts.compact)
21 return false;
22 if (stats.conflicts < lim.compact)
23 return false;
24 int inactive = max_var - active ();
25 CADICAL_assert (inactive >= 0);
26 if (!inactive)
27 return false;
28 if (inactive < opts.compactmin)
29 return false;
30 return inactive >= (1e-3 * opts.compactlim) * max_var;
31}
int active() const
Definition internal.hpp:362
Here is the call graph for this function:
Here is the caller graph for this function:

◆ compute_elim_score()

double CaDiCaL::Internal::compute_elim_score ( unsigned lit)
inline

Definition at line 25 of file cadical_elim.cpp.

25 {
26 CADICAL_assert (1 <= lit), CADICAL_assert (lit <= (unsigned) max_var);
27 const unsigned uidx = 2 * lit;
28 const double pos = internal->ntab[uidx];
29 const double neg = internal->ntab[uidx + 1];
30 if (!pos)
31 return -neg;
32 if (!neg)
33 return -pos;
34 double sum = 0, prod = 0;
35 if (opts.elimsum)
36 sum = opts.elimsum * (pos + neg);
37 if (opts.elimprod)
38 prod = opts.elimprod * (pos * neg);
39 return prod + sum;
40}

◆ compute_tier_limits()

void CaDiCaL::Internal::compute_tier_limits ( Vivifier & vivifier)

Definition at line 1792 of file cadical_vivify.cpp.

1792 {
1793 if (!opts.vivifycalctier) {
1794 vivifier.tier1_limit = 2;
1795 vivifier.tier2_limit = 6;
1796 return;
1797 }
1798 vivifier.tier1_limit = tier1[false];
1799 vivifier.tier2_limit = tier2[false];
1800}
struct vivifier vivifier
Definition vivify.c:167
Here is the caller graph for this function:

◆ conclude_unsat()

void CaDiCaL::Internal::conclude_unsat ( )

Definition at line 465 of file cadical_assume.cpp.

465 {
466 if (!proof || concluded)
467 return;
468 concluded = true;
469 if (!marked_failed) {
470 CADICAL_assert (conclusion.empty ());
471 if (!conflict_id)
472 failing ();
473 marked_failed = true;
474 }
475 ConclusionType con;
476 if (conflict_id)
477 con = CONFLICT;
478 else if (unsat_constraint)
479 con = CONSTRAINT;
480 else
481 con = ASSUMPTIONS;
482 proof->conclude_unsat (con, conclusion);
483}
ConclusionType
Definition tracer.hpp:15
@ CONFLICT
Definition tracer.hpp:15
@ ASSUMPTIONS
Definition tracer.hpp:15
@ CONSTRAINT
Definition tracer.hpp:15
Here is the call graph for this function:
Here is the caller graph for this function:

◆ condition()

void CaDiCaL::Internal::condition ( bool update_limits = true)

Definition at line 899 of file cadical_condition.cpp.

899 {
900
901 if (unsat)
902 return;
903 if (!stats.current.irredundant)
904 return;
905
907 stats.conditionings++;
908
909 // Propagation limit to avoid too much work in 'condition'. We mark
910 // tried candidate clauses after giving up, such that next time we run
911 // 'condition' we can try them.
912 //
913 long limit = stats.propagations.search;
914 limit *= opts.conditioneffort;
915 limit /= 1000;
916 if (limit < opts.conditionmineff)
917 limit = opts.conditionmineff;
918 if (limit > opts.conditionmaxeff)
919 limit = opts.conditionmaxeff;
920 CADICAL_assert (stats.current.irredundant);
921 limit *= 2.0 * active () / (double) stats.current.irredundant;
922 limit = max (limit, 2l * active ());
923
924 PHASE ("condition", stats.conditionings,
925 "started after %" PRIu64 " conflicts limited by %ld propagations",
926 stats.conflicts, limit);
927
928 long blocked = condition_round (limit);
929
931 report ('g', !blocked);
932
933 if (!update_limits)
934 return;
935
936 long delta = opts.conditionint * (stats.conditionings + 1);
937 lim.condition = stats.conflicts + delta;
938
939 PHASE ("condition", stats.conditionings,
940 "next limit at %" PRIu64 " after %ld conflicts", lim.condition,
941 delta);
942}
long condition_round(long unassigned_literal_propagation_limit)
bool limit(const char *name, int)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ condition_assign()

void CaDiCaL::Internal::condition_assign ( int lit)

Definition at line 90 of file cadical_condition.cpp.

90 {
91 LOG ("condition assign %d", lit);
93 set_val (lit, 1);
94}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ condition_round()

long CaDiCaL::Internal::condition_round ( long unassigned_literal_propagation_limit)

Definition at line 159 of file cadical_condition.cpp.

159 {
160
161 long limit;
162#ifndef CADICAL_QUIET
163 long props = 0;
164#endif
165 if (LONG_MAX - delta < stats.condprops)
166 limit = LONG_MAX;
167 else
168 limit = stats.condprops + delta;
169
170 size_t initial_trail_level = trail.size ();
171 int initial_level = level;
172
173 LOG ("initial trail level %zd", initial_trail_level);
174
176
177#if defined(LOGGING) || !defined(CADICAL_NDEBUG)
178 int additionally_assigned = 0;
179#endif
180
181 for (auto idx : vars) {
182 const signed char tmp = val (idx);
183 Var &v = var (idx);
184 if (tmp) {
185 if (v.level) {
186 const int lit = tmp < 0 ? -idx : idx;
187 if (!active (idx)) {
188 LOG ("temporarily unassigning inactive literal %d", lit);
190 }
191 if (frozen (idx)) {
192 LOG ("temporarily unassigning frozen literal %d", lit);
194 }
195 }
196 } else if (frozen (idx)) {
197 LOG ("keeping frozen literal %d unassigned", idx);
198 } else if (!active (idx)) {
199 LOG ("keeping inactive literal %d unassigned", idx);
200 } else { // if (preprocessing) {
201 if (initial_level == level) {
202 level++;
203 LOG ("new condition decision level");
204 }
205 const int lit = decide_phase (idx, true);
207 v.level = level;
208 trail.push_back (lit);
209#if defined(LOGGING) || !defined(CADICAL_NDEBUG)
210 additionally_assigned++;
211#endif
212 }
213 }
214 LOG ("assigned %d additional literals", additionally_assigned);
215
216 // We compute statistics about the size of the assignments.
217 //
218 // The initial assignment consists of the non-root-level assigned literals
219 // split into a conditional and an autarky part. The conditional part
220 // consists of literals assigned true and occurring negated in a clause
221 // (touch the clause), which does not contain another literal assigned to
222 // true. This initial partition is the same for all refinements used in
223 // checking whether a candidate clause is globally blocked.
224 //
225 // For each candidate clause some of the conditional literals have to be
226 // unassigned, and the autarky is shrunken by turning some of the autarky
227 // literals into conditional literals (which might get unassigned in a
228 // later refinement though).
229 //
230 // The fix-point of this procedure produces a final assignment, which
231 // consists of the remaining assigned literals, again split into a
232 // conditional and an autarky part.
233 //
234 struct {
235 size_t assigned, conditional, autarky;
236 } initial, remain;
237
238 initial.assigned = 0;
239 for (auto idx : vars) {
240 const signed char tmp = val (idx);
241 if (!tmp)
242 continue;
243 if (!var (idx).level)
244 continue;
245 LOG ("initial assignment %ds", tmp < 0 ? -idx : idx);
246 initial.assigned++;
247 }
248
249 PHASE ("condition", stats.conditionings, "initial assignment of size %zd",
250 initial.assigned);
251
252 // For each candidate clause we refine the assignment (monotonically),
253 // by unassigning some conditional literals and turning some autarky
254 // literals into conditionals.
255 //
256 // As the conditional part is usually smaller than the autarky part our
257 // implementation only explicitly maintains the initial conditional part,
258 // with conditional bit set to true through 'mark_as_conditional_literal'.
259 // The autarky part consists of all literals assigned true which do not
260 // have their conditional bit set to true. Since in both cases the
261 // literal has to be assigned true, we only need a single bit for both the
262 // literal as well as its negation (it does not have to be 'signed').
263 //
264 vector<int> conditional;
265
266 vector<Clause *> candidates; // Gather candidate clauses.
267#ifndef CADICAL_QUIET
268 size_t watched = 0; // Number of watched clauses.
269#endif
270
271 initial.autarky = initial.assigned; // Initially all are in autarky
272 initial.conditional = 0; // and none in conditional part.
273
274 // Upper bound on the number of watched clauses. In principle one could
275 // use 'SIZE_MAX' but this is not available by default (yet).
276 //
277 const size_t size_max = clauses.size () + 1;
278
279 // Initialize additional occurrence lists.
280 //
281 init_occs ();
282
283 // Number of previously conditioned and unconditioned candidates.
284 //
285 size_t conditioned = 0, unconditioned = 0;
286
287 // Now go over all (non-garbage) irredundant clauses and check whether
288 // they are candidates, have to be watched, or whether they force the
289 // negation of some of their literals to be conditional initially.
290 //
291 for (const auto &c : clauses) {
292 if (c->garbage)
293 continue; // Can already be ignored.
294 if (c->redundant)
295 continue; // Ignore redundant clauses too.
296
297 // First determine the following numbers for the candidate clause
298 // (restricted to non-root-level assignments).
299 //
300 int positive = 0; // Number true literals.
301 int negative = 0; // Number false literals.
302 int watch = 0; // True Literal to watch.
303 //
304 size_t minsize = size_max; // Number of occurrences of 'watch'.
305 //
306 // But also ignore root-level satisfied but not yet garbage clauses.
307 //
308 bool satisfied = false; // Root level satisfied.
309 //
310 for (const_literal_iterator l = c->begin ();
311 !satisfied && l != c->end (); l++) {
312 const int lit = *l;
313 const signed char tmp = val (lit);
314 if (tmp && !var (lit).level)
315 satisfied = (tmp > 0);
316 else if (tmp < 0)
317 negative++;
318 else if (tmp > 0) {
319 const size_t size = occs (lit).size ();
320 if (size < minsize)
321 watch = lit, minsize = size;
322 positive++;
323 }
324 }
325 if (satisfied) { // Ignore root-level satisfied clauses.
326 mark_garbage (c); // But mark them as garbage already now.
327 continue; // ... with next clause 'c'.
328 }
329
330 // Candidates are clauses with at least a positive literal in it.
331 //
332 if (positive > 0) {
333 LOG (c, "found %d positive literals in candidate", positive);
334 candidates.push_back (c);
335 if (c->conditioned)
336 conditioned++;
337 else
338 unconditioned++;
339 }
340
341 // Only one positive literal in each clauses with also at least one
342 // negative literal has to be watched in occurrence lists. These
343 // watched clauses will be checked to contain only negative literals as
344 // soon such a positive literal is unassigned. If this is the case
345 // these false literals have to be unassigned and potentially new
346 // conditional literals have to be determined.
347 //
348 // Note that only conditional literals are unassigned. However it does
349 // not matter that we might also watch autarky literals, because either
350 // such an autarky literal remains a witness that the clause is
351 // satisfied as long it remains an autarky literal. Otherwise at one
352 // point it becomes conditional and is unassigned, but then a
353 // replacement watch will be searched.
354 //
355 if (negative > 0 && positive > 0) {
356 LOG (c, "found %d negative literals in candidate", negative);
358 CADICAL_assert (val (watch) > 0);
359 Occs &os = occs (watch);
360 CADICAL_assert (os.size () == minsize);
361 os.push_back (c);
362#ifndef CADICAL_QUIET
363 watched++;
364#endif
365 LOG (c, "watching %d with %zd occurrences in", watch, minsize);
366 }
367
368 // The initial global conditional part for the current assignment is
369 // extracted from clauses with only negative literals. It is the same
370 // for all considered candidate clauses. These negative literals make up
371 // the global conditional part, are marked here.
372 //
373 if (negative > 0 && !positive) {
374
375 size_t new_conditionals = 0;
376
377 for (const_literal_iterator l = c->begin (); l != c->end (); l++) {
378 const int lit = *l;
379 signed char tmp = val (lit);
380 if (!tmp)
381 continue;
382 CADICAL_assert (tmp < 0);
383 if (!var (lit).level)
384 continue; // Not unassigned yet!
386 continue;
388 conditional.push_back (-lit);
389 new_conditionals++;
390 }
391 if (new_conditionals > 0)
392 LOG (c, "marked %zu negations of literals as conditional in",
393 new_conditionals);
394
395 initial.conditional += new_conditionals;
396 CADICAL_assert (initial.autarky >= new_conditionals);
397 initial.autarky -= new_conditionals;
398 }
399
400 } // End of loop over all clauses to collect candidates etc.
401
402 PHASE ("condition", stats.conditionings, "found %zd candidate clauses",
403 candidates.size ());
404 PHASE ("condition", stats.conditionings,
405 "watching %zu literals and clauses", watched);
406 PHASE ("condition", stats.conditionings,
407 "initially %zd conditional literals %.0f%%", initial.conditional,
408 percent (initial.conditional, initial.assigned));
409 PHASE ("condition", stats.conditionings,
410 "initially %zd autarky literals %.0f%%", initial.autarky,
411 percent (initial.autarky, initial.assigned));
412#ifdef LOGGING
413 for (size_t i = 0; i < conditional.size (); i++) {
414 LOG ("initial conditional %d", conditional[i]);
415 CADICAL_assert (is_conditional_literal (conditional[i]));
416 }
417 for (size_t i = 0; i < trail.size (); i++)
418 if (is_autarky_literal (trail[i]))
419 LOG ("initial autarky %d", trail[i]);
420#endif
421 CADICAL_assert (initial.conditional == conditional.size ());
422 CADICAL_assert (initial.assigned == initial.conditional + initial.autarky);
423
424 stats.condassinit += initial.assigned;
425 stats.condcondinit += initial.conditional;
426 stats.condautinit += initial.autarky;
427 stats.condassvars += active ();
428
429 // To speed-up and particularly simplify the code we unassign all
430 // root-level variables temporarily, actually all inactive assigned
431 // variables. This allows us to avoid tests on whether an assigned
432 // literal is actually root-level assigned and thus should be ignored (not
433 // considered to be assigned). For this to work we have to ignore root
434 // level satisfied clauses as done above. These are neither candidates
435 // nor have to be watched. Remaining originally root-level assigned
436 // literals in clauses are only set to false.
437 //
438 for (const auto &lit : trail)
439 if (fixed (lit))
441
442 // Stack to save temporarily unassigned (conditional) literals.
443 //
444 vector<int> unassigned;
445
446 // Make sure to focus on clauses not tried before by marking clauses which
447 // have been checked before using the 'conditioned' bit of clauses. If all
448 // candidates have their bit set, we have to reset it. Since the
449 // assignment might be completely different then last time and thus also
450 // the set of candidates this method does not really exactly lead to a
451 // round robin scheme of scheduling clauses.
452 //
453 // TODO consider computing conditioned and unconditioned over all clauses.
454 //
455 CADICAL_assert (conditioned + unconditioned == candidates.size ());
456 if (conditioned && unconditioned) {
457 stable_sort (candidates.begin (), candidates.end (),
458 less_conditioned ());
459 PHASE ("condition", stats.conditionings,
460 "focusing on %zd candidates %.0f%% not tried last time",
461 unconditioned, percent (unconditioned, candidates.size ()));
462 } else if (conditioned && !unconditioned) {
463 for (auto const &c : candidates) {
464 CADICAL_assert (c->conditioned);
465 c->conditioned = false; // Reset 'conditioned' bit.
466 }
467 PHASE ("condition", stats.conditionings,
468 "all %zd candidates tried before", conditioned);
469 } else {
470 CADICAL_assert (!conditioned);
471 PHASE ("condition", stats.conditionings, "all %zd candidates are fresh",
472 unconditioned);
473 }
474
475 // TODO prune assignments further!
476 // And thus might result in less watched clauses.
477 // So watching should be done here and not earlier.
478 // Also, see below, we might need to consider the negation of unassigned
479 // literals in candidate clauses as being watched.
480
481 // Now try to block all candidate clauses.
482 //
483 long blocked = 0; // Number of Successfully blocked clauses.
484 //
485#ifndef CADICAL_QUIET
486 size_t untried = candidates.size ();
487#endif
488 for (const auto &c : candidates) {
489
490 if (initial.autarky <= 0)
491 break;
492
493 if (c->reason)
494 continue;
495
496 bool terminated_or_limit_hit = true;
498 LOG ("asynchronous termination detected");
499 else if (stats.condprops >= limit)
500 LOG ("condition propagation limit %ld hit", limit);
501 else
502 terminated_or_limit_hit = false;
503
504 if (terminated_or_limit_hit) {
505 PHASE ("condition", stats.conditionings,
506 "%zd candidates %.0f%% not tried after %ld propagations",
507 untried, percent (untried, candidates.size ()), props);
508 break;
509 }
510#ifndef CADICAL_QUIET
511 untried--;
512#endif
513 CADICAL_assert (!c->garbage);
514 CADICAL_assert (!c->redundant);
515
516 LOG (c, "candidate");
517 c->conditioned = 1; // Next time later.
518
519 // We watch an autarky literal in the clause, and can stop trying to
520 // globally block the clause as soon it turns into a conditional
521 // literal and we can not find another one. If the fix-point assignment
522 // is reached and we still have an autarky literal left the watched one
523 // is reported as witness for this clause being globally blocked.
524 //
525 int watched_autarky_literal = 0;
526
527 // First mark all true literals in the candidate clause and find an
528 // autarky literal which witnesses that this clause has still a chance
529 // to be globally blocked.
530 //
531 for (const_literal_iterator l = c->begin (); l != c->end (); l++) {
532 const int lit = *l;
534 if (watched_autarky_literal)
535 continue;
536 if (!is_autarky_literal (lit))
537 continue;
538 watched_autarky_literal = lit;
539
540 // TODO assign non-assigned literals to false?
541 // Which might need to trigger watching additional clauses.
542 }
543
544 if (!watched_autarky_literal) {
545 LOG ("no initial autarky literal found");
546 for (const_literal_iterator l = c->begin (); l != c->end (); l++)
548 continue;
549 }
550
551 stats.condcands++; // Only now ...
552
553 LOG ("watching first autarky literal %d", watched_autarky_literal);
554
555 // Save assignment sizes for statistics, logging and checking.
556 //
557 remain = initial;
558
559 // Position of next conditional and unassigned literal to process in the
560 // 'conditional' and the 'unassigned' stack.
561 //
562 struct {
563 size_t conditional, unassigned;
564 } next = {0, 0};
565
566 CADICAL_assert (unassigned.empty ());
567 CADICAL_assert (conditional.size () == initial.conditional);
568
569 while (watched_autarky_literal && stats.condprops < limit &&
570 next.conditional < conditional.size ()) {
571
572 CADICAL_assert (next.unassigned == unassigned.size ());
573
574 const int conditional_lit = conditional[next.conditional++];
575 LOG ("processing next conditional %d", conditional_lit);
576 CADICAL_assert (is_conditional_literal (conditional_lit));
577
578 if (is_in_candidate_clause (-conditional_lit)) {
579 LOG ("conditional %d negated in candidate clause", conditional_lit);
580 continue;
581 }
582
583 LOG ("conditional %d does not occur negated in candidate clause",
584 conditional_lit);
585
586 condition_unassign (conditional_lit);
587 CADICAL_assert (!is_conditional_literal (conditional_lit));
588 unassigned.push_back (conditional_lit);
589
590 CADICAL_assert (remain.assigned > 0);
591 CADICAL_assert (remain.conditional > 0);
592 remain.conditional--;
593 remain.assigned--;
594
595 while (watched_autarky_literal && stats.condprops < limit &&
596 next.unassigned < unassigned.size ()) {
597 const int unassigned_lit = unassigned[next.unassigned++];
598 LOG ("processing next unassigned %d", unassigned_lit);
599 CADICAL_assert (!val (unassigned_lit));
600#ifndef CADICAL_QUIET
601 props++;
602#endif
603 stats.condprops++;
604
605 Occs &os = occs (unassigned_lit);
606 if (os.empty ())
607 continue;
608
609 // Traverse all watched clauses of 'unassigned_lit' and find
610 // replacement watches or if none is found turn the negation of all
611 // false autarky literals in that clause into conditional literals.
612 // If one of those autarky literals is the watched autarky literal
613 // in the candidate clause, that one has to be updated too.
614 //
615 // We expect that this loop is a hot-spot for the procedure and thus
616 // are more careful about accessing end points for iterating.
617 //
618 auto i = os.begin (), j = i;
619 for (; watched_autarky_literal && j != os.end (); j++) {
620 Clause *d = *i++ = *j;
621
622 int replacement = 0; // New watched literal in 'd'.
623 int negative = 0; // Negative autarky literals in 'd'.
624
625 for (const_literal_iterator l = d->begin (); l != d->end ();
626 l++) {
627 const int lit = *l;
628 const signed char tmp = val (lit);
629 if (tmp > 0)
630 replacement = lit;
631 if (tmp < 0 && is_autarky_literal (-lit))
632 negative++;
633 }
634
635 if (replacement) {
636 LOG ("found replacement %d for unassigned %d", replacement,
637 unassigned_lit);
638 LOG (d, "unwatching %d in", unassigned_lit);
639 i--; // Drop watch!
640 LOG (d, "watching %d in", replacement);
641
642 CADICAL_assert (replacement != unassigned_lit);
643 occs (replacement).push_back (d);
644
645 continue; // ... with next watched clause 'd'.
646 }
647
648 LOG ("no replacement found for unassigned %d", unassigned_lit);
649
650 // Keep watching 'd' by 'unassigned_lit' if no replacement found.
651
652 if (!negative) {
653 LOG (d, "no negative autarky literals left in");
654 continue; // ... with next watched clause 'd'.
655 }
656
657 LOG (d, "found %d negative autarky literals in", negative);
658
659 for (const_literal_iterator l = d->begin ();
660 watched_autarky_literal && l != d->end (); l++) {
661 const int lit = *l;
662 if (!is_autarky_literal (-lit))
663 continue;
665 conditional.push_back (-lit);
666
667 remain.conditional++;
668 CADICAL_assert (remain.autarky > 0);
669 remain.autarky--;
670
671 if (-lit != watched_autarky_literal)
672 continue;
673
674 LOG ("need to replace autarky literal %d in candidate", -lit);
675 replacement = 0;
676
677 // TODO save starting point because we only move it forward?
678
679 for (const_literal_iterator k = c->begin ();
680 !replacement && k != c->end (); k++) {
681 const int other = *k;
682 if (is_autarky_literal (other))
683 replacement = other;
684 }
685 watched_autarky_literal = replacement;
686
687 if (replacement) {
688 LOG (c, "watching autarky %d instead %d in candidate",
689 replacement, watched_autarky_literal);
690 watched_autarky_literal = replacement;
691 } else {
692 LOG ("failed to find an autarky replacement");
693 watched_autarky_literal = 0; // Breaks out of 4 loops!!!!!
694 }
695 } // End of loop of turning autarky literals into conditionals.
696 } // End of loop of all watched clauses of an unassigned literal.
697 //
698 // We might abort the occurrence traversal early but already
699 // removed some watches, thus have to just copy the rest.
700 //
701 if (i < j) {
702 while (j != os.end ())
703 *i++ = *j++;
704 LOG ("flushed %zd occurrences of %d", os.end () - i,
705 unassigned_lit);
706 os.resize (i - os.begin ());
707 }
708 } // End of loop which goes over all unprocessed unassigned literals.
709 } // End of loop which goes over all unprocessed conditional literals.
710
711 // We are still processing the candidate 'c' and now have reached a
712 // final fix-point assignment partitioned into a conditional and an
713 // autarky part, or during unassigned literals figured that there is no
714 // positive autarky literal left in 'c'.
715
716 LOG ("remaining assignment of size %zd", remain.assigned);
717 LOG ("remaining conditional part of size %zd", remain.conditional);
718 LOG ("remaining autarky part of size %zd", remain.autarky);
719 //
720 CADICAL_assert (remain.assigned - remain.conditional == remain.autarky);
721 //
722#if defined(LOGGING) || !defined(CADICAL_NDEBUG)
723 //
724 // This is a sanity check, that the size of our implicit representation
725 // of the autarky part matches our 'remain' counts. We need the same
726 // code for determining autarky literals as in the loop below which adds
727 // autarky literals to the extension stack.
728 //
729 struct {
730 size_t assigned, conditional, autarky;
731 } check;
732 check.assigned = check.conditional = check.autarky = 0;
733 for (size_t i = 0; i < trail.size (); i++) {
734 const int lit = trail[i];
735 if (val (lit)) {
736 check.assigned++;
738 LOG ("remaining conditional %d", lit);
740 check.conditional++;
741 } else {
743 LOG ("remaining autarky %d", lit);
744 check.autarky++;
745 }
746 } else {
749 }
750 }
751 CADICAL_assert (remain.assigned == check.assigned);
752 CADICAL_assert (remain.conditional == check.conditional);
753 CADICAL_assert (remain.autarky == check.autarky);
754#endif
755
756 // Success if an autarky literal is left in the clause and
757 // we did not abort the loop too early because the propagation
758 // limit was hit.
759 //
760 if (watched_autarky_literal && stats.condprops < limit) {
761 CADICAL_assert (is_autarky_literal (watched_autarky_literal));
762 CADICAL_assert (is_in_candidate_clause (watched_autarky_literal));
763
764 blocked++;
765 stats.conditioned++;
766 LOG (c, "positive autarky literal %d globally blocks",
767 watched_autarky_literal);
768
769 LOG ("remaining %zd assigned literals %.0f%%", remain.assigned,
770 percent (remain.assigned, initial.assigned));
771 LOG ("remaining %zd conditional literals %.0f%%", remain.conditional,
772 percent (remain.conditional, remain.assigned));
773 LOG ("remaining %zd autarky literals %.0f%%", remain.autarky,
774 percent (remain.autarky, remain.assigned));
775
776 // A satisfying assignment of a formula after removing a globally
777 // blocked clause might not satisfy that clause. As for variable
778 // elimination and classical blocked clauses, we thus maintain an
779 // extension stack for reconstructing an assignment which both
780 // satisfies the remaining formula as well as the clause.
781 //
782 // For globally blocked clauses we simply have to flip all literals in
783 // the autarky part and thus save the autarky on the extension stack
784 // in addition to the removed clause. In the classical situation (in
785 // bounded variable elimination etc.) we simply save one literal on
786 // the extension stack.
787 //
788 // TODO find a way to shrink the autarky part or some other way to
789 // avoid pushing too many literals on the extension stack.
790 //
791 external->push_zero_on_extension_stack ();
792 for (const auto &lit : trail)
794 external->push_witness_literal_on_extension_stack (lit);
795 if (proof)
796 proof->weaken_minus (c);
797 external->push_clause_on_extension_stack (c);
798
799 mark_garbage (c);
800
801 stats.condassrem += remain.assigned;
802 stats.condcondrem += remain.conditional;
803 stats.condautrem += remain.autarky;
804 stats.condassirem += initial.assigned;
805 }
806
807 // In this last part specific to one candidate clause, we have to get
808 // back to the initial assignment and reset conditionals. First we
809 // assign all the unassigned literals (if necessary).
810 //
811 if (!unassigned.empty ()) {
812 LOG ("reassigning %zd literals", unassigned.size ());
813 while (!unassigned.empty ()) {
814 const int lit = unassigned.back ();
815 unassigned.pop_back ();
817 }
818 }
819
820 // Then we remove from the conditional stack autarky literals which
821 // became conditional and also reset their 'conditional' bit.
822 //
823 if (initial.conditional < conditional.size ()) {
824 LOG ("flushing %zd autarky literals from conditional stack",
825 conditional.size () - initial.conditional);
826 while (initial.conditional < conditional.size ()) {
827 const int lit = conditional.back ();
828 conditional.pop_back ();
830 }
831 }
832
833 // Finally unmark all literals in the candidate clause.
834 //
835 for (const_literal_iterator l = c->begin (); l != c->end (); l++)
837
838 } // End of loop over all candidate clauses.
839
840 PHASE ("condition", stats.conditionings,
841 "globally blocked %ld clauses %.0f%%", blocked,
842 percent (blocked, candidates.size ()));
843
844 // Unmark initial conditional variables.
845 //
846 for (const auto &lit : conditional)
848
849 erase_vector (unassigned);
850 erase_vector (conditional);
851 erase_vector (candidates);
852
853 // Unassign additionally assigned literals.
854 //
855#if defined(LOGGING) || !defined(CADICAL_NDEBUG)
856 int additionally_unassigned = 0;
857#endif
858 while (trail.size () > initial_trail_level) {
859 int lit = trail.back ();
860 trail.pop_back ();
862#if defined(LOGGING) || !defined(CADICAL_NDEBUG)
863 additionally_unassigned++;
864#endif
865 }
866 LOG ("unassigned %d additionally assigned literals",
867 additionally_unassigned);
868 CADICAL_assert (additionally_unassigned == additionally_assigned);
869
870 if (level > initial_level) {
871 LOG ("reset condition decision level");
872 level = initial_level;
873 }
874
875 reset_occs ();
877
878 // Reassign previously assigned variables again.
879 //
880 LOG ("reassigning previously assigned variables");
881 for (size_t i = 0; i < initial_trail_level; i++) {
882 const int lit = trail[i];
883 const signed char tmp = val (lit);
884 CADICAL_assert (tmp >= 0);
885 if (!tmp)
887 }
888
889#ifndef CADICAL_NDEBUG
890 for (const auto &lit : trail)
892#endif
893
895
896 return blocked;
897}
void condition_assign(int lit)
void unmark_in_candidate_clause(int lit)
bool is_conditional_literal(int lit) const
void mark_as_conditional_literal(int lit)
int decide_phase(int idx, bool target)
bool is_autarky_literal(int lit) const
void condition_unassign(int lit)
void mark_in_candidate_clause(int lit)
bool is_in_candidate_clause(int lit) const
void unmark_as_conditional_literal(int lit)
typedefABC_NAMESPACE_HEADER_START union watch watch
Definition watch.h:14
Here is the call graph for this function:
Here is the caller graph for this function:

◆ condition_unassign()

void CaDiCaL::Internal::condition_unassign ( int lit)

Definition at line 84 of file cadical_condition.cpp.

84 {
85 LOG ("condition unassign %d", lit);
86 CADICAL_assert (val (lit) > 0);
87 set_val (lit, 0);
88}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ conditioning()

bool CaDiCaL::Internal::conditioning ( )

Definition at line 39 of file cadical_condition.cpp.

39 {
40
41 if (!opts.condition)
42 return false;
43 if (!preprocessing && !opts.inprocessing)
44 return false;
45 if (preprocessing)
46 CADICAL_assert (lim.preprocessing);
47
48 // Triggered in regular 'opts.conditionint' conflict intervals.
49 //
50 if (lim.condition > stats.conflicts)
51 return false;
52
53 if (!level)
54 return false; // One decision necessary.
55
56 if (level <= averages.current.jump)
57 return false; // Main heuristic.
58
59 if (!stats.current.irredundant)
60 return false;
61 double remain = active ();
62 if (!remain)
63 return false;
64 double ratio = stats.current.irredundant / remain;
65 return ratio <= opts.conditionmaxrat;
66}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ connect_binary_watches()

void CaDiCaL::Internal::connect_binary_watches ( )

Definition at line 86 of file cadical_watch.cpp.

86 {
87 START (connect);
89
90 LOG ("watching binary clauses");
91
92 // First connect binary clauses.
93 //
94 for (const auto &c : clauses) {
95 if (c->garbage || c->size > 2)
96 continue;
97 watch_clause (c);
98 }
99
100 STOP (connect);
101}
Here is the call graph for this function:

◆ connect_proof_tracer() [1/4]

void CaDiCaL::Internal::connect_proof_tracer ( FileTracer * tracer,
bool antecedents,
bool finalize_clauses = false )

Definition at line 73 of file cadical_proof.cpp.

74 {
76 if (antecedents)
77 force_lrat ();
78 if (finalize_clauses)
79 frat = true;
81 tracer->connect_internal (this);
82 proof->connect (tracer);
83 file_tracers.push_back (tracer);
84}
Here is the call graph for this function:

◆ connect_proof_tracer() [2/4]

void CaDiCaL::Internal::connect_proof_tracer ( InternalTracer * tracer,
bool antecedents,
bool finalize_clauses = false )

Definition at line 46 of file cadical_proof.cpp.

48 {
50 if (antecedents)
51 force_lrat ();
52 if (finalize_clauses)
53 frat = true;
55 tracer->connect_internal (this);
56 proof->connect (tracer);
57 tracers.push_back (tracer);
58}
Here is the call graph for this function:

◆ connect_proof_tracer() [3/4]

void CaDiCaL::Internal::connect_proof_tracer ( StatTracer * tracer,
bool antecedents,
bool finalize_clauses = false )

Definition at line 60 of file cadical_proof.cpp.

61 {
63 if (antecedents)
64 force_lrat ();
65 if (finalize_clauses)
66 frat = true;
68 tracer->connect_internal (this);
69 proof->connect (tracer);
70 stat_tracers.push_back (tracer);
71}
Here is the call graph for this function:

◆ connect_proof_tracer() [4/4]

void CaDiCaL::Internal::connect_proof_tracer ( Tracer * tracer,
bool antecedents,
bool finalize_clauses = false )

Definition at line 34 of file cadical_proof.cpp.

35 {
37 if (antecedents)
38 force_lrat ();
39 if (finalize_clauses)
40 frat = true;
42 proof->connect (tracer);
43 tracers.push_back (tracer);
44}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ connect_propagator()

void CaDiCaL::Internal::connect_propagator ( )

Definition at line 968 of file cadical_external_propagate.cpp.

968 {
969 if (level)
970 backtrack ();
971}
Here is the call graph for this function:

◆ connect_watches()

void CaDiCaL::Internal::connect_watches ( bool irredundant_only = false)

Definition at line 30 of file cadical_watch.cpp.

30 {
31 START (connect);
33
34 LOG ("watching all %sclauses", irredundant_only ? "irredundant " : "");
35
36 // First connect binary clauses.
37 //
38 for (const auto &c : clauses) {
39 if (irredundant_only && c->redundant)
40 continue;
41 if (c->garbage || c->size > 2)
42 continue;
43 watch_clause (c);
44 }
45
46 // Then connect non-binary clauses.
47 //
48 for (const auto &c : clauses) {
49 if (irredundant_only && c->redundant)
50 continue;
51 if (c->garbage || c->size == 2)
52 continue;
53 watch_clause (c);
54 if (!level) {
55 const int lit0 = c->literals[0];
56 const int lit1 = c->literals[1];
57 const signed char tmp0 = val (lit0);
58 const signed char tmp1 = val (lit1);
59 if (tmp0 > 0)
60 continue;
61 if (tmp1 > 0)
62 continue;
63 if (tmp0 < 0) {
64 const size_t pos0 = var (lit0).trail;
65 if (pos0 < propagated) {
66 propagated = pos0;
67 LOG ("literal %d resets propagated to %zd", lit0, pos0);
68 }
69 }
70 if (tmp1 < 0) {
71 const size_t pos1 = var (lit1).trail;
72 if (pos1 < propagated) {
73 propagated = pos1;
74 LOG ("literal %d resets propagated to %zd", lit1, pos1);
75 }
76 }
77 }
78 }
79
80 STOP (connect);
81}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ consider_to_vivify_clause()

bool CaDiCaL::Internal::consider_to_vivify_clause ( Clause * candidate)

Definition at line 511 of file cadical_vivify.cpp.

511 {
512 if (c->garbage)
513 return false;
514 if (opts.vivifyonce >= 1 && c->redundant && c->vivified)
515 return false;
516 if (opts.vivifyonce >= 2 && !c->redundant && c->vivified)
517 return false;
518 if (!c->redundant)
519 return true;
520 CADICAL_assert (c->redundant);
521
522 // likely_to_be_kept_clause is too aggressive at removing tier-3 clauses
523 return true;
524}
Here is the caller graph for this function:

◆ constrain()

void CaDiCaL::Internal::constrain ( int lit)

Definition at line 9 of file cadical_constrain.cpp.

9 {
10 if (lit)
11 constraint.push_back (lit);
12 else {
13 if (level)
14 backtrack ();
15 LOG (constraint, "shrinking constraint");
16 bool satisfied_constraint = false;
17 const vector<int>::const_iterator end = constraint.end ();
18 vector<int>::iterator i = constraint.begin ();
19 for (vector<int>::const_iterator j = i; j != end; j++) {
20 int tmp = marked (*j);
21 if (tmp > 0) {
22 LOG ("removing duplicated literal %d from constraint", *j);
23 } else if (tmp < 0) {
24 LOG ("tautological since both %d and %d occur in constraint", -*j,
25 *j);
26 satisfied_constraint = true;
27 break;
28 } else {
29 tmp = val (*j);
30 if (tmp < 0) {
31 LOG ("removing falsified literal %d from constraint clause", *j);
32 } else if (tmp > 0) {
33 LOG ("satisfied constraint with literal %d", *j);
34 satisfied_constraint = true;
35 break;
36 } else {
37 *i++ = *j;
38 mark (*j);
39 }
40 }
41 }
42 constraint.resize (i - constraint.begin ());
43 for (const auto &lit : constraint)
44 unmark (lit);
45 if (satisfied_constraint)
46 constraint.clear ();
47 else if (constraint.empty ()) {
48 unsat_constraint = true;
49 if (!conflict_id)
50 marked_failed = false; // allow to trigger failing ()
51 } else
52 for (const auto lit : constraint)
53 freeze (lit);
54 }
55}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ copy_clause()

void CaDiCaL::Internal::copy_clause ( Clause * c)

Definition at line 315 of file cadical_collect.cpp.

315 {
316 LOG (c, "moving");
317 CADICAL_assert (!c->moved);
318 char *p = (char *) c;
319 char *q = arena.copy (p, c->bytes ());
320 c->copy = (Clause *) q;
321 c->moved = true;
322 LOG ("copied clause[%" PRId64 "] from %p to %p", c->id, (void *) c,
323 (void *) c->copy);
324}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ copy_non_garbage_clauses()

void CaDiCaL::Internal::copy_non_garbage_clauses ( )

Definition at line 328 of file cadical_collect.cpp.

328 {
329
330 size_t collected_clauses = 0, collected_bytes = 0;
331 size_t moved_clauses = 0, moved_bytes = 0;
332
333 // First determine 'moved_bytes' and 'collected_bytes'.
334 //
335 for (const auto &c : clauses)
336 if (!c->collect ())
337 moved_bytes += c->bytes (), moved_clauses++;
338 else
339 collected_bytes += c->bytes (), collected_clauses++;
340
341 PHASE ("collect", stats.collections,
342 "moving %zd bytes %.0f%% of %zd non garbage clauses", moved_bytes,
343 percent (moved_bytes, collected_bytes + moved_bytes),
344 moved_clauses);
345 (void) moved_clauses, (void) collected_clauses, (void) collected_bytes;
346 // Prepare 'to' space of size 'moved_bytes'.
347 //
348 arena.prepare (moved_bytes);
349
350 // Keep clauses in arena in the same order.
351 //
352 if (opts.arenacompact)
353 for (const auto &c : clauses)
354 if (!c->collect () && arena.contains (c))
355 copy_clause (c);
356
357 if (opts.arenatype == 1 || !watching ()) {
358
359 // Localize according to current clause order.
360
361 // If the option 'opts.arenatype == 1' is set, then this means the
362 // solver uses the original order of clauses. If there are no watches,
363 // we can not use the watched based copying policies below. This
364 // happens if garbage collection is triggered during bounded variable
365 // elimination.
366
367 // Copy clauses according to the order of calling 'copy_clause', which
368 // in essence just gives a compacting garbage collector, since their
369 // relative order is kept, and actually already gives the largest
370 // benefit due to better cache locality.
371
372 for (const auto &c : clauses)
373 if (!c->moved && !c->collect ())
374 copy_clause (c);
375
376 } else if (opts.arenatype == 2) {
377
378 // Localize according to (original) variable order.
379
380 // This is almost the version used by MiniSAT and descendants.
381 // Our version uses saved phases too.
382
383 for (int sign = -1; sign <= 1; sign += 2)
384 for (auto idx : vars)
385 for (const auto &w : watches (sign * likely_phase (idx)))
386 if (!w.clause->moved && !w.clause->collect ())
387 copy_clause (w.clause);
388
389 } else {
390
391 // Localize according to decision queue order.
392
393 // This is the default for search. It allocates clauses in the order of
394 // the decision queue and also uses saved phases. It seems faster than
395 // the MiniSAT version and thus we keep 'opts.arenatype == 3'.
396
397 CADICAL_assert (opts.arenatype == 3);
398
399 for (int sign = -1; sign <= 1; sign += 2)
400 for (int idx = queue.last; idx; idx = link (idx).prev)
401 for (const auto &w : watches (sign * likely_phase (idx)))
402 if (!w.clause->moved && !w.clause->collect ())
403 copy_clause (w.clause);
404 }
405
406 // Do not forget to move clauses which are not watched, which happened in
407 // a rare situation, and now is only left as defensive code.
408 //
409 for (const auto &c : clauses)
410 if (!c->collect () && !c->moved)
411 copy_clause (c);
412
415
416 // Replace and flush clause references in 'clauses'.
417 //
418 const auto end = clauses.end ();
419 auto j = clauses.begin (), i = j;
420 for (; i != end; i++) {
421 Clause *c = *i;
422 if (c->collect ())
423 delete_clause (c);
424 else
425 CADICAL_assert (c->moved), *j++ = c->copy, deallocate_clause (c);
426 }
427 clauses.resize (j - clauses.begin ());
428 if (clauses.size () < clauses.capacity () / 2)
430
431 if (opts.arenasort)
432 rsort (clauses.begin (), clauses.end (), pointer_rank ());
433
434 // Release 'from' space completely and then swap 'to' with 'from'.
435 //
436 arena.swap ();
437
438 PHASE ("collect", stats.collections,
439 "collected %zd bytes %.0f%% of %zd garbage clauses",
440 collected_bytes,
441 percent (collected_bytes, collected_bytes + moved_bytes),
442 collected_clauses);
443}
void rsort(I first, I last, Rank rank)
Definition radix.hpp:45
void copy_clause(Clause *)
Link & link(int lit)
Definition internal.hpp:453
int likely_phase(int idx)
void deallocate_clause(Clause *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ copy_phases()

void CaDiCaL::Internal::copy_phases ( vector< signed char > & dst)

Definition at line 9 of file cadical_phases.cpp.

9 {
10 START (copy);
11 for (auto i : vars)
12 dst[i] = phases.saved[i];
13 STOP (copy);
14}
Here is the caller graph for this function:

◆ cover()

bool CaDiCaL::Internal::cover ( )

Definition at line 649 of file cadical_cover.cpp.

649 {
650
651 if (!opts.cover)
652 return false;
653 if (unsat)
654 return false;
656 return false;
657 if (!stats.current.irredundant)
658 return false;
659
660 // TODO: Our current algorithm for producing the necessary clauses on the
661 // reconstruction stack for extending the witness requires a covered
662 // literal addition step which (empirically) conflicts with flushing
663 // during restoring clauses (see 'regr00{48,51}.trace') even though
664 // flushing during restore is disabled by default (as is covered clause
665 // elimination). The consequence of combining these two options
666 // ('opts.cover' and 'opts.restoreflush') can thus produce incorrect
667 // witness reconstruction and thus invalid witnesses. This is quite
668 // infrequent (one out of half billion mobical test cases) but as the two
669 // regression traces show, does happen. Thus we disable the combination.
670 //
671 if (opts.restoreflush)
672 return false;
673
675
676 stats.cover.count++;
677
678 // During variable elimination unit clauses can be generated which need to
679 // be propagated properly over redundant clauses too. Since variable
680 // elimination avoids to have occurrence lists and watches at the same
681 // time this propagation is delayed until the end of variable elimination.
682 // Since we want to interleave CCE with it, we have to propagate here.
683 // Otherwise this triggers inconsistencies.
684 //
685 if (propagated < trail.size ()) {
686 init_watches ();
687 connect_watches (); // need to propagated over all clauses!
688 LOG ("elimination produced %zd units",
689 (size_t) (trail.size () - propagated));
690 if (!propagate ()) {
691 LOG ("propagating units before covered clause elimination "
692 "results in empty clause");
695 }
696 reset_watches ();
697 }
698 CADICAL_assert (unsat || propagated == trail.size ());
699
700 int64_t covered = cover_round ();
701
703 report ('c', !opts.reportall && !covered);
704
705 return covered;
706}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cover_clause()

bool CaDiCaL::Internal::cover_clause ( Clause * c,
Coveror & coveror )

Definition at line 327 of file cadical_cover.cpp.

327 {
328
330 CADICAL_assert (!c->garbage);
331
332 LOG (c, "trying covered clauses elimination on");
333 bool satisfied = false;
334 for (const auto &lit : *c)
335 if (val (lit) > 0)
336 satisfied = true;
337
338 if (satisfied) {
339 LOG (c, "clause already satisfied");
340 mark_garbage (c);
341 return false;
342 }
343
344 CADICAL_assert (coveror.added.empty ());
345 CADICAL_assert (coveror.extend.empty ());
346 CADICAL_assert (coveror.covered.empty ());
347
349 level = 1;
350 LOG ("assuming literals of candidate clause");
351 for (const auto &lit : *c) {
352 if (val (lit))
353 continue;
355 coveror.covered.push_back (lit);
356 }
357
358 bool tautological = false;
359
360 coveror.next.added = coveror.next.covered = 0;
361
362 while (!tautological) {
363 if (coveror.next.added < coveror.added.size ()) {
364 const int lit = coveror.added[coveror.next.added++];
365 tautological = cover_propagate_asymmetric (lit, c, coveror);
366 } else if (coveror.next.covered < coveror.covered.size ()) {
367 const int lit = coveror.covered[coveror.next.covered++];
368 tautological = cover_propagate_covered (lit, coveror);
369 } else
370 break;
371 }
372
373 if (tautological) {
374 if (coveror.extend.empty ()) {
375 stats.cover.asymmetric++;
376 stats.cover.total++;
377 LOG (c, "asymmetric tautological");
378 } else {
379 stats.cover.blocked++;
380 stats.cover.total++;
381 // Only copy extension stack if successful.
382 int prev = INT_MIN;
383 bool already_pushed = false;
384 int64_t last_id = 0;
385 LOG (c, "covered tautological");
386 CADICAL_assert (clause.empty ());
387 LOG (coveror.extend, "extension = ");
388 for (const auto &other : coveror.extend) {
389 if (!prev) {
390 // are we finishing a clause?
391 if (already_pushed) {
392 // add missing literals that are not needed for covering
393 // but avoid RAT proofs
394 for (auto i = 0, j = 0; i < c->size; ++i, ++j) {
395 const int lit = c->literals[i];
396 if (j >= (int) coveror.covered.size () ||
397 c->literals[i] != coveror.covered[j]) {
398 --j;
399 LOG ("adding lit %d not needed for ATA", lit);
400 clause.push_back (lit);
401 external->push_clause_literal_on_extension_stack (lit);
402 }
403 }
404 }
405 if (proof && already_pushed) {
406 if (lrat)
407 lrat_chain.push_back (c->id);
408 LOG ("LEARNING clause with id %" PRId64, last_id);
409 proof->add_derived_clause (last_id, false, clause, lrat_chain);
410 proof->weaken_plus (last_id, clause);
411 lrat_chain.clear ();
412 }
413 last_id = ++clause_id;
414 external->push_zero_on_extension_stack ();
415 external->push_witness_literal_on_extension_stack (other);
416 external->push_zero_on_extension_stack ();
417 external->push_id_on_extension_stack (last_id);
418 external->push_zero_on_extension_stack ();
419 clause.clear ();
420 already_pushed = true;
421 }
422 if (other) {
423 external->push_clause_literal_on_extension_stack (other);
424 clause.push_back (other);
425 LOG (clause, "current clause is");
426 }
427 prev = other;
428 }
429
430 if (proof) {
431 // add missing literals that are not needed for covering
432 // but avoid RAT proofs
433 for (auto i = 0, j = 0; i < c->size; ++i, ++j) {
434 const int lit = c->literals[i];
435 if (j >= (int) coveror.covered.size () ||
436 c->literals[i] != coveror.covered[j]) {
437 --j;
438 LOG ("adding lit %d not needed for ATA", lit);
439 clause.push_back (lit);
440 external->push_clause_literal_on_extension_stack (lit);
441 }
442 }
443 if (lrat)
444 lrat_chain.push_back (c->id);
445 proof->add_derived_clause (last_id, false, clause, lrat_chain);
446 proof->weaken_plus (last_id, clause);
447 lrat_chain.clear ();
448 }
449 clause.clear ();
450
451 mark_garbage (c);
452 }
453 }
454
455 // Backtrack and 'unassign' all literals.
456
457 CADICAL_assert (level == 1);
458 for (const auto &lit : coveror.added)
459 set_val (lit, 0);
460 level = 0;
461
462 coveror.covered.clear ();
463 coveror.extend.clear ();
464 coveror.added.clear ();
465
466 return tautological;
467}
void asymmetric_literal_addition(int lit, Coveror &)
bool cover_propagate_asymmetric(int lit, Clause *ignore, Coveror &)
bool cover_propagate_covered(int lit, Coveror &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cover_propagate_asymmetric()

bool CaDiCaL::Internal::cover_propagate_asymmetric ( int lit,
Clause * ignore,
Coveror & coveror )

Definition at line 104 of file cadical_cover.cpp.

105 {
107 stats.propagations.cover++;
108 CADICAL_assert (val (lit) < 0);
109 bool subsumed = false;
110 LOG ("asymmetric literal propagation of %d", lit);
111 Watches &ws = watches (lit);
112 const const_watch_iterator eow = ws.end ();
113 watch_iterator j = ws.begin ();
115 while (!subsumed && i != eow) {
116 const Watch w = *j++ = *i++;
117 if (w.clause == ignore)
118 continue; // costly but necessary here ...
119 const signed char b = val (w.blit);
120 if (b > 0)
121 continue;
122 if (w.clause->garbage)
123 j--;
124 else if (w.binary ()) {
125 if (b < 0) {
126 LOG (w.clause, "found subsuming");
127 subsumed = true;
128 } else
129 asymmetric_literal_addition (-w.blit, coveror);
130 } else {
131 literal_iterator lits = w.clause->begin ();
132 const int other = lits[0] ^ lits[1] ^ lit;
133 lits[0] = other, lits[1] = lit;
134 const signed char u = val (other);
135 if (u > 0)
136 j[-1].blit = other;
137 else {
138 const int size = w.clause->size;
139 const const_literal_iterator end = lits + size;
140 const literal_iterator middle = lits + w.clause->pos;
141 literal_iterator k = middle;
142 signed char v = -1;
143 int r = 0;
144 while (k != end && (v = val (r = *k)) < 0)
145 k++;
146 if (v < 0) {
147 k = lits + 2;
148 CADICAL_assert (w.clause->pos <= size);
149 while (k != middle && (v = val (r = *k)) < 0)
150 k++;
151 }
152 w.clause->pos = k - lits;
153 CADICAL_assert (lits + 2 <= k), CADICAL_assert (k <= w.clause->end ());
154 if (v > 0)
155 j[-1].blit = r;
156 else if (!v) {
157 LOG (w.clause, "unwatch %d in", lit);
158 lits[1] = r;
159 *k = lit;
160 watch_literal (r, lit, w.clause);
161 j--;
162 } else if (!u) {
163 CADICAL_assert (v < 0);
164 asymmetric_literal_addition (-other, coveror);
165 } else {
166 CADICAL_assert (u < 0), CADICAL_assert (v < 0);
167 LOG (w.clause, "found subsuming");
168 subsumed = true;
169 break;
170 }
171 }
172 }
173 }
174 if (j != i) {
175 while (i != eow)
176 *j++ = *i++;
177 ws.resize (j - ws.begin ());
178 }
179 return subsumed;
180}
Watches::const_iterator const_watch_iterator
Definition watch.hpp:48
vector< Watch > Watches
Definition watch.hpp:45
Watches::iterator watch_iterator
Definition watch.hpp:47
void watch_literal(int lit, int blit, Clause *c)
Definition internal.hpp:623
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cover_propagate_covered()

bool CaDiCaL::Internal::cover_propagate_covered ( int lit,
Coveror & coveror )

Definition at line 185 of file cadical_cover.cpp.

185 {
187
188 CADICAL_assert (val (lit) < 0);
189 if (frozen (lit)) {
190 LOG ("no covered propagation on frozen literal %d", lit);
191 return false;
192 }
193
194 stats.propagations.cover++;
195
196 LOG ("covered propagation of %d", lit);
197 CADICAL_assert (coveror.intersection.empty ());
198
199 Occs &os = occs (-lit);
200 const auto end = os.end ();
201 bool first = true;
202
203 // Compute the intersection of the literals in all the clauses with
204 // '-lit'. If all these clauses are double satisfied then we know that
205 // the extended clauses (in 'added') is blocked. All literals in the
206 // intersection can be added as covered literal. As soon the intersection
207 // becomes empty (during traversal of clauses with '-lit') we abort.
208
209 for (auto i = os.begin (); i != end; i++) {
210
211 Clause *c = *i;
212 if (c->garbage)
213 continue;
214
215 // First check whether clause is 'blocked', i.e., is double satisfied.
216
217 bool blocked = false;
218 for (const auto &other : *c) {
219 if (other == -lit)
220 continue;
221 const signed char tmp = val (other);
222 if (tmp < 0)
223 continue;
224 if (tmp > 0) {
225 blocked = true;
226 break;
227 }
228 }
229 if (blocked) { // ... if 'c' is double satisfied.
230 LOG (c, "blocked");
231 continue; // with next clause with '-lit'.
232 }
233
234 if (first) {
235
236 // Copy and mark literals of first clause.
237
238 for (const auto &other : *c) {
239 if (other == -lit)
240 continue;
241 const signed char tmp = val (other);
242 if (tmp < 0)
243 continue;
244 CADICAL_assert (!tmp);
245 coveror.intersection.push_back (other);
246 mark (other);
247 }
248
249 first = false;
250
251 } else {
252
253 // Unmark all literals in current clause.
254
255 for (const auto &other : *c) {
256 if (other == -lit)
257 continue;
258 signed char tmp = val (other);
259 if (tmp < 0)
260 continue;
261 CADICAL_assert (!tmp);
262 tmp = marked (other);
263 if (tmp > 0)
264 unmark (other);
265 }
266
267 // Then remove from intersection all marked literals.
268
269 const auto end = coveror.intersection.end ();
270 auto j = coveror.intersection.begin ();
271 for (auto k = j; k != end; k++) {
272 const int other = *j++ = *k;
273 const int tmp = marked (other);
274 CADICAL_assert (tmp >= 0);
275 if (tmp)
276 j--, unmark (other); // remove marked and unmark it
277 else
278 mark (other); // keep unmarked and mark it
279 }
280 const size_t new_size = j - coveror.intersection.begin ();
281 coveror.intersection.resize (new_size);
282
283 if (!coveror.intersection.empty ())
284 continue;
285
286 // No covered literal addition candidates in the intersection left!
287 // Move this clause triggering early abort to the beginning.
288 // This is a common move to front strategy to minimize effort.
289
290 auto begin = os.begin ();
291 while (i != begin) {
292 auto prev = i - 1;
293 *i = *prev;
294 i = prev;
295 }
296 *begin = c;
297
298 break; // early abort ...
299 }
300 }
301
302 bool res = false;
303 if (first) {
304 LOG ("all resolution candidates with %d blocked", -lit);
305 CADICAL_assert (coveror.intersection.empty ());
306 cover_push_extension (lit, coveror);
307 res = true;
308 } else if (coveror.intersection.empty ()) {
309 LOG ("empty intersection of resolution candidate literals");
310 } else {
311 LOG (coveror.intersection,
312 "non-empty intersection of resolution candidate literals");
313 covered_literal_addition (lit, coveror);
314 unmark (coveror.intersection);
315 coveror.intersection.clear ();
316 coveror.next.covered = 0; // Restart covering.
317 }
318
319 unmark (coveror.intersection);
320 coveror.intersection.clear ();
321
322 return res;
323}
void covered_literal_addition(int lit, Coveror &)
void cover_push_extension(int lit, Coveror &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cover_push_extension()

void CaDiCaL::Internal::cover_push_extension ( int lit,
Coveror & coveror )
inline

Definition at line 53 of file cadical_cover.cpp.

53 {
54 coveror.extend.push_back (0);
55 coveror.extend.push_back (lit); // blocking literal comes first
56 bool found = false;
57 for (const auto &other : coveror.covered)
58 if (lit == other)
59 CADICAL_assert (!found), found = true;
60 else
61 coveror.extend.push_back (other);
62 CADICAL_assert (found);
63 (void) found;
64}
Here is the caller graph for this function:

◆ cover_round()

int64_t CaDiCaL::Internal::cover_round ( )

Definition at line 483 of file cadical_cover.cpp.

483 {
484
485 if (unsat)
486 return 0;
487
488 init_watches ();
489 connect_watches (true); // irredundant watches only is enough
490
491 int64_t delta = stats.propagations.search;
492 delta *= 1e-3 * opts.covereffort;
493 if (delta < opts.covermineff)
494 delta = opts.covermineff;
495 if (delta > opts.covermaxeff)
496 delta = opts.covermaxeff;
497 delta = max (delta, ((int64_t) 2) * active ());
498
499 PHASE ("cover", stats.cover.count,
500 "covered clause elimination limit of %" PRId64 " propagations",
501 delta);
502
503 int64_t limit = stats.propagations.cover + delta;
504
505 init_occs ();
506
507 vector<Clause *> schedule;
508 Coveror coveror;
509
510 // First connect all clauses and find all not yet tried clauses.
511 //
512#ifndef CADICAL_QUIET
513 int64_t untried = 0;
514#endif
515 //
516 for (auto c : clauses) {
517 CADICAL_assert (!c->frozen);
518 if (c->garbage)
519 continue;
520 if (c->redundant)
521 continue;
522 bool satisfied = false, allfrozen = true;
523 for (const auto &lit : *c)
524 if (val (lit) > 0) {
525 satisfied = true;
526 break;
527 } else if (allfrozen && !frozen (lit))
528 allfrozen = false;
529 if (satisfied) {
530 mark_garbage (c);
531 continue;
532 }
533 if (allfrozen) {
534 c->frozen = true;
535 continue;
536 }
537 for (const auto &lit : *c)
538 occs (lit).push_back (c);
539 if (c->size < opts.coverminclslim)
540 continue;
541 if (c->size > opts.covermaxclslim)
542 continue;
543 if (c->covered)
544 continue;
545 schedule.push_back (c);
546#ifndef CADICAL_QUIET
547 untried++;
548#endif
549 }
550
551 if (schedule.empty ()) {
552
553 PHASE ("cover", stats.cover.count, "no previously untried clause left");
554
555 for (auto c : clauses) {
556 if (c->garbage)
557 continue;
558 if (c->redundant)
559 continue;
560 if (c->frozen) {
561 c->frozen = false;
562 continue;
563 }
564 if (c->size < opts.coverminclslim)
565 continue;
566 if (c->size > opts.covermaxclslim)
567 continue;
568 CADICAL_assert (c->covered);
569 c->covered = false;
570 schedule.push_back (c);
571 }
572 } else { // Mix of tried and not tried clauses ....
573
574 for (auto c : clauses) {
575 if (c->garbage)
576 continue;
577 if (c->redundant)
578 continue;
579 if (c->frozen) {
580 c->frozen = false;
581 continue;
582 }
583 if (c->size < opts.coverminclslim)
584 continue;
585 if (c->size > opts.covermaxclslim)
586 continue;
587 if (!c->covered)
588 continue;
589 schedule.push_back (c);
590 }
591 }
592
593 stable_sort (schedule.begin (), schedule.end (),
594 clause_covered_or_smaller ());
595
596#ifndef CADICAL_QUIET
597 const size_t scheduled = schedule.size ();
598 PHASE ("cover", stats.cover.count,
599 "scheduled %zd clauses %.0f%% with %" PRId64 " untried %.0f%%",
600 scheduled, percent (scheduled, stats.current.irredundant), untried,
601 percent (untried, scheduled));
602#endif
603
604 // Heuristically it should be beneficial to intersect with smaller clauses
605 // first, since then the chances are higher that the intersection of
606 // resolution candidates becomes emptier earlier.
607
608 for (auto lit : lits) {
609 if (!active (lit))
610 continue;
611 Occs &os = occs (lit);
612 stable_sort (os.begin (), os.end (), clause_smaller_size ());
613 }
614
615 // This is the main loop of trying to do CCE of candidate clauses.
616 //
617 int64_t covered = 0;
618 //
619 while (!terminated_asynchronously () && !schedule.empty () &&
620 stats.propagations.cover < limit) {
621 Clause *c = schedule.back ();
622 schedule.pop_back ();
623 c->covered = true;
624 if (cover_clause (c, coveror))
625 covered++;
626 }
627
628#ifndef CADICAL_QUIET
629 const size_t remain = schedule.size ();
630 const size_t tried = scheduled - remain;
631 PHASE ("cover", stats.cover.count,
632 "eliminated %" PRId64 " covered clauses out of %zd tried %.0f%%",
633 covered, tried, percent (covered, tried));
634 if (remain)
635 PHASE ("cover", stats.cover.count,
636 "remaining %zu clauses %.0f%% untried", remain,
637 percent (remain, scheduled));
638 else
639 PHASE ("cover", stats.cover.count, "all scheduled clauses tried");
640#endif
641 reset_occs ();
642 reset_watches ();
643
644 return covered;
645}
bool cover_clause(Clause *c, Coveror &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ covered_literal_addition()

void CaDiCaL::Internal::covered_literal_addition ( int lit,
Coveror & coveror )
inline

Definition at line 68 of file cadical_cover.cpp.

68 {
70 CADICAL_assert (level == 1);
71 cover_push_extension (lit, coveror);
72 for (const auto &other : coveror.intersection) {
73 LOG ("covered literal addition %d", other);
74 CADICAL_assert (!vals[other]), CADICAL_assert (!vals[-other]);
75 set_val (other, -1);
76 coveror.covered.push_back (other);
77 coveror.added.push_back (other);
78 coveror.clas++;
79 }
80 coveror.next.covered = 0;
81}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ deallocate_clause()

void CaDiCaL::Internal::deallocate_clause ( Clause * c)

Definition at line 250 of file cadical_clause.cpp.

250 {
251 char *p = (char *) c;
252 if (arena.contains (p))
253 return;
254 LOG (c, "deallocate pointer %p", (void *) c);
255 delete[] p;
256}
Here is the caller graph for this function:

◆ decide()

int CaDiCaL::Internal::decide ( )

Definition at line 126 of file cadical_decide.cpp.

126 {
128 START (decide);
129 int res = 0;
130 if ((size_t) level < assumptions.size ()) {
131 const int lit = assumptions[level];
133 const signed char tmp = val (lit);
134 if (tmp < 0) {
135 LOG ("assumption %d falsified", lit);
136 res = 20;
137 } else if (tmp > 0) {
138 LOG ("assumption %d already satisfied", lit);
139 new_trail_level (0);
140 LOG ("added pseudo decision level");
142 } else {
143 LOG ("deciding assumption %d", lit);
145 }
146 } else if ((size_t) level == assumptions.size () && constraint.size ()) {
147
148 int satisfied_lit = 0; // The literal satisfying the constrain.
149 int unassigned_lit = 0; // Highest score unassigned literal.
150 int previous_lit = 0; // Move satisfied literals to the front.
151
152 const size_t size_constraint = constraint.size ();
153
154#ifndef CADICAL_NDEBUG
155 unsigned sum = 0;
156 for (auto lit : constraint)
157 sum += lit;
158#endif
159 for (size_t i = 0; i != size_constraint; i++) {
160
161 // Get literal and move 'constraint[i] = constraint[i-1]'.
162
163 int lit = constraint[i];
164 constraint[i] = previous_lit;
165 previous_lit = lit;
166
167 const signed char tmp = val (lit);
168 if (tmp < 0) {
169 LOG ("constraint literal %d falsified", lit);
170 continue;
171 }
172
173 if (tmp > 0) {
174 LOG ("constraint literal %d satisfied", lit);
175 satisfied_lit = lit;
176 break;
177 }
178
179 CADICAL_assert (!tmp);
180 LOG ("constraint literal %d unassigned", lit);
181
182 if (!unassigned_lit || better_decision (lit, unassigned_lit))
183 unassigned_lit = lit;
184 }
185
186 if (satisfied_lit) {
187
188 constraint[0] = satisfied_lit; // Move satisfied to the front.
189
190 LOG ("literal %d satisfies constraint and "
191 "is implied by assumptions",
192 satisfied_lit);
193
194 new_trail_level (0);
195 LOG ("added pseudo decision level for constraint");
197
198 } else {
199
200 // Just move all the literals back. If we found an unsatisfied
201 // literal then it will be satisfied (most likely) at the next
202 // decision and moved then to the first position.
203
204 if (size_constraint) {
205
206 for (size_t i = 0; i + 1 != size_constraint; i++)
207 constraint[i] = constraint[i + 1];
208
209 constraint[size_constraint - 1] = previous_lit;
210 }
211
212 if (unassigned_lit) {
213
214 LOG ("deciding %d to satisfy constraint", unassigned_lit);
215 search_assume_decision (unassigned_lit);
216
217 } else {
218
219 LOG ("failing constraint");
220 unsat_constraint = true;
221 res = 20;
222 }
223 }
224
225#ifndef CADICAL_NDEBUG
226 for (auto lit : constraint)
227 sum -= lit;
228 CADICAL_assert (!sum); // Checksum of literal should not change!
229#endif
230
231 } else {
232
233 int decision = ask_decision ();
234 if ((size_t) level < assumptions.size () ||
235 ((size_t) level == assumptions.size () && constraint.size ())) {
236 // Forced backtrack below pseudo decision levels.
237 // So one of the two branches above will handle it.
238 STOP (decide);
239 res = decide (); // STARTS and STOPS profiling
240 START (decide);
241 } else {
242 stats.decisions++;
243 if (!decision) {
244 int idx = next_decision_variable ();
245 const bool target = (opts.target > 1 || (stable && opts.target));
246 decision = decide_phase (idx, target);
247 }
248 search_assume_decision (decision);
249 }
250 }
251 if (res)
252 marked_failed = false;
253 STOP (decide);
254 return res;
255}
void new_trail_level(int lit)
bool better_decision(int lit, int other)
void search_assume_decision(int decision)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ decide_phase()

int CaDiCaL::Internal::decide_phase ( int idx,
bool target )

Definition at line 57 of file cadical_decide.cpp.

57 {
58 const int initial_phase = opts.phase ? 1 : -1;
59 int phase = 0;
61 phase = phases.saved[idx];
62 if (!phase)
63 phase = phases.forced[idx]; // swapped with opts.forcephase case!
64 if (!phase && opts.forcephase)
65 phase = initial_phase;
66 if (!phase && target)
67 phase = phases.target[idx];
68 if (!phase)
69 phase = phases.saved[idx];
70
71 // The following should not be necessary and in some version we had even
72 // a hard 'COVER' CADICAL_assertion here to check for this. Unfortunately it
73 // triggered for some users and we could not get to the root cause of
74 // 'phase' still not being set here. The logic for phase and target
75 // saving is pretty complex, particularly in combination with local
76 // search, and to avoid running in such an issue in the future again, we
77 // now use this 'defensive' code here, even though such defensive code is
78 // considered bad programming practice.
79 //
80 if (!phase)
81 phase = initial_phase;
82
83 return phase * idx;
84}
void phase(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ decompose()

void CaDiCaL::Internal::decompose ( )

Definition at line 731 of file cadical_decompose.cpp.

731 {
732 for (int round = 1; round <= opts.decomposerounds; round++)
733 if (!decompose_round ())
734 break;
735}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ decompose_analyze_binary_chain()

void CaDiCaL::Internal::decompose_analyze_binary_chain ( DFS * dfs,
int from )

Definition at line 9 of file cadical_decompose.cpp.

9 {
10 if (!lrat)
11 return;
12 LOG ("binary chain starting at %d", from);
13 DFS &from_dfs = dfs[vlit (from)];
14 Clause *reason = from_dfs.parent;
15 if (!reason)
16 return;
17 CADICAL_assert (reason->size == 2);
18 mini_chain.push_back (reason->id);
19 int other = reason->literals[0];
20 other = other == from ? -reason->literals[1] : -other;
21 Flags &f = flags (other);
22 if (f.seen)
23 return;
24 f.seen = true;
25 analyzed.push_back (other);
27}
void decompose_analyze_binary_chain(DFS *dfs, int)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ decompose_analyze_binary_clauses()

vector< Clause * > CaDiCaL::Internal::decompose_analyze_binary_clauses ( DFS * dfs,
int from )

Definition at line 29 of file cadical_decompose.cpp.

30 {
31 vector<Clause *> result;
32 LOG ("binary chain starting at %d", from);
33 DFS &from_dfs = dfs[vlit (from)];
34 Clause *reason = from_dfs.parent;
35 while (reason) {
36 result.push_back (reason);
37 CADICAL_assert (reason->size == 2);
38 int other = reason->literals[0];
39 other = other == from ? -reason->literals[1] : -other;
40 Flags &f = flags (other);
41 if (f.seen)
42 break;
43 f.seen = true;
44 analyzed.push_back (other);
45 from = other;
46 DFS &from_dfs = dfs[vlit (from)];
47 reason = from_dfs.parent;
48 }
49 return result;
50}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ decompose_conflicting_scc_lrat()

void CaDiCaL::Internal::decompose_conflicting_scc_lrat ( DFS * dfs,
vector< int > & scc )

Definition at line 52 of file cadical_decompose.cpp.

52 {
53 if (!lrat)
54 return;
55 CADICAL_assert (lrat_chain.empty ());
56 CADICAL_assert (mini_chain.empty ());
57 for (auto &lit : scc) {
58 Flags &f = flags (lit);
59 if (f.seen)
60 return;
61 f.seen = true;
62 analyzed.push_back (lit);
64 for (auto p = mini_chain.rbegin (); p != mini_chain.rend (); p++) {
65 lrat_chain.push_back (*p);
66 }
67 mini_chain.clear ();
68 }
70}
Here is the call graph for this function:

◆ decompose_round()

bool CaDiCaL::Internal::decompose_round ( )

Definition at line 134 of file cadical_decompose.cpp.

134 {
135
136 if (!opts.decompose)
137 return false;
138 if (unsat)
139 return false;
141 return false;
142
144
146
147 stats.decompositions++;
148
149 const size_t size_dfs = 2 * (1 + (size_t) max_var);
150 DFS *dfs = new DFS[size_dfs];
151 DeferDeleteArray<DFS> dfs_delete (dfs);
152 int *reprs = new int[size_dfs];
153 DeferDeleteArray<int> reprs_delete (reprs);
154 clear_n (reprs, size_dfs);
155 vector<vector<Clause *>> dfs_chains;
156 dfs_chains.resize (size_dfs);
157 if (lrat) {
158 for (size_t i = 0; i > size_dfs; i++) {
159 vector<Clause *> empty;
160 dfs_chains[i] = empty;
161 }
162 }
163
164 int substituted = 0;
165#ifndef CADICAL_QUIET
166 int non_trivial_sccs = 0;
167 int before = active ();
168#endif
169 unsigned dfs_idx = 0;
170
171 vector<int> work; // depth first search working stack
172 vector<int> scc; // collects members of one SCC
173
174 // The binary implication graph might have disconnected components and
175 // thus we have in general to start several depth first searches.
176
177 for (auto root_idx : vars) {
178 if (unsat)
179 break;
180 if (!active (root_idx))
181 continue;
182 for (int root_sign = -1; !unsat && root_sign <= 1; root_sign += 2) {
183 int root = root_sign * root_idx;
184 if (dfs[vlit (root)].min == TRAVERSED)
185 continue; // skip traversed
186 LOG ("new dfs search starting at root %d", root);
187 CADICAL_assert (work.empty ());
188 CADICAL_assert (scc.empty ());
189 work.push_back (root);
190 while (!unsat && !work.empty ()) {
191 int parent = work.back ();
192 DFS &parent_dfs = dfs[vlit (parent)];
193 if (parent_dfs.min == TRAVERSED) { // skip traversed
194 CADICAL_assert (reprs[vlit (parent)]);
195 work.pop_back ();
196 } else {
197 CADICAL_assert (!reprs[vlit (parent)]);
198
199 // Go over all implied literals, thus need to iterate over all
200 // binary watched clauses with the negation of 'parent'.
201
202 Watches &ws = watches (-parent);
203
204 // Two cases: Either the node has never been visited before, i.e.,
205 // it's depth first search index is zero, then perform the
206 // 'pre-fix' work before visiting it's children. Otherwise all
207 // it's children and nodes reachable from those children have been
208 // visited and their minimum reachable depth first search index
209 // has been computed. This second case is the 'post-fix' work.
210
211 if (parent_dfs.idx) { // post-fix
212
213 work.pop_back (); // 'parent' done
214
215 // Get the minimum reachable depth first search index reachable
216 // from the children of 'parent'.
217
218 unsigned new_min = parent_dfs.min;
219
220 for (const auto &w : ws) {
221 if (!w.binary ())
222 continue;
223 const int child = w.blit;
224 if (!active (child))
225 continue;
226 DFS &child_dfs = dfs[vlit (child)];
227 if (new_min > child_dfs.min)
228 new_min = child_dfs.min;
229 }
230
231 LOG ("post-fix work dfs search %d index %u reaches minimum %u",
232 parent, parent_dfs.idx, new_min);
233
234 if (parent_dfs.idx == new_min) { // entry to SCC
235
236 // All nodes on the 'scc' stack after and including 'parent'
237 // are in the same SCC. Their representative is computed as
238 // the smallest literal (index-wise) in the SCC. If the SCC
239 // contains both a literal and its negation, then the formula
240 // becomes unsatisfiable.
241
242 if (lrat) {
243 CADICAL_assert (analyzed.empty ());
244 int other, first = 0;
245 bool conflicting = false;
246 size_t j = scc.size ();
247 do {
248 CADICAL_assert (j > 0);
249 other = scc[--j];
250 if (!first || vlit (other) < vlit (first))
251 first = other;
252 Flags &f = flags (other);
253 if (other == -parent) {
254 conflicting = true; // conflicting scc
255 }
256 if (f.seen) {
257 continue; // also conflicting scc
258 }
259 f.seen = true;
260 analyzed.push_back (other);
261 } while (other != parent);
262
263 CADICAL_assert (!conflicting || first > 0);
264 vector<int> to_justify;
265 if (conflicting) {
266 LOG ("conflicting scc simulating up at %d", parent);
267 to_justify.push_back (-parent);
268 } else
269 to_justify.push_back (first);
270 while (!to_justify.empty ()) {
271 const int next = to_justify.back ();
272 to_justify.pop_back ();
273 Watches &next_ws = watches (-next);
274 for (const auto &w : next_ws) {
275 if (!w.binary ())
276 continue;
277 const int child = w.blit;
278 if (!active (child))
279 continue;
280 if (!flags (child).seen)
281 continue;
282 DFS &child_dfs = dfs[vlit (child)];
283 if (child_dfs.parent)
284 continue;
285 child_dfs.parent = w.clause;
286 to_justify.push_back (child);
287 }
288 }
289
291 }
292
293 int other, repr = parent;
294#ifndef CADICAL_QUIET
295 int size = 0;
296#endif
297 CADICAL_assert (!scc.empty ());
298 size_t j = scc.size ();
299 do {
300 CADICAL_assert (j > 0);
301 other = scc[--j];
302 if (other == -parent) {
303 LOG ("both %d and %d in one SCC", parent, -parent);
304 if (lrat) {
305 Flags &f = flags (-parent);
306 f.seen = true;
307 analyzed.push_back (-parent);
308 decompose_analyze_binary_chain (dfs, parent);
309 for (auto p : mini_chain)
310 lrat_chain.push_back (p);
311 mini_chain.clear ();
312 }
313 assign_unit (parent);
314#ifndef CADICAL_NDEBUG
315 bool ok =
316#endif
317 propagate ();
318 CADICAL_assert (!ok);
320 lrat_chain.clear ();
321 } else {
322 if (abs (other) < abs (repr))
323 repr = other;
324#ifndef CADICAL_QUIET
325 size++;
326#endif
327 }
328 } while (!unsat && other != parent);
329
330 if (unsat)
331 break;
332#ifndef CADICAL_QUIET
333 LOG ("SCC of representative %d of size %d", repr, size);
334#endif
335 do {
336 CADICAL_assert (!scc.empty ());
337 other = scc.back ();
338 scc.pop_back ();
339 dfs[vlit (other)].min = TRAVERSED;
340 if (frozen (other)) {
341 reprs[vlit (other)] = other;
342 continue;
343 }
344 reprs[vlit (other)] = repr;
345 if (other == repr)
346 continue;
347 substituted++;
348 LOG ("literal %d in SCC of %d", other, repr);
349 if (!lrat)
350 continue;
351 CADICAL_assert (mini_chain.empty ());
352 Flags &f = flags (repr);
353 f.seen = true;
354 analyzed.push_back (repr);
355 // no need to reverse dfs_chain because this is handled by
356 // build_lrat_for_clause.
357 dfs_chains[vlit (other)] =
360 } while (other != parent);
361
362#ifndef CADICAL_QUIET
363 if (size > 1)
364 non_trivial_sccs++;
365#endif
366
367 } else {
368
369 // Current node 'parent' is in a non-trivial SCC but is not
370 // the entry point of the SCC in this depth first search, so
371 // keep it on the SCC stack until the entry point is reached.
372
373 parent_dfs.min = new_min;
374 }
375
376 } else { // pre-fix
377
378 dfs_idx++;
379 CADICAL_assert (dfs_idx < TRAVERSED);
380 parent_dfs.idx = parent_dfs.min = dfs_idx;
381 scc.push_back (parent);
382
383 LOG ("pre-fix work dfs search %d index %u", parent, dfs_idx);
384
385 // Now traverse all the children in the binary implication
386 // graph but keep 'parent' on the stack for 'post-fix' work.
387
388 for (const auto &w : ws) {
389 if (!w.binary ())
390 continue;
391 const int child = w.blit;
392 if (!active (child))
393 continue;
394 DFS &child_dfs = dfs[vlit (child)];
395 if (child_dfs.idx)
396 continue;
397 work.push_back (child);
398 }
399 }
400 }
401 }
402 }
403 }
404
405 erase_vector (work);
406 erase_vector (scc);
407 // delete [] dfs; need to postpone until after changing clauses...
408
409 // Only keep the representatives 'repr' mapping.
410
411 PHASE ("decompose", stats.decompositions,
412 "%d non-trivial sccs, %d substituted %.2f%%", non_trivial_sccs,
413 substituted, percent (substituted, before));
414
415 bool new_unit = false, new_binary_clause = false;
416
417 // Finally, mark substituted literals as such and push the equivalences of
418 // the substituted literals to their representative on the extension
419 // stack to fix an assignment during 'extend'.
420 // It is also necessary to do so for proper IDRUP/LIDRUP/Resolution proofs
421
422 vector<int64_t> decompose_ids;
423 const size_t size = 2 * (1 + (size_t) max_var);
424 decompose_ids.resize (size);
425
426 for (auto idx : vars) {
427 if (!substituted)
428 break;
429 if (unsat)
430 break;
431 if (!active (idx))
432 continue;
433 int other = reprs[vlit (idx)];
434 if (other == idx)
435 continue;
436 CADICAL_assert (!flags (other).eliminated ());
437 CADICAL_assert (!flags (other).substituted ());
438
439 LOG ("marking equivalence of %d and %d", idx, other);
440 CADICAL_assert (clause.empty ());
441 CADICAL_assert (lrat_chain.empty ());
442 clause.push_back (other);
443 clause.push_back (-idx);
444 if (lrat) {
445 build_lrat_for_clause (dfs_chains);
446 CADICAL_assert (!lrat_chain.empty ());
447 }
448
449 const int64_t id1 = ++clause_id;
450 if (proof) {
451 proof->add_derived_clause (id1, false, clause, lrat_chain);
452 proof->weaken_minus (id1, clause);
453 }
454 external->push_binary_clause_on_extension_stack (id1, -idx, other);
455
456 decompose_ids[vlit (-idx)] = id1;
457
458 lrat_chain.clear ();
459 clause.clear ();
460
461 CADICAL_assert (clause.empty ());
462 CADICAL_assert (lrat_chain.empty ());
463 clause.push_back (idx);
464 clause.push_back (-other);
465 if (lrat) {
466 build_lrat_for_clause (dfs_chains);
467 CADICAL_assert (!lrat_chain.empty ());
468 }
469 const int64_t id2 = ++clause_id;
470 if (proof) {
471 proof->add_derived_clause (id2, false, clause, lrat_chain);
472 proof->weaken_minus (id2, clause);
473 }
474 external->push_binary_clause_on_extension_stack (id2, idx, -other);
475 decompose_ids[vlit (idx)] = id2;
476
477 clause.clear ();
478 lrat_chain.clear ();
479 }
480
481 vector<Clause *> postponed_garbage;
482
483 // Now go over all clauses and find clause which contain literals that
484 // should be substituted by their representative.
485
486 size_t clauses_size = clauses.size ();
487#ifndef CADICAL_QUIET
488 size_t garbage = 0, replaced = 0;
489#endif
490 for (size_t i = 0; substituted && !unsat && i < clauses_size; i++) {
491 Clause *c = clauses[i];
492 if (c->garbage)
493 continue;
494 int j, size = c->size;
495 for (j = 0; j < size; j++) {
496 const int lit = c->literals[j];
497 if (reprs[vlit (lit)] != lit)
498 break;
499 }
500
501 if (j == size)
502 continue;
503
504#ifndef CADICAL_QUIET
505 replaced++;
506#endif
507 LOG (c, "first substituted literal %d in", substituted);
508
509 // Now copy the result to 'clause'. Substitute literals if they have a
510 // different representative. Skip duplicates and false literals. If a
511 // literal occurs in both phases or is assigned to true the clause is
512 // satisfied and can be marked as garbage.
513
514 CADICAL_assert (clause.empty ());
515 CADICAL_assert (lrat_chain.empty ());
516 CADICAL_assert (analyzed.empty ());
517 bool satisfied = false;
518
519 for (int k = 0; !satisfied && k < size; k++) {
520 const int lit = c->literals[k];
521 signed char tmp = val (lit);
522 if (tmp > 0)
523 satisfied = true;
524 else if (tmp < 0) {
525 if (!lrat)
526 continue;
527 Flags &f = flags (lit);
528 if (f.seen)
529 continue;
530 f.seen = true;
531 analyzed.push_back (lit);
532 int64_t id = unit_id (-lit);
533 lrat_chain.push_back (id);
534 continue;
535 } else {
536 const int other = reprs[vlit (lit)];
537 tmp = val (other);
538 if (tmp < 0) {
539 if (!lrat)
540 continue;
541 Flags &f = flags (other);
542 if (!f.seen) {
543 f.seen = true;
544 analyzed.push_back (other);
545 int64_t id = unit_id (-other);
546 lrat_chain.push_back (id);
547 }
548 if (other == lit)
549 continue;
550 int64_t id = decompose_ids[vlit (-lit)];
551 CADICAL_assert (id);
552 lrat_chain.push_back (id);
553 continue;
554 } else if (tmp > 0)
555 satisfied = true;
556 else {
557 tmp = marked (other);
558 if (tmp < 0)
559 satisfied = true;
560 else if (!tmp) {
561 mark (other);
562 clause.push_back (other);
563 }
564 if (other == lit)
565 continue;
566 if (!lrat)
567 continue;
568 int64_t id = decompose_ids[vlit (-lit)];
569 CADICAL_assert (id);
570 lrat_chain.push_back (id);
571 }
572 }
573 }
574 if (lrat)
575 lrat_chain.push_back (c->id);
577 LOG (lrat_chain, "lrat_chain:");
578 if (satisfied) {
579 LOG (c, "satisfied after substitution (postponed)");
580 postponed_garbage.push_back (c);
581#ifndef CADICAL_QUIET
582 garbage++;
583#endif
584 } else if (!clause.size ()) {
585 LOG ("learned empty clause during decompose");
587 } else if (clause.size () == 1) {
588 LOG (c, "unit %d after substitution", clause[0]);
589 assign_unit (clause[0]);
590 mark_garbage (c);
591 new_unit = true;
592#ifndef CADICAL_QUIET
593 garbage++;
594#endif
595 } else if (c->literals[0] != clause[0] || c->literals[1] != clause[1]) {
596 LOG ("need new clause since at least one watched literal changed");
597 if (clause.size () == 2)
598 new_binary_clause = true;
599 size_t d_clause_idx = clauses.size ();
600 Clause *d = new_clause_as (c);
601 CADICAL_assert (clauses[d_clause_idx] == d);
602 clauses[d_clause_idx] = c;
603 clauses[i] = d;
604 mark_garbage (c);
605#ifndef CADICAL_QUIET
606 garbage++;
607#endif
608 } else {
609 LOG ("simply shrinking clause since watches did not change");
610 CADICAL_assert (c->size > 2);
611 if (!c->redundant)
612 mark_removed (c);
613 if (proof) {
614 proof->add_derived_clause (++clause_id, c->redundant, clause,
615 lrat_chain);
616 proof->delete_clause (c);
617 c->id = clause_id;
618 }
619 size_t l;
620 int *literals = c->literals;
621 for (l = 2; l < clause.size (); l++)
622 literals[l] = clause[l];
623 int flushed = c->size - (int) l;
624 if (flushed) {
625 if (l == 2)
626 new_binary_clause = true;
627 LOG ("flushed %d literals", flushed);
628 (void) shrink_clause (c, l);
629 } else if (likely_to_be_kept_clause (c))
630 mark_added (c);
631 // we have shrunken c->size to l so even though there is an CADICAL_assertion
632 // for c->size > 2 at the beginning of this else block, the new size
633 // can be 2 now.
634 if (c->size == 2) { // cheaper to update only new binary clauses
635 CADICAL_assert (new_binary_clause);
636 update_watch_size (watches (c->literals[0]), c->literals[1], c);
637 update_watch_size (watches (c->literals[1]), c->literals[0], c);
638 }
639 LOG (c, "substituted");
640 }
641 while (!clause.empty ()) {
642 int lit = clause.back ();
643 clause.pop_back ();
644 CADICAL_assert (marked (lit) > 0);
645 unmark (lit);
646 }
647 lrat_chain.clear ();
648 }
649
650 if (proof) {
651 for (auto idx : vars) {
652 if (!substituted)
653 break;
654 if (!active (idx))
655 continue;
656 const int64_t id1 = decompose_ids[vlit (-idx)];
657 if (!id1)
658 continue;
659 int other = reprs[vlit (idx)];
660 CADICAL_assert (other != idx);
661 CADICAL_assert (!flags (other).eliminated ());
662 CADICAL_assert (!flags (other).substituted ());
663
664 clause.push_back (other);
665 clause.push_back (-idx);
666 proof->delete_clause (id1, false, clause);
667 clause.clear ();
668
669 clause.push_back (idx);
670 clause.push_back (-other);
671 const int64_t id2 = decompose_ids[vlit (idx)];
672 proof->delete_clause (id2, false, clause);
673 clause.clear ();
674 }
675 }
676
677 if (!unsat && !postponed_garbage.empty ()) {
678 LOG ("now marking %zd postponed garbage clauses",
679 postponed_garbage.size ());
680 for (const auto &c : postponed_garbage)
681 mark_garbage (c);
682 }
683 erase_vector (postponed_garbage);
684
685 PHASE ("decompose", stats.decompositions,
686 "%zd clauses replaced %.2f%% producing %zd garbage clauses %.2f%%",
687 replaced, percent (replaced, clauses_size), garbage,
688 percent (garbage, replaced));
689
690 erase_vector (scc);
691
692 // Propagate found units.
693
694 if (!unsat && propagated < trail.size () && !propagate ()) {
695 LOG ("empty clause after propagating units from substitution");
697 }
698
699 for (auto idx : vars) {
700 if (!substituted)
701 break;
702 if (unsat)
703 break;
704 if (!active (idx))
705 continue;
706 int other = reprs[vlit (idx)];
707 if (other == idx)
708 continue;
709 CADICAL_assert (!flags (other).eliminated ());
710 CADICAL_assert (!flags (other).substituted ());
711 if (!flags (other).fixed ())
712 mark_substituted (idx);
713 }
714
715 reprs_delete.free ();
716 dfs_delete.free ();
717 erase_vector (dfs_chains);
718
719 if (substituted)
720 flush_all_occs_and_watches (); // particularly the 'blit's
721
722 bool success =
723 unsat || (substituted > 0 && (new_unit || new_binary_clause));
724 report ('d', !opts.reportall && !success);
725
727
728 return success;
729}
#define TRAVERSED
Definition decompose.hpp:16
void clear_n(T *base, size_t n)
Definition util.hpp:149
void update_watch_size(Watches &ws, int blit, Clause *conflict)
Definition watch.hpp:63
void mark_removed(int lit)
void mark_substituted(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)
size_t shrink_clause(Clause *, int new_size)
void mark_added(int lit, int size, bool redundant)
Clause * new_clause_as(const Clause *orig)
bool likely_to_be_kept_clause(Clause *c)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_clause()

void CaDiCaL::Internal::delete_clause ( Clause * c)

Definition at line 258 of file cadical_clause.cpp.

258 {
259 LOG (c, "delete pointer %p", (void *) c);
260 size_t bytes = c->bytes ();
261 stats.collected += bytes;
262 if (c->garbage) {
263 CADICAL_assert (stats.garbage.bytes >= (int64_t) bytes);
264 stats.garbage.bytes -= bytes;
265 CADICAL_assert (stats.garbage.clauses > 0);
266 stats.garbage.clauses--;
267 CADICAL_assert (stats.garbage.literals >= c->size);
268 stats.garbage.literals -= c->size;
269
270 // See the discussion in 'propagate' on avoiding to eagerly trace binary
271 // clauses as deleted (produce 'd ...' lines) as soon they are marked
272 // garbage. We avoid this and only trace them as deleted when they are
273 // actually deleted here. This allows the solver to propagate binary
274 // garbage clauses without producing incorrect 'd' lines. The effect
275 // from the proof perspective is that the deletion of these binary
276 // clauses occurs later in the proof file.
277 //
278 if (proof && c->size == 2 && !c->flushed) {
279 proof->delete_clause (c);
280 }
281 }
283}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_garbage_clauses()

void CaDiCaL::Internal::delete_garbage_clauses ( )

Definition at line 279 of file cadical_collect.cpp.

279 {
280
282
283 LOG ("deleting garbage clauses");
284#ifndef CADICAL_QUIET
285 int64_t collected_bytes = 0, collected_clauses = 0;
286#endif
287 const auto end = clauses.end ();
288 auto j = clauses.begin (), i = j;
289 while (i != end) {
290 Clause *c = *j++ = *i++;
291 if (!c->collect ())
292 continue;
293#ifndef CADICAL_QUIET
294 collected_bytes += c->bytes ();
295 collected_clauses++;
296#endif
297 delete_clause (c);
298 j--;
299 }
300 clauses.resize (j - clauses.begin ());
302
303 PHASE ("collect", stats.collections,
304 "collected %" PRId64 " bytes of %" PRId64 " garbage clauses",
305 collected_bytes, collected_clauses);
306}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_sweep_binary()

void CaDiCaL::Internal::delete_sweep_binary ( const sweep_binary & sb)

Definition at line 931 of file cadical_sweep.cpp.

931 {
932 if (unsat)
933 return;
934 if (!proof)
935 return;
936 vector<int> bin;
937 bin.push_back (sb.lit);
938 bin.push_back (sb.other);
939 proof->delete_clause (sb.id, false, bin);
940}
Here is the caller graph for this function:

◆ delete_unfactored()

void CaDiCaL::Internal::delete_unfactored ( Quotient * q)

Definition at line 690 of file cadical_factor.cpp.

690 {
691 LOG ("deleting unfactored quotient[%zu] clauses", q->id);
692 for (auto c : q->qlauses) {
694 mark_garbage (c);
695 stats.literals_unfactored += c->size;
696 stats.clauses_unfactored++;
697 }
698}
void eagerly_remove_from_occurences(Clause *c)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ demote_clause()

void CaDiCaL::Internal::demote_clause ( Clause * c)
inline

Definition at line 120 of file cadical_vivify.cpp.

120 {
121 stats.subsumed++;
122 stats.vivifydemote++;
123 LOG (c, "demoting");
124 CADICAL_assert (!c->redundant);
125 mark_removed (c);
126 c->redundant = true;
127 CADICAL_assert (stats.current.irredundant > 0);
128 stats.current.irredundant--;
129 CADICAL_assert (stats.added.irredundant > 0);
130 stats.added.irredundant--;
131 stats.irrlits -= c->size;
132 stats.current.redundant++;
133 stats.added.redundant++;
134 c->glue = c->size - 1;
135 // ... and keep 'stats.added.total'.
136}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ determine_actual_backtrack_level()

int CaDiCaL::Internal::determine_actual_backtrack_level ( int jump)
inline

Definition at line 652 of file cadical_analyze.cpp.

652 {
653
654 int res;
655
656 CADICAL_assert (level > jump);
657
658 if (!opts.chrono) {
659 res = jump;
660 LOG ("chronological backtracking disabled using jump level %d", res);
661 } else if (opts.chronoalways) {
662 stats.chrono++;
663 res = level - 1;
664 LOG ("forced chronological backtracking to level %d", res);
665 } else if (jump >= level - 1) {
666 res = jump;
667 LOG ("jump level identical to chronological backtrack level %d", res);
668 } else if ((size_t) jump < assumptions.size ()) {
669 res = jump;
670 LOG ("using jump level %d since it is lower than assumption level %zd",
671 res, assumptions.size ());
672 } else if (level - jump > opts.chronolevelim) {
673 stats.chrono++;
674 res = level - 1;
675 LOG ("back-jumping over %d > %d levels prohibited"
676 "thus backtracking chronologically to level %d",
677 level - jump, opts.chronolevelim, res);
678 } else if (opts.chronoreusetrail) {
679 int best_idx = 0, best_pos = 0;
680
681 if (use_scores ()) {
682 for (size_t i = control[jump + 1].trail; i < trail.size (); i++) {
683 const int idx = abs (trail[i]);
684 if (best_idx && !score_smaller (this) (best_idx, idx))
685 continue;
686 best_idx = idx;
687 best_pos = i;
688 }
689 LOG ("best variable score %g", score (best_idx));
690 } else {
691 for (size_t i = control[jump + 1].trail; i < trail.size (); i++) {
692 const int idx = abs (trail[i]);
693 if (best_idx && bumped (best_idx) >= bumped (idx))
694 continue;
695 best_idx = idx;
696 best_pos = i;
697 }
698 LOG ("best variable bumped %" PRId64 "", bumped (best_idx));
699 }
700 CADICAL_assert (best_idx);
701 LOG ("best variable %d at trail position %d", best_idx, best_pos);
702
703 // Now find the frame and decision level in the control stack of that
704 // best variable index. Note that, as in 'reuse_trail', the frame
705 // 'control[i]' for decision level 'i' contains the trail before that
706 // decision level, i.e., the decision 'control[i].decision' sits at
707 // 'control[i].trail' in the trail and we thus have to check the level
708 // of the control frame one higher than at the result level.
709 //
710 res = jump;
711 while (res < level - 1 && control[res + 1].trail <= best_pos)
712 res++;
713
714 if (res == jump)
715 LOG ("default non-chronological back-jumping to level %d", res);
716 else {
717 stats.chrono++;
718 LOG ("chronological backtracking to level %d to reuse trail", res);
719 }
720
721 } else {
722 res = jump;
723 LOG ("non-chronological back-jumping to level %d", res);
724 }
725
726 return res;
727}
int64_t & bumped(int lit)
Definition internal.hpp:455
Here is the call graph for this function:
Here is the caller graph for this function:

◆ disconnect_proof_tracer() [1/3]

bool CaDiCaL::Internal::disconnect_proof_tracer ( FileTracer * tracer)

Definition at line 108 of file cadical_proof.cpp.

108 {
109 auto it = std::find (file_tracers.begin (), file_tracers.end (), tracer);
110 if (it != file_tracers.end ()) {
111 file_tracers.erase (it);
113 proof->disconnect (tracer);
114 return true;
115 }
116 return false;
117}

◆ disconnect_proof_tracer() [2/3]

bool CaDiCaL::Internal::disconnect_proof_tracer ( StatTracer * tracer)

Definition at line 97 of file cadical_proof.cpp.

97 {
98 auto it = std::find (stat_tracers.begin (), stat_tracers.end (), tracer);
99 if (it != stat_tracers.end ()) {
100 stat_tracers.erase (it);
102 proof->disconnect (tracer);
103 return true;
104 }
105 return false;
106}

◆ disconnect_proof_tracer() [3/3]

bool CaDiCaL::Internal::disconnect_proof_tracer ( Tracer * tracer)

Definition at line 86 of file cadical_proof.cpp.

86 {
87 auto it = std::find (tracers.begin (), tracers.end (), tracer);
88 if (it != tracers.end ()) {
89 tracers.erase (it);
91 proof->disconnect (tracer);
92 return true;
93 }
94 return false;
95}

◆ dump() [1/2]

void CaDiCaL::Internal::dump ( )

Definition at line 1114 of file cadical_internal.cpp.

1114 {
1115 int64_t m = assumptions.size ();
1116 for (auto idx : vars)
1117 if (fixed (idx))
1118 m++;
1119 for (const auto &c : clauses)
1120 if (!c->garbage)
1121 m++;
1122 printf ("p cnf %d %" PRId64 "\n", max_var, m);
1123 for (auto idx : vars) {
1124 const int tmp = fixed (idx);
1125 if (tmp)
1126 printf ("%d 0\n", tmp < 0 ? -idx : idx);
1127 }
1128 for (const auto &c : clauses)
1129 if (!c->garbage)
1130 dump (c);
1131 for (const auto &lit : assumptions)
1132 printf ("%d 0\n", lit);
1133 fflush (stdout);
1134}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ dump() [2/2]

void CaDiCaL::Internal::dump ( Clause * c)

Definition at line 1108 of file cadical_internal.cpp.

1108 {
1109 for (const auto &lit : *c)
1110 printf ("%d ", lit);
1111 printf ("0\n");
1112}

◆ eagerly_remove_from_occurences()

void CaDiCaL::Internal::eagerly_remove_from_occurences ( Clause * c)

Definition at line 672 of file cadical_factor.cpp.

672 {
673 for (const auto &lit : *c) {
674 auto &occ = occs (lit);
675 auto p = occ.begin ();
676 auto q = occ.begin ();
677 auto begin = occ.begin ();
678 auto end = occ.end ();
679 while (p != end) {
680 *q = *p++;
681 if (*q != c)
682 q++;
683 }
684 CADICAL_assert (q + 1 == p);
685 occ.resize (q - begin);
686 }
687}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ eagerly_subsume_recently_learned_clauses()

void CaDiCaL::Internal::eagerly_subsume_recently_learned_clauses ( Clause * c)

Definition at line 731 of file cadical_analyze.cpp.

731 {
732 CADICAL_assert (opts.eagersubsume);
733 LOG (c, "trying eager subsumption with");
734 mark (c);
735 int64_t lim = stats.eagertried + opts.eagersubsumelim;
736 const auto begin = clauses.begin ();
737 auto it = clauses.end ();
738#ifdef LOGGING
739 int64_t before = stats.eagersub;
740#endif
741 while (it != begin && stats.eagertried++ <= lim) {
742 Clause *d = *--it;
743 if (c == d)
744 continue;
745 if (d->garbage)
746 continue;
747 if (!d->redundant)
748 continue;
749 int needed = c->size;
750 for (auto &lit : *d) {
751 if (marked (lit) <= 0)
752 continue;
753 if (!--needed)
754 break;
755 }
756 if (needed)
757 continue;
758 LOG (d, "eager subsumed");
759 stats.eagersub++;
760 stats.subsumed++;
761 mark_garbage (d);
762 }
763 unmark (c);
764#ifdef LOGGING
765 uint64_t subsumed = stats.eagersub - before;
766 if (subsumed)
767 LOG ("eagerly subsumed %" PRIu64 " clauses", subsumed);
768#endif
769}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elim()

void CaDiCaL::Internal::elim ( bool update_limits = true)

Definition at line 1020 of file cadical_elim.cpp.

1020 {
1021
1022 if (unsat)
1023 return;
1024 if (level)
1025 backtrack ();
1026 if (!propagate ()) {
1028 return;
1029 }
1030
1031 stats.elimphases++;
1032 PHASE ("elim-phase", stats.elimphases,
1033 "starting at most %d elimination rounds", opts.elimrounds);
1034
1035 if (external_prop) {
1037 private_steps = true;
1038 }
1039
1040#ifndef CADICAL_QUIET
1041 int old_active_variables = active ();
1042 int old_eliminated = stats.all.eliminated;
1043#endif
1044
1045 // Make sure there was a complete subsumption phase since last
1046 // elimination including vivification etc.
1047 //
1048 if (last.elim.subsumephases == stats.subsumephases)
1049 subsume ();
1050
1051 reset_watches (); // saves lots of memory
1052
1053 init_citten ();
1054
1055 // Alternate one round of bounded variable elimination ('elim_round') and
1056 // subsumption ('subsume_round'), blocked ('block') and covered clause
1057 // elimination ('cover') until nothing changes, or the round limit is hit.
1058 // The loop also aborts early if no variable could be eliminated, the
1059 // empty clause is resolved, it is asynchronously terminated or a
1060 // resolution limit is hit.
1061
1062 // This variable determines whether the whole loop of this bounded
1063 // variable elimination phase ('elim') ran until completion. This
1064 // potentially triggers an incremental increase of the elimination bound.
1065 //
1066 bool phase_complete = false, deleted_binary_clause = false;
1067
1068 int round = 1;
1069#ifndef CADICAL_QUIET
1070 int eliminated = 0;
1071#endif
1072
1073 bool round_complete = false;
1074 while (!unsat && !phase_complete && !terminated_asynchronously ()) {
1075#ifndef CADICAL_QUIET
1076 int eliminated =
1077#endif
1078 elim_round (round_complete, deleted_binary_clause);
1079
1080 if (!round_complete) {
1081 PHASE ("elim-phase", stats.elimphases, "last round %d incomplete %s",
1082 round, eliminated ? "but successful" : "and unsuccessful");
1083 CADICAL_assert (!phase_complete);
1084 break;
1085 }
1086
1087 if (round++ >= opts.elimrounds) {
1088 PHASE ("elim-phase", stats.elimphases, "round limit %d hit (%s)",
1089 round - 1,
1090 eliminated ? "though last round successful"
1091 : "last round unsuccessful anyhow");
1092 CADICAL_assert (!phase_complete);
1093 break;
1094 }
1095
1096 // Prioritize 'subsumption' over blocked and covered clause elimination.
1097
1098 if (subsume_round ())
1099 continue;
1100 if (block ())
1101 continue;
1102 if (cover ())
1103 continue;
1104
1105 // Was not able to generate new variable elimination candidates after
1106 // variable elimination round, neither through subsumption, nor blocked,
1107 // nor covered clause elimination.
1108 //
1109 PHASE ("elim-phase", stats.elimphases,
1110 "no new variable elimination candidates");
1111
1112 CADICAL_assert (round_complete);
1113 phase_complete = true;
1114 }
1115
1116 if (phase_complete) {
1117 stats.elimcompleted++;
1118 PHASE ("elim-phase", stats.elimphases,
1119 "fully completed elimination %" PRId64
1120 " at elimination bound %" PRId64 "",
1121 stats.elimcompleted, lim.elimbound);
1122 } else {
1123 PHASE ("elim-phase", stats.elimphases,
1124 "incomplete elimination %" PRId64
1125 " at elimination bound %" PRId64 "",
1126 stats.elimcompleted + 1, lim.elimbound);
1127 }
1128
1129 reset_citten ();
1130 if (deleted_binary_clause)
1132 init_watches ();
1133 connect_watches ();
1134
1135 if (unsat)
1136 LOG ("elimination derived empty clause");
1137 else if (propagated < trail.size ()) {
1138 LOG ("elimination produced %zd units",
1139 (size_t) (trail.size () - propagated));
1140 if (!propagate ()) {
1141 LOG ("propagating units after elimination results in empty clause");
1143 }
1144 }
1145
1146 // If we ran variable elimination until completion we increase the
1147 // variable elimination bound and reschedule elimination of all variables.
1148 //
1149 if (phase_complete)
1151
1152#ifndef CADICAL_QUIET
1153 eliminated = stats.all.eliminated - old_eliminated;
1154 PHASE ("elim-phase", stats.elimphases, "eliminated %d variables %.2f%%",
1155 eliminated, percent (eliminated, old_active_variables));
1156#endif
1157
1158 if (external_prop) {
1160 private_steps = false;
1161 }
1162
1163 if (!update_limits)
1164 return;
1165
1166 int64_t delta = scale (opts.elimint * (stats.elimphases + 1));
1167 lim.elim = stats.conflicts + delta;
1168
1169 PHASE ("elim-phase", stats.elimphases,
1170 "new limit at %" PRId64 " conflicts after %" PRId64 " conflicts",
1171 lim.elim, delta);
1172
1173 last.elim.fixed = stats.all.fixed;
1174}
void increase_elimination_bound()
double scale(double v) const
int elim_round(bool &completed, bool &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elim_add_resolvents()

void CaDiCaL::Internal::elim_add_resolvents ( Eliminator & eliminator,
int pivot )
inline

Definition at line 542 of file cadical_elim.cpp.

543 {
544
545 const bool substitute = !eliminator.gates.empty ();
546 const bool resolve_gates = eliminator.definition_unit;
547 if (substitute) {
548 LOG ("substituting pivot %d by resolving with %zd gate clauses", pivot,
549 eliminator.gates.size ());
550 stats.elimsubst++;
551 }
552 switch (eliminator.gatetype) {
553 case EQUI:
554 stats.eliminated_equi++;
555 break;
556 case AND:
557 stats.eliminated_and++;
558 break;
559 case ITE:
560 stats.eliminated_ite++;
561 break;
562 case XOR:
563 stats.eliminated_xor++;
564 break;
565 case DEF:
566 stats.eliminated_def++;
567 break;
568 default:
569 CADICAL_assert (eliminator.gatetype == NO);
570 }
571
572 LOG ("adding all resolvents on %d", pivot);
573
574 CADICAL_assert (!val (pivot));
575 CADICAL_assert (!flags (pivot).eliminated ());
576
577 const Occs &ps = occs (pivot);
578 const Occs &ns = occs (-pivot);
579#ifdef LOGGING
580 int64_t resolvents = 0;
581#endif
582 for (auto &c : ps) {
583 if (unsat)
584 break;
585 if (c->garbage)
586 continue;
587 for (auto &d : ns) {
588 if (unsat)
589 break;
590 if (d->garbage)
591 continue;
592 if (!resolve_gates && substitute && c->gate == d->gate)
593 continue;
594 if (!resolve_clauses (eliminator, c, pivot, d, false))
595 continue;
596 CADICAL_assert (!lrat || !lrat_chain.empty ());
597 Clause *r = new_resolved_irredundant_clause ();
598 elim_update_added_clause (eliminator, r);
599 eliminator.enqueue (r);
600 lrat_chain.clear ();
601 clause.clear ();
602#ifdef LOGGING
603 resolvents++;
604#endif
605 }
606 }
607
608 LOG ("added %" PRId64 " resolvents to eliminate %d", resolvents, pivot);
609}
@ DEF
Definition elim.hpp:31
@ NO
Definition elim.hpp:31
@ EQUI
Definition elim.hpp:31
@ ITE
Definition elim.hpp:31
@ AND
Definition elim.hpp:31
@ XOR
Definition elim.hpp:31
void elim_update_added_clause(Eliminator &, Clause *)
bool resolve_clauses(Eliminator &, Clause *, int pivot, Clause *, bool)
Clause * new_resolved_irredundant_clause()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elim_backward_clause()

void CaDiCaL::Internal::elim_backward_clause ( Eliminator & eliminator,
Clause * c )

Definition at line 44 of file cadical_backward.cpp.

44 {
45 CADICAL_assert (opts.elimbackward);
46 CADICAL_assert (!c->redundant);
47 if (c->garbage)
48 return;
49 LOG (c, "attempting backward subsumption and strengthening with");
50 size_t len = UINT_MAX;
51 unsigned size = 0;
52 int best = 0;
53 bool satisfied = false;
54 CADICAL_assert (mini_chain.empty ());
55 for (const auto &lit : *c) {
56 const signed char tmp = val (lit);
57 if (tmp > 0) {
58 satisfied = true;
59 break;
60 }
61 if (tmp < 0)
62 continue;
63 size_t l = occs (lit).size ();
64 LOG ("literal %d occurs %zd times", lit, l);
65 if (l < len)
66 best = lit, len = l;
67 mark (lit);
68 size++;
69 }
70 if (satisfied) {
71 LOG ("clause actually already satisfied");
72 elim_update_removed_clause (eliminator, c);
73 mark_garbage (c);
74 } else if (len > (size_t) opts.elimocclim) {
75 LOG ("skipping backward subsumption due to too many occurrences");
76 } else {
77 CADICAL_assert (len);
78 LOG ("literal %d has smallest number of occurrences %zd", best, len);
79 LOG ("marked %d literals in clause of size %d", size, c->size);
80 for (auto &d : occs (best)) {
81 if (d == c)
82 continue;
83 if (d->garbage)
84 continue;
85 if ((unsigned) d->size < size)
86 continue;
87 int negated = 0;
88 unsigned found = 0;
89 satisfied = false;
90 for (const auto &lit : *d) {
91 signed char tmp = val (lit);
92 if (tmp > 0) {
93 satisfied = true;
94 break;
95 }
96 if (tmp < 0)
97 continue;
98 tmp = marked (lit);
99 if (!tmp)
100 continue;
101 if (tmp < 0) {
102 if (negated) {
103 size = UINT_MAX;
104 break;
105 } else
106 negated = lit;
107 }
108 if (++found == size)
109 break;
110 }
111 if (satisfied) {
112 LOG (d, "found satisfied clause");
113 elim_update_removed_clause (eliminator, d);
114 mark_garbage (d);
115 } else if (found == size) {
116 if (!negated) {
117 LOG (d, "found subsumed clause");
118 elim_update_removed_clause (eliminator, d);
119 mark_garbage (d);
120 stats.subsumed++;
121 stats.elimbwsub++;
122 } else {
123 int unit = 0;
125 CADICAL_assert (analyzed.empty ());
126 CADICAL_assert (lrat_chain.empty ());
127 // figure out wether we strengthen c or get a new unit
128 for (const auto &lit : *d) {
129 const signed char tmp = val (lit);
130 if (tmp < 0) {
131 if (!lrat)
132 continue;
133 Flags &f = flags (lit);
134 CADICAL_assert (!f.seen);
135 if (f.seen)
136 continue;
137 f.seen = true;
138 analyzed.push_back (lit);
139 continue;
140 }
141 if (tmp > 0) {
142 satisfied = true;
143 break;
144 }
145 if (lit == negated)
146 continue;
147 if (unit) {
148 unit = INT_MIN;
149 continue; // needed to guarantee d is not satsified
150 } else
151 unit = lit;
152 }
153 if (lrat && !satisfied) {
154 // if we found a unit we need to add all unit ids from
155 // {c\d}U{d\c} otherwise just the unit ids from {c\d}
156 for (const auto &lit : *c) {
157 const signed char tmp = val (lit);
158 CADICAL_assert (tmp <= 0);
159 if (tmp >= 0)
160 continue;
161 Flags &f = flags (lit);
162 if (f.seen && unit && unit == INT_MIN) {
163 f.seen = false;
164 continue;
165 } else if (!f.seen) {
166 f.seen = true;
167 analyzed.push_back (lit);
168 }
169 }
170 if (unit == INT_MIN) { // we do not need units from {d\c}
171 for (const auto &lit : *d) {
172 flags (lit).seen = false;
173 }
174 }
175 for (const auto &lit : analyzed) {
176 Flags &f = flags (lit);
177 if (!f.seen) {
178 f.seen = true;
179 continue;
180 }
181 int64_t id = unit_id (-lit);
182 lrat_chain.push_back (id);
183 }
185 lrat_chain.push_back (d->id);
186 lrat_chain.push_back (c->id);
187 } else if (lrat)
189 if (satisfied) {
190 CADICAL_assert (lrat_chain.empty ());
191 mark_garbage (d);
192 elim_update_removed_clause (eliminator, d);
193 } else if (unit && unit != INT_MIN) {
194 CADICAL_assert (unit);
195 LOG (d, "unit %d through hyper unary resolution with", unit);
196 assign_unit (unit);
197 elim_propagate (eliminator, unit);
198 lrat_chain.clear ();
199 break;
200 } else if (occs (negated).size () <= (size_t) opts.elimocclim) {
201 strengthen_clause (d, negated);
202 remove_occs (occs (negated), d);
203 elim_update_removed_lit (eliminator, negated);
204 stats.elimbwstr++;
205 CADICAL_assert (negated != best);
206 eliminator.enqueue (d);
207 }
208 lrat_chain.clear ();
209 }
210 }
211 }
212 }
213 mini_chain.clear ();
214 unmark (c);
215}
void remove_occs(Occs &os, Clause *c)
Definition occs.hpp:23
void elim_update_removed_lit(Eliminator &, int lit)
void elim_update_removed_clause(Eliminator &, Clause *, int except=0)
void strengthen_clause(Clause *, int)
vector< int64_t > minimize_chain
Definition internal.hpp:212
void elim_propagate(Eliminator &, int unit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elim_backward_clauses()

void CaDiCaL::Internal::elim_backward_clauses ( Eliminator & eliminator)

Definition at line 219 of file cadical_backward.cpp.

219 {
220 if (!opts.elimbackward) {
221 CADICAL_assert (eliminator.backward.empty ());
222 return;
223 }
224 START (backward);
225 LOG ("attempting backward subsumption and strengthening with %zd clauses",
226 eliminator.backward.size ());
227 Clause *c;
228 while (!unsat && (c = eliminator.dequeue ()))
229 elim_backward_clause (eliminator, c);
230 STOP (backward);
231}
void elim_backward_clause(Eliminator &, Clause *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elim_on_the_fly_self_subsumption()

void CaDiCaL::Internal::elim_on_the_fly_self_subsumption ( Eliminator & eliminator,
Clause * c,
int pivot )

Definition at line 214 of file cadical_elim.cpp.

215 {
216 LOG (c, "pivot %d on-the-fly self-subsuming resolution", pivot);
217 stats.elimotfstr++;
218 stats.strengthened++;
219 CADICAL_assert (clause.empty ());
220 for (const auto &lit : *c) {
221 if (lit == pivot)
222 continue;
223 const signed char tmp = val (lit);
224 CADICAL_assert (tmp <= 0);
225 if (tmp < 0)
226 continue;
227 clause.push_back (lit);
228 }
229 Clause *r = new_resolved_irredundant_clause ();
230 elim_update_added_clause (eliminator, r);
231 clause.clear ();
232 lrat_chain.clear ();
233 elim_update_removed_clause (eliminator, c, pivot);
234 mark_garbage (c);
235}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elim_propagate()

void CaDiCaL::Internal::elim_propagate ( Eliminator & eliminator,
int unit )

Definition at line 147 of file cadical_elim.cpp.

147 {
148 CADICAL_assert (val (root) > 0);
149 vector<int> work;
150 size_t i = 0;
151 work.push_back (root);
152 while (i < work.size ()) {
153 int lit = work[i++];
154 LOG ("elimination propagation of %d", lit);
155 CADICAL_assert (val (lit) > 0);
156 const Occs &ns = occs (-lit);
157 for (const auto &c : ns) {
158 if (c->garbage)
159 continue;
160 int unit = 0, satisfied = 0;
161 for (const auto &other : *c) {
162 const signed char tmp = val (other);
163 if (tmp < 0)
164 continue;
165 if (tmp > 0) {
166 satisfied = other;
167 break;
168 }
169 if (unit)
170 unit = INT_MIN;
171 else
172 unit = other;
173 }
174 if (satisfied) {
175 LOG (c, "elimination propagation of %d finds %d satisfied", lit,
176 satisfied);
177 elim_update_removed_clause (eliminator, c, satisfied);
178 mark_garbage (c);
179 } else if (!unit) {
180 LOG ("empty clause during elimination propagation of %d", lit);
181 // need to set conflict = c for lrat
182 conflict = c;
184 conflict = 0;
185 break;
186 } else if (unit != INT_MIN) {
187 LOG ("new unit %d during elimination propagation of %d", unit, lit);
188 build_chain_for_units (unit, c, 0);
189 assign_unit (unit);
190 work.push_back (unit);
191 }
192 }
193 if (unsat)
194 break;
195 const Occs &ps = occs (lit);
196 for (const auto &c : ps) {
197 if (c->garbage)
198 continue;
199 LOG (c, "elimination propagation of %d produces satisfied", lit);
200 elim_update_removed_clause (eliminator, c, lit);
201 mark_garbage (c);
202 }
203 }
204}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elim_resolvents_are_bounded()

bool CaDiCaL::Internal::elim_resolvents_are_bounded ( Eliminator & eliminator,
int pivot )

Definition at line 467 of file cadical_elim.cpp.

468 {
469 const bool substitute = !eliminator.gates.empty ();
470 const bool resolve_gates = eliminator.definition_unit;
471 if (substitute)
472 LOG ("trying to substitute %d", pivot);
473
474 stats.elimtried++;
475
477 CADICAL_assert (active (pivot));
478
479 const Occs &ps = occs (pivot);
480 const Occs &ns = occs (-pivot);
481 const int64_t pos = ps.size ();
482 const int64_t neg = ns.size ();
483 if (!pos || !neg)
484 return lim.elimbound >= 0;
485 const int64_t bound = pos + neg + lim.elimbound;
486
487 LOG ("checking number resolvents on %d bounded by "
488 "%" PRId64 " = %" PRId64 " + %" PRId64 " + %" PRId64,
489 pivot, bound, pos, neg, lim.elimbound);
490
491 // Try all resolutions between a positive occurrence (outer loop) of
492 // 'pivot' and a negative occurrence of 'pivot' (inner loop) as long the
493 // bound on non-tautological resolvents is not hit and the size of the
494 // generated resolvents does not exceed the resolvent clause size limit.
495
496 int64_t resolvents = 0; // Non-tautological resolvents.
497
498 for (const auto &c : ps) {
499 CADICAL_assert (!c->redundant);
500 if (c->garbage)
501 continue;
502 for (const auto &d : ns) {
503 CADICAL_assert (!d->redundant);
504 if (d->garbage)
505 continue;
506 if (!resolve_gates && substitute && c->gate == d->gate)
507 continue;
508 stats.elimrestried++;
509 if (resolve_clauses (eliminator, c, pivot, d, true)) {
510 resolvents++;
511 int size = clause.size ();
512 clause.clear ();
513 LOG ("now at least %" PRId64
514 " non-tautological resolvents on pivot %d",
515 resolvents, pivot);
516 if (size > opts.elimclslim) {
517 LOG ("resolvent size %d too big after %" PRId64
518 " resolvents on %d",
519 size, resolvents, pivot);
520 return false;
521 }
522 if (resolvents > bound) {
523 LOG ("too many non-tautological resolvents on %d", pivot);
524 return false;
525 }
526 } else if (unsat)
527 return false;
528 else if (val (pivot))
529 return false;
530 }
531 }
532
533 LOG ("need %" PRId64 " <= %" PRId64 " non-tautological resolvents",
534 resolvents, bound);
535
536 return true;
537}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elim_round()

int CaDiCaL::Internal::elim_round ( bool & completed,
bool & deleted_binary_clause )

Definition at line 771 of file cadical_elim.cpp.

771 {
772
773 CADICAL_assert (opts.elim);
775
777 stats.elimrounds++;
778
779 int64_t marked_before = last.elim.marked;
780 last.elim.marked = stats.mark.elim;
782
783 int64_t resolution_limit;
784
785 if (opts.elimlimited) {
786 int64_t delta = stats.propagations.search;
787 delta *= 1e-3 * opts.elimeffort;
788 if (delta < opts.elimmineff)
789 delta = opts.elimmineff;
790 if (delta > opts.elimmaxeff)
791 delta = opts.elimmaxeff;
792 delta = max (delta, (int64_t) 2l * active ());
793
794 PHASE ("elim-round", stats.elimrounds,
795 "limit of %" PRId64 " resolutions", delta);
796
797 resolution_limit = stats.elimres + delta;
798 } else {
799 PHASE ("elim-round", stats.elimrounds, "resolutions unlimited");
800 resolution_limit = LONG_MAX;
801 }
802
803 init_noccs ();
804
805 // First compute the number of occurrences of each literal and at the same
806 // time mark satisfied clauses and update 'elim' flags of variables in
807 // clauses with root level assigned literals (both false and true).
808 //
809 for (const auto &c : clauses) {
810 if (c->garbage || c->redundant)
811 continue;
812 bool satisfied = false, falsified = false;
813 for (const auto &lit : *c) {
814 const signed char tmp = val (lit);
815 if (tmp > 0)
816 satisfied = true;
817 else if (tmp < 0)
818 falsified = true;
819 else
821 }
822 if (satisfied)
823 mark_garbage (c); // forces more precise counts
824 else {
825 for (const auto &lit : *c) {
826 if (!active (lit))
827 continue;
828 if (falsified)
829 mark_elim (lit); // simulate unit propagation
830 noccs (lit)++;
831 }
832 }
833 }
834
835 init_occs ();
836
837 Eliminator eliminator (this);
838 ElimSchedule &schedule = eliminator.schedule;
839 CADICAL_assert (schedule.empty ());
840
841 // Now find elimination candidates which occurred in clauses removed since
842 // the last time we ran bounded variable elimination, which in turned
843 // triggered their 'elim' bit to be set.
844 //
845 for (auto idx : vars) {
846 if (!active (idx))
847 continue;
848 if (frozen (idx))
849 continue;
850 if (!flags (idx).elim)
851 continue;
852 LOG ("scheduling %d for elimination initially", idx);
853 schedule.push_back (idx);
854 }
855
856 schedule.shrink ();
857
858#ifndef CADICAL_QUIET
859 int64_t scheduled = schedule.size ();
860#endif
861
862 PHASE ("elim-round", stats.elimrounds,
863 "scheduled %" PRId64 " variables %.0f%% for elimination",
864 scheduled, percent (scheduled, active ()));
865
866 // Connect irredundant clauses.
867 //
868 for (const auto &c : clauses)
869 if (!c->garbage && !c->redundant)
870 for (const auto &lit : *c)
871 if (active (lit))
872 occs (lit).push_back (c);
873
874#ifndef CADICAL_QUIET
875 const int64_t old_resolutions = stats.elimres;
876#endif
877 const int old_eliminated = stats.all.eliminated;
878 const int old_fixed = stats.all.fixed;
879
880 // Limit on garbage literals during variable elimination. If the limit is
881 // hit a garbage collection is performed.
882 //
883 const int64_t garbage_limit = (2 * stats.irrlits / 3) + (1 << 20);
884
885 // Main loops tries to eliminate variables according to the schedule. The
886 // schedule is updated dynamically and variables are potentially
887 // rescheduled to be tried again if they occur in a removed clause.
888 //
889#ifndef CADICAL_QUIET
890 int64_t tried = 0;
891#endif
892 while (!unsat && !terminated_asynchronously () &&
893 stats.elimres <= resolution_limit && !schedule.empty ()) {
894 int idx = schedule.front ();
895 schedule.pop_front ();
896 flags (idx).elim = false;
897 try_to_eliminate_variable (eliminator, idx, deleted_binary_clause);
898#ifndef CADICAL_QUIET
899 tried++;
900#endif
901 if (stats.garbage.literals <= garbage_limit)
902 continue;
905 }
906
907 // If the schedule is empty all variables have been tried (even
908 // rescheduled ones). Otherwise asynchronous termination happened or we
909 // ran into the resolution limit (or derived unsatisfiability).
910 //
911 completed = !schedule.size ();
912
913 if (!completed)
914 last.elim.marked = marked_before;
915
916 PHASE ("elim-round", stats.elimrounds,
917 "tried to eliminate %" PRId64 " variables %.0f%% (%zd remain)",
918 tried, percent (tried, scheduled), schedule.size ());
919
920 schedule.erase ();
921
922 // Collect potential literal clause instantiation pairs, which needs full
923 // occurrence lists and thus we have it here before resetting them.
924 //
925 Instantiator instantiator;
926 if (!unsat && !terminated_asynchronously () && opts.instantiate)
928
929 reset_occs ();
930 reset_noccs ();
931
932 // Mark all redundant clauses with eliminated variables as garbage.
933 //
934 if (!unsat)
936
937 int eliminated = stats.all.eliminated - old_eliminated;
938#ifndef CADICAL_QUIET
939 int64_t resolutions = stats.elimres - old_resolutions;
940 PHASE ("elim-round", stats.elimrounds,
941 "eliminated %d variables %.0f%% in %" PRId64 " resolutions",
942 eliminated, percent (eliminated, scheduled), resolutions);
943#endif
944
945 last.elim.subsumephases = stats.subsumephases;
946 const int units = stats.all.fixed - old_fixed;
947 report ('e', !opts.reportall && !(eliminated + units));
949
950 if (!unsat && !terminated_asynchronously () &&
951 instantiator) // Do we have candidate pairs?
952 instantiate (instantiator);
953
954 return eliminated; // non-zero if successful
955}
heap< elim_more > ElimSchedule
Definition elim.hpp:20
void try_to_eliminate_variable(Eliminator &, int pivot, bool &)
void collect_instantiation_candidates(Instantiator &)
void mark_elim(int lit)
void instantiate(Instantiator &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elim_update_added_clause()

void CaDiCaL::Internal::elim_update_added_clause ( Eliminator & eliminator,
Clause * c )

Definition at line 95 of file cadical_elim.cpp.

96 {
97 CADICAL_assert (!c->redundant);
98 ElimSchedule &schedule = eliminator.schedule;
99 for (const auto &lit : *c) {
100 if (!active (lit))
101 continue;
102 occs (lit).push_back (c);
103 if (frozen (lit))
104 continue;
105 noccs (lit)++;
106 const int idx = abs (lit);
107 if (schedule.contains (idx))
108 schedule.update (idx);
109 }
110}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elim_update_removed_clause()

void CaDiCaL::Internal::elim_update_removed_clause ( Eliminator & eliminator,
Clause * c,
int except = 0 )

Definition at line 130 of file cadical_elim.cpp.

131 {
132 CADICAL_assert (!c->redundant);
133 for (const auto &lit : *c) {
134 if (lit == except)
135 continue;
136 CADICAL_assert (lit != -except);
137 elim_update_removed_lit (eliminator, lit);
138 }
139}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elim_update_removed_lit()

void CaDiCaL::Internal::elim_update_removed_lit ( Eliminator & eliminator,
int lit )

Definition at line 112 of file cadical_elim.cpp.

112 {
113 if (!active (lit))
114 return;
115 if (frozen (lit))
116 return;
117 int64_t &score = noccs (lit);
118 CADICAL_assert (score > 0);
119 score--;
120 const int idx = abs (lit);
121 ElimSchedule &schedule = eliminator.schedule;
122 if (schedule.contains (idx))
123 schedule.update (idx);
124 else {
125 LOG ("rescheduling %d for elimination after removing clause", idx);
126 schedule.push_back (idx);
127 }
128}
void update(unsigned e)
Definition heap.hpp:182
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elimfast()

void CaDiCaL::Internal::elimfast ( )

Definition at line 442 of file cadical_elimfast.cpp.

442 {
443
444 if (unsat)
445 return;
446 if (level)
447 backtrack ();
448 if (!propagate ()) {
450 return;
451 }
452
453 stats.elimfastphases++;
454 PHASE ("fastelim-phase", stats.elimfastphases,
455 "starting at most %d elimination rounds", opts.fastelimrounds);
456
457 if (external_prop) {
459 private_steps = true;
460 }
461
462#ifndef CADICAL_QUIET
463 int old_active_variables = active ();
464 int old_eliminated = stats.all.eliminated;
465#endif
466
467 reset_watches (); // saves lots of memory
468
469 // Alternate one round of bounded variable elimination ('elim_round') and
470 // subsumption ('subsume_round'), blocked ('block') and covered clause
471 // elimination ('cover') until nothing changes, or the round limit is hit.
472 // The loop also aborts early if no variable could be eliminated, the
473 // empty clause is resolved, it is asynchronously terminated or a
474 // resolution limit is hit.
475
476 // This variable determines whether the whole loop of this bounded
477 // variable elimination phase ('elim') ran until completion. This
478 // potentially triggers an incremental increase of the elimination bound.
479 //
480 bool phase_complete = false, deleted_binary_clause = false;
481
482 int round = 1;
483#ifndef CADICAL_QUIET
484 int eliminated = 0;
485#endif
486
487 bool round_complete = false;
488 while (!unsat && !phase_complete && !terminated_asynchronously ()) {
489#ifndef CADICAL_QUIET
490 int eliminated =
491#endif
492 elimfast_round (round_complete, deleted_binary_clause);
493
494 if (!round_complete) {
495 PHASE ("fastelim-phase", stats.elimphases,
496 "last round %d incomplete %s", round,
497 eliminated ? "but successful" : "and unsuccessful");
498 CADICAL_assert (!phase_complete);
499 break;
500 }
501
502 if (round++ >= opts.fastelimrounds) {
503 PHASE ("fastelim-phase", stats.elimphases, "round limit %d hit (%s)",
504 round - 1,
505 eliminated ? "though last round successful"
506 : "last round unsuccessful anyhow");
507 CADICAL_assert (!phase_complete);
508 break;
509 }
510
511 // Prioritize 'subsumption' over blocked and covered clause elimination.
512
513 if (subsume_round ())
514 continue;
515
516 // Was not able to generate new variable elimination candidates after
517 // variable elimination round, neither through subsumption, nor blocked,
518 // nor covered clause elimination.
519 //
520 PHASE ("fastelim-phase", stats.elimphases,
521 "no new variable elimination candidates");
522
523 CADICAL_assert (round_complete);
524 phase_complete = true;
525 }
526
527 for (auto idx : vars) {
528 if (active (idx))
529 flags (idx).elim = true;
530 }
531
532 if (phase_complete) {
533 stats.elimcompleted++;
534 PHASE ("fastelim-phase", stats.elimphases,
535 "fully completed elimination %" PRId64
536 " at elimination bound %" PRId64 "",
537 stats.elimcompleted, lim.elimbound);
538 } else {
539 PHASE ("fastelim-phase", stats.elimphases,
540 "incomplete elimination %" PRId64
541 " at elimination bound %" PRId64 "",
542 stats.elimcompleted + 1, lim.elimbound);
543 }
544
545 if (deleted_binary_clause)
547 init_watches ();
549
550 if (unsat)
551 LOG ("elimination derived empty clause");
552 else if (propagated < trail.size ()) {
553 LOG ("elimination produced %zd units",
554 (size_t) (trail.size () - propagated));
555 if (!propagate ()) {
556 LOG ("propagating units after elimination results in empty clause");
558 }
559 }
560
561#ifndef CADICAL_QUIET
562 eliminated = stats.all.eliminated - old_eliminated;
563 PHASE ("fastelim-phase", stats.elimphases,
564 "eliminated %d variables %.2f%%", eliminated,
565 percent (eliminated, old_active_variables));
566#endif
567
568 if (external_prop) {
570 private_steps = false;
571 }
572}
int elimfast_round(bool &completed, bool &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elimfast_add_resolvents()

void CaDiCaL::Internal::elimfast_add_resolvents ( Eliminator & eliminator,
int pivot )
inline

Definition at line 143 of file cadical_elimfast.cpp.

144 {
145
146 CADICAL_assert (eliminator.gates.empty ());
147 CADICAL_assert (!eliminator.definition_unit);
148
149 LOG ("adding all resolvents on %d", pivot);
150
151 CADICAL_assert (!val (pivot));
152 CADICAL_assert (!flags (pivot).eliminated ());
153
154 const Occs &ps = occs (pivot);
155 const Occs &ns = occs (-pivot);
156#ifdef LOGGING
157 int64_t resolvents = 0;
158#endif
159 for (auto &c : ps) {
160 if (unsat)
161 break;
162 if (c->garbage)
163 continue;
164 for (auto &d : ns) {
165 if (unsat)
166 break;
167 if (d->garbage)
168 continue;
169 if (!resolve_clauses (eliminator, c, pivot, d, false))
170 continue;
171 CADICAL_assert (!lrat || !lrat_chain.empty ());
172 Clause *r = new_resolved_irredundant_clause ();
173 elim_update_added_clause (eliminator, r);
174 eliminator.enqueue (r);
175 lrat_chain.clear ();
176 clause.clear ();
177#ifdef LOGGING
178 resolvents++;
179#endif
180 }
181 }
182
183 LOG ("added %" PRId64 " resolvents to eliminate %d", resolvents, pivot);
184}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elimfast_resolvents_are_bounded()

bool CaDiCaL::Internal::elimfast_resolvents_are_bounded ( Eliminator & eliminator,
int pivot )

Definition at line 59 of file cadical_elimfast.cpp.

60 {
61 CADICAL_assert (eliminator.gates.empty ());
62 CADICAL_assert (!eliminator.definition_unit);
63
64 stats.elimtried++;
65
67 CADICAL_assert (active (pivot));
68
69 const Occs &ps = occs (pivot);
70 const Occs &ns = occs (-pivot);
71
72 int64_t pos = ps.size ();
73 int64_t neg = ns.size ();
74
75 int64_t bound = opts.fastelimbound;
76
77 if (!pos || !neg)
78 return bound >= 0;
79
80 const int64_t sum = pos + neg;
81 const int64_t product = pos * neg;
82 if (bound > sum)
83 bound = sum;
84
85 LOG ("checking number resolvents on %d bounded by "
86 "%" PRId64 " = %" PRId64 " + %" PRId64 " + %d",
87 pivot, bound, pos, neg, opts.fastelimbound);
88
89 if (product <= bound) {
90 LOG ("fast elimination occurrence limits sufficiently small enough");
91 return true;
92 }
93
94 // Try all resolutions between a positive occurrence (outer loop) of
95 // 'pivot' and a negative occurrence of 'pivot' (inner loop) as long the
96 // bound on non-tautological resolvents is not hit and the size of the
97 // generated resolvents does not exceed the resolvent clause size limit.
98
99 int64_t resolvents = 0; // Non-tautological resolvents.
100
101 for (const auto &c : ps) {
102 CADICAL_assert (!c->redundant);
103 if (c->garbage)
104 continue;
105 for (const auto &d : ns) {
106 CADICAL_assert (!d->redundant);
107 if (d->garbage)
108 continue;
109 if (resolve_clauses (eliminator, c, pivot, d, true)) {
110 resolvents++;
111 int size = clause.size ();
112 clause.clear ();
113 LOG ("now at least %" PRId64
114 " non-tautological resolvents on pivot %d",
115 resolvents, pivot);
116 if (size > opts.fastelimclslim) {
117 LOG ("resolvent size %d too big after %" PRId64
118 " resolvents on %d",
119 size, resolvents, pivot);
120 return false;
121 }
122 if (resolvents > bound) {
123 LOG ("too many non-tautological resolvents on %d", pivot);
124 return false;
125 }
126 } else if (unsat)
127 return false;
128 else if (val (pivot))
129 return false;
130 }
131 }
132
133 LOG ("need %" PRId64 " <= %" PRId64 " non-tautological resolvents",
134 resolvents, bound);
135
136 return true;
137}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ elimfast_round()

int CaDiCaL::Internal::elimfast_round ( bool & completed,
bool & deleted_binary_clause )

Definition at line 268 of file cadical_elimfast.cpp.

269 {
270
271 CADICAL_assert (opts.fastelim);
273
274 START_SIMPLIFIER (fastelim, ELIM);
275
276 stats.elimfastrounds++;
277
279
280 int64_t resolution_limit;
281
282 if (opts.elimlimited) {
283 int64_t delta = stats.propagations.search;
284 delta *= 1e-3 * opts.elimeffort;
285 if (delta < opts.elimmineff)
286 delta = opts.elimmineff;
287 if (delta > opts.elimmaxeff)
288 delta = opts.elimmaxeff;
289 delta = max (delta, (int64_t) 2l * active ());
290
291 PHASE ("fastelim-round", stats.elimfastrounds,
292 "limit of %" PRId64 " resolutions", delta);
293
294 resolution_limit = stats.elimres + delta;
295 } else {
296 PHASE ("fastelim-round", stats.elimfastrounds, "resolutions unlimited");
297 resolution_limit = LONG_MAX;
298 }
299
300 init_noccs ();
301
302 // First compute the number of occurrences of each literal and at the same
303 // time mark satisfied clauses and update 'elim' flags of variables in
304 // clauses with root level assigned literals (both false and true).
305 //
306 for (const auto &c : clauses) {
307 if (c->garbage || c->redundant)
308 continue;
309 bool satisfied = false, falsified = false;
310 for (const auto &lit : *c) {
311 const signed char tmp = val (lit);
312 if (tmp > 0)
313 satisfied = true;
314 else if (tmp < 0)
315 falsified = true;
316 else
318 }
319 if (satisfied)
320 mark_garbage (c); // forces more precise counts
321 else {
322 for (const auto &lit : *c) {
323 if (!active (lit))
324 continue;
325 if (falsified)
326 mark_elim (lit); // simulate unit propagation
327 noccs (lit)++;
328 }
329 }
330 }
331
332 init_occs ();
333
334 Eliminator eliminator (this);
335 ElimSchedule &schedule = eliminator.schedule;
336 CADICAL_assert (schedule.empty ());
337
338 // Now find elimination candidates which occurred in clauses removed since
339 // the last time we ran bounded variable elimination, which in turned
340 // triggered their 'elim' bit to be set.
341 //
342 for (auto idx : vars) {
343 if (!active (idx))
344 continue;
345 if (frozen (idx))
346 continue;
347 if (!flags (idx).elim)
348 continue;
349 LOG ("scheduling %d for elimination initially", idx);
350 schedule.push_back (idx);
351 }
352
353 schedule.shrink ();
354
355#ifndef CADICAL_QUIET
356 int64_t scheduled = schedule.size ();
357#endif
358
359 PHASE ("fastelim-round", stats.elimfastrounds,
360 "scheduled %" PRId64 " variables %.0f%% for elimination",
361 scheduled, percent (scheduled, active ()));
362
363 // Connect irredundant clauses.
364 //
365 for (const auto &c : clauses)
366 if (!c->garbage && !c->redundant)
367 for (const auto &lit : *c)
368 if (active (lit))
369 occs (lit).push_back (c);
370
371#ifndef CADICAL_QUIET
372 const int64_t old_resolutions = stats.elimres;
373#endif
374 const int old_eliminated = stats.all.eliminated;
375 const int old_fixed = stats.all.fixed;
376
377 // Limit on garbage literals during variable elimination. If the limit is
378 // hit a garbage collection is performed.
379 //
380 const int64_t garbage_limit = (2 * stats.irrlits / 3) + (1 << 20);
381
382 // Main loops tries to eliminate variables according to the schedule. The
383 // schedule is updated dynamically and variables are potentially
384 // rescheduled to be tried again if they occur in a removed clause.
385 //
386#ifndef CADICAL_QUIET
387 int64_t tried = 0;
388#endif
389 while (!unsat && !terminated_asynchronously () &&
390 stats.elimres <= resolution_limit && !schedule.empty ()) {
391 int idx = schedule.front ();
392 schedule.pop_front ();
393 flags (idx).elim = false;
394 try_to_fasteliminate_variable (eliminator, idx, deleted_binary_clause);
395#ifndef CADICAL_QUIET
396 tried++;
397#endif
398 if (stats.garbage.literals <= garbage_limit)
399 continue;
402 }
403
404 // If the schedule is empty all variables have been tried (even
405 // rescheduled ones). Otherwise asynchronous termination happened or we
406 // ran into the resolution limit (or derived unsatisfiability).
407 //
408 completed = !schedule.size ();
409
410 PHASE ("fastelim-round", stats.elimfastrounds,
411 "tried to eliminate %" PRId64 " variables %.0f%% (%zd remain)",
412 tried, percent (tried, scheduled), schedule.size ());
413
414 schedule.erase ();
415
416 reset_occs ();
417 reset_noccs ();
418
419 // Mark all redundant clauses with eliminated variables as garbage.
420 //
421 if (!unsat)
423
424 int eliminated = stats.all.eliminated - old_eliminated;
425 stats.all.fasteliminated += eliminated;
426#ifndef CADICAL_QUIET
427 int64_t resolutions = stats.elimres - old_resolutions;
428 PHASE ("fastelim-round", stats.elimfastrounds,
429 "eliminated %d variables %.0f%% in %" PRId64 " resolutions",
430 eliminated, percent (eliminated, scheduled), resolutions);
431#endif
432
433 const int units = stats.all.fixed - old_fixed;
434 report ('e', !opts.reportall && !(eliminated + units));
435 STOP_SIMPLIFIER (fastelim, ELIM);
436
437 return eliminated; // non-zero if successful
438}
void try_to_fasteliminate_variable(Eliminator &, int pivot, bool &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ enlarge()

void CaDiCaL::Internal::enlarge ( int new_max_var)

Definition at line 121 of file cadical_internal.cpp.

121 {
122 // New variables can be created that can invoke enlarge anytime (via calls
123 // during ipasir-up call-backs), thus assuming (!level) is not correct
124 size_t new_vsize = vsize ? 2 * vsize : 1 + (size_t) new_max_var;
125 while (new_vsize <= (size_t) new_max_var)
126 new_vsize *= 2;
127 LOG ("enlarge internal size from %zd to new size %zd", vsize, new_vsize);
128 // Ordered in the size of allocated memory (larger block first).
129 if (lrat || frat)
130 enlarge_zero (unit_clauses_idx, 2 * new_vsize);
131 enlarge_only (wtab, 2 * new_vsize);
132 enlarge_only (vtab, new_vsize);
133 enlarge_zero (parents, new_vsize);
134 enlarge_only (links, new_vsize);
135 enlarge_zero (btab, new_vsize);
136 enlarge_zero (gtab, new_vsize);
137 enlarge_zero (stab, new_vsize);
138 enlarge_init (ptab, 2 * new_vsize, -1);
139 enlarge_only (ftab, new_vsize);
140 enlarge_vals (new_vsize);
141 vsize = new_vsize;
142 if (external)
143 enlarge_zero (relevanttab, new_vsize);
144 const signed char val = opts.phase ? 1 : -1;
145 enlarge_init (phases.saved, new_vsize, val);
146 enlarge_zero (phases.forced, new_vsize);
147 enlarge_zero (phases.target, new_vsize);
148 enlarge_zero (phases.best, new_vsize);
149 enlarge_zero (phases.prev, new_vsize);
150 enlarge_zero (phases.min, new_vsize);
151 enlarge_zero (marks, new_vsize);
152}
void enlarge_vals(size_t new_vsize)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ enlarge_vals()

void CaDiCaL::Internal::enlarge_vals ( size_t new_vsize)

Definition at line 102 of file cadical_internal.cpp.

102 {
103 signed char *new_vals;
104 const size_t bytes = 2u * new_vsize;
105 new_vals = new signed char[bytes]; // g++-4.8 does not like ... { 0 };
106 memset (new_vals, 0, bytes);
107 ignore_clang_analyze_memory_leak_warning = new_vals;
108 new_vals += new_vsize;
109
110 if (vals) {
111 memcpy (new_vals - max_var, vals - max_var, 2u * max_var + 1u);
112 vals -= vsize;
113 delete[] vals;
114 } else
116 vals = new_vals;
117}
char * memcpy()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ error()

void CaDiCaL::Internal::error ( const char * fmt,
... )

Definition at line 181 of file cadical_message.cpp.

181 {
182 va_list ap;
183 va_start (ap, fmt);
184 verror (fmt, ap);
185 va_end (ap); // unreachable
186}
void verror(const char *, va_list &)
Here is the call graph for this function:

◆ error_message_end()

void CaDiCaL::Internal::error_message_end ( )

Definition at line 168 of file cadical_message.cpp.

168 {
169 fputc ('\n', stderr);
170 fflush (stderr);
171 // TODO add possibility to use call back instead.
172 exit (1);
173}
VOID_HACK exit()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ error_message_start()

void CaDiCaL::Internal::error_message_start ( )

Definition at line 158 of file cadical_message.cpp.

158 {
159 fflush (stdout);
160 terr.bold ();
161 fputs ("cadical: ", stderr);
162 terr.red (1);
163 fputs ("error:", stderr);
164 terr.normal ();
165 fputc (' ', stderr);
166}
void red(bool bright=false)
Definition terminal.hpp:55
Terminal terr(stderr)
Definition terminal.hpp:98
Here is the caller graph for this function:

◆ explain_external_propagations()

void CaDiCaL::Internal::explain_external_propagations ( )

Definition at line 583 of file cadical_external_propagate.cpp.

583 {
585 CADICAL_assert (clause.empty ());
586
587 Clause *reason = conflict;
588 std::vector<int> seen_lits;
589 int open = 0; // Seen but not explained literal
590
591 explain_reason (0, reason, open); // marks conflict clause lits as seen
592 int i = trail.size (); // Start at end-of-trail
593 while (i > 0) {
594 const int lit = trail[--i];
595 if (!flags (lit).seen)
596 continue;
597 seen_lits.push_back (lit);
598 Var &v = var (lit);
599 if (!v.level)
600 continue;
601 if (v.reason) {
602 open--;
603 explain_reason (lit, v.reason, open);
604 }
605 if (!open)
606 break;
607 }
608 CADICAL_assert (!open);
609
610 if (!opts.exteagerrecalc) {
611 for (auto lit : seen_lits) {
612 Flags &f = flags (lit);
613 f.seen = false;
614 }
615#ifndef CADICAL_NDEBUG
616 for (auto idx : vars) {
617 CADICAL_assert (!flags (idx).seen);
618 }
619#endif
620 }
621
622 // Traverse now in the opposite direction (from lower to higher levels)
623 // and calculate the actual assignment level for the seen assignments.
624 for (auto it = seen_lits.rbegin (); it != seen_lits.rend (); ++it) {
625 const int lit = *it;
626 Flags &f = flags (lit);
627 Var &v = var (lit);
628 if (v.reason) {
629 int real_level = 0;
630 for (const auto &other : *v.reason) {
631 if (other == lit)
632 continue;
633 int tmp = var (other).level;
634 if (tmp > real_level)
635 real_level = tmp;
636 }
637 if (v.level && !real_level) {
638 build_chain_for_units (lit, v.reason, 1);
640 lrat_chain.clear ();
641 v.reason = 0;
642 }
643 CADICAL_assert (v.level >= real_level);
644 if (v.level > real_level) {
645 v.level = real_level;
646 }
647 }
648 f.seen = false;
649 }
650
651#if 0 // has been fuzzed extensively
652 for (auto idx : vars) {
653 CADICAL_assert (!flags (idx).seen);
654 }
655#endif
656}
void explain_reason(int lit, Clause *, int &open)
void learn_unit_clause(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ explain_reason()

void CaDiCaL::Internal::explain_reason ( int lit,
Clause * reason,
int & open )

Definition at line 534 of file cadical_external_propagate.cpp.

534 {
535 if (!opts.exteagerreasons)
536 return;
537#ifndef CADICAL_NDEBUG
538 LOG (reason, "explain_reason of %d (open: %d)", ilit, open);
539#endif
540 CADICAL_assert (reason);
542 for (const auto &other : *reason) {
543 if (other == ilit)
544 continue;
545 Flags &f = flags (other);
546 if (f.seen)
547 continue;
548 Var &v = var (other);
549 if (!v.level)
550 continue;
551 CADICAL_assert (val (other) < 0);
552 CADICAL_assert (v.level <= level);
553 if (v.reason == external_reason) {
554 v.reason = learn_external_reason_clause (-other, 0, true);
555 }
556 if (v.level && v.reason) {
557 f.seen = true;
558 open++;
559 }
560 }
561}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ external_check_solution()

bool CaDiCaL::Internal::external_check_solution ( )

Definition at line 830 of file cadical_external_propagate.cpp.

830 {
831 if (!external_prop)
832 return true;
833
834 bool trail_changed = true;
835 bool added_new_clauses = false;
836 while (trail_changed || added_new_clauses) {
838 if (!satisfied ())
839 break;
840 trail_changed = false; // to be on the safe side
841 added_new_clauses = false;
842 LOG ("Final check by external propagator is invoked.");
843 stats.ext_prop.echeck_call++;
844 external->reset_extended ();
845 external->extend ();
846
847 std::vector<int> etrail;
848
849 // Here the variables must be filtered by external->is_observed,
850 // because fixed variables are internally not necessarily observed
851 // anymore.
852 for (int idx = 1; idx <= external->max_var; idx++) {
853 if (!external->is_observed[idx])
854 continue;
855 const int lit = external->ival (idx);
856 etrail.push_back (lit);
857#ifndef CADICAL_NDEBUG
858#ifdef LOGGING
859 bool p = external->vals[idx];
860 LOG ("evals[%d]: %d ival(%d): %d", idx, p, idx, lit);
861#endif
862#endif
863 }
864
865 bool is_consistent =
866 external->propagator->cb_check_found_model (etrail);
867 stats.ext_prop.ext_cb++;
868 if (is_consistent) {
869 LOG ("Found solution is approved by external propagator.");
870 return true;
871 }
872
873 bool has_external_clause = ask_external_clause ();
874
875 stats.ext_prop.ext_cb++;
876 stats.ext_prop.elearn_call++;
877
878 if (has_external_clause)
879 LOG (
880 "Found solution triggered new clauses from external propagator.");
881
882 while (has_external_clause) {
883 int level_before = level;
884 size_t assigned = num_assigned;
886 bool trail_changed =
887 (num_assigned != assigned || level != level_before ||
888 propagated < trail.size ());
889 added_new_clauses = true;
890 //
891 // There are many possible scenarios here:
892 // - Learned conflicting clause: return to CDCL loop (conflict true)
893 // - Learned conflicting unit clause that after backtrack+BCP leads to
894 // a new complete solution: force the outer loop to check the new
895 // model (trail_changed is true, but (conflict & unsat) is false)
896 // - Learned empty clause: return to CDCL loop (unsat true)
897 // - Learned a non-conflicting unit clause:
898 // Though it does not invalidate the current solution, the solver
899 // will backtrack to the root level and will repropagate it. The
900 // search will start again (saved phases hopefully make it quick),
901 // but it is needed in order to guarantee that every fixed variable
902 // is properly handled+notified (important for incremental use
903 // cases).
904 // - Otherwise: the solution is considered approved and the CDCL-loop
905 // can return with res = 10.
906 //
907 if (unsat || conflict || trail_changed)
908 break;
909 has_external_clause = ask_external_clause ();
910 stats.ext_prop.ext_cb++;
911 stats.ext_prop.elearn_call++;
912 }
913 LOG ("No more external clause to add.");
914 if (unsat || conflict)
915 break;
916 }
917
918 if (!unsat && conflict) {
919 const int conflict_level = var (conflict->literals[0]).level;
920 if (conflict_level != level) {
921 backtrack (conflict_level);
922 }
923 }
924
925 return !conflict;
926}
void add_external_clause(int propagated_lit=0, bool no_backtrack=false)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ external_propagate()

bool CaDiCaL::Internal::external_propagate ( )

Definition at line 235 of file cadical_external_propagate.cpp.

235 {
236 if (level)
239
240 size_t before = num_assigned;
241 bool cb_repropagate_needed = true;
242 while (cb_repropagate_needed && !conflict && external_prop &&
244#ifndef CADICAL_NDEBUG
245 LOG ("external propagation starts (decision level: %d, trail size: "
246 "%zd, notified %zd)",
247 level, trail.size (), notified);
248#endif
249 cb_repropagate_needed = false;
250 // external->reset_extended (); //TODO for inprocessing
251
253
254 int elit = external->propagator->cb_propagate ();
255 stats.ext_prop.ext_cb++;
256 stats.ext_prop.eprop_call++;
257 while (elit) {
258 CADICAL_assert (external->is_observed[abs (elit)]);
259 int ilit = external->e2i[abs (elit)];
260 if (elit < 0)
261 ilit = -ilit;
262 int tmp = val (ilit);
263#ifndef CADICAL_NDEBUG
264 CADICAL_assert (fixed (ilit) || observed (ilit));
265 LOG ("External propagation of e%d (i%d val: %d)", elit, ilit, tmp);
266#endif
267 if (!tmp) {
268 // variable is not assigned, it can be propagated
269 if (!level) {
270 Clause *res = learn_external_reason_clause (ilit, elit);
271#ifndef LOGGING
272 LOG (res, "reason clause of external propagation of %d:", elit);
273#endif
274 (void) res;
275 } else
277 stats.ext_prop.eprop_prop++;
278
279 if (unsat || conflict)
280 break;
281 propagate ();
282 if (unsat || conflict)
283 break;
285 } else if (tmp < 0) {
286 LOG ("External propgation of %d is falsified under current trail",
287 ilit);
288 stats.ext_prop.eprop_conf++;
289 int level_before = level;
290 size_t assigned = num_assigned;
291 Clause *res = learn_external_reason_clause (ilit, elit);
292#ifndef LOGGING
293 LOG (res, "reason clause of external propagation of %d:", elit);
294#endif
295 (void) res;
296 bool trail_changed =
297 (num_assigned != assigned || level != level_before ||
298 propagated < trail.size ());
299
300 if (unsat || conflict)
301 break;
302
303 if (trail_changed) {
304 propagate ();
305 if (unsat || conflict)
306 break;
308 }
309 } // else (tmp > 0) -> the case of a satisfied literal is ignored
310 elit = external->propagator->cb_propagate ();
311 stats.ext_prop.ext_cb++;
312 stats.ext_prop.eprop_call++;
313 }
314
315#ifndef CADICAL_NDEBUG
316 LOG ("External propagation ends (decision level: %d, trail size: %zd, "
317 "notified %zd)",
318 level, trail.size (), notified);
319#endif
320 if (!unsat && !conflict) {
321 int level_before = level;
322 size_t assigned = num_assigned;
323 bool has_external_clause = ask_external_clause ();
324 // New observed variable might have triggered a backtrack during this
325 // ask_external_clause call, so we need to propagate before continuing
326 stats.ext_prop.ext_cb++;
327 stats.ext_prop.elearn_call++;
328
329 bool trail_changed =
330 (num_assigned != assigned || level != level_before ||
331 propagated < trail.size ());
332 if (trail_changed) {
333 propagate (); // unsat or conflict will be caught later
334 if (!unsat || !conflict)
336 }
337
338#ifndef CADICAL_NDEBUG
339 if (has_external_clause)
340 LOG ("New external clauses are to be added.");
341 else
342 LOG ("No external clauses to be added.");
343#endif
344
345 while (has_external_clause) {
346 level_before = level;
348
350 trail_changed =
351 (num_assigned != assigned || level != level_before ||
352 propagated < trail.size ());
353 cb_repropagate_needed = true;
354
355 if (unsat || conflict) {
356 cb_repropagate_needed = false;
357 break;
358 }
359
360 if (trail_changed) {
361 propagate ();
362 if (unsat || conflict) {
363 cb_repropagate_needed = false;
364 break;
365 }
366
368 }
369 has_external_clause = ask_external_clause ();
370 stats.ext_prop.ext_cb++;
371 stats.ext_prop.elearn_call++;
372 }
373 }
374#ifndef CADICAL_NDEBUG
375 LOG ("External clause addition ends on decision level %d at trail "
376 "size "
377 "%zd (notified %zd)",
378 level, trail.size (), notified);
379#endif
380 }
381 if (before < num_assigned)
382 did_external_prop = true;
383 return !conflict;
384}
void search_assign_external(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ externalize()

int CaDiCaL::Internal::externalize ( int lit)
inline

Definition at line 1557 of file internal.hpp.

1557 {
1558 CADICAL_assert (lit != INT_MIN);
1559 const int idx = abs (lit);
1560 CADICAL_assert (idx);
1561 CADICAL_assert (idx <= max_var);
1562 int res = i2e[idx];
1563 if (lit < 0)
1564 res = -res;
1565 return res;
1566 }
Here is the caller graph for this function:

◆ extract_gates()

bool CaDiCaL::Internal::extract_gates ( )

Definition at line 7429 of file cadical_congruence.cpp.

7429 {
7430 if (unsat)
7431 return false;
7432 if (!opts.congruence)
7433 return false;
7434 if (level)
7435 backtrack ();
7436 if (!propagate ()) {
7438 return false;
7439 }
7440 if (congruence_delay.bumpreasons.limit) {
7441 LOG ("delaying congruence %" PRId64 " more times",
7442 congruence_delay.bumpreasons.limit);
7443 congruence_delay.bumpreasons.limit--;
7444 return false;
7445 }
7446
7447 // to remove false literals from clauses
7448 // It makes the technique stronger as long clauses
7449 // can become binary / ternary
7450 // garbage_collection ();
7451
7452 const int64_t old = stats.congruence.congruent;
7453 const int old_merged = stats.congruence.congruent;
7454
7455 // congruencebinary is already doing it (and more actually)
7456 if (!internal->opts.congruencebinaries) {
7457 const bool dedup = opts.deduplicate;
7458 opts.deduplicate = true;
7460 opts.deduplicate = dedup;
7461 }
7462 ++stats.congruence.rounds;
7463 clear_watches ();
7464 // connect_binary_watches ();
7465
7466 START_SIMPLIFIER (congruence, CONGRUENCE);
7467 Closure closure (this);
7468
7469 closure.init_closure ();
7470 CADICAL_assert (unsat || closure.chain.empty ());
7471 CADICAL_assert (unsat || lrat_chain.empty ());
7472 closure.extract_binaries ();
7473 CADICAL_assert (unsat || closure.chain.empty ());
7474 CADICAL_assert (unsat || lrat_chain.empty ());
7475 closure.extract_gates ();
7476 CADICAL_assert (unsat || closure.chain.empty ());
7477 CADICAL_assert (unsat || lrat_chain.empty ());
7478 internal->clear_watches ();
7479 internal->connect_watches ();
7480 closure.reset_extraction ();
7481
7482 if (!unsat) {
7483 closure.find_units ();
7484 CADICAL_assert (unsat || closure.chain.empty ());
7485 CADICAL_assert (unsat || lrat_chain.empty ());
7486 if (!internal->unsat) {
7487 closure.find_equivalences ();
7488 CADICAL_assert (unsat || closure.chain.empty ());
7489 CADICAL_assert (unsat || lrat_chain.empty ());
7490
7491 if (!unsat) {
7492 const int propagated = closure.propagate_units_and_equivalences ();
7493 CADICAL_assert (unsat || closure.chain.empty ());
7494 if (!unsat && propagated)
7495 closure.forward_subsume_matching_clauses ();
7496 }
7497 }
7498 }
7499
7500 closure.reset_closure ();
7501 internal->clear_watches ();
7502 internal->connect_watches ();
7503 if (!internal->unsat) {
7504 propagated2 = propagated = 0;
7505 propagate ();
7506 }
7507 CADICAL_assert (closure.new_unwatched_binary_clauses.empty ());
7508 internal->reset_occs ();
7509 internal->reset_noccs ();
7510 CADICAL_assert (!internal->occurring ());
7511 CADICAL_assert (lrat_chain.empty ());
7512
7513 const int64_t new_merged = stats.congruence.congruent;
7514
7515#ifndef CADICAL_QUIET
7516 phase ("congruence-phase", stats.congruence.rounds, "merged %ld literals",
7517 new_merged - old_merged);
7518#endif
7519 if (!unsat && !internal->propagate ())
7520 unsat = true;
7521
7522 STOP_SIMPLIFIER (congruence, CONGRUENCE);
7523 report ('c', !opts.reportall && !(stats.congruence.congruent - old));
7524#ifndef CADICAL_NDEBUG
7525 size_t watched = 0;
7526 for (auto v : vars) {
7527 for (auto sgn = -1; sgn <= 1; sgn += 2) {
7528 const int lit = v * sgn;
7529 for (auto w : watches (lit)) {
7530 if (w.binary ())
7531 CADICAL_assert (!w.clause->garbage);
7532 if (w.clause->garbage)
7533 continue;
7534 ++watched;
7535 LOG (w.clause, "watched");
7536 }
7537 }
7538 }
7539 LOG ("and now the clauses:");
7540 size_t nb_clauses = 0;
7541 for (auto c : clauses) {
7542 if (c->garbage)
7543 continue;
7544 LOG (c, "watched");
7545 ++nb_clauses;
7546 }
7547 CADICAL_assert (watched == nb_clauses * 2);
7548#endif
7549 CADICAL_assert (!internal->occurring ());
7550
7551 if (new_merged == old_merged) {
7552 congruence_delay.bumpreasons.interval++;
7553 } else {
7554 congruence_delay.bumpreasons.interval /= 2;
7555 }
7556
7557 LOG ("delay congruence internal %" PRId64,
7558 congruence_delay.bumpreasons.interval);
7559 congruence_delay.bumpreasons.limit =
7560 congruence_delay.bumpreasons.interval;
7561
7562 return new_merged != old_merged;
7563}
struct closure closure
Definition congruence.c:145
void mark_duplicated_binary_clauses_as_garbage()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ factor()

bool CaDiCaL::Internal::factor ( )

Definition at line 859 of file cadical_factor.cpp.

859 {
860 if (unsat)
861 return false;
863 return false;
864 if (!opts.factor)
865 return false;
866 // The following CADICAL_assertion fails if there are *only* user propagator
867 // clauses (which are redundant).
868 // CADICAL_assert (stats.mark.factor || clauses.empty ());
869 if (last.factor.marked >= stats.mark.factor) {
870 VERBOSE (3,
871 "factorization skipped as no literals have been"
872 "marked to be added (%" PRIu64 " < %" PRIu64 ")",
873 last.factor.marked, stats.mark.factor);
874 return false;
875 }
877
879 if (!stats.factor)
880 limit += opts.factoriniticks * 1e6;
881
883 stats.factor++;
884
885#ifndef CADICAL_QUIET
886 struct {
887 int64_t variables, clauses, ticks;
888 } before, after, delta;
889 before.variables = stats.variables_extension + stats.variables_original;
890 before.ticks = stats.ticks.factor;
891 before.clauses = stats.current.irredundant;
892#endif
893
894 factor_mode ();
895 bool completed = run_factorization (limit);
897
898 propagated = 0;
899 if (!unsat && !propagate ()) {
901 }
902
903#ifndef CADICAL_QUIET
904 after.variables = stats.variables_extension + stats.variables_original;
905 after.clauses = stats.current.irredundant;
906 after.ticks = stats.ticks.factor;
907 delta.variables = after.variables - before.variables;
908 delta.clauses = before.clauses - after.clauses;
909 delta.ticks = after.ticks - before.ticks;
910 VERBOSE (2, "used %f million factorization ticks", delta.ticks * 1e-6);
911 phase ("factorization", stats.factor,
912 "introduced %" PRId64 " extension variables %.0f%%",
913 delta.variables, percent (delta.variables, before.variables));
914 phase ("factorization", stats.factor,
915 "removed %" PRId64 " irredundant clauses %.0f%%", delta.clauses,
916 percent (delta.clauses, before.clauses));
917#endif
918
919 if (completed)
920 last.factor.marked = stats.mark.factor;
922 return true;
923}
#define SET_EFFORT_LIMIT(LIMIT, NAME, THRESHHOLD)
Definition limit.hpp:131
bool run_factorization(int64_t limit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ factor_mode()

void CaDiCaL::Internal::factor_mode ( )

Definition at line 24 of file cadical_factor.cpp.

24 {
26
28 init_occs ();
29
30 const int size_limit = opts.factorsize;
31
32 vector<unsigned> bincount, largecount;
33 const unsigned max_lit = 2 * (max_var + 1);
34 enlarge_zero (bincount, max_lit);
35 if (size_limit > 2)
36 enlarge_zero (largecount, max_lit);
37
38 vector<Clause *> candidates;
39 int64_t &ticks = stats.ticks.factor;
40 ticks += 1 + cache_lines (clauses.size (), sizeof (Clause *));
41
42 // push binary clauses on the occurrence stack.
43 for (const auto &c : clauses) {
44 ticks++;
45 if (c->garbage)
46 continue;
47 if (c->redundant && c->size > 2)
48 continue;
49 if (c->size > size_limit)
50 continue;
51 if (c->size == 2) {
52 const int lit = c->literals[0];
53 const int other = c->literals[1];
54 bincount[vlit (lit)]++;
55 bincount[vlit (other)]++;
56 occs (lit).push_back (c);
57 occs (other).push_back (c);
58 continue;
59 }
60 candidates.push_back (c);
61 for (const auto &lit : *c) {
62 largecount[vlit (lit)]++;
63 }
64 }
65 if (size_limit == 2)
66 return;
67
68 // iterate counts of larger clauses rounds often
69 const unsigned rounds = opts.factorcandrounds;
70 unsigned candidates_before = 0;
71 for (unsigned round = 1; round <= rounds; round++) {
72 LOG ("factor round %d", round);
73 if (candidates.size () == candidates_before)
74 break;
75 ticks += 1 + cache_lines (candidates.size (), sizeof (Clause *));
76 candidates_before = candidates.size ();
77 vector<unsigned> newlargecount;
78 enlarge_zero (newlargecount, max_lit);
79 const auto begin = candidates.begin ();
80 auto p = candidates.begin ();
81 auto q = p;
82 const auto end = candidates.end ();
83 while (p != end) {
84 Clause *c = *q++ = *p++;
85 ticks++;
86 for (const auto &lit : *c) {
87 const auto idx = vlit (lit);
88 if (bincount[idx] + largecount[idx] < 2) {
89 q--;
90 goto CONTINUE_WITH_NEXT_CLAUSE;
91 }
92 }
93 for (const auto &lit : *c) {
94 const auto idx = vlit (lit);
95 newlargecount[idx]++;
96 }
97 CONTINUE_WITH_NEXT_CLAUSE:
98 continue;
99 }
100 candidates.resize (q - begin);
101 largecount.swap (newlargecount);
102 }
103
104 // finally push remaining clause on the occurrence stack
105 for (const auto &c : candidates)
106 for (const auto &lit : *c)
107 occs (lit).push_back (c);
108}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ factorize_next()

void CaDiCaL::Internal::factorize_next ( Factoring & factoring,
int next,
unsigned expected_next_count )

Definition at line 391 of file cadical_factor.cpp.

392 {
393 Quotient *last_quotient = factoring.quotients.last;
394 Quotient *next_quotient = new_quotient (factoring, next);
395
396 CADICAL_assert (last_quotient);
397 vector<Clause *> &last_clauses = last_quotient->qlauses;
398 vector<Clause *> &next_clauses = next_quotient->qlauses;
399 vector<size_t> &matches = next_quotient->matches;
400 vector<Clause *> &flauses = factoring.flauses;
401 CADICAL_assert (flauses.empty ());
402
403 int64_t ticks = 1 + cache_lines (last_clauses.size (), sizeof (Clause *));
404
405 size_t i = 0;
406
407 for (auto c : last_clauses) {
408 CADICAL_assert (!c->swept);
409 int min_lit = 0;
410 unsigned factors = 0;
411 size_t min_size = 0;
412 ticks++;
413 for (const auto &other : *c) {
414 if (getfact (other, FACTORS)) {
415 if (factors++)
416 break;
417 } else {
418 CADICAL_assert (!getfact (other, QUOTIENT));
419 markfact (other, QUOTIENT);
420 const size_t other_size = occs (other).size ();
421 if (!min_lit || other_size < min_size) {
422 min_lit = other;
423 min_size = other_size;
424 }
425 }
426 }
427 CADICAL_assert (factors);
428 if (factors == 1) {
429 CADICAL_assert (min_lit);
430 const int c_size = c->size;
431 ticks += 1 + cache_lines (occs (min_lit).size (), sizeof (Clause *));
432 for (auto d : occs (min_lit)) {
433 if (c == d)
434 continue;
435 ticks++;
436 if (d->swept)
437 continue;
438 if (d->size != c_size)
439 continue;
440 for (const auto &other : *d) {
441 if (getfact (other, QUOTIENT))
442 continue;
443 if (other != next)
444 goto CONTINUE_WITH_NEXT_MIN_WATCH;
445 }
446 LOG (c, "matched");
447 LOG (d, "keeping");
448
449 next_clauses.push_back (d);
450 matches.push_back (i);
451 flauses.push_back (d);
452 d->swept = true;
453 break;
454
455 CONTINUE_WITH_NEXT_MIN_WATCH:;
456 }
457 }
458 for (const auto &other : *c)
459 if (getfact (other, QUOTIENT))
460 unmarkfact (other, QUOTIENT);
461 i++;
462 }
463 clear_flauses (flauses);
464 stats.ticks.factor += ticks;
465
466 CADICAL_assert (expected_next_count <= next_clauses.size ());
467 (void) expected_next_count;
468}
#define QUOTIENT
#define FACTORS
void clear_flauses(vector< Clause * > &)
Quotient * new_quotient(Factoring &, int)
void markfact(int lit, int fact)
Definition internal.hpp:580
quotient * last
Definition factor.c:60
Here is the call graph for this function:
Here is the caller graph for this function:

◆ failed()

bool CaDiCaL::Internal::failed ( int lit)

Definition at line 453 of file cadical_assume.cpp.

453 {
454 if (!marked_failed) {
455 if (!conflict_id)
456 failing ();
457 marked_failed = true;
458 }
460 Flags &f = flags (lit);
461 const unsigned bit = bign (lit);
462 return (f.failed & bit) != 0;
463}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ failed_constraint()

bool CaDiCaL::Internal::failed_constraint ( )

Definition at line 57 of file cadical_constrain.cpp.

57{ return unsat_constraint; }

◆ failed_literal()

void CaDiCaL::Internal::failed_literal ( int lit)

Definition at line 517 of file cadical_probe.cpp.

517 {
518
519 LOG ("analyzing failed literal probe %d", failed);
520 stats.failed++;
521 stats.probefailed++;
522
525 CADICAL_assert (level == 1);
526 CADICAL_assert (analyzed.empty ());
527 CADICAL_assert (lrat_chain.empty ());
528
529 START (analyze);
530
531 LOG (conflict, "analyzing failed literal conflict");
532
533 int uip = 0;
534 for (const auto &lit : *conflict) {
535 const int other = -lit;
536 if (!var (other).level) {
537 CADICAL_assert (val (other) > 0);
538 continue;
539 }
540 uip = uip ? probe_dominator (uip, other) : other;
541 }
543 if (lrat)
545
546 LOG ("found probing UIP %d", uip);
547 CADICAL_assert (uip);
548
549 vector<int> work;
550
551 int parent = uip;
552 while (parent != failed) {
553 const int next = get_parent_reason_literal (parent);
554 parent = next;
555 CADICAL_assert (parent);
556 work.push_back (parent);
557 }
558
559 backtrack ();
560 conflict = 0;
561
562 CADICAL_assert (!val (uip));
563 probe_assign_unit (-uip);
564 lrat_chain.clear ();
565
566 if (!probe_propagate ())
568
569 size_t j = 0;
570 while (!unsat && j < work.size ()) {
571 // CADICAL_assert (!opts.probehbr); CADICAL_assertion fails ...
572 const int parent = work[j++];
573 const signed char tmp = val (parent);
574 if (tmp > 0) {
575 CADICAL_assert (!opts.probehbr); // ... CADICAL_assertion should hold here
576 get_probehbr_lrat (parent, uip);
577 LOG ("clashing failed parent %d", parent);
579 } else if (tmp == 0) {
580 CADICAL_assert (!opts.probehbr); // ... and here
581 LOG ("found unassigned failed parent %d", parent);
582 get_probehbr_lrat (parent, uip); // this is computed during
583 probe_assign_unit (-parent); // propagation and can include
584 lrat_chain.clear (); // multiple chains where only one
585 if (!probe_propagate ())
586 learn_empty_clause (); // is needed!
587 }
588 uip = parent;
589 }
590 work.clear ();
591 erase_vector (work);
592
593 STOP (analyze);
594
595 CADICAL_assert (unsat || val (failed) < 0);
596}
void probe_assign_unit(int lit)
int probe_dominator(int a, int b)
void get_probehbr_lrat(int lit, int uip)
int get_parent_reason_literal(int lit)
void probe_dominator_lrat(int dom, Clause *reason)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ failing()

void CaDiCaL::Internal::failing ( )

Definition at line 81 of file cadical_assume.cpp.

81 {
82
83 START (analyze);
84
85 LOG ("analyzing failing assumptions");
86
87 CADICAL_assert (analyzed.empty ());
88 CADICAL_assert (clause.empty ());
89 CADICAL_assert (lrat_chain.empty ());
92
93 if (!unsat_constraint) {
94 // Search for failing assumptions in the (internal) assumption stack.
95
96 // There are in essence three cases: (1) An assumption is falsified on
97 // the root-level and then 'failed_unit' is set to that assumption, (2)
98 // two clashing assumptions are assumed and then 'failed_clashing' is
99 // set to the second assumed one, or otherwise (3) there is a failing
100 // assumption 'first_failed' with minimum (non-zero) decision level
101 // 'failed_level'.
102
103 int failed_unit = 0;
104 int failed_clashing = 0;
105 int first_failed = 0;
106 int failed_level = INT_MAX;
107 int efailed = 0;
108
109 for (auto &elit : external->assumptions) {
110 int lit = external->e2i[abs (elit)];
111 if (elit < 0)
112 lit = -lit;
113 if (val (lit) >= 0)
114 continue;
115 const Var &v = var (lit);
116 if (!v.level) {
117 failed_unit = lit;
118 efailed = elit;
119 break;
120 }
121 if (failed_clashing)
122 continue;
123 if (v.reason == external_reason) {
124 Var &ev = var (lit);
125 ev.reason = learn_external_reason_clause (-lit);
126 if (!ev.reason) {
127 ev.level = 0;
128 failed_unit = lit;
129 efailed = elit;
130 break;
131 }
132 ev.level = 0;
133 // Recalculate assignment level
134 for (const auto &other : *ev.reason) {
135 if (other == -lit)
136 continue;
137 CADICAL_assert (val (other));
138 int tmp = var (other).level;
139 if (tmp > ev.level)
140 ev.level = tmp;
141 }
142 if (!ev.level) {
143 failed_unit = lit;
144 efailed = elit;
145 break;
146 }
147 }
148 CADICAL_assert (v.reason != external_reason);
149 if (!v.reason) {
150 failed_clashing = lit;
151 efailed = elit;
152 } else if (!first_failed || v.level < failed_level) {
153 first_failed = lit;
154 efailed = elit;
155 failed_level = v.level;
156 }
157 }
158
159 CADICAL_assert (clause.empty ());
160
161 // Get the 'failed' assumption from one of the three cases.
162 int failed;
163 if (failed_unit)
164 failed = failed_unit;
165 else if (failed_clashing)
166 failed = failed_clashing;
167 else
168 failed = first_failed;
170 CADICAL_assert (efailed);
171
172 // In any case mark literal 'failed' as failed assumption.
173 {
174 Flags &f = flags (failed);
175 const unsigned bit = bign (failed);
176 CADICAL_assert (!(f.failed & bit));
177 f.failed |= bit;
178 }
179
180 // First case (1).
181 if (failed_unit) {
182 CADICAL_assert (failed == failed_unit);
183 LOG ("root-level falsified assumption %d", failed);
184 if (proof) {
185 if (lrat) {
186 unsigned eidx = (efailed > 0) + 2u * (unsigned) abs (efailed);
187 CADICAL_assert ((size_t) eidx < external->ext_units.size ());
188 const int64_t id = external->ext_units[eidx];
189 if (id) {
190 lrat_chain.push_back (id);
191 } else {
192 int64_t id = unit_id (-failed_unit);
193 lrat_chain.push_back (id);
194 }
195 }
196 proof->add_assumption_clause (++clause_id, -efailed, lrat_chain);
197 conclusion.push_back (clause_id);
198 lrat_chain.clear ();
199 }
200 goto DONE;
201 }
202
203 // Second case (2).
204 if (failed_clashing) {
205 CADICAL_assert (failed == failed_clashing);
206 LOG ("clashing assumptions %d and %d", failed, -failed);
207 Flags &f = flags (-failed);
208 const unsigned bit = bign (-failed);
209 CADICAL_assert (!(f.failed & bit));
210 f.failed |= bit;
211 if (proof) {
212 vector<int> clash = {externalize (failed), externalize (-failed)};
213 proof->add_assumption_clause (++clause_id, clash, lrat_chain);
214 conclusion.push_back (clause_id);
215 }
216 goto DONE;
217 }
218
219 // Fall through to third case (3).
220 LOG ("starting with assumption %d falsified on minimum decision level "
221 "%d",
222 first_failed, failed_level);
223
224 CADICAL_assert (first_failed);
225 CADICAL_assert (failed_level > 0);
226
227 // The 'analyzed' stack serves as working stack for a BFS through the
228 // implication graph until decisions, which are all assumptions, or
229 // units are reached. This is simpler than corresponding code in
230 // 'analyze'.
231 {
232 LOG ("failed assumption %d", first_failed);
233 Flags &f = flags (first_failed);
234 CADICAL_assert (!f.seen);
235 f.seen = true;
236 CADICAL_assert (f.failed & bign (first_failed));
237 analyzed.push_back (-first_failed);
238 clause.push_back (-first_failed);
239 }
240 } else {
241 // unsat_constraint
242 // The assumptions necessary to fail each literal in the constraint are
243 // collected.
244 for (auto lit : constraint) {
245 lit *= -1;
246 CADICAL_assert (lit != INT_MIN);
247 flags (lit).seen = true;
248 analyzed.push_back (lit);
249 }
250 }
251
252 {
253 // used for unsat_constraint lrat
254 vector<vector<int64_t>> constraint_chains;
255 vector<vector<int>> constraint_clauses;
256 vector<int> sum_constraints;
257 vector<int> econstraints;
258 for (auto &elit : external->constraint) {
259 int lit = external->e2i[abs (elit)];
260 if (elit < 0)
261 lit = -lit;
262 if (!lit)
263 continue;
264 Flags &f = flags (lit);
265 if (f.seen)
266 continue;
267 if (std::find (econstraints.begin (), econstraints.end (), elit) !=
268 econstraints.end ())
269 continue;
270 econstraints.push_back (elit);
271 }
272
273 // no LRAT do bfs as it was before
274 if (!lrat) {
275 size_t next = 0;
276 while (next < analyzed.size ()) {
277 const int lit = analyzed[next++];
278 CADICAL_assert (val (lit) > 0);
279 Var &v = var (lit);
280 if (!v.level)
281 continue;
282 if (v.reason == external_reason) {
284 if (!v.reason) {
285 v.level = 0;
286 continue;
287 }
288 }
289 CADICAL_assert (v.reason != external_reason);
290 if (v.reason) {
291 CADICAL_assert (v.level);
292 LOG (v.reason, "analyze reason");
293 for (const auto &other : *v.reason) {
294 Flags &f = flags (other);
295 if (f.seen)
296 continue;
297 f.seen = true;
298 CADICAL_assert (val (other) < 0);
299 analyzed.push_back (-other);
300 }
301 } else {
303 LOG ("failed assumption %d", lit);
304 clause.push_back (-lit);
305 Flags &f = flags (lit);
306 const unsigned bit = bign (lit);
307 CADICAL_assert (!(f.failed & bit));
308 f.failed |= bit;
309 }
310 }
312 } else if (!unsat_constraint) { // LRAT for case (3)
313 CADICAL_assert (clause.size () == 1);
314 const int lit = clause[0];
315 Var &v = var (lit);
316 CADICAL_assert (v.reason);
317 if (v.reason == external_reason) { // does this even happen?
319 }
320 CADICAL_assert (v.reason != external_reason);
321 if (v.reason)
322 assume_analyze_reason (lit, v.reason);
323 else {
324 int64_t id = unit_id (lit);
325 lrat_chain.push_back (id);
326 }
327 for (auto &lit : clause) {
328 Flags &f = flags (lit);
329 const unsigned bit = bign (-lit);
330 if (!(f.failed & bit))
331 f.failed |= bit;
332 }
334 } else { // LRAT for unsat_constraint
335 CADICAL_assert (clause.empty ());
337 for (auto lit : constraint) {
338 // make sure nothing gets marked failed twice
339 // also might shortcut the case where
340 // lrat_chain is empty because clause is tautological
341 CADICAL_assert (lit != INT_MIN);
343 vector<int64_t> empty;
344 vector<int> empty2;
345 constraint_chains.push_back (empty);
346 constraint_clauses.push_back (empty2);
347 for (auto ign : clause) {
348 constraint_clauses.back ().push_back (ign);
349 Flags &f = flags (ign);
350 const unsigned bit = bign (-ign);
351 if (!(f.failed & bit)) {
352 sum_constraints.push_back (ign);
353 CADICAL_assert (!(f.failed & bit));
354 f.failed |= bit;
355 }
356 }
357 clause.clear ();
359 for (auto p : lrat_chain) {
360 constraint_chains.back ().push_back (p);
361 }
362 lrat_chain.clear ();
363 }
364 for (auto &lit : sum_constraints)
365 clause.push_back (lit);
366 }
368
369 // Doing clause minimization here does not do anything because
370 // the clause already contains only one literal of each level
371 // and minimization can never reduce the number of levels
372
373 VERBOSE (1, "found %zd failed assumptions %.0f%%", clause.size (),
374 percent (clause.size (), assumptions.size ()));
375
376 // We do not actually need to learn this clause, since the conflict is
377 // forced already by some other clauses. There is also no bumping
378 // of variables nor clauses necessary. But we still want to check
379 // correctness of the claim that the determined subset of failing
380 // assumptions are a high-level core or equivalently their negations
381 // form a unit-implied clause.
382 //
383 if (!unsat_constraint) {
384 external->check_learned_clause ();
385 if (proof) {
386 vector<int> eclause;
387 for (auto &lit : clause)
388 eclause.push_back (externalize (lit));
389 proof->add_assumption_clause (++clause_id, eclause, lrat_chain);
390 conclusion.push_back (clause_id);
391 }
392 } else {
393 CADICAL_assert (!lrat || (constraint.size () == constraint_clauses.size () &&
394 constraint.size () == constraint_chains.size ()));
395 for (auto p = constraint.rbegin (); p != constraint.rend (); p++) {
396 const auto &lit = *p;
397 if (lrat) {
398 clause.clear ();
399 for (auto &ign : constraint_clauses.back ())
400 clause.push_back (ign);
401 constraint_clauses.pop_back ();
402 }
403 clause.push_back (-lit);
404 external->check_learned_clause ();
405 if (proof) {
406 if (lrat) {
407 for (auto p : constraint_chains.back ()) {
408 lrat_chain.push_back (p);
409 }
410 constraint_chains.pop_back ();
411 LOG (lrat_chain, "assume proof chain with constraints");
412 }
413 vector<int> eclause;
414 for (auto &lit : clause)
415 eclause.push_back (externalize (lit));
416 proof->add_assumption_clause (++clause_id, eclause, lrat_chain);
417 conclusion.push_back (clause_id);
418 lrat_chain.clear ();
419 }
420 clause.pop_back ();
421 }
422 if (proof) {
423 for (auto &elit : econstraints) {
424 if (lrat) {
425 unsigned eidx = (elit > 0) + 2u * (unsigned) abs (elit);
426 CADICAL_assert ((size_t) eidx < external->ext_units.size ());
427 const int64_t id = external->ext_units[eidx];
428 if (id) {
429 lrat_chain.push_back (id);
430 } else {
431 int lit = external->e2i[abs (elit)];
432 if (elit < 0)
433 lit = -lit;
434 int64_t id = unit_id (-lit);
435 lrat_chain.push_back (id);
436 }
437 }
438 proof->add_assumption_clause (++clause_id, -elit, lrat_chain);
439 conclusion.push_back (clause_id);
440 lrat_chain.clear ();
441 }
442 }
443 }
444 lrat_chain.clear ();
445 clause.clear ();
446 }
447
448DONE:
449
450 STOP (analyze);
451}
@ DONE
Definition inflate.h:51
void assume_analyze_reason(int lit, Clause *reason)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ finalize()

void CaDiCaL::Internal::finalize ( int res)

Definition at line 1041 of file cadical_internal.cpp.

1041 {
1042 if (!proof)
1043 return;
1044 LOG ("finalizing");
1045 // finalize external units
1046 if (frat) {
1047 for (const auto &evar : external->vars) {
1048 CADICAL_assert (evar > 0);
1049 const auto eidx = 2 * evar;
1050 int sign = 1;
1051 int64_t id = external->ext_units[eidx];
1052 if (!id) {
1053 sign = -1;
1054 id = external->ext_units[eidx + 1];
1055 }
1056 if (id) {
1057 proof->finalize_external_unit (id, evar * sign);
1058 }
1059 }
1060 // finalize internal units
1061 for (const auto &lit : lits) {
1062 const auto elit = externalize (lit);
1063 if (elit) {
1064 const unsigned eidx = (elit < 0) + 2u * (unsigned) abs (elit);
1065 const int64_t id = external->ext_units[eidx];
1066 if (id) {
1067 CADICAL_assert (unit_clauses (vlit (lit)) == id);
1068 continue;
1069 }
1070 }
1071 const int64_t id = unit_clauses (vlit (lit));
1072 if (!id)
1073 continue;
1074 proof->finalize_unit (id, lit);
1075 }
1076 // See the discussion in 'propagate' on why garbage binary clauses stick
1077 // around.
1078 for (const auto &c : clauses)
1079 if (!c->garbage || (c->size == 2 && !c->flushed))
1080 proof->finalize_clause (c);
1081
1082 // finalize conflict and proof
1083 if (conflict_id) {
1084 proof->finalize_clause (conflict_id, {});
1085 }
1086 }
1087 proof->report_status (res, conflict_id);
1088 if (res == 10)
1089 external->conclude_sat ();
1090 else if (res == 20)
1091 conclude_unsat ();
1092 else if (!res)
1093 external->conclude_unknown ();
1094}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_and_gate()

void CaDiCaL::Internal::find_and_gate ( Eliminator & eliminator,
int pivot )

Definition at line 323 of file cadical_gates.cpp.

323 {
324
325 if (!opts.elimands)
326 return;
327
328 CADICAL_assert (opts.elimsubst);
329
330 if (unsat)
331 return;
332 if (val (pivot))
333 return;
334 if (!eliminator.gates.empty ())
335 return;
336
337 mark_binary_literals (eliminator, pivot);
338 if (unsat || val (pivot))
339 goto DONE;
340
341 for (const auto &c : occs (-pivot)) {
342
343 if (c->garbage)
344 continue;
345 if (c->size < 3)
346 continue;
347
348 bool all_literals_marked = true;
349 unsigned arity = 0;
350 int satisfied = 0;
351
352 for (const auto &lit : *c) {
353 if (lit == -pivot)
354 continue;
355 CADICAL_assert (lit != pivot);
356 signed char tmp = val (lit);
357 if (tmp < 0)
358 continue;
359 if (tmp > 0) {
360 satisfied = lit;
361 break;
362 }
363 tmp = marked (lit);
364 if (tmp < 0) {
365 arity++;
366 continue;
367 }
368 all_literals_marked = false;
369 break;
370 }
371
372 if (!all_literals_marked)
373 continue;
374
375 if (satisfied) {
376 LOG (c, "satisfied by %d candidate base clause", satisfied);
377 mark_garbage (c);
378 continue;
379 }
380
381#ifdef LOGGING
382 if (opts.log) {
383 Logger::print_log_prefix (this);
384 tout.magenta ();
385 printf ("found arity %u AND gate %d = ", arity, -pivot);
386 bool first = true;
387 for (const auto &lit : *c) {
388 if (lit == -pivot)
389 continue;
390 CADICAL_assert (lit != pivot);
391 if (!first)
392 fputs (" & ", stdout);
393 printf ("%d", -lit);
394 first = false;
395 }
396 fputc ('\n', stdout);
397 tout.normal ();
398 fflush (stdout);
399 }
400#endif
401 stats.elimands++;
402 stats.elimgates++;
403 eliminator.gatetype = AND;
404
405 (void) arity;
406 CADICAL_assert (!c->gate);
407 c->gate = true;
408 eliminator.gates.push_back (c);
409 for (const auto &lit : *c) {
410 if (lit == -pivot)
411 continue;
412 CADICAL_assert (lit != pivot);
413 signed char tmp = val (lit);
414 if (tmp < 0)
415 continue;
416 CADICAL_assert (!tmp);
417 CADICAL_assert (marked (lit) < 0);
418 marks[vidx (lit)] *= 2;
419 }
420
421 unsigned count = 0;
422 for (const auto &d : occs (pivot)) {
423 if (d->garbage)
424 continue;
425 const int other =
426 second_literal_in_binary_clause (eliminator, d, pivot);
427 if (!other)
428 continue;
429 const int tmp = marked (other);
430 if (tmp != 2)
431 continue;
432 LOG (d, "AND gate binary side clause");
433 CADICAL_assert (!d->gate);
434 d->gate = true;
435 eliminator.gates.push_back (d);
436 count++;
437 }
438 CADICAL_assert (count >= arity);
439 (void) count;
440
441 break;
442 }
443
444DONE:
445 unmark_binary_literals (eliminator);
446}
void magenta(bool bright=false)
Definition terminal.hpp:59
Terminal tout(stdout)
Definition terminal.hpp:97
int second_literal_in_binary_clause(Eliminator &, Clause *, int first)
void unmark_binary_literals(Eliminator &)
void mark_binary_literals(Eliminator &, int pivot)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_binary_clause()

Clause * CaDiCaL::Internal::find_binary_clause ( int first,
int second )

Definition at line 94 of file cadical_gates.cpp.

94 {
95 int best = first;
96 int other = second;
97 if (occs (first).size () > occs (second).size ()) {
98 best = second;
99 other = first;
100 }
101 for (auto c : occs (best))
102 if (second_literal_in_binary_clause_lrat (c, best) == other)
103 return c;
104 return 0;
105}
int second_literal_in_binary_clause_lrat(Clause *, int first)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_clause()

Clause * CaDiCaL::Internal::find_clause ( const vector< int > & lits)

Definition at line 621 of file cadical_gates.cpp.

621 {
622 int best = 0;
623 size_t len = 0;
624 for (const auto &lit : lits) {
625 size_t l = occs (lit).size ();
626 if (best && l >= len)
627 continue;
628 len = l, best = lit;
629 }
630 for (auto c : occs (best))
631 if (is_clause (c, lits))
632 return c;
633 return 0;
634}
bool is_clause(Clause *, const vector< int > &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_conflict_level()

int CaDiCaL::Internal::find_conflict_level ( int & forced)
inline

Definition at line 575 of file cadical_analyze.cpp.

575 {
576
578 CADICAL_assert (opts.chrono || opts.otfs || external_prop);
579
580 int res = 0, count = 0;
581
582 forced = 0;
583
584 for (const auto &lit : *conflict) {
585 const int tmp = var (lit).level;
586 if (tmp > res) {
587 res = tmp;
588 forced = lit;
589 count = 1;
590 } else if (tmp == res) {
591 count++;
592 if (res == level && count > 1)
593 break;
594 }
595 }
596
597 LOG ("%d literals on actual conflict level %d", count, res);
598
599 const int size = conflict->size;
600 int *lits = conflict->literals;
601
602 // Move the two highest level literals to the front.
603 //
604 for (int i = 0; i < 2; i++) {
605
606 const int lit = lits[i];
607
608 int highest_position = i;
609 int highest_literal = lit;
610 int highest_level = var (highest_literal).level;
611
612 for (int j = i + 1; j < size; j++) {
613 const int other = lits[j];
614 const int tmp = var (other).level;
615 if (highest_level >= tmp)
616 continue;
617 highest_literal = other;
618 highest_position = j;
619 highest_level = tmp;
620 if (highest_level == res)
621 break;
622 }
623
624 // No unwatched higher assignment level literal.
625 //
626 if (highest_position == i)
627 continue;
628
629 if (highest_position > 1) {
630 LOG (conflict, "unwatch %d in", lit);
632 }
633
634 lits[highest_position] = lit;
635 lits[i] = highest_literal;
636
637 if (highest_position > 1)
638 watch_literal (highest_literal, lits[!i], conflict);
639 }
640
641 // Only if the number of highest level literals in the conflict is one
642 // then we can reuse the conflict clause as driving clause for 'forced'.
643 //
644 if (count != 1)
645 forced = 0;
646
647 return res;
648}
void remove_watch(Watches &ws, Clause *clause)
Definition watch.hpp:50
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_definition()

void CaDiCaL::Internal::find_definition ( Eliminator & eliminator,
int lit )

Definition at line 182 of file cadical_definition.cpp.

182 {
183 if (!opts.elimdef)
184 return;
185 if (unsat)
186 return;
187 if (val (lit))
188 return;
189 if (!eliminator.gates.empty ())
190 return;
194 const int not_lit = -lit;
195 definition_extractor extractor;
196 extractor.lit = lit;
197 extractor.clauses[0] = occs (lit);
198 extractor.clauses[1] = occs (not_lit);
199 extractor.eliminator = &eliminator;
200 extractor.internal = internal;
202 unsigned exported = 0;
203 for (unsigned sign = 0; sign < 2; sign++) {
204 const unsigned except = sign ? lit2citten (not_lit) : lit2citten (lit);
205 for (auto c : extractor.clauses[sign]) {
206 // to avoid copying the literals of c in their unsigned
207 // representation we instead implement the translation in cadical_kitten
208 if (!c->garbage) {
209 LOG (c, "adding to cadical_kitten");
210 citten_clause_with_id_and_exception (citten, exported, c->size,
211 c->literals, except);
212 }
213 exported++;
214 }
215 }
216 stats.definitions_checked++;
217 const size_t limit = opts.elimdefticks;
219 int status = cadical_kitten_solve (citten);
220 if (!exported)
221 goto ABORT;
222 if (status == 20) {
223 LOG ("sub-solver result UNSAT shows definition exists");
224 uint64_t learned;
225 unsigned reduced = cadical_kitten_compute_clausal_core (citten, &learned);
226 LOG ("1st sub-solver core of size %u original clauses out of %u",
227 reduced, exported);
228 for (int i = 2; i <= opts.elimdefcores; i++) {
232 int tmp = cadical_kitten_solve (citten);
233 CADICAL_assert (!tmp || tmp == 20);
234 if (!tmp) {
235 LOG ("aborting core extraction");
236 goto ABORT;
237 }
238#ifndef CADICAL_NDEBUG
239 unsigned previous = reduced;
240#endif
241 reduced = cadical_kitten_compute_clausal_core (citten, &learned);
242 LOG ("%d sub-solver core of size %u original clauses out of %u", i,
243 reduced, exported);
244 CADICAL_assert (reduced <= previous);
245#if not defined(LOGGING) && defined(CADICAL_NDEBUG)
246 (void) reduced;
247#endif
248 }
249 stats.definitions_extracted++;
250 eliminator.gatetype = DEF;
251 eliminator.definition_unit = 0;
252 cadical_kitten_traverse_core_ids (citten, &extractor, traverse_definition_core);
253 CADICAL_assert (eliminator.definition_unit);
254 int unit = 0;
255 if (eliminator.definition_unit == 2) {
256 unit = not_lit;
257 } else if (eliminator.definition_unit == 1)
258 unit = lit;
259
260 if (unit) {
261 stats.definition_units++;
262 VERBOSE (2, "one sided core "
263 "definition extraction yields "
264 "failed literal");
265 if (proof) {
266 if (lrat) {
267 extractor.unit = unit;
269 traverse_one_sided_core_lemma_with_lrat);
270 } else {
271 extractor.unit = unit;
273 traverse_one_sided_core_lemma);
274 }
275 } else
276 assign_unit (unit);
277 elim_propagate (eliminator, unit);
278 }
279 } else {
280 ABORT:
281 LOG ("sub-solver failed to show that definition exists");
282 }
283 stats.definition_ticks += cadical_kitten_current_ticks (citten);
284 return;
285}
void cadical_kitten_shuffle_clauses(cadical_kitten *cadical_kitten)
unsigned cadical_kitten_compute_clausal_core(cadical_kitten *cadical_kitten, uint64_t *learned_ptr)
void cadical_kitten_set_ticks_limit(cadical_kitten *cadical_kitten, uint64_t delta)
void cadical_kitten_traverse_core_clauses(cadical_kitten *cadical_kitten, void *state, void(*traverse)(void *, bool, size_t, const unsigned *))
int cadical_kitten_solve(cadical_kitten *cadical_kitten)
void cadical_kitten_trace_core(cadical_kitten *cadical_kitten, void *state, void(*trace)(void *, unsigned, unsigned, bool, size_t, const unsigned *, size_t, const unsigned *))
void cadical_kitten_shrink_to_clausal_core(cadical_kitten *cadical_kitten)
void cadical_kitten_traverse_core_ids(cadical_kitten *cadical_kitten, void *state, void(*traverse)(void *, unsigned))
typedefABC_NAMESPACE_IMPL_START struct definition_extractor definition_extractor
Definition definition.c:10
unsigned lit2citten(int lit)
Definition internal.hpp:429
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_equivalence()

void CaDiCaL::Internal::find_equivalence ( Eliminator & eliminator,
int pivot )

Definition at line 204 of file cadical_gates.cpp.

204 {
205
206 if (!opts.elimequivs)
207 return;
208
209 CADICAL_assert (opts.elimsubst);
210
211 if (unsat)
212 return;
213 if (val (pivot))
214 return;
215 if (!eliminator.gates.empty ())
216 return;
217
218 mark_binary_literals (eliminator, pivot);
219 if (unsat || val (pivot))
220 goto DONE;
221
222 for (const auto &c : occs (-pivot)) {
223
224 if (c->garbage)
225 continue;
226
227 const int second =
228 second_literal_in_binary_clause (eliminator, c, -pivot);
229 if (!second)
230 continue;
231 const int tmp = marked (second);
232 if (tmp > 0) {
233 LOG ("found binary resolved unit %d", second);
234 // did not find a bug where units could occur multiple times here
235 // still solved potential issues with flags
236 if (lrat) {
237 Clause *d = find_binary_clause (pivot, second);
238 CADICAL_assert (d);
239 for (auto &lit : *d) {
240 if (lit == pivot || lit == second)
241 continue;
242 CADICAL_assert (val (lit) < 0);
243 Flags &f = flags (lit);
244 if (f.seen)
245 continue;
246 analyzed.push_back (lit);
247 f.seen = true;
248 int64_t id = unit_id (-lit);
249 lrat_chain.push_back (id);
250 // LOG ("gates added id %" PRId64, id);
251 }
252 for (auto &lit : *c) {
253 if (lit == -pivot || lit == second)
254 continue;
255 CADICAL_assert (val (lit) < 0);
256 Flags &f = flags (lit);
257 if (f.seen)
258 continue;
259 analyzed.push_back (lit);
260 f.seen = true;
261 int64_t id = unit_id (-lit);
262 lrat_chain.push_back (id);
263 // LOG ("gates added id %" PRId64, id);
264 }
265 lrat_chain.push_back (c->id);
266 lrat_chain.push_back (d->id);
268 // LOG ("gates added id %" PRId64, c->id);
269 // LOG ("gates added id %" PRId64, d->id);
270 }
271 assign_unit (second);
272 elim_propagate (eliminator, second);
273 if (val (pivot))
274 break;
275 if (unsat)
276 break;
277 }
278 if (tmp >= 0)
279 continue;
280
281 LOG ("found equivalence %d = %d", pivot, -second);
282 stats.elimequivs++;
283 stats.elimgates++;
284
285 LOG (c, "first gate clause");
286 CADICAL_assert (!c->gate);
287 c->gate = true;
288 eliminator.gates.push_back (c);
289
290 Clause *d = 0;
291 const Occs &ps = occs (pivot);
292 for (const auto &e : ps) {
293 if (e->garbage)
294 continue;
295 const int other =
296 second_literal_in_binary_clause (eliminator, e, pivot);
297 if (other == -second) {
298 d = e;
299 break;
300 }
301 }
302 CADICAL_assert (d);
303
304 LOG (d, "second gate clause");
305 CADICAL_assert (!d->gate);
306 d->gate = true;
307 eliminator.gates.push_back (d);
308 eliminator.gatetype = EQUI;
309
310 break;
311 }
312
313DONE:
314 unmark_binary_literals (eliminator);
315}
Clause * find_binary_clause(int, int)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_gate_clauses()

void CaDiCaL::Internal::find_gate_clauses ( Eliminator & eliminator,
int pivot )

Definition at line 739 of file cadical_gates.cpp.

739 {
740 if (!opts.elimsubst)
741 return;
742
743 if (unsat)
744 return;
745 if (val (pivot))
746 return;
747
748 CADICAL_assert (eliminator.gates.empty ());
749
750 find_equivalence (eliminator, pivot);
751 find_and_gate (eliminator, pivot);
752 find_and_gate (eliminator, -pivot);
753 find_if_then_else (eliminator, pivot);
754 find_xor_gate (eliminator, pivot);
755 find_definition (eliminator, pivot);
756}
void find_if_then_else(Eliminator &, int pivot)
void find_equivalence(Eliminator &, int pivot)
void find_and_gate(Eliminator &, int pivot)
void find_xor_gate(Eliminator &, int pivot)
void find_definition(Eliminator &, int)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_if_then_else()

void CaDiCaL::Internal::find_if_then_else ( Eliminator & eliminator,
int pivot )

Definition at line 505 of file cadical_gates.cpp.

505 {
506
507 if (!opts.elimites)
508 return;
509
510 CADICAL_assert (opts.elimsubst);
511
512 if (unsat)
513 return;
514 if (val (pivot))
515 return;
516 if (!eliminator.gates.empty ())
517 return;
518
519 const Occs &os = occs (pivot);
520 const auto end = os.end ();
521 for (auto i = os.begin (); i != end; i++) {
522 Clause *di = *i;
523 int ai, bi, ci;
524 if (!get_ternary_clause (di, ai, bi, ci))
525 continue;
526 if (bi == pivot)
527 swap (ai, bi);
528 if (ci == pivot)
529 swap (ai, ci);
530 CADICAL_assert (ai == pivot);
531 for (auto j = i + 1; j != end; j++) {
532 Clause *dj = *j;
533 int aj, bj, cj;
534 if (!get_ternary_clause (dj, aj, bj, cj))
535 continue;
536 if (bj == pivot)
537 swap (aj, bj);
538 if (cj == pivot)
539 swap (aj, cj);
540 CADICAL_assert (aj == pivot);
541 if (abs (bi) == abs (cj))
542 swap (bj, cj);
543 if (abs (ci) == abs (cj))
544 continue;
545 if (bi != -bj)
546 continue;
547 Clause *d1 = find_ternary_clause (-pivot, bi, -ci);
548 if (!d1)
549 continue;
550 Clause *d2 = find_ternary_clause (-pivot, bj, -cj);
551 if (!d2)
552 continue;
553 LOG (di, "1st if-then-else");
554 LOG (dj, "2nd if-then-else");
555 LOG (d1, "3rd if-then-else");
556 LOG (d2, "4th if-then-else");
557 LOG ("found ITE gate %d == (%d ? %d : %d)", pivot, -bi, -ci, -cj);
558 CADICAL_assert (!di->gate);
559 CADICAL_assert (!dj->gate);
560 CADICAL_assert (!d1->gate);
561 CADICAL_assert (!d2->gate);
562 di->gate = true;
563 dj->gate = true;
564 d1->gate = true;
565 d2->gate = true;
566 eliminator.gates.push_back (di);
567 eliminator.gates.push_back (dj);
568 eliminator.gates.push_back (d1);
569 eliminator.gates.push_back (d2);
570 stats.elimgates++;
571 stats.elimites++;
572 eliminator.gatetype = ITE;
573 return;
574 }
575 }
576}
bool get_ternary_clause(Clause *, int &, int &, int &)
Clause * find_ternary_clause(int, int, int)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_ternary_clause()

Clause * CaDiCaL::Internal::find_ternary_clause ( int a,
int b,
int c )

Definition at line 490 of file cadical_gates.cpp.

490 {
491 if (occs (b).size () > occs (c).size ())
492 swap (b, c);
493 if (occs (a).size () > occs (b).size ())
494 swap (a, b);
495 for (auto d : occs (a))
496 if (match_ternary_clause (d, a, b, c))
497 return d;
498 return 0;
499}
bool match_ternary_clause(Clause *, int, int, int)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_xor_gate()

void CaDiCaL::Internal::find_xor_gate ( Eliminator & eliminator,
int pivot )

Definition at line 636 of file cadical_gates.cpp.

636 {
637
638 if (!opts.elimxors)
639 return;
640
641 CADICAL_assert (opts.elimsubst);
642
643 if (unsat)
644 return;
645 if (val (pivot))
646 return;
647 if (!eliminator.gates.empty ())
648 return;
649
650 vector<int> lits;
651
652 for (auto d : occs (pivot)) {
653
654 if (!get_clause (d, lits))
655 continue;
656
657 const int size = lits.size (); // clause size
658 const int arity = size - 1; // arity of XOR
659
660 if (size < 3)
661 continue;
662 if (arity > opts.elimxorlim)
663 continue;
664
665 CADICAL_assert (eliminator.gates.empty ());
666
667 unsigned needed = (1u << arity) - 1; // additional clauses
668 unsigned signs = 0; // literals to negate
669
670 do {
671 const unsigned prev = signs;
672 while (parity (++signs))
673 ;
674 for (int j = 0; j < size; j++) {
675 const unsigned bit = 1u << j;
676 int lit = lits[j];
677 if ((prev & bit) != (signs & bit))
678 lits[j] = lit = -lit;
679 }
680 Clause *e = find_clause (lits);
681 if (!e)
682 break;
683 eliminator.gates.push_back (e);
684 } while (--needed);
685
686 if (needed) {
687 eliminator.gates.clear ();
688 continue;
689 }
690
691 eliminator.gates.push_back (d);
692 CADICAL_assert (eliminator.gates.size () == (1u << arity));
693
694#ifdef LOGGING
695 if (opts.log) {
696 Logger::print_log_prefix (this);
697 tout.magenta ();
698 printf ("found arity %u XOR gate %d = ", arity, -pivot);
699 bool first = true;
700 for (const auto &lit : *d) {
701 if (lit == pivot)
702 continue;
703 CADICAL_assert (lit != -pivot);
704 if (!first)
705 fputs (" ^ ", stdout);
706 printf ("%d", lit);
707 first = false;
708 }
709 fputc ('\n', stdout);
710 tout.normal ();
711 fflush (stdout);
712 }
713#endif
714 stats.elimgates++;
715 stats.elimxors++;
716 const auto end = eliminator.gates.end ();
717 auto j = eliminator.gates.begin ();
718 for (auto i = j; i != end; i++) {
719 Clause *e = *i;
720 if (e->gate)
721 continue;
722 e->gate = true;
723 LOG (e, "contributing");
724 *j++ = e;
725 }
726 eliminator.gates.resize (j - eliminator.gates.begin ());
727 eliminator.gatetype = XOR;
728 break;
729 }
730}
bool parity(unsigned a)
Definition util.hpp:71
bool get_clause(Clause *, vector< int > &)
Clause * find_clause(const vector< int > &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ finish_added_clause_with_id()

void CaDiCaL::Internal::finish_added_clause_with_id ( int64_t id,
bool restore = false )

Definition at line 219 of file cadical_internal.cpp.

219 {
220 if (proof) {
221 // Use the external form of the clause for printing in proof
222 // Externalize(internalized literal) != external literal
223 CADICAL_assert (!original.size () || !external->eclause.empty ());
224 proof->add_external_original_clause (id, false, external->eclause,
225 restore);
226 }
228 original.clear ();
229}
Here is the call graph for this function:

◆ first_factor()

size_t CaDiCaL::Internal::first_factor ( Factoring & factoring,
int factor )

Definition at line 184 of file cadical_factor.cpp.

184 {
186 Quotient *quotient = new_quotient (factoring, factor);
187 vector<Clause *> &qlauses = quotient->qlauses;
188 int64_t ticks = 0;
189 for (const auto &c : occs (factor)) {
190 qlauses.push_back (c);
191 ticks++;
192 }
193 size_t res = qlauses.size ();
194 LOG ("quotient[0] factor %d size %zu", factor, res);
195 // This invariant can of course be broken by previous factorings
196 // CADICAL_assert (res > 1);
197 stats.ticks.factor += ticks;
198 return res;
199}
struct quotient quotient
Definition factor.c:37
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fixed()

int CaDiCaL::Internal::fixed ( int lit)
inline

Definition at line 1542 of file internal.hpp.

1542 {
1546 const int idx = vidx (lit);
1547 int res = vals[idx];
1548 if (res && vtab[idx].level)
1549 res = 0;
1550 if (lit < 0)
1551 res = -res;
1552 return res;
1553 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ flags() [1/2]

Flags & CaDiCaL::Internal::flags ( int lit)
inline

Definition at line 454 of file internal.hpp.

454{ return ftab[vidx (lit)]; }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ flags() [2/2]

const Flags & CaDiCaL::Internal::flags ( int lit) const
inline

Definition at line 459 of file internal.hpp.

459{ return ftab[vidx (lit)]; }
Here is the call graph for this function:

◆ flip()

bool CaDiCaL::Internal::flip ( int lit)

Definition at line 9 of file cadical_flip.cpp.

9 {
10
11 // Do not try to flip inactive literals except for unused variables.
12
13 if (!active (lit) && !flags (lit).unused ())
14 return false;
15
16 /*
17 if (flags (lit).unused ()) {
18 CADICAL_assert (lit <= max_var);
19 mark_active (lit);
20 set_val (lit, 1);
21 return true;
22 }
23 */
24
25 // TODO: Unused case is not handled yet.
26 // if (flags (lit).unused ()) return false;
27
28 // Need to reestablish proper watching invariants as if there are no
29 // blocking literals as flipping in principle does not work with them.
30
31 if (propergated < trail.size ())
32 propergate ();
33
34 LOG ("trying to flip %d", lit);
35
36 const int idx = vidx (lit);
37 const signed char original_value = vals[idx];
38 CADICAL_assert (original_value);
39 lit = original_value < 0 ? -idx : idx;
40 CADICAL_assert (val (lit) > 0);
41
42 // Here we go over all the clauses in which 'lit' is watched by 'lit' and
43 // check whether assigning 'lit' to false would break watching invariants
44 // or even make the clause false. We also try to find replacement
45 // watches in case this fixes the watching invariant. This code is very
46 // similar to propagation of a literal in 'Internal::propagate'.
47
48 bool res = true;
49
50 Watches &ws = watches (lit);
51 const const_watch_iterator eow = ws.end ();
52 watch_iterator bow = ws.begin ();
53
54 // We first go over binary watches/clauses first as this is cheaper and
55 // has higher chance of failure and we can not use blocking literals.
56
57 for (const_watch_iterator i = bow; i != eow; i++) {
58 const Watch w = *i;
59 if (!w.binary ())
60 continue;
61 const signed char b = val (w.blit);
62 if (b > 0)
63 continue;
64 CADICAL_assert (b < 0);
65 res = false;
66 break;
67 }
68
69 if (res) {
71 watch_iterator j = bow;
72
73 while (i != eow) {
74
75 const Watch w = *j++ = *i++;
76
77 if (w.binary ())
78 continue;
79
80 if (w.clause->garbage) {
81 j--;
82 continue;
83 }
84
85 literal_iterator lits = w.clause->begin ();
86
87 const int other = lits[0] ^ lits[1] ^ lit;
88 const signed char u = val (other);
89 if (u > 0)
90 continue;
91
92 const int size = w.clause->size;
93 const literal_iterator middle = lits + w.clause->pos;
94 const const_literal_iterator end = lits + size;
95 literal_iterator k = middle;
96
97 int r = 0;
98 signed char v = -1;
99 while (k != end && (v = val (r = *k)) < 0)
100 k++;
101 if (v < 0) {
102 k = lits + 2;
103 CADICAL_assert (w.clause->pos <= size);
104 while (k != middle && (v = val (r = *k)) < 0)
105 k++;
106 }
107
108 if (v < 0) {
109 res = false;
110 break;
111 }
112
113 CADICAL_assert (v > 0);
114 CADICAL_assert (lits + 2 <= k), CADICAL_assert (k <= w.clause->end ());
115 w.clause->pos = k - lits;
116 lits[0] = other, lits[1] = r, *k = lit;
117 watch_literal (r, lit, w.clause);
118 j--;
119 }
120
121 if (j != i) {
122
123 while (i != eow)
124 *j++ = *i++;
125
126 ws.resize (j - ws.begin ());
127 }
128 }
129#ifdef LOGGING
130 if (res)
131 LOG ("literal %d can be flipped", lit);
132 else
133 LOG ("literal %d can not be flipped", lit);
134#endif
135
136 if (res) {
137
138 const int idx = vidx (lit);
139 const signed char original_value = vals[idx];
140 CADICAL_assert (original_value);
141 lit = original_value < 0 ? -idx : idx;
142 CADICAL_assert (val (lit) > 0);
143
144 LOG ("flipping value of %d = 1 to %d = -1", lit, lit);
145
146 set_val (idx, -original_value);
147 CADICAL_assert (val (-lit) > 0);
148 CADICAL_assert (val (lit) < 0);
149
150 Var &v = var (idx);
151 CADICAL_assert (trail[v.trail] == lit);
152 trail[v.trail] = -lit;
153 if (opts.ilb) {
154 if (!tainted_literal)
156 else {
158 if (v.level < var (tainted_literal).level) {
160 }
161 }
162 }
163 } else
164 LOG ("flipping value of %d failed", lit);
165
166 return res;
167}
Here is the call graph for this function:

◆ flip_backbone_literals()

void CaDiCaL::Internal::flip_backbone_literals ( struct Sweeper & sweeper)

Definition at line 774 of file cadical_sweep.cpp.

774 {
775 const unsigned max_rounds = opts.sweepfliprounds;
776 if (!max_rounds)
777 return;
779 if (cadical_kitten_status (citten) != 10)
780 return;
781#ifdef LOGGING
782 unsigned total_flipped = 0;
783#endif
784 unsigned flipped, round = 0;
785 do {
786 round++;
787 flipped = 0;
788 bool refine = false;
789 auto begin = sweeper.backbone.begin (), q = begin, p = q;
790 const auto end = sweeper.backbone.end ();
791 bool limit_hit = false;
792 while (p != end) {
793 const int lit = *p++;
794 stats.sweep_flip_backbone++;
795 if (limit_hit || terminated_asynchronously ()) {
796 break;
797 } else if (sweep_flip (lit)) {
798 LOG ("flipping backbone candidate %d succeeded", lit);
799#ifdef LOGGING
800 total_flipped++;
801#endif
802 stats.sweep_flipped_backbone++;
803 flipped++;
804 } else {
805 LOG ("flipping backbone candidate %d failed", lit);
806 *q++ = lit;
807 }
808 }
809 while (p != end)
810 *q++ = *p++;
811 sweeper.backbone.resize (q - sweeper.backbone.begin ());
812 LOG ("flipped %u backbone candidates in round %u", flipped, round);
813
814 if (limit_hit)
815 break;
817 break;
818 if (cadical_kitten_ticks_limit_hit (sweeper, "backbone flipping"))
819 break;
820 if (refine)
822 } while (flipped && round < max_rounds);
823 LOG ("flipped %u backbone candidates in total in %u rounds",
824 total_flipped, round);
825}
int cadical_kitten_status(cadical_kitten *cadical_kitten)
void sweep_refine(Sweeper &sweeper)
bool cadical_kitten_ticks_limit_hit(Sweeper &sweeper, const char *when)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ flip_partition_literals()

void CaDiCaL::Internal::flip_partition_literals ( struct Sweeper & sweeper)

Definition at line 1273 of file cadical_sweep.cpp.

1273 {
1274 const unsigned max_rounds = opts.sweepfliprounds;
1275 if (!max_rounds)
1276 return;
1278 if (cadical_kitten_status (citten) != 10)
1279 return;
1280#ifdef LOGGING
1281 unsigned total_flipped = 0;
1282#endif
1283 unsigned flipped, round = 0;
1284 do {
1285 round++;
1286 flipped = 0;
1287 bool refine = false;
1288 bool limit_hit = false;
1289 auto begin = sweeper.partition.begin (), dst = begin, src = dst;
1290 const auto end = sweeper.partition.end ();
1291 while (src != end) {
1292 auto end_src = src;
1293 while (CADICAL_assert (end_src != end), *end_src != 0)
1294 end_src++;
1295 unsigned size = end_src - src;
1296 CADICAL_assert (size > 1);
1297 auto q = dst;
1298 for (auto p = src; p != end_src; p++) {
1299 const int lit = *p;
1300 if (limit_hit) {
1301 *q++ = lit;
1302 continue;
1303 } else if (cadical_kitten_ticks_limit_hit (sweeper, "partition flipping")) {
1304 *q++ = lit;
1305 limit_hit = true;
1306 continue;
1307 } else if (sweep_flip (lit)) {
1308 LOG ("flipping equivalence candidate %d succeeded", lit);
1309#ifdef LOGGING
1310 total_flipped++;
1311#endif
1312 flipped++;
1313 if (--size < 2)
1314 break;
1315 } else {
1316 LOG ("flipping equivalence candidate %d failed", lit);
1317 *q++ = lit;
1318 }
1319 stats.sweep_flip_equivalences++;
1320 }
1321 if (size > 1) {
1322 *q++ = 0;
1323 dst = q;
1324 }
1325 src = end_src + 1;
1326 }
1327 stats.sweep_flipped_equivalences += flipped;
1328 sweeper.partition.resize (dst - sweeper.partition.begin ());
1329 LOG ("flipped %u equivalence candidates in round %u", flipped, round);
1331 break;
1332 if (cadical_kitten_ticks_limit_hit (sweeper, "partition flipping"))
1333 break;
1334 if (refine)
1336 } while (flipped && round < max_rounds);
1337 LOG ("flipped %u equivalence candidates in total in %u rounds",
1338 total_flipped, round);
1339}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ flippable()

bool CaDiCaL::Internal::flippable ( int lit)

Definition at line 169 of file cadical_flip.cpp.

169 {
170
171 // Can not check inactive literals except for unused variables.
172
173 if (!active (lit) && !flags (lit).unused ())
174 return false;
175
176 /*
177 if (flags (lit).unused ()) {
178 CADICAL_assert (lit <= max_var);
179 mark_active (lit);
180 return true;
181 }
182 */
183 // TODO: Unused case is not handled yet
184 // if (flags (lit).unused ()) return false;
185
186 // Need to reestablish proper watching invariants as if there are no
187 // blocking literals as flipping in principle does not work with them.
188
189 if (propergated < trail.size ())
190 propergate ();
191
192 LOG ("checking whether %d is flippable", lit);
193
194 const int idx = vidx (lit);
195 const signed char original_value = vals[idx];
196 CADICAL_assert (original_value);
197 lit = original_value < 0 ? -idx : idx;
198 CADICAL_assert (val (lit) > 0);
199
200 // Here we go over all the clauses in which 'lit' is watched by 'lit' and
201 // check whether assigning 'lit' to false would break watching invariants
202 // or even make the clause false. In contrast to 'flip' we do not try to
203 // find replacement literals but do use blocking literals'. Therefore we
204 // also do not split the traversal code into two parts.
205
206 bool res = true;
207
208 Watches &ws = watches (lit);
209 const const_watch_iterator eow = ws.end ();
210 for (watch_iterator i = ws.begin (); i != eow; i++) {
211
212 const Watch w = *i;
213 const signed char b = val (w.blit);
214 if (b > 0)
215 continue;
216 CADICAL_assert (b < 0);
217
218 if (w.binary ()) {
219 res = false;
220 break;
221 }
222
223 if (w.clause->garbage)
224 continue;
225
226 literal_iterator lits = w.clause->begin ();
227
228 const int other = lits[0] ^ lits[1] ^ lit;
229 const signed char u = val (other);
230 if (u > 0) {
231 i->blit = other;
232 continue;
233 }
234
235 const int size = w.clause->size;
236 const literal_iterator middle = lits + w.clause->pos;
237 const const_literal_iterator end = lits + size;
238 literal_iterator k = middle;
239
240 int r = 0;
241 signed char v = -1;
242 while (k != end && (v = val (r = *k)) < 0)
243 k++;
244 if (v < 0) {
245 k = lits + 2;
246 CADICAL_assert (w.clause->pos <= size);
247 while (k != middle && (v = val (r = *k)) < 0)
248 k++;
249 }
250
251 if (v < 0) {
252 res = false;
253 break;
254 }
255
256 CADICAL_assert (v > 0);
257 CADICAL_assert (lits + 2 <= k);
258 CADICAL_assert (k <= w.clause->end ());
259 w.clause->pos = k - lits;
260 i->blit = r;
261 }
262
263#ifdef LOGGING
264 if (res)
265 LOG ("literal %d can be flipped", lit);
266 else
267 LOG ("literal %d can not be flipped", lit);
268#endif
269
270 return res;
271}
Here is the call graph for this function:

◆ flush_all_occs_and_watches()

void CaDiCaL::Internal::flush_all_occs_and_watches ( )

Definition at line 232 of file cadical_collect.cpp.

232 {
233 if (occurring ())
234 for (auto idx : vars)
235 flush_occs (idx), flush_occs (-idx);
236
237 if (watching ()) {
238 Watches tmp;
239 for (auto idx : vars)
240 flush_watches (idx, tmp), flush_watches (-idx, tmp);
241 }
242}
void flush_watches(int lit, Watches &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ flush_elimfast_occs()

int64_t CaDiCaL::Internal::flush_elimfast_occs ( int lit)

Definition at line 19 of file cadical_elimfast.cpp.

19 {
20 const int64_t occslim = opts.fastelimbound;
21 const int64_t clslim = opts.fastelimocclim;
22 const int64_t failed = occslim + 1;
23 Occs &os = occs (lit);
24 const const_occs_iterator end = os.end ();
25 occs_iterator j = os.begin (), i = j;
26 int64_t res = 0;
27 while (i != end) {
28 Clause *c = *i++;
29 if (c->collect ())
30 continue;
31 *j++ = c;
32 if (c->size > clslim) {
33 res = failed;
34 break;
35 }
36 if (++res > occslim) {
37 CADICAL_assert (opts.fastelimbound < 0 || res == failed);
38 break;
39 }
40 }
41 if (i != j) {
42 while (i != end)
43 *j++ = *i++;
44 os.resize (j - os.begin ());
45 shrink_occs (os);
46 }
47 return res;
48}
Occs::iterator occs_iterator
Definition occs.hpp:35
void shrink_occs(Occs &os)
Definition occs.hpp:20
Occs::const_iterator const_occs_iterator
Definition occs.hpp:36
Here is the call graph for this function:
Here is the caller graph for this function:

◆ flush_occs()

size_t CaDiCaL::Internal::flush_occs ( int lit)

Definition at line 176 of file cadical_collect.cpp.

176 {
177 Occs &os = occs (lit);
178 const const_occs_iterator end = os.end ();
179 occs_iterator j = os.begin ();
181 size_t res = 0;
182 Clause *c;
183 for (i = j; i != end; i++) {
184 c = *i;
185 if (c->collect ())
186 continue;
187 *j++ = c->moved ? c->copy : c;
188 // CADICAL_assert (!c->redundant); // -> not true in sweeping
189 res++;
190 }
191 os.resize (j - os.begin ());
192 shrink_occs (os);
193 return res;
194}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ flush_probes()

void CaDiCaL::Internal::flush_probes ( )

Definition at line 702 of file cadical_probe.cpp.

702 {
703
704 CADICAL_assert (!probes.empty ());
705 int64_t &ticks = stats.ticks.probe;
706
707 init_noccs ();
708 ticks += 1 + cache_lines (clauses.size (), sizeof (Clause *));
709 for (const auto &c : clauses) {
710 int a, b;
711 ticks++;
712 if (!is_binary_clause (c, a, b))
713 continue;
714 noccs (a)++;
715 noccs (b)++;
716 }
717
718 const auto eop = probes.end ();
719 auto j = probes.begin ();
720 for (auto i = j; i != eop; i++) {
721 int lit = *i;
722 if (!active (lit))
723 continue;
724 ticks += 2;
725 const bool have_pos_bin_occs = noccs (lit) > 0;
726 const bool have_neg_bin_occs = noccs (-lit) > 0;
727 if (have_pos_bin_occs == have_neg_bin_occs)
728 continue;
729 if (have_pos_bin_occs)
730 lit = -lit;
732 if (propfixed (lit) >= stats.all.fixed)
733 continue;
734 LOG ("keeping probe %d negated occs %" PRId64 "", lit, noccs (-lit));
735 *j++ = lit;
736 }
737 size_t remain = j - probes.begin ();
738#ifndef CADICAL_QUIET
739 size_t flushed = probes.size () - remain;
740#endif
741 probes.resize (remain);
742
743 rsort (probes.begin (), probes.end (), probe_negated_noccs_rank (this));
744
745 reset_noccs ();
747
748 PHASE ("probe-round", stats.probingrounds,
749 "flushed %zd literals %.0f%% remaining %zd", flushed,
750 percent (flushed, remain + flushed), remain);
751}
int & propfixed(int lit)
Definition internal.hpp:456
bool is_binary_clause(Clause *c, int &, int &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ flush_trace()

void CaDiCaL::Internal::flush_trace ( bool stats = false)

Definition at line 195 of file cadical_proof.cpp.

195 {
196 for (auto &tracer : file_tracers)
197 tracer->flush (print);
198}

◆ flush_unmatched_clauses()

void CaDiCaL::Internal::flush_unmatched_clauses ( Quotient * q)

Definition at line 479 of file cadical_factor.cpp.

479 {
480 Quotient *prev = q->prev;
481 vector<size_t> &q_matches = q->matches, &prev_matches = prev->matches;
482 vector<Clause *> &q_clauses = q->qlauses, &prev_clauses = prev->qlauses;
483 const size_t n = q_clauses.size ();
484 CADICAL_assert (n == q_matches.size ());
485 bool prev_is_first = !prev->id;
486 size_t i = 0;
487 while (i < q_matches.size ()) {
488 size_t j = q_matches[i];
489 q_matches[i] = i;
490 CADICAL_assert (i <= j);
491 if (!prev_is_first) {
492 size_t matches = prev_matches[j];
493 prev_matches[i] = matches;
494 }
495 Clause *c = prev_clauses[j];
496 prev_clauses[i] = c;
497 i++;
498 }
499 LOG ("flushing %zu clauses of quotient[%zu]", prev_clauses.size () - n,
500 prev->id);
501 if (!prev_is_first)
502 prev_matches.resize (n);
503 prev_clauses.resize (n);
504}
Here is the caller graph for this function:

◆ flush_vivification_schedule()

void CaDiCaL::Internal::flush_vivification_schedule ( std::vector< Clause * > & schedule,
int64_t & ticks )

Definition at line 456 of file cadical_vivify.cpp.

457 {
458 ticks += 1 + 3 * cache_lines (schedule.size (), sizeof (Clause *));
459 stable_sort (schedule.begin (), schedule.end (), vivify_flush_smaller ());
460
461 const auto end = schedule.end ();
462 auto j = schedule.begin (), i = j;
463
464 Clause *prev = 0;
465 int64_t subsumed = 0;
466 for (; i != end; i++) {
467 ticks++;
468 Clause *c = *j++ = *i;
469 if (!prev || c->size < prev->size) {
470 prev = c;
471 continue;
472 }
473 const auto eop = prev->end ();
474 auto k = prev->begin ();
475 for (auto l = c->begin (); k != eop; k++, l++)
476 if (*k != *l)
477 break;
478 if (k == eop) {
479 LOG (c, "found subsumed");
480 LOG (prev, "subsuming");
481 CADICAL_assert (!c->garbage);
482 CADICAL_assert (!prev->garbage);
483 CADICAL_assert (c->redundant || !prev->redundant);
484 mark_garbage (c);
485 subsumed++;
486 j--;
487 } else
488 prev = c;
489 }
490
491 if (subsumed)
492 PHASE ("vivify", stats.vivifications,
493 "flushed %" PRId64 " subsumed scheduled clauses", subsumed);
494
495 stats.vivifysubs += subsumed;
496
497 if (subsumed) {
498 schedule.resize (j - schedule.begin ());
499 shrink_vector (schedule);
500 } else
501 CADICAL_assert (j == end);
502}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ flush_watches()

void CaDiCaL::Internal::flush_watches ( int lit,
Watches & saved )
inline

Definition at line 202 of file cadical_collect.cpp.

202 {
203 CADICAL_assert (saved.empty ());
204 Watches &ws = watches (lit);
205 const const_watch_iterator end = ws.end ();
206 watch_iterator j = ws.begin ();
208 for (i = j; i != end; i++) {
209 Watch w = *i;
210 Clause *c = w.clause;
211 if (c->collect ())
212 continue;
213 if (c->moved)
214 c = w.clause = c->copy;
215 w.size = c->size;
216 const int new_blit_pos = (c->literals[0] == lit);
217 LOG (c, "clause in flush_watch starting from %d", lit);
218 CADICAL_assert (c->literals[!new_blit_pos] == lit); /*FW1*/
219 w.blit = c->literals[new_blit_pos];
220 if (w.binary ())
221 *j++ = w;
222 else
223 saved.push_back (w);
224 }
225 ws.resize (j - ws.begin ());
226 for (const auto &w : saved)
227 ws.push_back (w);
228 saved.clear ();
229 shrink_vector (ws);
230}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ flushing()

bool CaDiCaL::Internal::flushing ( )

Definition at line 30 of file cadical_reduce.cpp.

30 {
31 if (!opts.flush)
32 return false;
33 return stats.conflicts >= lim.flush;
34}
Here is the caller graph for this function:

◆ force_backtrack()

void CaDiCaL::Internal::force_backtrack ( size_t new_level)

Definition at line 214 of file cadical_external_propagate.cpp.

214 {
216 return;
217
218#ifndef CADICAL_NDEBUG
219 LOG ("external propagator forces backtrack to decision level"
220 "%zd (from level %d)",
221 new_level, level);
222#endif
223 backtrack (new_level);
224}
Here is the call graph for this function:

◆ force_lrat()

void CaDiCaL::Internal::force_lrat ( )

Definition at line 27 of file cadical_proof.cpp.

27 {
28 if (lrat)
29 return;
31 lrat = true;
32}
Here is the caller graph for this function:

◆ forward_false_satisfiable()

int CaDiCaL::Internal::forward_false_satisfiable ( )

Definition at line 154 of file cadical_lucky.cpp.

154 {
155 LOG ("checking increasing variable index false assignment");
158 CADICAL_assert (assumptions.empty ());
159 for (auto idx : vars) {
160 START:
162 return unlucky (-1);
163 if (val (idx))
164 continue;
165 if (lucky_propagate_discrepency (-idx)) {
166 if (unsat)
167 return 20;
168 else
169 return unlucky (0);
170 } else
171 goto START;
172 }
173 VERBOSE (1, "forward assuming variables false satisfies formula");
175 stats.lucky.forward.zero++;
176 return 10;
177}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ forward_true_satisfiable()

int CaDiCaL::Internal::forward_true_satisfiable ( )

Definition at line 179 of file cadical_lucky.cpp.

179 {
180 LOG ("checking increasing variable index true assignment");
183 CADICAL_assert (assumptions.empty ());
184 for (auto idx : vars) {
185 START:
187 return unlucky (-1);
188 if (val (idx))
189 continue;
190 if (lucky_propagate_discrepency (idx)) {
191 if (unsat)
192 return 20;
193 else
194 return unlucky (0);
195 } else
196 goto START;
197 }
198 VERBOSE (1, "forward assuming variables true satisfies formula");
200 stats.lucky.forward.one++;
201 return 10;
202}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freeze()

void CaDiCaL::Internal::freeze ( int lit)
inline

Definition at line 1570 of file internal.hpp.

1570 {
1571 int idx = vidx (lit);
1572 if ((size_t) idx >= frozentab.size ()) {
1573 size_t new_vsize = vsize ? 2 * vsize : 1 + (size_t) max_var;
1574 while (new_vsize <= (size_t) max_var)
1575 new_vsize *= 2;
1576 frozentab.resize (new_vsize);
1577 }
1578 unsigned &ref = frozentab[idx];
1579 if (ref < UINT_MAX) {
1580 ref++;
1581 LOG ("variable %d frozen %u times", idx, ref);
1582 } else
1583 LOG ("variable %d remains frozen forever", idx);
1584 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ frozen()

bool CaDiCaL::Internal::frozen ( int lit)
inline

Definition at line 1602 of file internal.hpp.

1602 {
1603 return (size_t) vidx (lit) < frozentab.size () &&
1604 frozentab[vidx (lit)] > 0;
1605 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ garbage_collection()

void CaDiCaL::Internal::garbage_collection ( )

Definition at line 529 of file cadical_collect.cpp.

529 {
530 if (unsat)
531 return;
532 START (collect);
533 report ('G', 1);
534 stats.collections++;
538 if (arenaing ())
540 else
545 report ('C', 1);
546 STOP (collect);
547}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ generate_cubes()

CubesWithStatus CaDiCaL::Internal::generate_cubes ( int depth,
int min_depth )

Definition at line 408 of file cadical_lookahead.cpp.

408 {
409 if (!active () || depth == 0) {
410 CubesWithStatus cubes;
411 cubes.status = 0;
412 cubes.cubes.push_back (std::vector<int> ());
413 return cubes;
414 }
415
416 lookingahead = true;
418 MSG ("Generating cubes of depth %i", depth);
419
420 // presimplify required due to assumptions
421
422 termination_forced = false;
423 int res = already_solved ();
424 if (res == 0)
425 res = restore_clauses ();
426 if (unsat)
427 res = 10;
428 if (res != 0)
429 res = solve (true);
430 if (res != 0) {
431 MSG ("Solved during preprocessing");
432 CubesWithStatus cubes;
433 cubes.status = res;
434 lookingahead = false;
435 STOP (lookahead);
436 return cubes;
437 }
438
439 reset_limits ();
440 MSG ("generate cubes with %zu assumptions\n", assumptions.size ());
441
442 CADICAL_assert (ntab.empty ());
443 std::vector<int> current_assumptions{assumptions};
444 std::vector<std::vector<int>> cubes{{assumptions}};
445 auto loccs{lookahead_populate_locc ()};
446 LOG ("loccs populated\n");
447 CADICAL_assert (ntab.empty ());
448
449 for (int i = 0; i < depth; ++i) {
450 LOG ("Probing at depth %i, currently %zu have been generated", i,
451 cubes.size ());
452 std::vector<std::vector<int>> cubes2{std::move (cubes)};
453 cubes.clear ();
454
455 for (size_t j = 0; j < cubes2.size (); ++j) {
456 CADICAL_assert (ntab.empty ());
459 for (auto lit : cubes2[j])
460 assume (lit);
462 propagate ();
463 // preprocess_round(0); //uncomment maybe
464
465 if (unsat) {
466 LOG ("current cube is unsat; skipping");
467 unsat = false;
468 continue;
469 }
470
471 int res = terminating_asked () ? lookahead_locc (loccs)
473 if (unsat) {
474 LOG ("current cube is unsat; skipping");
475 unsat = false;
476 continue;
477 }
478
479 if (res == 0) {
480 LOG ("no lit to split %i", res);
481 cubes.push_back (cubes2[j]);
482 continue;
483 }
484
485 CADICAL_assert (res != 0);
486 LOG ("splitting on lit %i", res);
487 std::vector<int> cube1{cubes2[j]};
488 cube1.push_back (res);
489 std::vector<int> cube2{std::move (cubes2[j])};
490 cube2.push_back (-res);
491 cubes.push_back (cube1);
492 cubes.push_back (cube2);
493 }
494
495 if (terminating_asked () && i >= min_depth)
496 break;
497 }
498
499 CADICAL_assert (std::for_each (
500 std::begin (cubes), std::end (cubes),
501 [] (std::vector<int> cube) { return non_tautological_cube (cube); }));
503
504 for (auto lit : current_assumptions)
505 assume (lit);
506
507 STOP (lookahead);
508 lookingahead = false;
509
510 if (unsat) {
511 LOG ("Solved during preprocessing");
512 CubesWithStatus cubes;
513 cubes.status = 20;
514 return cubes;
515 }
516
517 CubesWithStatus rcubes;
518 rcubes.status = 0;
519 rcubes.cubes = cubes;
520
521 return rcubes;
522}
#define MSG(...)
Definition message.hpp:49
bool non_tautological_cube(std::vector< int > cube)
std::vector< int > lookahead_populate_locc()
int solve(bool preprocess_only=false)
int lookahead_locc(const std::vector< int > &)
Here is the call graph for this function:

◆ generate_probes()

void CaDiCaL::Internal::generate_probes ( )

Definition at line 637 of file cadical_probe.cpp.

637 {
638
639 CADICAL_assert (probes.empty ());
640
641 int64_t &ticks = stats.ticks.probe;
642
643 // First determine all the literals which occur in binary clauses. It is
644 // way faster to go over the clauses once, instead of walking the watch
645 // lists for each literal.
646 //
647 init_noccs ();
648 ticks += 1 + cache_lines (clauses.size (), sizeof (Clause *));
649 for (const auto &c : clauses) {
650 int a, b;
651 ticks++;
652 if (!is_binary_clause (c, a, b))
653 continue;
654 noccs (a)++;
655 noccs (b)++;
656 }
657
658 for (auto idx : vars) {
659
660 // Then focus on roots of the binary implication graph, which are
661 // literals occurring negatively in a binary clause, but not positively.
662 // If neither 'idx' nor '-idx' is a root it makes less sense to probe
663 // this variable.
664
665 // This argument requires that equivalent literal substitution through
666 // 'decompose' is performed, because otherwise there might be 'cyclic
667 // roots' which are not tried, i.e., -1 2 0, 1 -2 0, 1 2 3 0, 1 2 -3 0.
668
669 ticks += 2;
670
671 const bool have_pos_bin_occs = noccs (idx) > 0;
672 const bool have_neg_bin_occs = noccs (-idx) > 0;
673
674 if (have_pos_bin_occs == have_neg_bin_occs)
675 continue;
676
677 int probe = have_neg_bin_occs ? idx : -idx;
678
679 // See the discussion where 'propfixed' is used below.
680 //
681 if (propfixed (probe) >= stats.all.fixed)
682 continue;
683
684 LOG ("scheduling probe %d negated occs %" PRId64 "", probe,
685 noccs (-probe));
686 probes.push_back (probe);
687 }
688
689 rsort (probes.begin (), probes.end (), probe_negated_noccs_rank (this));
690
691 reset_noccs ();
693
694 PHASE ("probe-round", stats.probingrounds,
695 "scheduled %zd literals %.0f%%", probes.size (),
696 percent (probes.size (), 2u * max_var));
697}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_clause()

bool CaDiCaL::Internal::get_clause ( Clause * c,
vector< int > & l )

Definition at line 582 of file cadical_gates.cpp.

582 {
583 if (c->garbage)
584 return false;
585 l.clear ();
586 for (const auto &lit : *c) {
587 if (val (lit) < 0)
588 continue;
589 if (val (lit) > 0) {
590 l.clear ();
591 return false;
592 }
593 l.push_back (lit);
594 }
595 return true;
596}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_new_extension_variable()

int CaDiCaL::Internal::get_new_extension_variable ( )

Definition at line 845 of file cadical_factor.cpp.

845 {
846 const int current_max_external = external->max_var;
847 const int new_external = current_max_external + 1;
848 const int new_internal = external->internalize (new_external, true);
849 // one sideeffect of internalize is enlarging the internal datastructures
850 // which can initialize the watches (wtab)
851 if (watching ())
852 reset_watches ();
853 // it does not enlarge otab, however, so we do this manually
854 init_occs ();
855 CADICAL_assert (vlit (new_internal));
856 return new_internal;
857}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_parent_reason_literal()

int CaDiCaL::Internal::get_parent_reason_literal ( int lit)
inline

Definition at line 34 of file cadical_probe.cpp.

34 {
35 const int idx = vidx (lit);
36 int res = parents[idx];
37 if (lit < 0)
38 res = -res;
39 return res;
40}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_probehbr_lrat()

void CaDiCaL::Internal::get_probehbr_lrat ( int lit,
int uip )

Definition at line 90 of file cadical_probe.cpp.

90 {
91 if (!lrat || opts.probehbr)
92 return;
94 CADICAL_assert (lrat_chain.empty ());
95 CADICAL_assert (val (uip) < 0);
97 int64_t id = unit_id (-uip);
98 lrat_chain.push_back (id);
99}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_ternary_clause()

bool CaDiCaL::Internal::get_ternary_clause ( Clause * d,
int & a,
int & b,
int & c )

Definition at line 452 of file cadical_gates.cpp.

452 {
453 if (d->garbage)
454 return false;
455 if (d->size < 3)
456 return false;
457 int found = 0;
458 a = b = c = 0;
459 for (const auto &lit : *d) {
460 if (val (lit))
461 continue;
462 if (++found == 1)
463 a = lit;
464 else if (found == 2)
465 b = lit;
466 else if (found == 3)
467 c = lit;
468 else
469 return false;
470 }
471 return found == 3;
472}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ getbit()

bool CaDiCaL::Internal::getbit ( int lit,
int bit ) const
inline

Definition at line 536 of file internal.hpp.

536 {
537 CADICAL_assert (0 <= bit), CADICAL_assert (bit < 6);
538 return marks[vidx (lit)] & (1 << bit);
539 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ getfact()

bool CaDiCaL::Internal::getfact ( int lit,
int fact ) const
inline

Definition at line 568 of file internal.hpp.

568 {
569 CADICAL_assert (fact == 1 || fact == 2 || fact == 4);
570 int res = marks[vidx (lit)];
571 if (lit < 0) {
572 res >>= 3;
573 } else {
574 res &= 7;
575 }
576 // CADICAL_assert (!res || res == 1 || res == 2 || res == 4);
577 return res & fact;
578 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_external_clause()

void CaDiCaL::Internal::handle_external_clause ( Clause * res)

Definition at line 744 of file cadical_external_propagate.cpp.

744 {
745 if (from_propagator)
746 stats.ext_prop.elearned++;
747 // at level 0 we have to do nothing...
748 if (!level)
749 return;
750 if (!res) {
751 if (from_propagator)
752 stats.ext_prop.elearn_prop++;
753 // new unit clause. For now just backtrack.
756 // if (!opts.chrono) {
757 backtrack ();
758 // }
759 return;
760 }
761 if (from_propagator)
762 stats.ext_prop.elearned++;
763 CADICAL_assert (res->size >= 2);
764 const int pos0 = res->literals[0];
765 const int pos1 = res->literals[1];
766 if (force_no_backtrack) {
767 CADICAL_assert (val (pos1) < 0);
768 CADICAL_assert (val (pos0) >= 0);
769 return;
770 // TODO: maybe fix levels
771 }
772 const int l1 = var (pos1).level;
773 if (val (pos0) < 0) { // conflicting or propagating clause
774 CADICAL_assert (0 < l1 && l1 <= var (pos0).level);
775 if (!opts.chrono) {
776 backtrack (l1);
777 }
778 if (val (pos0) < 0) {
779 conflict = res;
780 if (!from_propagator) {
781 // its better to backtrack instead of analyze
782 backtrack (l1 - 1);
783 conflict = 0;
784 CADICAL_assert (!val (pos0) && !val (pos1));
785 }
786 } else {
787 search_assign_driving (pos0, res);
788 }
789 if (from_propagator)
790 stats.ext_prop.elearn_conf++;
791 return;
792 }
793 if (val (pos1) < 0 && !val (pos0)) { // propagating clause
794 if (!opts.chrono) {
795 backtrack (l1);
796 }
797 search_assign_driving (pos0, res);
798 if (from_propagator)
799 stats.ext_prop.elearn_conf++;
800 return;
801 }
802}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hyper_binary_resolve()

int CaDiCaL::Internal::hyper_binary_resolve ( Clause * reason)
inline

Definition at line 222 of file cadical_probe.cpp.

222 {
224 CADICAL_assert (level == 1);
225 CADICAL_assert (reason->size > 2);
226 const const_literal_iterator end = reason->end ();
227 const int *lits = reason->literals;
229#ifndef CADICAL_NDEBUG
230 // First literal unassigned, all others false.
231 CADICAL_assert (!val (lits[0]));
232 for (k = lits + 1; k != end; k++)
233 CADICAL_assert (val (*k) < 0);
234 CADICAL_assert (var (lits[1]).level == 1);
235#endif
236 LOG (reason, "hyper binary resolving");
237 stats.hbrs++;
238 stats.hbrsizes += reason->size;
239 const int lit = lits[1];
240 int dom = -lit, non_root_level_literals = 0;
241 for (k = lits + 2; k != end; k++) {
242 const int other = -*k;
243 CADICAL_assert (val (other) > 0);
244 if (!var (other).level)
245 continue;
246 dom = probe_dominator (dom, other);
247 non_root_level_literals++;
248 }
249 probe_reason = reason;
250 if (non_root_level_literals && opts.probehbr) { // !(A)
251 bool contained = false;
252 for (k = lits + 1; !contained && k != end; k++)
253 contained = (*k == -dom);
254 const bool red = !contained || reason->redundant;
255 if (red)
256 stats.hbreds++;
257 LOG ("new %s hyper binary resolvent %d %d",
258 (red ? "redundant" : "irredundant"), -dom, lits[0]);
259 CADICAL_assert (clause.empty ());
260 clause.push_back (-dom);
261 clause.push_back (lits[0]);
262 probe_dominator_lrat (dom, reason);
263 if (lrat)
265 Clause *c = new_hyper_binary_resolved_clause (red, 2);
266 probe_reason = c;
267 if (red)
268 c->hyper = true;
269 clause.clear ();
270 lrat_chain.clear ();
271 if (contained) {
272 stats.hbrsubs++;
273 LOG (reason, "subsumed original");
274 mark_garbage (reason);
275 }
276 } else if (non_root_level_literals && lrat) {
277 // still calculate LRAT and remember for later
278 CADICAL_assert (!opts.probehbr);
279 probe_dominator_lrat (dom, reason);
281 set_probehbr_lrat (dom, lits[0]);
282 }
283 return dom;
284}
bool contained(int64_t c, int64_t l, int64_t u)
Definition util.hpp:49
Clause * new_hyper_binary_resolved_clause(bool red, int glue)
void set_probehbr_lrat(int lit, int uip)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hyper_ternary_resolve()

bool CaDiCaL::Internal::hyper_ternary_resolve ( Clause * c,
int pivot,
Clause * d )

Definition at line 113 of file cadical_ternary.cpp.

113 {
114 LOG ("hyper binary resolving on pivot %d", pivot);
115 LOG (c, "1st antecedent");
116 LOG (d, "2nd antecedent");
117 stats.ternres++;
118 CADICAL_assert (c->size == 3);
119 CADICAL_assert (d->size == 3);
120 CADICAL_assert (clause.empty ());
121 for (const auto &lit : *c)
122 if (lit != pivot)
123 clause.push_back (lit);
124 for (const auto &lit : *d) {
125 if (lit == -pivot)
126 continue;
127 if (lit == clause[0])
128 continue;
129 if (lit == -clause[0])
130 return false;
131 if (lit == clause[1])
132 continue;
133 if (lit == -clause[1])
134 return false;
135 clause.push_back (lit);
136 }
137 size_t size = clause.size ();
138 if (size > 3)
139 return false;
140 if (size == 2 && ternary_find_binary_clause (clause[0], clause[1]))
141 return false;
142 if (size == 3 &&
144 return false;
145 return true;
146}
bool ternary_find_binary_clause(int, int)
bool ternary_find_ternary_clause(int, int, int)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ implied()

void CaDiCaL::Internal::implied ( std::vector< int > & entrailed)

Definition at line 418 of file cadical_internal.cpp.

418 {
419 int last_assumption_level = assumptions.size ();
420 if (constraint.size ())
421 last_assumption_level++;
422
423 size_t trail_limit = trail.size();
424 if (level > last_assumption_level)
425 trail_limit = control[last_assumption_level + 1].trail;
426
427 for (size_t i = 0; i < trail_limit; i++)
428 entrailed.push_back (trail[i]);
429}
Here is the caller graph for this function:

◆ in_mode()

bool CaDiCaL::Internal::in_mode ( Mode m) const
inline

Definition at line 164 of file internal.hpp.

164{ return (mode & m) != 0; }

◆ incomplete_variables()

unsigned CaDiCaL::Internal::incomplete_variables ( )

Definition at line 1793 of file cadical_sweep.cpp.

1793 {
1794 unsigned res = 0;
1795 for (const auto &idx : vars) {
1796 Flags &f = flags (idx);
1797 if (!f.active ())
1798 continue;
1799 if (f.sweep)
1800 res++;
1801 }
1802 return res;
1803}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ increase_elimination_bound()

void CaDiCaL::Internal::increase_elimination_bound ( )

Definition at line 966 of file cadical_elim.cpp.

966 {
967
968 if (lim.elimbound >= opts.elimboundmax)
969 return;
970
971 if (lim.elimbound < 0)
972 lim.elimbound = 0;
973 else if (!lim.elimbound)
974 lim.elimbound = 1;
975 else
976 lim.elimbound *= 2;
977
978 if (lim.elimbound > opts.elimboundmax)
979 lim.elimbound = opts.elimboundmax;
980
981 PHASE ("elim-phase", stats.elimphases,
982 "new elimination bound %" PRId64 "", lim.elimbound);
983
984 // Now reschedule all active variables for elimination again.
985 //
986#ifdef LOGGING
987 int count = 0;
988#endif
989 for (auto idx : vars) {
990 if (!active (idx))
991 continue;
992 if (flags (idx).elim)
993 continue;
994 mark_elim (idx);
995#ifdef LOGGING
996 count++;
997#endif
998 }
999 LOG ("marked %d variables as elimination candidates", count);
1000
1001 report ('^');
1002}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ineliminating()

bool CaDiCaL::Internal::ineliminating ( )

Definition at line 65 of file cadical_elim.cpp.

65 {
66
67 if (!opts.elim)
68 return false;
69 if (!preprocessing && !opts.inprocessing)
70 return false;
71 if (preprocessing)
72 CADICAL_assert (lim.preprocessing);
73
74 // Respect (increasing) conflict limit.
75 //
76 if (lim.elim >= stats.conflicts)
77 return false;
78
79 // Wait until there are new units or new removed variables
80 // (in removed or shrunken irredundant clauses and thus marked).
81 //
82 if (last.elim.fixed < stats.all.fixed)
83 return true;
84 if (last.elim.marked < stats.mark.elim)
85 return true;
86
87 // VERBOSE (3, "elim not scheduled due to fixpoint");
88 return false;
89}
Here is the caller graph for this function:

◆ init_averages()

void CaDiCaL::Internal::init_averages ( )

Definition at line 9 of file cadical_averages.cpp.

9 {
10
11 LOG ("initializing averages");
12
13 INIT_EMA (averages.current.jump, opts.emajump);
14 INIT_EMA (averages.current.level, opts.emalevel);
15 INIT_EMA (averages.current.size, opts.emasize);
16
17 INIT_EMA (averages.current.glue.fast, opts.emagluefast);
18 INIT_EMA (averages.current.glue.slow, opts.emaglueslow);
19
20 INIT_EMA (averages.current.decisions, opts.emadecisions);
21
22 INIT_EMA (averages.current.trail.fast, opts.ematrailfast);
23 INIT_EMA (averages.current.trail.slow, opts.ematrailslow);
24
25 CADICAL_assert (!averages.swapped);
26}
Here is the caller graph for this function:

◆ init_backbone_and_partition()

void CaDiCaL::Internal::init_backbone_and_partition ( Sweeper & sweeper)

Definition at line 632 of file cadical_sweep.cpp.

632 {
633 LOG ("initializing backbone and equivalent literals candidates");
634 sweeper.backbone.clear ();
635 sweeper.partition.clear ();
636 for (const auto &idx : sweeper.vars) {
637 if (!active (idx))
638 continue;
639 CADICAL_assert (idx > 0);
640 const int lit = idx;
641 const int not_lit = -lit;
642 const signed char tmp = cadical_kitten_signed_value (citten, lit);
643 const int candidate = (tmp < 0) ? not_lit : lit;
644 LOG ("sweeping candidate %d", candidate);
645 sweeper.backbone.push_back (candidate);
646 sweeper.partition.push_back (candidate);
647 }
648 sweeper.partition.push_back (0);
649
650 LOG (sweeper.backbone, "initialized backbone candidates");
651 LOG (sweeper.partition, "initialized equivalence candidates");
652}
signed char cadical_kitten_signed_value(cadical_kitten *cadical_kitten, int selit)
struct candidate candidate
Definition fastel.c:819
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_bins()

void CaDiCaL::Internal::init_bins ( )

Definition at line 13 of file cadical_bins.cpp.

13 {
14 CADICAL_assert (big.empty ());
15 if (big.size () < 2 * vsize)
16 big.resize (2 * vsize, Bins ());
17 LOG ("initialized binary implication graph");
18}
vector< Bin > Bins
Definition bins.hpp:19
Here is the caller graph for this function:

◆ init_citten()

void CaDiCaL::Internal::init_citten ( )

Definition at line 1004 of file cadical_elim.cpp.

1004 {
1005 if (!opts.elimdef)
1006 return;
1009}
cadical_kitten * cadical_kitten_init(void)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_enqueue()

void CaDiCaL::Internal::init_enqueue ( int idx)
inline

Definition at line 12 of file cadical_queue.cpp.

12 {
13 Link &l = links[idx];
14 if (opts.reverse) {
15 l.prev = 0;
16 if (queue.first) {
17 CADICAL_assert (!links[queue.first].prev);
18 links[queue.first].prev = idx;
19 btab[idx] = btab[queue.first] - 1;
20 } else {
21 CADICAL_assert (!queue.last);
22 queue.last = idx;
23 btab[idx] = 0;
24 }
25 CADICAL_assert (btab[idx] <= stats.bumped);
26 l.next = queue.first;
27 queue.first = idx;
28 if (!queue.unassigned)
30 } else {
31 l.next = 0;
32 if (queue.last) {
33 CADICAL_assert (!links[queue.last].next);
34 links[queue.last].next = idx;
35 } else {
36 CADICAL_assert (!queue.first);
37 queue.first = idx;
38 }
39 btab[idx] = ++stats.bumped;
40 l.prev = queue.last;
41 queue.last = idx;
43 }
44}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_noccs()

void CaDiCaL::Internal::init_noccs ( )

Definition at line 36 of file cadical_occs.cpp.

36 {
37 CADICAL_assert (ntab.empty ());
38 if (ntab.size () < 2 * vsize)
39 ntab.resize (2 * vsize, 0);
40 LOG ("initialized two-sided occurrence counters");
41}
Here is the caller graph for this function:

◆ init_occs()

void CaDiCaL::Internal::init_occs ( )

Definition at line 13 of file cadical_occs.cpp.

13 {
14 if (otab.size () < 2 * vsize)
15 otab.resize (2 * vsize, Occs ());
16 LOG ("initialized occurrence lists");
17}
Here is the caller graph for this function:

◆ init_preprocessing_limits()

void CaDiCaL::Internal::init_preprocessing_limits ( )

Definition at line 443 of file cadical_internal.cpp.

443 {
444
445 const bool incremental = lim.initialized;
446 if (incremental)
447 LOG ("reinitializing preprocessing limits incrementally");
448 else
449 LOG ("initializing preprocessing limits and increments");
450
451 const char *mode = 0;
452
453 /*----------------------------------------------------------------------*/
454
455 if (incremental)
456 mode = "keeping";
457 else {
458 last.elim.marked = -1;
459 lim.elim = stats.conflicts + scale (opts.elimint);
460 mode = "initial";
461 }
462 (void) mode;
463 LOG ("%s elim limit %" PRId64 " after %" PRId64 " conflicts", mode,
464 lim.elim, lim.elim - stats.conflicts);
465
466 // Initialize and reset elimination bounds in any case.
467
468 lim.elimbound = opts.elimboundmin;
469 LOG ("elimination bound %" PRId64 "", lim.elimbound);
470
471 /*----------------------------------------------------------------------*/
472
473 if (!incremental) {
474
475 last.ternary.marked = -1; // TODO this should not be necessary...
476
477 lim.compact = stats.conflicts + opts.compactint;
478 LOG ("initial compact limit %" PRId64 " increment %" PRId64 "",
479 lim.compact, lim.compact - stats.conflicts);
480 }
481
482 /*----------------------------------------------------------------------*/
483
484 if (incremental)
485 mode = "keeping";
486 else {
487 double delta = log10 (stats.added.irredundant);
488 delta = delta * delta;
489 lim.inprobe = stats.conflicts + opts.inprobeint * delta;
490 mode = "initial";
491 }
492 (void) mode;
493 LOG ("%s probe limit %" PRId64 " after %" PRId64 " conflicts", mode,
494 lim.inprobe, lim.inprobe - stats.conflicts);
495
496 /*----------------------------------------------------------------------*/
497
498 if (incremental)
499 mode = "keeping";
500 else {
501 lim.condition = stats.conflicts + opts.conditionint;
502 mode = "initial";
503 }
504 LOG ("%s condition limit %" PRId64 " increment %" PRId64, mode,
505 lim.condition, lim.condition - stats.conflicts);
506
507 /*----------------------------------------------------------------------*/
508
509 // Initial preprocessing rounds.
510
511 if (inc.preprocessing <= 0) {
512 lim.preprocessing = 0;
513 LOG ("no preprocessing");
514 } else {
515 lim.preprocessing = inc.preprocessing;
516 LOG ("limiting to %" PRId64 " preprocessing rounds", lim.preprocessing);
517 }
518}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_probehbr_lrat()

void CaDiCaL::Internal::init_probehbr_lrat ( )

Definition at line 70 of file cadical_probe.cpp.

70 {
71 if (!lrat || opts.probehbr)
72 return;
73 const size_t size = 2 * (1 + (size_t) max_var);
74 probehbr_chains.resize (size);
75 for (size_t i = 0; i < size; i++) {
76 probehbr_chains[i].resize (size);
77 // commented because not needed... should be empty already
78 /*
79 for (size_t j = 0; j < size; j++) {
80 vector<int64_t> empty;
81 probehbr_chains[i][j] = empty;
82 }
83 */
84 }
85}
Here is the caller graph for this function:

◆ init_queue()

void CaDiCaL::Internal::init_queue ( int old_max_var,
int new_max_var )

Definition at line 51 of file cadical_queue.cpp.

51 {
52 LOG ("initializing VMTF queue from %d to %d", old_max_var + 1,
53 new_max_var);
54 CADICAL_assert (old_max_var < new_max_var);
55 // New variables can be created that can invoke enlarge anytime (eg via
56 // calls during ipasir-up call-backs), thus assuming (!level) is not
57 // correct
58 for (int idx = old_max_var; idx < new_max_var; idx++)
59 init_enqueue (idx + 1);
60}
void init_enqueue(int idx)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_report_limits()

void CaDiCaL::Internal::init_report_limits ( )

Definition at line 437 of file cadical_internal.cpp.

437 {
438 reported = false;
439 lim.report = 0;
440 lim.recompute_tier = 5000;
441}
Here is the caller graph for this function:

◆ init_scores()

void CaDiCaL::Internal::init_scores ( int old_max_var,
int new_max_var )

Definition at line 13 of file cadical_score.cpp.

13 {
14 LOG ("initializing EVSIDS scores from %d to %d", old_max_var + 1,
15 new_max_var);
16 for (int i = old_max_var; i < new_max_var; i++)
17 scores.push_back (i + 1);
18}
Here is the caller graph for this function:

◆ init_search_limits()

void CaDiCaL::Internal::init_search_limits ( )

Definition at line 520 of file cadical_internal.cpp.

520 {
521
522 const bool incremental = lim.initialized;
523 if (incremental)
524 LOG ("reinitializing search limits incrementally");
525 else
526 LOG ("initializing search limits and increments");
527
528 const char *mode = 0;
529
530 /*----------------------------------------------------------------------*/
531
532 if (incremental)
533 mode = "keeping";
534 else {
535 last.reduce.conflicts = -1;
536 lim.reduce = stats.conflicts + opts.reduceinit;
537 mode = "initial";
538 }
539 (void) mode;
540 LOG ("%s reduce limit %" PRId64 " after %" PRId64 " conflicts", mode,
541 lim.reduce, lim.reduce - stats.conflicts);
542
543 /*----------------------------------------------------------------------*/
544
545 if (incremental)
546 mode = "keeping";
547 else {
548 lim.flush = opts.flushint;
549 inc.flush = opts.flushint;
550 mode = "initial";
551 }
552 (void) mode;
553 LOG ("%s flush limit %" PRId64 " interval %" PRId64 "", mode, lim.flush,
554 inc.flush);
555
556 /*----------------------------------------------------------------------*/
557
558 // Initialize or reset 'rephase' limits in any case.
559
560 lim.rephase = stats.conflicts + opts.rephaseint;
561 lim.rephased[0] = lim.rephased[1] = 0;
562 LOG ("new rephase limit %" PRId64 " after %" PRId64 " conflicts",
563 lim.rephase, lim.rephase - stats.conflicts);
564
565 /*----------------------------------------------------------------------*/
566
567 // Initialize or reset 'restart' limits in any case.
568
569 lim.restart = stats.conflicts + opts.restartint;
570 LOG ("new restart limit %" PRId64 " increment %" PRId64 "", lim.restart,
571 lim.restart - stats.conflicts);
572
573 /*----------------------------------------------------------------------*/
574
575 if (!incremental) {
576 stable = opts.stabilize && opts.stabilizeonly;
577 if (stable)
578 LOG ("starting in always forced stable phase");
579 else
580 LOG ("starting in default non-stable phase");
581 init_averages ();
582 } else if (opts.stabilize && opts.stabilizeonly) {
583 LOG ("keeping always forced stable phase");
585 } else if (stable) {
586 LOG ("switching back to default non-stable phase");
587 stable = false;
588 swap_averages ();
589 } else
590 LOG ("keeping non-stable phase");
591
592 if (!incremental) {
593 inc.stabilize = 0;
594 lim.stabilize = stats.conflicts + opts.stabilizeinit;
595 LOG ("initial stabilize limit %" PRId64 " after %d conflicts",
596 lim.stabilize, (int) opts.stabilizeinit);
597 }
598
599 if (opts.stabilize && opts.reluctant) {
600 LOG ("new restart reluctant doubling sequence period %d",
601 opts.reluctant);
602 reluctant.enable (opts.reluctant, opts.reluctantmax);
603 } else
604 reluctant.disable ();
605
606 /*----------------------------------------------------------------------*/
607
608 // Conflict and decision limits.
609
610 if (inc.conflicts < 0) {
611 lim.conflicts = -1;
612 LOG ("no limit on conflicts");
613 } else {
614 lim.conflicts = stats.conflicts + inc.conflicts;
615 LOG ("conflict limit after %" PRId64 " conflicts at %" PRId64
616 " conflicts",
617 inc.conflicts, lim.conflicts);
618 }
619
620 if (inc.decisions < 0) {
621 lim.decisions = -1;
622 LOG ("no limit on decisions");
623 } else {
624 lim.decisions = stats.decisions + inc.decisions;
625 LOG ("conflict limit after %" PRId64 " decisions at %" PRId64
626 " decisions",
627 inc.decisions, lim.decisions);
628 }
629
630 /*----------------------------------------------------------------------*/
631
632 // Initial preprocessing rounds.
633
634 if (inc.localsearch <= 0) {
635 lim.localsearch = 0;
636 LOG ("no local search");
637 } else {
638 lim.localsearch = inc.localsearch;
639 LOG ("limiting to %" PRId64 " local search rounds", lim.localsearch);
640 }
641
642 /*----------------------------------------------------------------------*/
643
644 lim.initialized = true;
645}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_sweeper()

void CaDiCaL::Internal::init_sweeper ( Sweeper & sweeper)

Definition at line 216 of file cadical_sweep.cpp.

216 {
217 sweeper.encoded = 0;
218 enlarge_zero (sweeper.depths, max_var + 1);
219 sweeper.reprs = new int[2 * max_var + 1];
221 enlarge_zero (sweeper.prev, max_var + 1);
222 enlarge_zero (sweeper.next, max_var + 1);
223 for (const auto &lit : lits)
224 sweeper.reprs[lit] = lit;
226 sweeper.current_ticks =
227 2 *
228 clauses
229 .size (); // initialize with the cost of building full occ list.
230 sweeper.current_ticks +=
231 2 + 2 * cache_lines (clauses.size (), sizeof (Clause *));
235
236 sweep_dense_mode_and_watch_irredundant (); // full occurence list
237
238 if (lrat) {
239 sweeper.prev_units.push_back (0);
240 for (const auto &idx : vars) {
241 sweeper.prev_units.push_back (val (idx) != 0);
242 }
243 }
244
245 unsigned completed = stats.sweep_completed;
246 const unsigned max_completed = 32;
247 if (completed > max_completed)
248 completed = max_completed;
249
250 uint64_t vars_limit = opts.sweepvars;
251 vars_limit <<= completed;
252 const unsigned max_vars_limit = opts.sweepmaxvars;
253 if (vars_limit > max_vars_limit)
254 vars_limit = max_vars_limit;
255 sweeper.limit.vars = vars_limit;
256 VERBOSE (3, "sweeper variable limit %u", sweeper.limit.vars);
257
258 uint64_t depth_limit = stats.sweep_completed;
259 depth_limit += opts.sweepdepth;
260 const unsigned max_depth = opts.sweepmaxdepth;
261 if (depth_limit > max_depth)
262 depth_limit = max_depth;
263 sweeper.limit.depth = depth_limit;
264 VERBOSE (3, "sweeper depth limit %u", sweeper.limit.depth);
265
266 uint64_t clause_limit = opts.sweepclauses;
267 clause_limit <<= completed;
268 const unsigned max_clause_limit = opts.sweepmaxclauses;
269 if (clause_limit > max_clause_limit)
270 clause_limit = max_clause_limit;
271 sweeper.limit.clauses = clause_limit;
272 VERBOSE (3, "sweeper clause limit %u", sweeper.limit.clauses);
273}
void sweep_dense_mode_and_watch_irredundant()
unsigned last
Definition sweep.c:25
unsigned * reprs
Definition sweep.c:23
unsigned first
Definition sweep.c:25
unsigned * next
Definition sweep.c:24
unsigned * prev
Definition sweep.c:24
unsigned depth
Definition sweep.c:36
Here is the call graph for this function:

◆ init_vars()

void CaDiCaL::Internal::init_vars ( int new_max_var)

Definition at line 154 of file cadical_internal.cpp.

154 {
155 if (new_max_var <= max_var)
156 return;
157 // New variables can be created that can invoke enlarge anytime (via calls
158 // during ipasir-up call-backs), thus assuming (!level) is not correct
159 LOG ("initializing %d internal variables from %d to %d",
160 new_max_var - max_var, max_var + 1, new_max_var);
161 if ((size_t) new_max_var >= vsize)
162 enlarge (new_max_var);
163#ifndef CADICAL_NDEBUG
164 for (int64_t i = -new_max_var; i < -max_var; i++)
165 CADICAL_assert (!vals[i]);
166 for (unsigned i = max_var + 1; i <= (unsigned) new_max_var; i++)
168 for (uint64_t i = 2 * ((uint64_t) max_var + 1);
169 i <= 2 * (uint64_t) new_max_var + 1; i++)
170 CADICAL_assert (ptab[i] == -1);
171#endif
172 CADICAL_assert (!btab[0]);
173 int old_max_var = max_var;
174 max_var = new_max_var;
175 init_queue (old_max_var, new_max_var);
176 init_scores (old_max_var, new_max_var);
177 int initialized = new_max_var - old_max_var;
178 stats.vars += initialized;
179 stats.unused += initialized;
180 stats.inactive += initialized;
181 LOG ("finished initializing %d internal variables", initialized);
182}
void init_scores(int old_max_var, int new_max_var)
void init_queue(int old_max_var, int new_max_var)
void enlarge(int new_max_var)
Here is the call graph for this function:

◆ init_watches()

void CaDiCaL::Internal::init_watches ( )

Definition at line 9 of file cadical_watch.cpp.

9 {
10 CADICAL_assert (wtab.empty ());
11 if (wtab.size () < 2 * vsize)
12 wtab.resize (2 * vsize, Watches ());
13 LOG ("initialized watcher tables");
14}
Here is the caller graph for this function:

◆ inprobe()

void CaDiCaL::Internal::inprobe ( bool update_limits = true)

Definition at line 918 of file cadical_probe.cpp.

918 {
919
920 if (unsat)
921 return;
922 if (level)
923 backtrack ();
924 if (!propagate ()) {
926 return;
927 }
928
929 stats.inprobingphases++;
930 if (external_prop) {
932 private_steps = true;
933 }
934 const int before = active ();
935 const int before_extended = stats.variables_extension;
936
937 // schedule of inprobing techniques.
938 //
939 {
941 decompose ();
942 if (ternary ())
943 decompose (); // If we derived a binary clause
944 if (probe ())
945 decompose ();
946
947 if (extract_gates ())
948 decompose ();
949 if (sweep ()) // full occurrence list
950 decompose (); // ... and (ELS) afterwards.
951 (void) vivify (); // resets watches
952 transred (); // builds big.
953 factor (); // resets watches, partial occurrence list
954 }
955
956 if (external_prop) {
958 private_steps = false;
959 }
960
961 if (!update_limits)
962 return;
963
964 const int after = active ();
965 const int after_extended = stats.variables_extension;
966 const int diff_extended = after_extended - before_extended;
967 CADICAL_assert (diff_extended >= 0);
968 const int removed = before - after + diff_extended;
969 CADICAL_assert (removed >= 0);
970
971 if (removed) {
972 stats.inprobesuccess++;
973 PHASE ("probe-phase", stats.inprobingphases,
974 "successfully removed %d active variables %.0f%%", removed,
975 percent (removed, before));
976 } else
977 PHASE ("probe-phase", stats.inprobingphases,
978 "could not remove any active variable");
979
980 const int64_t delta =
981 25 * opts.inprobeint * log10 (stats.inprobingphases + 9);
982 lim.inprobe = stats.conflicts + delta;
983
984 PHASE ("probe-phase", stats.inprobingphases,
985 "new limit at %" PRId64 " conflicts after %" PRId64 " conflicts",
986 lim.inprobe, delta);
987
988 last.inprobe.reductions = stats.reductions;
989}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ inprobing()

bool CaDiCaL::Internal::inprobing ( )

Definition at line 20 of file cadical_probe.cpp.

20 {
21 if (!opts.inprobing)
22 return false;
23 if (!preprocessing && !opts.inprocessing)
24 return false;
25 if (preprocessing)
26 CADICAL_assert (lim.preprocessing);
27 if (stats.inprobingphases && last.inprobe.reductions == stats.reductions)
28 return false;
29 return lim.inprobe <= stats.conflicts;
30}
Here is the caller graph for this function:

◆ inst_assign()

void CaDiCaL::Internal::inst_assign ( int lit)
inline

Definition at line 68 of file cadical_instantiate.cpp.

68 {
69 LOG ("instantiate assign %d", lit);
73 set_val (lit, 1);
74 trail.push_back (lit);
75}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ inst_propagate()

bool CaDiCaL::Internal::inst_propagate ( )

Definition at line 82 of file cadical_instantiate.cpp.

82 { // Adapted from 'propagate'.
84 int64_t before = propagated;
85 bool ok = true;
86 while (ok && propagated != trail.size ()) {
87 const int lit = -trail[propagated++];
88 LOG ("instantiate propagating %d", -lit);
89 Watches &ws = watches (lit);
90 const const_watch_iterator eow = ws.end ();
91 const_watch_iterator i = ws.begin ();
92 watch_iterator j = ws.begin ();
93 while (i != eow) {
94 const Watch w = *j++ = *i++;
95 const signed char b = val (w.blit);
96 if (b > 0)
97 continue;
98 if (w.binary ()) {
99 if (b < 0) {
100 ok = false;
101 LOG (w.clause, "conflict");
102 if (lrat) {
103 inst_chain.push_back (w.clause);
104 }
105 break;
106 } else {
107 if (lrat) {
108 inst_chain.push_back (w.clause);
109 }
110 inst_assign (w.blit);
111 }
112 } else {
113 literal_iterator lits = w.clause->begin ();
114 const int other = lits[0] ^ lits[1] ^ lit;
115 lits[0] = other, lits[1] = lit;
116 const signed char u = val (other);
117 if (u > 0)
118 j[-1].blit = other;
119 else {
120 const int size = w.clause->size;
121 const const_literal_iterator end = lits + size;
122 const literal_iterator middle = lits + w.clause->pos;
123 literal_iterator k = middle;
124 signed char v = -1;
125 int r = 0;
126 while (k != end && (v = val (r = *k)) < 0)
127 k++;
128 if (v < 0) {
129 k = lits + 2;
130 CADICAL_assert (w.clause->pos <= size);
131 while (k != middle && (v = val (r = *k)) < 0)
132 k++;
133 }
134 w.clause->pos = k - lits;
135 CADICAL_assert (lits + 2 <= k), CADICAL_assert (k <= w.clause->end ());
136 if (v > 0) {
137 j[-1].blit = r;
138 } else if (!v) {
139 LOG (w.clause, "unwatch %d in", r);
140 lits[1] = r;
141 *k = lit;
142 watch_literal (r, lit, w.clause);
143 j--;
144 } else if (!u) {
145 CADICAL_assert (v < 0);
146 if (lrat) {
147 inst_chain.push_back (w.clause);
148 }
149 inst_assign (other);
150 } else {
151 CADICAL_assert (u < 0);
152 CADICAL_assert (v < 0);
153 if (lrat) {
154 inst_chain.push_back (w.clause);
155 }
156 LOG (w.clause, "conflict");
157 ok = false;
158 break;
159 }
160 }
161 }
162 }
163 if (j != i) {
164 while (i != eow)
165 *j++ = *i++;
166 ws.resize (j - ws.begin ());
167 }
168 }
169 int64_t delta = propagated - before;
170 stats.propagations.instantiate += delta;
171 STOP (propagate);
172 return ok;
173}
vector< Clause * > inst_chain
Definition internal.hpp:214
Here is the call graph for this function:
Here is the caller graph for this function:

◆ instantiate()

void CaDiCaL::Internal::instantiate ( Instantiator & instantiator)

Definition at line 316 of file cadical_instantiate.cpp.

316 {
317 CADICAL_assert (opts.instantiate);
319 stats.instrounds++;
320#ifndef CADICAL_QUIET
321 const int64_t candidates = instantiator.candidates.size ();
322 int64_t tried = 0;
323#endif
324 int64_t instantiated = 0;
325 init_watches ();
327 if (propagated < trail.size ()) {
328 if (!propagate ()) {
329 LOG ("propagation after connecting watches failed");
332 }
333 }
334 PHASE ("instantiate", stats.instrounds,
335 "attempting to instantiate %" PRId64
336 " candidate literal clause pairs",
337 candidates);
338 while (!unsat && !terminated_asynchronously () &&
339 !instantiator.candidates.empty ()) {
340 Instantiator::Candidate cand = instantiator.candidates.back ();
341 instantiator.candidates.pop_back ();
342#ifndef CADICAL_QUIET
343 tried++;
344#endif
345 if (!active (cand.lit))
346 continue;
347 LOG (cand.clause,
348 "trying to instantiate %d with "
349 "%zd negative occurrences in",
350 cand.lit, cand.negoccs);
351 if (!instantiate_candidate (cand.lit, cand.clause))
352 continue;
353 instantiated++;
354 VERBOSE (2,
355 "instantiation %" PRId64 " (%.1f%%) succeeded "
356 "(%.1f%%) with %zd negative occurrences in size %d clause",
357 tried, percent (tried, candidates),
358 percent (instantiated, tried), cand.negoccs, cand.size);
359 }
360 PHASE ("instantiate", stats.instrounds,
361 "instantiated %" PRId64 " candidate successfully "
362 "out of %" PRId64 " tried %.1f%%",
363 instantiated, tried, percent (instantiated, tried));
364 report ('I', !instantiated);
365 reset_watches ();
367}
bool instantiate_candidate(int lit, Clause *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ instantiate_candidate()

bool CaDiCaL::Internal::instantiate_candidate ( int lit,
Clause * c )

Definition at line 179 of file cadical_instantiate.cpp.

179 {
180 stats.instried++;
181 if (c->garbage)
182 return false;
184 bool found = false, satisfied = false, inactive = false;
185 int unassigned = 0;
186 for (const auto &other : *c) {
187 if (other == lit)
188 found = true;
189 const signed char tmp = val (other);
190 if (tmp > 0) {
191 satisfied = true;
192 break;
193 }
194 if (!tmp && !active (other)) {
195 inactive = true;
196 break;
197 }
198 if (!tmp)
199 unassigned++;
200 }
201 if (!found)
202 return false;
203 if (inactive)
204 return false;
205 if (satisfied)
206 return false;
207 if (unassigned < 3)
208 return false;
209 size_t before = trail.size ();
210 CADICAL_assert (propagated == before);
212 CADICAL_assert (inst_chain.empty ());
213 LOG (c, "trying to instantiate %d in", lit);
214 CADICAL_assert (!c->garbage);
215 c->instantiated = true;
216 CADICAL_assert (lrat_chain.empty ());
217 level++;
218 inst_assign (lit); // Assume 'lit' to true.
219 for (const auto &other : *c) {
220 if (other == lit)
221 continue;
222 const signed char tmp = val (other);
223 if (tmp) {
224 CADICAL_assert (tmp < 0);
225 continue;
226 }
227 inst_assign (-other); // Assume other to false.
228 }
229 bool ok = inst_propagate (); // Propagate.
230 CADICAL_assert (lrat_chain.empty ()); // chain will be built here
231 if (ok) {
232 inst_chain.clear ();
233 } else if (lrat) { // analyze conflict for lrat
234 CADICAL_assert (inst_chain.size ());
235 Clause *reason = inst_chain.back ();
236 inst_chain.pop_back ();
237 lrat_chain.push_back (reason->id);
238 for (const auto &other : *reason) {
239 Flags &f = flags (other);
240 CADICAL_assert (!f.seen);
241 f.seen = true;
242 analyzed.push_back (other);
243 }
244 }
245 while (trail.size () > before) { // Backtrack.
246 const int other = trail.back ();
247 LOG ("instantiate unassign %d", other);
248 trail.pop_back ();
249 CADICAL_assert (val (other) > 0);
250 num_assigned--;
251 set_val (other, 0);
252 // this is a variant of conflict analysis which is only needed for lrat
253 if (!ok && inst_chain.size () && lrat) {
254 Flags &f = flags (other);
255 if (f.seen) {
256 Clause *reason = inst_chain.back ();
257 lrat_chain.push_back (reason->id);
258 for (const auto &other : *reason) {
259 Flags &f = flags (other);
260 if (f.seen)
261 continue;
262 f.seen = true;
263 analyzed.push_back (other);
264 }
265 f.seen = false;
266 }
267 inst_chain.pop_back ();
268 }
269 }
270 CADICAL_assert (inst_chain.empty ());
271 // post processing step for lrat
272 if (!ok && lrat) {
273 if (flags (lit).seen)
274 lrat_chain.push_back (c->id);
275 for (const auto &other : *c) {
276 Flags &f = flags (other);
277 f.seen = false;
278 }
279 for (int other : analyzed) {
280 Flags &f = flags (other);
281 if (!f.seen) {
282 f.seen = true;
283 continue;
284 }
285 int64_t id = unit_id (-other);
286 lrat_chain.push_back (id);
287 }
289 reverse (lrat_chain.begin (), lrat_chain.end ());
290 }
291 CADICAL_assert (analyzed.empty ());
292 propagated = before;
293 CADICAL_assert (level == 1);
294 level = 0;
295 if (ok) {
296 CADICAL_assert (lrat_chain.empty ());
297 LOG ("instantiation failed");
298 return false;
299 }
300 unwatch_clause (c);
301 LOG (lrat_chain, "instantiate proof chain");
303 watch_clause (c);
304 lrat_chain.clear ();
305 CADICAL_assert (c->size > 1);
306 LOG ("instantiation succeeded");
307 stats.instantiated++;
308 return true;
309}
void unwatch_clause(Clause *c)
Definition internal.hpp:640
Here is the call graph for this function:
Here is the caller graph for this function:

◆ irredundant()

int64_t CaDiCaL::Internal::irredundant ( ) const
inline

Definition at line 383 of file internal.hpp.

383{ return stats.current.irredundant; }
Here is the caller graph for this function:

◆ is_autarky_literal()

bool CaDiCaL::Internal::is_autarky_literal ( int lit) const
inline

Definition at line 105 of file cadical_condition.cpp.

105 {
106 return val (lit) > 0 && !getbit (lit, 0);
107}
bool getbit(int lit, int bit) const
Definition internal.hpp:536
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_binary_clause()

bool CaDiCaL::Internal::is_binary_clause ( Clause * c,
int & a,
int & b )

Definition at line 600 of file cadical_probe.cpp.

600 {
602 if (c->garbage)
603 return false;
604 int first = 0, second = 0;
605 for (const auto &lit : *c) {
606 const signed char tmp = val (lit);
607 if (tmp > 0)
608 return false;
609 if (tmp < 0)
610 continue;
611 if (second)
612 return false;
613 if (first)
614 second = lit;
615 else
616 first = lit;
617 }
618 if (!second)
619 return false;
620 a = first, b = second;
621 return true;
622}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_blocked_clause()

bool CaDiCaL::Internal::is_blocked_clause ( Clause * c,
int pivot )

Definition at line 47 of file cadical_block.cpp.

47 {
48
49 LOG (c, "trying to block on %d", lit);
50
51 CADICAL_assert (c->size >= opts.blockminclslim);
52 CADICAL_assert (c->size <= opts.blockmaxclslim);
55 CADICAL_assert (!c->garbage);
56 CADICAL_assert (!c->redundant);
58
59 mark (c); // First mark all literals in 'c'.
60
61 Occs &os = occs (-lit);
62 LOG ("resolving against at most %zd clauses with %d", os.size (), -lit);
63
64 bool res = true; // Result is true if all resolvents tautological.
65
66 // Can not use 'auto' here since we update 'os' during traversal.
67 //
68 const auto end_of_os = os.end ();
69 auto i = os.begin ();
70
71 Clause *prev_d = 0; // Previous non-tautological clause.
72
73 for (; i != end_of_os; i++) {
74 // Move the first clause with non-tautological resolvent to the front of
75 // the occurrence list to improve finding it faster later.
76 //
77 Clause *d = *i;
78
79 CADICAL_assert (!d->garbage);
80 CADICAL_assert (!d->redundant);
81 CADICAL_assert (d->size <= opts.blockmaxclslim);
82
83 *i = prev_d; // Move previous non-tautological clause
84 prev_d = d; // backwards but remember clause at this position.
85
86 LOG (d, "resolving on %d against", lit);
87 stats.blockres++;
88
89 int prev_other = 0; // Previous non-tautological literal.
90
91 // No 'auto' since we update literals of 'd' during traversal.
92 //
93 const const_literal_iterator end_of_d = d->end ();
95
96 for (l = d->begin (); l != end_of_d; l++) {
97 // Same move-to-front mechanism for literals within a clause. It
98 // moves the first negatively marked literal to the front to find it
99 // faster in the future.
100 //
101 const int other = *l;
102 *l = prev_other;
103 prev_other = other;
104 if (other == -lit)
105 continue;
106 CADICAL_assert (other != lit);
107 CADICAL_assert (active (other));
108 CADICAL_assert (!val (other));
109 if (marked (other) < 0) {
110 LOG ("found tautological literal %d", other);
111 d->literals[0] = other; // Move to front of 'd'.
112 break;
113 }
114 }
115
116 if (l == end_of_d) {
117 LOG ("no tautological literal found");
118 //
119 // Since we did not find a tautological literal we restore the old
120 // order of literals in the clause.
121 //
122 const const_literal_iterator begin_of_d = d->begin ();
123 while (l-- != begin_of_d) {
124 const int other = *l;
125 *l = prev_other;
126 prev_other = other;
127 }
128 res = false; // Now 'd' is a witness that 'c' is not blocked.
129 os[0] = d; // Move it to the front of the occurrence list.
130 break;
131 }
132 }
133 unmark (c); // ... all literals of the candidate clause.
134
135 // If all resolvents are tautological and thus the clause is blocked we
136 // restore the old order of clauses in the occurrence list of '-lit'.
137 //
138 if (res) {
139 CADICAL_assert (i == end_of_os);
140 const auto boc = os.begin ();
141 while (i != boc) {
142 Clause *d = *--i;
143 *i = prev_d;
144 prev_d = d;
145 }
146 }
147
148 return res;
149}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_clause()

bool CaDiCaL::Internal::is_clause ( Clause * c,
const vector< int > & lits )

Definition at line 600 of file cadical_gates.cpp.

600 {
601 if (c->garbage)
602 return false;
603 int size = lits.size ();
604 if (c->size < size)
605 return false;
606 int found = 0;
607 for (const auto &lit : *c) {
608 if (val (lit) < 0)
609 continue;
610 if (val (lit) > 0)
611 return false;
612 const auto it = find (lits.begin (), lits.end (), lit);
613 if (it == lits.end ())
614 return false;
615 if (++found > size)
616 return false;
617 }
618 return found == size;
619}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_conditional_literal()

bool CaDiCaL::Internal::is_conditional_literal ( int lit) const
inline

Definition at line 101 of file cadical_condition.cpp.

101 {
102 return val (lit) > 0 && getbit (lit, 0);
103}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_decision()

bool CaDiCaL::Internal::is_decision ( int ilit)

Definition at line 196 of file cadical_external_propagate.cpp.

196 {
197 if (!level || fixed (ilit) || !val (ilit))
198 return false;
199
200 const int idx = vidx (ilit);
201 Var &v = var (idx);
202#ifndef CADICAL_NDEBUG
203 LOG (v.reason,
204 "is_decision: i%d (current level: %d, is_fixed: %d, v.level: %d, "
205 "is_external_reason: %d, v.reason: )",
206 ilit, level, fixed (ilit), v.level, v.reason == external_reason);
207#endif
208 if (!v.level || v.reason)
209 return false;
210 CADICAL_assert (!v.reason);
211 return true;
212}
Here is the call graph for this function:

◆ is_external_forgettable()

bool CaDiCaL::Internal::is_external_forgettable ( int64_t id)

Definition at line 1058 of file cadical_external_propagate.cpp.

1058 {
1059 CADICAL_assert (opts.check);
1060 return (external->forgettable_original.find (id) !=
1061 external->forgettable_original.end ());
1062}
Here is the caller graph for this function:

◆ is_in_candidate_clause()

bool CaDiCaL::Internal::is_in_candidate_clause ( int lit) const
inline

Definition at line 130 of file cadical_condition.cpp.

130 {
131 return marked67 (lit) > 0;
132}
signed char marked67(int lit) const
Definition internal.hpp:498
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_valid_limit()

bool CaDiCaL::Internal::is_valid_limit ( const char * name)
static

Definition at line 93 of file cadical_limit.cpp.

93 {
94 if (!strcmp (name, "terminate"))
95 return true;
96 if (!strcmp (name, "conflicts"))
97 return true;
98 if (!strcmp (name, "decisions"))
99 return true;
100 if (!strcmp (name, "preprocessing"))
101 return true;
102 if (!strcmp (name, "localsearch"))
103 return true;
104 return false;
105}
char * name
Definition main.h:24
int strcmp()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ iterate()

void CaDiCaL::Internal::iterate ( )

Definition at line 1278 of file cadical_analyze.cpp.

1278 {
1279 iterating = false;
1280 report ('i');
1281}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ learn_empty_clause()

void CaDiCaL::Internal::learn_empty_clause ( )

Definition at line 19 of file cadical_analyze.cpp.

19 {
22 LOG ("learned empty clause");
23 external->check_learned_empty_clause ();
24 int64_t id = ++clause_id;
25 if (proof) {
26 proof->add_derived_empty_clause (id, lrat_chain);
27 }
28 unsat = true;
29 conflict_id = id;
30 marked_failed = true;
31 conclusion.push_back (id);
32 lrat_chain.clear ();
33}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ learn_external_reason_clause()

Clause * CaDiCaL::Internal::learn_external_reason_clause ( int lit,
int falsified_elit = 0,
bool no_backtrack = false )

Definition at line 668 of file cadical_external_propagate.cpp.

670 {
671 CADICAL_assert (external->propagator);
672 // we cannot modify clause during analysis
673 auto clause_tmp = std::move (clause);
674
675 CADICAL_assert (clause.empty ());
676 CADICAL_assert (original.empty ());
677
678 stats.ext_prop.eprop_expl++;
679
680 int elit = 0;
681 if (!falsified_elit) {
682 CADICAL_assert (!fixed (ilit));
683 elit = externalize (ilit);
684 } else
685 elit = falsified_elit;
686
687 LOG ("ilit: %d, elit: %d", ilit, elit);
688 add_external_clause (elit, no_backtrack);
689
690#ifndef CADICAL_NDEBUG
691 if (!falsified_elit && newest_clause) {
692 // Check if external propagation is correct wrt to the topological order
693 // defined by the trail. In case it is a falsified external propagation
694 // step, the order does not matter, the reason simply supposed to be a
695 // falsified clause.
696 const int propagated_ilit = ilit;
697 for (auto const reason_ilit : *newest_clause) {
698 CADICAL_assert (var (reason_ilit).trail <= var (propagated_ilit).trail);
699 }
700 }
701#endif
702
703 clause = std::move (clause_tmp);
704 return newest_clause;
705}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ learn_unit_clause()

void CaDiCaL::Internal::learn_unit_clause ( int lit)

Definition at line 35 of file cadical_analyze.cpp.

35 {
37 LOG ("learned unit clause %d, stored at position %d", lit, vlit (lit));
38 external->check_learned_unit_clause (lit);
39 int64_t id = ++clause_id;
40 if (lrat || frat) {
41 const unsigned uidx = vlit (lit);
42 unit_clauses (uidx) = id;
43 }
44 if (proof) {
45 proof->add_derived_unit_clause (id, lit, lrat_chain);
46 }
48}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ likely_phase()

int CaDiCaL::Internal::likely_phase ( int idx)

Definition at line 89 of file cadical_decide.cpp.

89{ return decide_phase (idx, false); }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ likely_to_be_kept_clause()

bool CaDiCaL::Internal::likely_to_be_kept_clause ( Clause * c)
inline

Definition at line 1006 of file internal.hpp.

1006 {
1007 if (!c->redundant)
1008 return true;
1009 if (c->glue <= tier2[false])
1010 return true;
1011 if (c->glue > lim.keptglue)
1012 return false;
1013 if (c->size > lim.keptsize)
1014 return false;
1015 return true;
1016 }
Here is the caller graph for this function:

◆ limit()

bool CaDiCaL::Internal::limit ( const char * name,
int l )

Definition at line 107 of file cadical_limit.cpp.

107 {
108 bool res = true;
109 if (!strcmp (name, "terminate"))
110 limit_terminate (l);
111 else if (!strcmp (name, "conflicts"))
112 limit_conflicts (l);
113 else if (!strcmp (name, "decisions"))
114 limit_decisions (l);
115 else if (!strcmp (name, "preprocessing"))
117 else if (!strcmp (name, "localsearch"))
119 else
120 res = false;
121 return res;
122}
void limit_local_search(int)
void limit_terminate(int)
void limit_preprocessing(int)
void limit_decisions(int)
void limit_conflicts(int)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ limit_conflicts()

void CaDiCaL::Internal::limit_conflicts ( int l)

Definition at line 45 of file cadical_limit.cpp.

45 {
46 if (l < 0 && inc.conflicts < 0) {
47 LOG ("keeping unbounded conflict limit");
48 } else if (l < 0) {
49 LOG ("reset conflict limit to be unbounded");
50 inc.conflicts = -1;
51 } else {
52 inc.conflicts = l;
53 LOG ("new conflict limit of %d conflicts", l);
54 }
55}
Here is the caller graph for this function:

◆ limit_decisions()

void CaDiCaL::Internal::limit_decisions ( int l)

Definition at line 57 of file cadical_limit.cpp.

57 {
58 if (l < 0 && inc.decisions < 0) {
59 LOG ("keeping unbounded decision limit");
60 } else if (l < 0) {
61 LOG ("reset decision limit to be unbounded");
62 inc.decisions = -1;
63 } else {
64 inc.decisions = l;
65 LOG ("new decision limit of %d decisions", l);
66 }
67}
Here is the caller graph for this function:

◆ limit_local_search()

void CaDiCaL::Internal::limit_local_search ( int l)

Definition at line 81 of file cadical_limit.cpp.

81 {
82 if (l < 0) {
83 LOG ("ignoring invalid local search limit %d", l);
84 } else if (!l) {
85 LOG ("reset local search limit to no local search");
86 inc.localsearch = 0;
87 } else {
88 inc.localsearch = l;
89 LOG ("new local search limit of %d local search rounds", l);
90 }
91}
Here is the caller graph for this function:

◆ limit_preprocessing()

void CaDiCaL::Internal::limit_preprocessing ( int l)

Definition at line 69 of file cadical_limit.cpp.

69 {
70 if (l < 0) {
71 LOG ("ignoring invalid preprocessing limit %d", l);
72 } else if (!l) {
73 LOG ("reset preprocessing limit to no preprocessing");
74 inc.preprocessing = 0;
75 } else {
76 inc.preprocessing = l;
77 LOG ("new preprocessing limit of %d preprocessing rounds", l);
78 }
79}
Here is the caller graph for this function:

◆ limit_terminate()

void CaDiCaL::Internal::limit_terminate ( int l)

Definition at line 33 of file cadical_limit.cpp.

33 {
34 if (l <= 0 && !lim.terminate.forced) {
35 LOG ("keeping unbounded terminate limit");
36 } else if (l <= 0) {
37 LOG ("reset terminate limit to be unbounded");
38 lim.terminate.forced = 0;
39 } else {
40 lim.terminate.forced = l;
41 LOG ("new terminate limit of %d calls", l);
42 }
43}
Here is the caller graph for this function:

◆ link()

Link & CaDiCaL::Internal::link ( int lit)
inline

Definition at line 453 of file internal.hpp.

453{ return links[vidx (lit)]; }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lit2citten()

unsigned CaDiCaL::Internal::lit2citten ( int lit)
inline

Definition at line 429 of file internal.hpp.

429 {
430 int idx = vidx (lit) - 1;
431 return (lit < 0) + 2u * (unsigned) idx;
432 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ local_search()

int CaDiCaL::Internal::local_search ( )

Definition at line 850 of file cadical_internal.cpp.

850 {
851
852 if (unsat)
853 return 0;
854 if (!max_var)
855 return 0;
856 if (!opts.walk)
857 return 0;
858 if (constraint.size ())
859 return 0;
860
861 int res = 0;
862
863 for (int i = 1; !res && i <= lim.localsearch; i++)
864 res = local_search_round (i);
865
866 if (res == 10) {
867 LOG ("local search determined formula to be satisfiable");
868 CADICAL_assert (!stats.walk.minimum);
870 } else if (res == 20) {
871 LOG ("local search determined assumptions to be inconsistent");
872 CADICAL_assert (!assumptions.empty ());
874 }
875
876 return res;
877}
int local_search_round(int round)
int try_to_satisfy_formula_by_saved_phases()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ local_search_round()

int CaDiCaL::Internal::local_search_round ( int round)

Definition at line 817 of file cadical_internal.cpp.

817 {
818
819 CADICAL_assert (round > 0);
820
821 if (unsat)
822 return false;
823 if (!max_var)
824 return false;
825
828 localsearching = true;
829
830 // Determine propagation limit quadratically scaled with rounds.
831 //
832 int64_t limit = opts.walkmineff;
833 limit *= round;
834 if (LONG_MAX / round > limit)
835 limit *= round;
836 else
837 limit = LONG_MAX;
838
839 int res = walk_round (limit, true);
840
842 localsearching = false;
844
845 report ('L');
846
847 return res;
848}
#define START_OUTER_WALK()
Definition profile.hpp:259
#define STOP_OUTER_WALK()
Definition profile.hpp:270
int walk_round(int64_t limit, bool prev)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookahead()

int CaDiCaL::Internal::lookahead ( )

Definition at line 1004 of file cadical_internal.cpp.

1004 {
1005 CADICAL_assert (clause.empty ());
1006 START (lookahead);
1008 lookingahead = true;
1009 if (external_prop) {
1010 if (level) {
1011 // Combining lookahead with external propagator is limited
1012 // Note that lookahead_probing (); would also force backtrack anyway
1013 backtrack ();
1014 }
1015 LOG ("external notifications are turned off during preprocessing.");
1016 private_steps = true;
1017 }
1018 int tmp = already_solved ();
1019 if (!tmp)
1020 tmp = restore_clauses ();
1021 int res = 0;
1022 if (!tmp)
1023 res = lookahead_probing ();
1024 if (res == INT_MIN)
1025 res = 0;
1026 reset_solving ();
1027 report_solving (tmp);
1029 lookingahead = false;
1030 STOP (lookahead);
1031 if (external_prop) {
1032 private_steps = false;
1033 LOG ("external notifications are turned back on.");
1034 notify_assignments (); // In case fixed assignments were found.
1035 }
1036 return res;
1037}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookahead_flush_probes()

void CaDiCaL::Internal::lookahead_flush_probes ( )

Definition at line 98 of file cadical_lookahead.cpp.

98 {
99
100 CADICAL_assert (!probes.empty ());
101
102 init_noccs ();
103 for (const auto &c : clauses) {
104 int a, b;
105 if (!is_binary_clause (c, a, b))
106 continue;
107 noccs (a)++;
108 noccs (b)++;
109 }
110
111 const auto eop = probes.end ();
112 auto j = probes.begin ();
113 for (auto i = j; i != eop; i++) {
114 int lit = *i;
115 if (!active (lit))
116 continue;
117 const bool have_pos_bin_occs = noccs (lit) > 0;
118 const bool have_neg_bin_occs = noccs (-lit) > 0;
119 if (have_pos_bin_occs == have_neg_bin_occs)
120 continue;
121 if (have_pos_bin_occs)
122 lit = -lit;
124 if (propfixed (lit) >= stats.all.fixed)
125 continue;
126 MSG ("keeping probe %d negated occs %" PRId64 "", lit, noccs (-lit));
127 *j++ = lit;
128 }
129 size_t remain = j - probes.begin ();
130#ifndef CADICAL_QUIET
131 size_t flushed = probes.size () - remain;
132#endif
133 probes.resize (remain);
134
135 rsort (probes.begin (), probes.end (), probe_negated_noccs_rank (this));
136
137 reset_noccs ();
139
140 PHASE ("probe-round", stats.probingrounds,
141 "flushed %zd literals %.0f%% remaining %zd", flushed,
142 percent (flushed, remain + flushed), remain);
143}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookahead_generate_probes()

void CaDiCaL::Internal::lookahead_generate_probes ( )

Definition at line 145 of file cadical_lookahead.cpp.

145 {
146
147 CADICAL_assert (probes.empty ());
148
149 // First determine all the literals which occur in binary clauses. It is
150 // way faster to go over the clauses once, instead of walking the watch
151 // lists for each literal.
152 //
153 init_noccs ();
154 for (const auto &c : clauses) {
155 int a, b;
156 if (!is_binary_clause (c, a, b))
157 continue;
158 noccs (a)++;
159 noccs (b)++;
160 }
161
162 for (int idx = 1; idx <= max_var; idx++) {
163
164 // Then focus on roots of the binary implication graph, which are
165 // literals occurring negatively in a binary clause, but not positively.
166 // If neither 'idx' nor '-idx' is a root it makes less sense to probe
167 // this variable.
168
169 // This argument requires that equivalent literal substitution through
170 // 'decompose' is performed, because otherwise there might be 'cyclic
171 // roots' which are not tried, i.e., -1 2 0, 1 -2 0, 1 2 3 0, 1 2 -3 0.
172
173 const bool have_pos_bin_occs = noccs (idx) > 0;
174 const bool have_neg_bin_occs = noccs (-idx) > 0;
175
176 // if (have_pos_bin_occs == have_neg_bin_occs) continue;
177
178 if (have_pos_bin_occs) {
179 int probe = -idx;
180
181 // See the discussion where 'propfixed' is used below.
182 //
183 if (propfixed (probe) >= stats.all.fixed)
184 continue;
185
186 MSG ("scheduling probe %d negated occs %" PRId64 "", probe,
187 noccs (-probe));
188 probes.push_back (probe);
189 }
190
191 if (have_neg_bin_occs) {
192 int probe = idx;
193
194 // See the discussion where 'propfixed' is used below.
195 //
196 if (propfixed (probe) >= stats.all.fixed)
197 continue;
198
199 MSG ("scheduling probe %d negated occs %" PRId64 "", probe,
200 noccs (-probe));
201 probes.push_back (probe);
202 }
203 }
204
205 rsort (probes.begin (), probes.end (), probe_negated_noccs_rank (this));
206
207 reset_noccs ();
209
210 PHASE ("probe-round", stats.probingrounds,
211 "scheduled %zd literals %.0f%%", probes.size (),
212 percent (probes.size (), 2 * max_var));
213}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookahead_locc()

int CaDiCaL::Internal::lookahead_locc ( const std::vector< int > & loccs)

Definition at line 39 of file cadical_lookahead.cpp.

39 {
40 for (auto lit : loccs)
41 if (active (abs (lit)) && !assumed (lit) && !assumed (-lit) &&
42 !val (lit))
43 return lit;
44 return 0;
45}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookahead_next_probe()

int CaDiCaL::Internal::lookahead_next_probe ( )

Definition at line 215 of file cadical_lookahead.cpp.

215 {
216
217 int generated = 0;
218
219 for (;;) {
220
221 if (probes.empty ()) {
222 if (generated++)
223 return 0;
225 }
226
227 while (!probes.empty ()) {
228
229 int probe = probes.back ();
230 probes.pop_back ();
231
232 // Eliminated or assigned.
233 //
234 if (!active (probe) || assumed (probe) || assumed (-probe))
235 continue;
236
237 // There is now new unit since the last time we propagated this probe,
238 // thus we propagated it before without obtaining a conflict and
239 // nothing changed since then. Thus there is no need to propagate it
240 // again. This observation was independently made by Partik Simons
241 // et.al. in the context of implementing 'smodels' (see for instance
242 // Alg. 4 in his JAIR article from 2002) and it has also been
243 // contributed to the thesis work of Yacine Boufkhad.
244 //
245 if (propfixed (probe) >= stats.all.fixed)
246 continue;
247
248 return probe;
249 }
250 }
251}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookahead_populate_locc()

std::vector< int > CaDiCaL::Internal::lookahead_populate_locc ( )

Definition at line 21 of file cadical_lookahead.cpp.

21 {
22 std::vector<literal_occ> loccs ((std::size_t) max_var + 1);
23 for (std::size_t lit = 0; lit < loccs.size (); ++lit) {
24 loccs[lit].lit = lit;
25 }
26 for (const auto &c : clauses)
27 if (!c->redundant)
28 for (const auto &lit : *c)
29 if (active (lit))
30 ++loccs[std::abs (lit)];
31 std::sort (begin (loccs), end (loccs));
32 std::vector<int> locc_map;
33 locc_map.reserve (max_var);
34 for (const auto &locc : loccs)
35 locc_map.push_back (locc.lit);
36 return locc_map;
37}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookahead_probing()

int CaDiCaL::Internal::lookahead_probing ( )

Definition at line 290 of file cadical_lookahead.cpp.

290 {
291
292 if (!active ())
293 return 0;
294
295 MSG ("lookahead-probe-round %" PRId64
296 " without propagations limit and %zu assumptions",
297 stats.probingrounds, assumptions.size ());
298
299 termination_forced = false;
300
301#ifndef CADICAL_QUIET
302 int old_failed = stats.failed;
303 int64_t old_probed = stats.probed;
304#endif
305 int64_t old_hbrs = stats.hbrs;
306
307 if (unsat)
308 return INT_MIN;
309 if (level)
310 backtrack ();
311 if (!propagate ()) {
312 MSG ("empty clause before probing");
314 return INT_MIN;
315 }
316
317 if (terminating_asked ())
318 return most_occurring_literal ();
319
320 decompose ();
321
322 if (ternary ()) // If we derived a binary clause
323 decompose (); // then start another round of ELS.
324
325 // Remove duplicated binary clauses and perform in essence hyper unary
326 // resolution, i.e., derive the unit '2' from '1 2' and '-1 2'.
327 //
329
330 lim.conflicts = -1;
331
332 if (!probes.empty ())
334
335 // We reset 'propfixed' since there was at least another conflict thus
336 // a new learned clause, which might produce new propagations (and hyper
337 // binary resolvents). During 'generate_probes' we keep the old value.
338 //
339 for (int idx = 1; idx <= max_var; idx++)
340 propfixed (idx) = propfixed (-idx) = -1;
341
342 CADICAL_assert (unsat || propagated == trail.size ());
343 propagated = propagated2 = trail.size ();
344
345 int probe;
346 int res = most_occurring_literal ();
347 int max_hbrs = -1;
348
349 set_mode (PROBE);
350
351 MSG ("unsat = %d, terminating_asked () = %d ", unsat,
354 while (!unsat && !terminating_asked () &&
356 stats.probed++;
357 int hbrs;
358
360 if (probe_propagate ())
361 hbrs = trail.size (), backtrack ();
362 else
363 hbrs = 0, failed_literal (probe);
365 if (max_hbrs < hbrs ||
366 (max_hbrs == hbrs &&
367 internal->bumped (probe) > internal->bumped (res))) {
368 res = probe;
369 max_hbrs = hbrs;
370 }
371 }
372
374
375 if (unsat) {
376 MSG ("probing derived empty clause");
377 res = INT_MIN;
378 } else if (propagated < trail.size ()) {
379 MSG ("probing produced %zd units",
380 (size_t) (trail.size () - propagated));
381 if (!propagate ()) {
382 MSG ("propagating units after probing results in empty clause");
384 res = INT_MIN;
385 } else
386 sort_watches ();
387 }
388
389#ifndef CADICAL_QUIET
390 int failed = stats.failed - old_failed;
391 int64_t probed = stats.probed - old_probed;
392#endif
393 int64_t hbrs = stats.hbrs - old_hbrs;
394
395 MSG ("lookahead-probe-round %" PRId64 " probed %" PRId64
396 " and found %d failed literals",
397 stats.probingrounds, probed, failed);
398
399 if (hbrs)
400 PHASE ("lookahead-probe-round", stats.probingrounds,
401 "found %" PRId64 " hyper binary resolvents", hbrs);
402
403 MSG ("lookahead literal %d with %d\n", res, max_hbrs);
404
405 return res;
406}
void failed_literal(int lit)
void reset_mode(Mode m)
Definition internal.hpp:169
void set_mode(Mode m)
Definition internal.hpp:165
void probe_assign_decision(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lucky_phases()

int CaDiCaL::Internal::lucky_phases ( )

Definition at line 386 of file cadical_lucky.cpp.

386 {
389 if (!opts.lucky)
390 return 0;
391
392 // TODO: Some of the lucky assignments can also be found if there are
393 // assumptions, but this is not completely implemented nor tested yet.
394 // Nothing done for constraint either.
395 // External propagator assumes a CDCL loop, so lucky is not tried here.
396 if (!assumptions.empty () || !constraint.empty () || external_prop)
397 return 0;
398
399 START (search);
400 START (lucky);
403 stats.lucky.tried++;
404 const int64_t active_before = stats.active;
405 int res = trivially_false_satisfiable ();
406 if (!res)
408 if (!res)
410 if (!res)
412 if (!res)
414 if (!res)
416 if (!res)
418 if (!res)
420 if (res < 0)
422 if (res == 10)
423 stats.lucky.succeeded++;
424 report ('l', !res);
426
427 const int64_t units = active_before - stats.active;
428
429 if (!res && units)
430 LOG ("lucky %zd units", units);
432 STOP (lucky);
433 STOP (search);
434
435 return res;
436}
int trivially_false_satisfiable()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lucky_propagate_discrepency()

bool CaDiCaL::Internal::lucky_propagate_discrepency ( int dec)
inline

Definition at line 129 of file cadical_lucky.cpp.

129 {
131 bool no_conflict = propagate ();
132 if (no_conflict)
133 return false;
134 if (level > 1) {
135 backtrack (level - 1);
137 no_conflict = propagate ();
138 if (no_conflict)
139 return false;
140 return true;
141 } else {
142 analyze ();
144 no_conflict = propagate ();
145 if (!no_conflict) {
146 analyze ();
147 LOG ("lucky inconsistency backward assigning to true");
148 return true;
149 }
150 }
151 return false;
152}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark() [1/2]

void CaDiCaL::Internal::mark ( Clause * c)

Definition at line 13 of file cadical_clause.cpp.

13 {
14 for (const auto &lit : *c)
15 mark (lit);
16}

◆ mark() [2/2]

void CaDiCaL::Internal::mark ( int lit)
inline

Definition at line 484 of file internal.hpp.

484 {
486 marks[vidx (lit)] = sign (lit);
487 CADICAL_assert (marked (lit) > 0);
488 CADICAL_assert (marked (-lit) < 0);
489 }
Here is the call graph for this function:

◆ mark2() [1/2]

void CaDiCaL::Internal::mark2 ( Clause * c)

Definition at line 18 of file cadical_clause.cpp.

18 {
19 for (const auto &lit : *c)
20 mark2 (lit);
21}
Here is the call graph for this function:

◆ mark2() [2/2]

void CaDiCaL::Internal::mark2 ( int lit)
inline

Definition at line 561 of file internal.hpp.

561 {
562 marks[vidx (lit)] |= bign (lit);
564 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark67()

void CaDiCaL::Internal::mark67 ( int lit)
inline

Definition at line 504 of file internal.hpp.

504 {
505 signed char &m = marks[vidx (lit)];
506 const signed char mask = 0x3f;
507#ifndef CADICAL_NDEBUG
508 const signed char bits = m & mask;
509#endif
510 m = (m & mask) | (sign (lit) << 6);
511 CADICAL_assert (marked (lit) > 0);
512 CADICAL_assert (marked (-lit) < 0);
513 CADICAL_assert ((m & mask) == bits);
515 CADICAL_assert (marked67 (-lit) < 0);
516 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_active()

void CaDiCaL::Internal::mark_active ( int lit)

Definition at line 80 of file cadical_flags.cpp.

80 {
81 Flags &f = flags (lit);
82 CADICAL_assert (f.status == Flags::UNUSED);
83 f.status = Flags::ACTIVE;
84 LOG ("activate %d previously unused", abs (lit));
85 CADICAL_assert (stats.inactive);
86 stats.inactive--;
87 CADICAL_assert (stats.unused);
88 stats.unused--;
89 stats.active++;
91}
Here is the call graph for this function:

◆ mark_added() [1/2]

void CaDiCaL::Internal::mark_added ( Clause * c)

Definition at line 73 of file cadical_clause.cpp.

73 {
74 LOG (c, "marking added");
76 for (const auto &lit : *c)
77 mark_added (lit, c->size, c->redundant);
78}
Here is the call graph for this function:

◆ mark_added() [2/2]

void CaDiCaL::Internal::mark_added ( int lit,
int size,
bool redundant )
inline

Definition at line 63 of file cadical_clause.cpp.

63 {
65 if (size == 3)
67 if (!redundant)
69 if (!redundant || size == 2)
71}
void mark_ternary(int lit)
void mark_block(int lit)
void mark_subsume(int lit)
void mark_factor(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_as_conditional_literal()

void CaDiCaL::Internal::mark_as_conditional_literal ( int lit)
inline

Definition at line 109 of file cadical_condition.cpp.

109 {
110 LOG ("marking %d as conditional literal", lit);
111 CADICAL_assert (val (lit) > 0);
112 setbit (lit, 0);
115}
void setbit(int lit, int bit)
Definition internal.hpp:540
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_binary_literals()

void CaDiCaL::Internal::mark_binary_literals ( Eliminator & eliminator,
int pivot )

Definition at line 113 of file cadical_gates.cpp.

113 {
114
115 if (unsat)
116 return;
117 if (val (first))
118 return;
119 if (!eliminator.gates.empty ())
120 return;
121
122 CADICAL_assert (!marked (first));
123 CADICAL_assert (eliminator.marked.empty ());
124
125 const Occs &os = occs (first);
126 for (const auto &c : os) {
127 if (c->garbage)
128 continue;
129 const int second =
130 second_literal_in_binary_clause (eliminator, c, first);
131 if (!second)
132 continue;
133 const int tmp = marked (second);
134 if (tmp < 0) {
135 // had a bug where units could occur multiple times here
136 // solved with flags
137 LOG ("found binary resolved unit %d", first);
138 if (lrat) {
139 Clause *d = find_binary_clause (first, -second);
140 CADICAL_assert (d);
141 for (auto &lit : *d) {
142 if (lit == first || lit == -second)
143 continue;
144 CADICAL_assert (val (lit) < 0);
145 Flags &f = flags (lit);
146 if (f.seen)
147 continue;
148 analyzed.push_back (lit);
149 f.seen = true;
150 int64_t id = unit_id (-lit);
151 lrat_chain.push_back (id);
152 // LOG ("gates added id %" PRId64, id);
153 }
154 for (auto &lit : *c) {
155 if (lit == first || lit == second)
156 continue;
157 CADICAL_assert (val (lit) < 0);
158 Flags &f = flags (lit);
159 if (f.seen)
160 continue;
161 analyzed.push_back (lit);
162 f.seen = true;
163 int64_t id = unit_id (-lit);
164 lrat_chain.push_back (id);
165 // LOG ("gates added id %" PRId64, id);
166 }
167 lrat_chain.push_back (c->id);
168 lrat_chain.push_back (d->id);
169 // LOG ("gates added id %" PRId64, c->id);
170 // LOG ("gates added id %" PRId64, d->id);
172 }
173 assign_unit (first);
174 elim_propagate (eliminator, first);
175 return;
176 }
177 if (tmp > 0) {
178 LOG (c, "duplicated actual binary clause");
179 elim_update_removed_clause (eliminator, c);
180 mark_garbage (c);
181 continue;
182 }
183 eliminator.marked.push_back (second);
184 mark (second);
185 LOG ("marked second literal %d in binary clause %d %d", second, first,
186 second);
187 }
188}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_block()

void CaDiCaL::Internal::mark_block ( int lit)
inline

Definition at line 1072 of file internal.hpp.

1072 {
1073 Flags &f = flags (lit);
1074 const unsigned bit = bign (lit);
1075 if (f.block & bit)
1076 return;
1077 LOG ("marking %d as blocking literal candidate", lit);
1078 stats.mark.block++;
1079 f.block |= bit;
1080 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_clause()

void CaDiCaL::Internal::mark_clause ( )

Definition at line 28 of file cadical_clause.cpp.

28 {
29 for (const auto &lit : clause)
30 mark (lit);
31}

◆ mark_clauses_to_be_flushed()

void CaDiCaL::Internal::mark_clauses_to_be_flushed ( )

Definition at line 38 of file cadical_reduce.cpp.

38 {
39 const int tier1limit = tier1[false];
40 const int tier2limit = max (tier1limit, tier2[false]);
41 for (const auto &c : clauses) {
42 if (!c->redundant)
43 continue; // keep irredundant
44 if (c->garbage)
45 continue; // already marked as garbage
46 if (c->reason)
47 continue; // need to keep reasons
48 const unsigned used = c->used;
49 if (used)
50 c->used--;
51 if (c->glue < tier1limit && used)
52 continue;
53 if (c->glue < tier2limit && used >= max_used - 1)
54 continue;
55 mark_garbage (c); // flush unused clauses
56 if (c->hyper)
57 stats.flush.hyper++;
58 else
59 stats.flush.learned++;
60 }
61 // No change to 'lim.kept{size,glue}'.
62}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_decomposed()

void CaDiCaL::Internal::mark_decomposed ( int lit)
inline

Definition at line 1119 of file internal.hpp.

1119 {
1120 Flags &f = flags (lit);
1121 const unsigned bit = bign (lit);
1122 CADICAL_assert ((f.marked_signed & bit) == 0);
1123 sign_marked.push_back (lit);
1124 f.marked_signed |= bit;
1125 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_duplicated_binary_clauses_as_garbage()

void CaDiCaL::Internal::mark_duplicated_binary_clauses_as_garbage ( )

Definition at line 24 of file cadical_deduplicate.cpp.

24 {
25
26 if (!opts.deduplicate)
27 return;
28 if (unsat)
29 return;
31 return;
32
33 START_SIMPLIFIER (deduplicate, DEDUP);
34 stats.deduplications++;
35
38
39 vector<int> stack; // To save marked literals and unmark them later.
40
41 int64_t subsumed = 0;
42 int64_t units = 0;
43
44 for (auto idx : vars) {
45
46 if (unsat)
47 break;
48 if (!active (idx))
49 continue;
50 int unit = 0;
51
52 for (int sign = -1; !unit && sign <= 1; sign += 2) {
53
54 const int lit = sign * idx; // Consider all literals.
55
56 CADICAL_assert (stack.empty ());
57 Watches &ws = watches (lit);
58
59 // We are removing references to garbage clause. Thus no 'auto'.
60
61 const const_watch_iterator end = ws.end ();
62 watch_iterator j = ws.begin ();
64
65 for (i = j; !unit && i != end; i++) {
66 Watch w = *j++ = *i;
67 if (!w.binary ())
68 continue;
69 int other = w.blit;
70 const int tmp = marked (other);
71 Clause *c = w.clause;
72
73 if (tmp > 0) { // Found duplicated binary clause.
74
75 if (c->garbage) {
76 j--;
77 continue;
78 }
79 LOG (c, "found duplicated");
80
81 // The previous identical clause 'd' might be redundant and if the
82 // second clause 'c' is not (so irredundant), then we have to keep
83 // 'c' instead of 'd', thus we search for it and replace it.
84
85 if (!c->redundant) {
87 for (k = ws.begin ();; k++) {
88 CADICAL_assert (k != i);
89 if (!k->binary ())
90 continue;
91 if (k->blit != other)
92 continue;
93 Clause *d = k->clause;
94 if (d->garbage)
95 continue;
96 c = d;
97 break;
98 }
99 *k = w;
100 }
101
102 LOG (c, "mark garbage duplicated");
103 stats.subsumed++;
104 stats.deduplicated++;
105 subsumed++;
106 mark_garbage (c);
107 j--;
108
109 } else if (tmp < 0) { // Hyper unary resolution.
110
111 LOG ("found %d %d and %d %d which produces unit %d", lit, -other,
112 lit, other, lit);
113 unit = lit;
114 if (lrat) {
115 // taken from fradical
116 CADICAL_assert (lrat_chain.empty ());
117 lrat_chain.push_back (c->id);
118 // We've forgotten where the other binary clause is, so go find
119 // it again
120 for (watch_iterator k = ws.begin ();; k++) {
121 CADICAL_assert (k != i);
122 if (!k->binary ())
123 continue;
124 if (k->blit != -other)
125 continue;
126 lrat_chain.push_back (k->clause->id);
127 break;
128 }
129 }
130 j = ws.begin (); // Flush 'ws'.
131 units++;
132
133 } else {
134 if (c->garbage)
135 continue;
136 mark (other);
137 stack.push_back (other);
138 }
139 }
140
141 if (j == ws.begin ())
142 erase_vector (ws);
143 else if (j != end)
144 ws.resize (j - ws.begin ()); // Shrink watchers.
145
146 for (const auto &other : stack)
147 unmark (other);
148
149 stack.clear ();
150 }
151
152 // Propagation potentially messes up the watches and thus we can not
153 // propagate the unit immediately after finding it. Instead we break
154 // out of both loops and assign and propagate the unit here.
155
156 if (unit) {
157
158 stats.failed++;
159 stats.hyperunary++;
160 assign_unit (unit);
161 // lrat_chain.clear (); done in search_assign
162
163 if (!propagate ()) {
164 LOG ("empty clause after propagating unit");
166 }
167 }
168 }
169 STOP_SIMPLIFIER (deduplicate, DEDUP);
170
171 report ('2', !opts.reportall && !(subsumed + units));
172}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_elim()

void CaDiCaL::Internal::mark_elim ( int lit)
inline

Definition at line 1064 of file internal.hpp.

1064 {
1065 Flags &f = flags (lit);
1066 if (f.elim)
1067 return;
1068 LOG ("marking %d as elimination literal candidate", lit);
1069 stats.mark.elim++;
1070 f.elim = true;
1071 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_eliminated()

void CaDiCaL::Internal::mark_eliminated ( int lit)

Definition at line 38 of file cadical_flags.cpp.

38 {
39 Flags &f = flags (lit);
40 CADICAL_assert (f.status == Flags::ACTIVE);
41 f.status = Flags::ELIMINATED;
42 LOG ("eliminated %d", abs (lit));
43 stats.all.eliminated++;
44 stats.now.eliminated++;
45 stats.inactive++;
46 CADICAL_assert (stats.active);
47 stats.active--;
49 CADICAL_assert (f.eliminated ());
50}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_eliminated_clauses_as_garbage()

void CaDiCaL::Internal::mark_eliminated_clauses_as_garbage ( Eliminator & eliminator,
int pivot,
bool & deleted_binary_clause )

Definition at line 616 of file cadical_elim.cpp.

617 {
619
620 LOG ("marking irredundant clauses with %d as garbage", pivot);
621
622 const int64_t substitute = eliminator.gates.size ();
623 if (substitute)
624 LOG ("pushing %" PRId64 " gate clauses on extension stack", substitute);
625#ifndef CADICAL_NDEBUG
626 int64_t pushed = 0;
627#endif
628 Occs &ps = occs (pivot);
629 for (const auto &c : ps) {
630 if (c->garbage)
631 continue;
632 CADICAL_assert (!c->redundant);
633 if (!substitute || c->gate) {
634 if (proof)
635 proof->weaken_minus (c);
636 if (c->size == 2)
637 deleted_binary_clause = true;
638 external->push_clause_on_extension_stack (c, pivot);
639#ifndef CADICAL_NDEBUG
640 pushed++;
641#endif
642 }
643 mark_garbage (c);
644 elim_update_removed_clause (eliminator, c, pivot);
645 }
646 erase_occs (ps);
647
648 LOG ("marking irredundant clauses with %d as garbage", -pivot);
649
650 Occs &ns = occs (-pivot);
651 for (const auto &d : ns) {
652 if (d->garbage)
653 continue;
654 CADICAL_assert (!d->redundant);
655 if (!substitute || d->gate) {
656 if (proof)
657 proof->weaken_minus (d);
658 if (d->size == 2)
659 deleted_binary_clause = true;
660 external->push_clause_on_extension_stack (d, -pivot);
661#ifndef CADICAL_NDEBUG
662 pushed++;
663#endif
664 }
665 mark_garbage (d);
666 elim_update_removed_clause (eliminator, d, -pivot);
667 }
668 erase_occs (ns);
669
670 if (substitute)
671 CADICAL_assert (pushed <= substitute);
672
673 // Unfortunately, we can not use the trick by Niklas Soerensson anymore,
674 // which avoids saving all clauses on the extension stack. This would
675 // break our new incremental 'restore' logic.
676}
void erase_occs(Occs &os)
Definition occs.hpp:21
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_factor()

void CaDiCaL::Internal::mark_factor ( int lit)
inline

Definition at line 1043 of file internal.hpp.

1043 {
1044 Flags &f = flags (lit);
1045 const unsigned bit = bign (lit);
1046 if (f.factor & bit)
1047 return;
1048 LOG ("marking %d as factor literal candidate", lit);
1049 stats.mark.factor++;
1050 f.factor |= bit;
1051 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_fixed()

void CaDiCaL::Internal::mark_fixed ( int lit)

Definition at line 9 of file cadical_flags.cpp.

9 {
10 if (external->fixed_listener) {
11 int elit = externalize (lit);
12 CADICAL_assert (elit);
13 const int eidx = abs (elit);
14 if (!external->ervars[eidx])
15 external->fixed_listener->notify_fixed_assignment (elit);
16 }
17 Flags &f = flags (lit);
18 CADICAL_assert (f.status == Flags::ACTIVE);
19 f.status = Flags::FIXED;
20 LOG ("fixed %d", abs (lit));
21 stats.all.fixed++;
22 stats.now.fixed++;
23 stats.inactive++;
24 CADICAL_assert (stats.active);
25 stats.active--;
27 CADICAL_assert (f.fixed ());
28
30 // If pre/inprocessing found a fixed assignment, we want the propagator
31 // to know about it.
32 // But at that point it is not guaranteed to be already on the trail, so
33 // notification will happen only later.
35 }
36}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_garbage()

void CaDiCaL::Internal::mark_garbage ( Clause * c)

Definition at line 301 of file cadical_clause.cpp.

301 {
302
303 CADICAL_assert (!c->garbage);
304
305 // Delay tracing deletion of binary clauses. See the discussion above in
306 // 'delete_clause' and also in 'propagate'.
307 //
308 if (proof && (c->size != 2 || !watching ())) {
309 c->flushed = true;
310 proof->delete_clause (c);
311 }
312
313 // Because of the internal model checking, external forgettable clauses
314 // must be marked as removed already upon mark_garbage, can not wait until
315 // actual deletion.
316 if (opts.check && is_external_forgettable (c->id))
318
319 CADICAL_assert (stats.current.total > 0);
320 stats.current.total--;
321
322 size_t bytes = c->bytes ();
323 if (c->redundant) {
324 CADICAL_assert (stats.current.redundant > 0);
325 stats.current.redundant--;
326 } else {
327 CADICAL_assert (stats.current.irredundant > 0);
328 stats.current.irredundant--;
329 CADICAL_assert (stats.irrlits >= c->size);
330 stats.irrlits -= c->size;
331 mark_removed (c);
332 }
333 stats.garbage.bytes += bytes;
334 stats.garbage.clauses++;
335 stats.garbage.literals += c->size;
336 c->garbage = true;
337 c->used = 0;
338
339 LOG (c, "marked garbage pointer %p", (void *) c);
340}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_garbage_external_forgettable()

void CaDiCaL::Internal::mark_garbage_external_forgettable ( int64_t id)

Definition at line 1070 of file cadical_external_propagate.cpp.

1070 {
1071 CADICAL_assert (opts.check);
1073
1074 LOG (external->forgettable_original[id],
1075 "forgettable external lemma is deleted:");
1076 // Mark as removed by flipping the first flag to false.
1077 external->forgettable_original[id][0] = 0;
1078}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_in_candidate_clause()

void CaDiCaL::Internal::mark_in_candidate_clause ( int lit)
inline

Definition at line 134 of file cadical_condition.cpp.

134 {
135 LOG ("marking %d as literal of the candidate clause", lit);
136 mark67 (lit);
139}
void mark67(int lit)
Definition internal.hpp:504
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_incomplete()

void CaDiCaL::Internal::mark_incomplete ( Sweeper & sweeper)

Definition at line 1805 of file cadical_sweep.cpp.

1805 {
1806 unsigned marked = 0;
1807 for (all_scheduled (idx)) {
1808 if (!flags (idx).sweep) {
1809 flags (idx).sweep = true;
1810 marked++;
1811 }
1812 }
1813 sweep_incomplete = true;
1814#ifndef CADICAL_QUIET
1815 VERBOSE (2, "marked %u scheduled sweeping variables as incomplete",
1816 marked);
1817#else
1818 (void) marked;
1819#endif
1820}
#define all_scheduled(IDX)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_pure()

void CaDiCaL::Internal::mark_pure ( int lit)

Definition at line 52 of file cadical_flags.cpp.

52 {
53 Flags &f = flags (lit);
54 CADICAL_assert (f.status == Flags::ACTIVE);
55 f.status = Flags::PURE;
56 LOG ("pure %d", abs (lit));
57 stats.all.pure++;
58 stats.now.pure++;
59 stats.inactive++;
60 CADICAL_assert (stats.active);
61 stats.active--;
63 CADICAL_assert (f.pure ());
64}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_redundant_clauses_with_eliminated_variables_as_garbage()

void CaDiCaL::Internal::mark_redundant_clauses_with_eliminated_variables_as_garbage ( )

Definition at line 741 of file cadical_elim.cpp.

742 {
743 for (const auto &c : clauses) {
744 if (c->garbage || !c->redundant)
745 continue;
746 bool clean = true;
747 for (const auto &lit : *c) {
748 Flags &f = flags (lit);
749 if (f.eliminated ()) {
750 clean = false;
751 break;
752 }
753 if (f.pure ()) {
754 clean = false;
755 break;
756 }
757 }
758 if (!clean)
759 mark_garbage (c);
760 }
761}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_removed() [1/2]

void CaDiCaL::Internal::mark_removed ( Clause * c,
int except = 0 )

Definition at line 46 of file cadical_clause.cpp.

46 {
47 LOG (c, "marking removed");
48 CADICAL_assert (!c->redundant);
49 for (const auto &lit : *c)
50 if (lit != except)
52}
Here is the call graph for this function:

◆ mark_removed() [2/2]

void CaDiCaL::Internal::mark_removed ( int lit)
inline

Definition at line 1081 of file internal.hpp.

1081 {
1082 mark_elim (lit);
1083 mark_block (-lit);
1084 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_satisfied_clauses_as_garbage()

void CaDiCaL::Internal::mark_satisfied_clauses_as_garbage ( )

Definition at line 77 of file cadical_collect.cpp.

77 {
78
79 if (last.collect.fixed >= stats.all.fixed)
80 return;
81 last.collect.fixed = stats.all.fixed;
82
83 LOG ("marking satisfied clauses and removing falsified literals");
84
85 for (const auto &c : clauses) {
86 if (c->garbage)
87 continue;
88 const int tmp = clause_contains_fixed_literal (c);
89 if (tmp > 0)
90 mark_garbage (c);
91 else if (tmp < 0)
93 }
94}
void remove_falsified_literals(Clause *)
int clause_contains_fixed_literal(Clause *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_shrinkable_as_removable()

void CaDiCaL::Internal::mark_shrinkable_as_removable ( int blevel,
std::vector< int >::size_type minimized_start )

Definition at line 26 of file cadical_shrink.cpp.

27 {
28#ifdef LOGGING
29 size_t marked = 0, reset = 0;
30#endif
31#ifndef CADICAL_NDEBUG
32 unsigned kept = 0, minireset = 0;
33 for (; minimized_start < minimized.size (); ++minimized_start) {
34 const int lit = minimized[minimized_start];
35 Flags &f = flags (lit);
36 const Var &v = var (lit);
37 if (v.level == blevel) {
38 CADICAL_assert (!f.poison);
39 ++minireset;
40 } else
41 ++kept;
42 }
43 (void) kept;
44 (void) minireset;
45#else
46 (void) blevel;
47 (void) minimized_start;
48#endif
49
50 for (const int lit : shrinkable) {
51 Flags &f = flags (lit);
52 CADICAL_assert (f.shrinkable);
53 CADICAL_assert (!f.poison);
54 f.shrinkable = false;
55#ifdef LOGGING
56 ++reset;
57#endif
58 if (f.removable)
59 continue;
60 f.removable = true;
61 minimized.push_back (lit);
62#ifdef LOGGING
63 ++marked;
64#endif
65 }
66 LOG ("resetting %zu shrinkable variables", reset);
67 LOG ("marked %zu removable variables", marked);
68}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_skip()

void CaDiCaL::Internal::mark_skip ( int lit)
inline

Definition at line 1103 of file internal.hpp.

1103 {
1104 Flags &f = flags (lit);
1105 const unsigned bit = bign (lit);
1106 if (f.skip & bit)
1107 return;
1108 LOG ("marking %d to be skipped as blocking literal", lit);
1109 f.skip |= bit;
1110 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_substituted()

void CaDiCaL::Internal::mark_substituted ( int lit)

Definition at line 66 of file cadical_flags.cpp.

66 {
67 Flags &f = flags (lit);
68 CADICAL_assert (f.status == Flags::ACTIVE);
69 f.status = Flags::SUBSTITUTED;
70 LOG ("substituted %d", abs (lit));
71 stats.all.substituted++;
72 stats.now.substituted++;
73 stats.inactive++;
74 CADICAL_assert (stats.active);
75 stats.active--;
77 CADICAL_assert (f.substituted ());
78}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_subsume()

void CaDiCaL::Internal::mark_subsume ( int lit)
inline

Definition at line 1027 of file internal.hpp.

1027 {
1028 Flags &f = flags (lit);
1029 if (f.subsume)
1030 return;
1031 LOG ("marking %d as subsuming literal candidate", abs (lit));
1032 stats.mark.subsume++;
1033 f.subsume = true;
1034 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_ternary()

void CaDiCaL::Internal::mark_ternary ( int lit)
inline

Definition at line 1035 of file internal.hpp.

1035 {
1036 Flags &f = flags (lit);
1037 if (f.ternary)
1038 return;
1039 LOG ("marking %d as ternary resolution literal candidate", abs (lit));
1040 stats.mark.ternary++;
1041 f.ternary = true;
1042 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_useless_redundant_clauses_as_garbage()

void CaDiCaL::Internal::mark_useless_redundant_clauses_as_garbage ( )

Definition at line 92 of file cadical_reduce.cpp.

92 {
93
94 // We use a separate stack for sorting candidates for removal. This uses
95 // (slightly) more memory but has the advantage to keep the relative order
96 // in 'clauses' intact, which actually due to using stable sorting goes
97 // into the candidate selection (more recently learned clauses are kept if
98 // they otherwise have the same glue and size).
99
100 vector<Clause *> stack;
101 const int tier1limit = tier1[false];
102 const int tier2limit = max (tier1limit, tier2[false]);
103
104 stack.reserve (stats.current.redundant);
105
106 for (const auto &c : clauses) {
107 if (!c->redundant)
108 continue; // Keep irredundant.
109 if (c->garbage)
110 continue; // Skip already marked.
111 if (c->reason)
112 continue; // Need to keep reasons.
113 const unsigned used = c->used;
114 if (used)
115 c->used--;
116 if (c->glue <= tier1limit && used)
117 continue;
118 if (c->glue <= tier2limit && used >= max_used - 1)
119 continue;
120 if (c->hyper) { // Hyper binary and ternary resolvents
121 CADICAL_assert (c->size <= 3); // are only kept for one reduce round
122 if (!used)
123 mark_garbage (c); // unless
124 continue; // used recently.
125 }
126 stack.push_back (c);
127 }
128
129 stable_sort (stack.begin (), stack.end (), reduce_less_useful ());
130 size_t target = 1e-2 * opts.reducetarget * stack.size ();
131
132 // This is defensive code, which I usually consider a bug, but here I am
133 // just not sure that using floating points in the line above is precise
134 // in all situations and instead of figuring that out, I just use this.
135 //
136 if (target > stack.size ())
137 target = stack.size ();
138
139 PHASE ("reduce", stats.reductions, "reducing %zd clauses %.0f%%", target,
140 percent (target, stats.current.redundant));
141
142 auto i = stack.begin ();
143 const auto t = i + target;
144 while (i != t) {
145 Clause *c = *i++;
146 LOG (c, "marking useless to be collected");
147 mark_garbage (c);
148 stats.reduced++;
149 }
150
151 lim.keptsize = lim.keptglue = 0;
152
153 const auto end = stack.end ();
154 for (i = t; i != end; i++) {
155 Clause *c = *i;
156 LOG (c, "keeping");
157 if (c->size > lim.keptsize)
158 lim.keptsize = c->size;
159 if (c->glue > lim.keptglue)
160 lim.keptglue = c->glue;
161 }
162
163 erase_vector (stack);
164
165 PHASE ("reduce", stats.reductions, "maximum kept size %d glue %d",
166 lim.keptsize, lim.keptglue);
167}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ marked()

signed char CaDiCaL::Internal::marked ( int lit) const
inline

Definition at line 478 of file internal.hpp.

478 {
479 signed char res = marks[vidx (lit)];
480 if (lit < 0)
481 res = -res;
482 return res;
483 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ marked2()

bool CaDiCaL::Internal::marked2 ( int lit) const
inline

Definition at line 555 of file internal.hpp.

555 {
556 unsigned res = marks[vidx (lit)];
557 CADICAL_assert (res <= 3);
558 unsigned bit = bign (lit);
559 return (res & bit) != 0;
560 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ marked67()

signed char CaDiCaL::Internal::marked67 ( int lit) const
inline

Definition at line 498 of file internal.hpp.

498 {
499 signed char res = marks[vidx (lit)] >> 6;
500 if (lit < 0)
501 res = -res;
502 return res;
503 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ marked_block()

bool CaDiCaL::Internal::marked_block ( int lit) const
inline

Definition at line 1089 of file internal.hpp.

1089 {
1090 const Flags &f = flags (lit);
1091 const unsigned bit = bign (lit);
1092 return (f.block & bit) != 0;
1093 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ marked_decomposed()

bool CaDiCaL::Internal::marked_decomposed ( int lit)
inline

Definition at line 1131 of file internal.hpp.

1131 {
1132 const Flags &f = flags (lit);
1133 const unsigned bit = bign (lit);
1134 return (f.marked_signed & bit) != 0;
1135 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ marked_skip()

bool CaDiCaL::Internal::marked_skip ( int lit)
inline

Definition at line 1111 of file internal.hpp.

1111 {
1112 const Flags &f = flags (lit);
1113 const unsigned bit = bign (lit);
1114 return (f.skip & bit) != 0;
1115 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ marked_subsume()

bool CaDiCaL::Internal::marked_subsume ( int lit) const
inline

Definition at line 1055 of file internal.hpp.

1055{ return flags (lit).subsume; }
Here is the call graph for this function:

◆ markfact()

void CaDiCaL::Internal::markfact ( int lit,
int fact )
inline

Definition at line 580 of file internal.hpp.

580 {
581 CADICAL_assert (fact == 1 || fact == 2 || fact == 4);
582 CADICAL_assert (!getfact (lit, fact));
583#ifndef CADICAL_NDEBUG
584 int before = getfact (-lit, fact);
585#endif
586 int res = marks[vidx (lit)];
587 if (lit < 0) {
588 res |= fact << 3;
589 } else {
590 res |= fact;
591 }
592 marks[vidx (lit)] = res;
593 CADICAL_assert (getfact (lit, fact));
594#ifndef CADICAL_NDEBUG
595 CADICAL_assert (getfact (-lit, fact) == before);
596#endif
597 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ match_ternary_clause()

bool CaDiCaL::Internal::match_ternary_clause ( Clause * d,
int a,
int b,
int c )

Definition at line 476 of file cadical_gates.cpp.

476 {
477 if (d->garbage)
478 return false;
479 int found = 0;
480 for (const auto &lit : *d) {
481 if (val (lit))
482 continue;
483 if (a != lit && b != lit && c != lit)
484 return false;
485 found++;
486 }
487 return found == 3;
488}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ melt()

void CaDiCaL::Internal::melt ( int lit)
inline

Definition at line 1585 of file internal.hpp.

1585 {
1586 int idx = vidx (lit);
1587 unsigned &ref = frozentab[idx];
1588 if (ref < UINT_MAX) {
1589 if (!--ref) {
1590 if (relevanttab[idx]) {
1591 LOG ("variable %d is observed, can not be completely molten",
1592 idx);
1593 ref++;
1594 } else
1595 LOG ("variable %d completely molten", idx);
1596 } else
1597 LOG ("variable %d melted once but remains frozen %u times", lit,
1598 ref);
1599 } else
1600 LOG ("variable %d remains frozen forever", idx);
1601 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ minimize_and_shrink_block()

std::vector< int >::reverse_iterator CaDiCaL::Internal::minimize_and_shrink_block ( std::vector< int >::reverse_iterator & ,
unsigned int & ,
unsigned int & ,
const int  )

Definition at line 371 of file cadical_shrink.cpp.

375{
376 LOG ("shrinking block");
377 CADICAL_assert (rbegin_block < clause.rend () - 1);
378 int blevel;
379 unsigned open = 0;
380 unsigned max_trail;
381
382 // find begining of block;
383 std::vector<int>::reverse_iterator rend_block;
384 {
385 CADICAL_assert (rbegin_block <= clause.rend ());
386 const int lit = *rbegin_block;
387 const int idx = vidx (lit);
388 blevel = vtab[idx].level;
389 max_trail = vtab[idx].trail;
390 LOG ("Block at level %i (first lit: %i)", blevel, lit);
391
392 rend_block = rbegin_block;
393 bool finished;
394 do {
395 CADICAL_assert (rend_block < clause.rend () - 1);
396 const int lit = *(++rend_block);
397 const int idx = vidx (lit);
398 finished = (blevel != vtab[idx].level);
399 if (!finished && (unsigned) vtab[idx].trail > max_trail)
400 max_trail = vtab[idx].trail;
401 ++open;
402 LOG (
403 "testing if lit %i is on the same level (of lit: %i, global: %i)",
404 lit, vtab[idx].level, blevel);
405
406 } while (!finished);
407 }
408 CADICAL_assert (open > 0);
409 CADICAL_assert (open < clause.size ());
410 CADICAL_assert (rbegin_block < clause.rend ());
411 CADICAL_assert (rend_block < clause.rend ());
412
413 unsigned block_shrunken = 0, block_minimized = 0;
414 if (open < 2) {
415 flags (*rbegin_block).keep = true;
416 minimized.push_back (*rbegin_block);
417 } else
418 block_shrunken = shrink_block (rbegin_block, rend_block, blevel, open,
419 block_minimized, uip0, max_trail);
420
421 LOG ("shrunken %u literals on level %u (including %u minimized)",
422 block_shrunken, blevel, block_minimized);
423
424 total_shrunken += block_shrunken;
425 total_minimized += block_minimized;
426
427 return rend_block;
428}
unsigned shrink_block(std::vector< int >::reverse_iterator &, std::vector< int >::reverse_iterator &, int, unsigned &, unsigned &, const int, unsigned)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ minimize_clause()

void CaDiCaL::Internal::minimize_clause ( )

Definition at line 114 of file cadical_minimize.cpp.

114 {
115 START (minimize);
116 LOG (clause, "minimizing first UIP clause");
117
118 external->check_learned_clause (); // check 1st UIP learned clause first
120
121 CADICAL_assert (minimized.empty ());
123 const auto end = clause.end ();
124 auto j = clause.begin (), i = j;
125 std::vector<int> stack;
126 for (; i != end; i++) {
127 if (minimize_literal (-*i)) {
128 if (lrat) {
129 CADICAL_assert (mini_chain.empty ());
130 calculate_minimize_chain (-*i, stack);
131 for (auto p : mini_chain) {
132 minimize_chain.push_back (p);
133 }
134 mini_chain.clear ();
135 }
136 stats.minimized++;
137 } else
138 flags (*j++ = *i).keep = true;
139 }
140 LOG ("minimized %zd literals", (size_t) (clause.end () - j));
141 if (j != end)
142 clause.resize (j - clause.begin ());
144 for (auto p = minimize_chain.rbegin (); p != minimize_chain.rend ();
145 p++) {
146 lrat_chain.push_back (*p);
147 }
148 minimize_chain.clear ();
149 STOP (minimize);
150}
void calculate_minimize_chain(int lit, std::vector< int > &stack)
bool minimize_literal(int lit, int depth=0)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ minimize_literal()

bool CaDiCaL::Internal::minimize_literal ( int lit,
int depth = 0 )

Definition at line 21 of file cadical_minimize.cpp.

21 {
22 LOG ("attempt to minimize lit %d at depth %d", lit, depth);
23 CADICAL_assert (val (lit) > 0);
24 Flags &f = flags (lit);
25 Var &v = var (lit);
26 if (!v.level || f.removable || f.keep)
27 return true;
28 if (!v.reason || f.poison || v.level == level)
29 return false;
30 const Level &l = control[v.level];
31 if (!depth && l.seen.count < 2)
32 return false; // Don Knuth's idea
33 if (v.trail <= l.seen.trail)
34 return false; // new early abort
35 if (depth > opts.minimizedepth)
36 return false;
37 bool res = true;
38 CADICAL_assert (v.reason);
39 if (opts.minimizeticks)
40 stats.ticks.search[stable]++;
41 if (v.reason == external_reason) {
42 CADICAL_assert (!opts.exteagerreasons);
43 v.reason = learn_external_reason_clause (lit, 0, true);
44 if (!v.reason) {
45 CADICAL_assert (!v.level);
46 return true;
47 }
48 }
49 CADICAL_assert (v.reason != external_reason);
50 const const_literal_iterator end = v.reason->end ();
52 for (i = v.reason->begin (); res && i != end; i++) {
53 const int other = *i;
54 if (other == lit)
55 continue;
56 res = minimize_literal (-other, depth + 1);
57 }
58 if (res)
59 f.removable = true;
60 else
61 f.poison = true;
62 minimized.push_back (lit);
63 if (!depth) {
64 LOG ("minimizing %d %s", lit, res ? "succeeded" : "failed");
65 }
66 return res;
67}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ minimize_sort_clause()

void CaDiCaL::Internal::minimize_sort_clause ( )

Definition at line 209 of file cadical_minimize.cpp.

209 {
210 MSORT (opts.radixsortlim, clause.begin (), clause.end (),
211 minimize_trail_positive_rank (this),
212 minimize_trail_smaller (this));
213}
Here is the caller graph for this function:

◆ most_occurring_literal()

int CaDiCaL::Internal::most_occurring_literal ( )

Definition at line 51 of file cadical_lookahead.cpp.

51 {
52 init_noccs ();
53 for (const auto &c : clauses)
54 if (!c->redundant)
55 for (const auto &lit : *c)
56 if (active (lit))
57 noccs (lit)++;
58 int64_t max_noccs = 0;
59 int res = 0;
60
61 if (unsat)
62 return INT_MIN;
63
64 propagate ();
65 for (int idx = 1; idx <= max_var; idx++) {
66 if (!active (idx) || assumed (idx) || assumed (-idx) || val (idx))
67 continue;
68 for (int sign = -1; sign <= 1; sign += 2) {
69 const int lit = sign * idx;
70 if (!active (lit))
71 continue;
72 int64_t tmp = noccs (lit);
73 if (tmp <= max_noccs)
74 continue;
75 max_noccs = tmp;
76 res = lit;
77 }
78 }
79 MSG ("maximum occurrence %" PRId64 " of literal %d", max_noccs, res);
80 reset_noccs ();
81 return res;
82}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ move_literals_to_watch()

void CaDiCaL::Internal::move_literals_to_watch ( )

Definition at line 404 of file cadical_external_propagate.cpp.

404 {
405 if (clause.size () < 2)
406 return;
407 if (!level)
408 return;
409
410 for (int i = 0; i < 2; i++) {
411 int highest_position = i;
412 int highest_literal = clause[i];
413
414 int highest_level = var (highest_literal).level;
415 int highest_value = val (highest_literal);
416
417 for (size_t j = i + 1; j < clause.size (); j++) {
418 const int other = clause[j];
419 const int other_level = var (other).level;
420 const int other_value = val (other);
421
422 if (other_value < 0) {
423 if (highest_value >= 0)
424 continue;
425 if (other_level <= highest_level)
426 continue;
427 } else if (other_value > 0) {
428 if (highest_value > 0 && other_level >= highest_level)
429 continue;
430 } else {
431 if (highest_value >= 0)
432 continue;
433 }
434
435 highest_position = j;
436 highest_literal = other;
437 highest_level = other_level;
438 highest_value = other_value;
439 }
440#ifndef CADICAL_NDEBUG
441 LOG ("highest position: %d highest level: %d highest value: %d",
442 highest_position, highest_level, highest_value);
443#endif
444
445 if (highest_position == i)
446 continue;
447 if (highest_position > i) {
448 std::swap (clause[i], clause[highest_position]);
449 }
450 }
451}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ negative_horn_satisfiable()

int CaDiCaL::Internal::negative_horn_satisfiable ( )

Definition at line 323 of file cadical_lucky.cpp.

323 {
324 LOG ("checking that all clauses are negative horn satisfiable");
326 CADICAL_assert (assumptions.empty ());
327 for (const auto &c : clauses) {
329 return unlucky (-1);
330 if (c->garbage)
331 continue;
332 if (c->redundant)
333 continue;
334 int negative_literal = 0;
335 bool satisfied = false;
336 for (const auto &lit : *c) {
337 const signed char tmp = val (lit);
338 if (tmp > 0) {
339 satisfied = true;
340 break;
341 }
342 if (tmp < 0)
343 continue;
344 if (lit > 0)
345 continue;
346 negative_literal = lit;
347 break;
348 }
349 if (satisfied)
350 continue;
351 if (!negative_literal) {
352 if (level > 0)
353 backtrack ();
354 LOG (c, "no negative unassigned literal in");
355 return unlucky (0);
356 }
357 CADICAL_assert (negative_literal < 0);
358 LOG (c, "found negative literal %d in", negative_literal);
359 search_assume_decision (negative_literal);
360 if (propagate ())
361 continue;
362 LOG ("propagation of negative literal %d leads to conflict",
363 negative_literal);
364 return unlucky (0);
365 }
366 for (auto idx : vars) {
368 return unlucky (-1);
369 if (val (idx))
370 continue;
372 if (propagate ())
373 continue;
374 LOG ("propagation of remaining literal %d leads to conflict", idx);
375 return unlucky (0);
376 }
377 VERBOSE (1, "clauses are negative horn satisfied");
380 stats.lucky.horn.negative++;
381 return 10;
382}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_clause()

Clause * CaDiCaL::Internal::new_clause ( bool red,
int glue = 0 )

Definition at line 82 of file cadical_clause.cpp.

82 {
83
84 CADICAL_assert (clause.size () <= (size_t) INT_MAX);
85 const int size = (int) clause.size ();
86 CADICAL_assert (size >= 2);
87
88 if (glue > size)
89 glue = size;
90
91 size_t bytes = Clause::bytes (size);
92 Clause *c = (Clause *) new char[bytes];
93 DeferDeleteArray<char> clause_delete ((char *) c);
94
95 c->id = ++clause_id;
96
97 c->conditioned = false;
98 c->covered = false;
99 c->enqueued = false;
100 c->frozen = false;
101 c->garbage = false;
102 c->gate = false;
103 c->hyper = false;
104 c->instantiated = false;
105 c->moved = false;
106 c->reason = false;
107 c->redundant = red;
108 c->transred = false;
109 c->subsume = false;
110 c->swept = false;
111 c->flushed = false;
112 c->vivified = false;
113 c->vivify = false;
114 c->used = 0;
115
116 c->glue = glue;
117 c->size = size;
118 c->pos = 2;
119
120 for (int i = 0; i < size; i++)
121 c->literals[i] = clause[i];
122
123 // Just checking that we did not mess up our sophisticated memory layout.
124 // This might be compiler dependent though. Crucial for correctness.
125 //
126 CADICAL_assert (c->bytes () == bytes);
127
128 stats.current.total++;
129 stats.added.total++;
130
131 if (red) {
132 stats.current.redundant++;
133 stats.added.redundant++;
134 } else {
135 stats.irrlits += size;
136 stats.current.irredundant++;
137 stats.added.irredundant++;
138 }
139
140 clauses.push_back (c);
141 clause_delete.release ();
142 LOG (c, "new pointer %p", (void *) c);
143
145 mark_added (c);
146
147 return c;
148}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_clause_as()

Clause * CaDiCaL::Internal::new_clause_as ( const Clause * orig)

Definition at line 622 of file cadical_clause.cpp.

622 {
623 external->check_learned_clause ();
624 const int new_glue = orig->glue;
625 Clause *res = new_clause (orig->redundant, new_glue);
626 if (proof) {
627 proof->add_derived_clause (res, lrat_chain);
628 }
630 watch_clause (res);
631 return res;
632}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_driving_clause()

Clause * CaDiCaL::Internal::new_driving_clause ( const int glue,
int & jump )

Definition at line 506 of file cadical_analyze.cpp.

506 {
507
508 const size_t size = clause.size ();
509 Clause *res;
510
511 if (!size) {
512
513 jump = 0;
514 res = 0;
515
516 } else if (size == 1) {
517
518 iterating = true;
519 jump = 0;
520 res = 0;
521
522 } else {
523
524 CADICAL_assert (clause.size () > 1);
525
526 // We have to get the last assigned literals into the watch position.
527 // Sorting all literals with respect to reverse assignment order is
528 // overkill but seems to get slightly faster run-time. For 'minimize'
529 // we sort the literals too heuristically along the trail order (so in
530 // the opposite order) with the hope to hit the recursion limit less
531 // frequently. Thus sorting effort is doubled here.
532 //
533 MSORT (opts.radixsortlim, clause.begin (), clause.end (),
534 analyze_trail_negative_rank (this), analyze_trail_larger (this));
535
536 jump = var (clause[1]).level;
537 res = new_learned_redundant_clause (glue);
538 res->used = 1 + (glue <= opts.reducetier2glue);
539 }
540
541 LOG ("jump level %d", jump);
542
543 return res;
544}
Clause * new_learned_redundant_clause(int glue)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_factor_clause()

Clause * CaDiCaL::Internal::new_factor_clause ( )

Definition at line 585 of file cadical_clause.cpp.

585 {
586 external->check_learned_clause ();
587 stats.factor_added++;
588 stats.literals_factored += clause.size ();
589 Clause *res = new_clause (false, 0);
590 if (proof) {
591 proof->add_derived_clause (res, lrat_chain);
592 }
595 for (const auto &lit : *res) {
596 occs (lit).push_back (res);
597 }
598 return res;
599}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_hyper_binary_resolved_clause()

Clause * CaDiCaL::Internal::new_hyper_binary_resolved_clause ( bool red,
int glue )

Definition at line 561 of file cadical_clause.cpp.

561 {
562 external->check_learned_clause ();
563 Clause *res = new_clause (red, glue);
564 if (proof) {
565 proof->add_derived_clause (res, lrat_chain);
566 }
568 watch_clause (res);
569 return res;
570}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_hyper_ternary_resolved_clause()

Clause * CaDiCaL::Internal::new_hyper_ternary_resolved_clause ( bool red)

Definition at line 574 of file cadical_clause.cpp.

574 {
575 external->check_learned_clause ();
576 size_t size = clause.size ();
577 Clause *res = new_clause (red, size);
578 if (proof) {
579 proof->add_derived_clause (res, lrat_chain);
580 }
582 return res;
583}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_hyper_ternary_resolved_clause_and_watch()

Clause * CaDiCaL::Internal::new_hyper_ternary_resolved_clause_and_watch ( bool red,
bool full_watching )

Definition at line 604 of file cadical_clause.cpp.

605 {
606 external->check_learned_clause ();
607 size_t size = clause.size ();
608 Clause *res = new_clause (red, size);
609 if (proof) {
610 proof->add_derived_clause (res, lrat_chain);
611 }
612 if (full_watching) {
614 watch_clause (res);
615 }
616 return res;
617}
Here is the call graph for this function:

◆ new_learned_redundant_clause()

Clause * CaDiCaL::Internal::new_learned_redundant_clause ( int glue)

Definition at line 542 of file cadical_clause.cpp.

542 {
543 CADICAL_assert (clause.size () > 1);
544#ifndef CADICAL_NDEBUG
545 for (size_t i = 2; i < clause.size (); i++)
548#endif
549 external->check_learned_clause ();
550 Clause *res = new_clause (true, glue);
551 if (proof) {
552 proof->add_derived_clause (res, lrat_chain);
553 }
555 watch_clause (res);
556 return res;
557}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_proof_on_demand()

void CaDiCaL::Internal::new_proof_on_demand ( )

Definition at line 15 of file cadical_proof.cpp.

15 {
16 if (!proof) {
17 LOG ("connecting proof to internal solver");
18 proof = new Proof (this);
19 }
20}
Here is the caller graph for this function:

◆ new_quotient()

Quotient * CaDiCaL::Internal::new_quotient ( Factoring & factoring,
int factor )

Definition at line 149 of file cadical_factor.cpp.

149 {
152 Quotient *res = new Quotient (factor);
153 res->next = 0;
154 res->matched = 0;
155 Quotient *last = factoring.quotients.last;
156 res->bid = 0;
157 if (last) {
159 CADICAL_assert (!last->next);
160 last->next = res;
161 res->id = last->id + 1;
162 } else {
165 res->id = 0;
166 }
168 res->prev = last;
169 LOG ("new quotient[%zu] with factor %d", res->id, factor);
170 return res;
171}
struct quotient * prev
Definition factor.c:30
size_t id
Definition factor.c:29
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_resolved_irredundant_clause()

Clause * CaDiCaL::Internal::new_resolved_irredundant_clause ( )

Definition at line 637 of file cadical_clause.cpp.

637 {
638 external->check_learned_clause ();
639 if (proof) {
640 proof->add_derived_clause (clause_id + 1, false, clause, lrat_chain);
641 }
642 Clause *res = new_clause (false);
644 return res;
645}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_trail_level()

void CaDiCaL::Internal::new_trail_level ( int lit)

Definition at line 95 of file cadical_decide.cpp.

95 {
96 level++;
97 control.push_back (Level (lit, trail.size ()));
98}
Here is the caller graph for this function:

◆ next_decision_variable()

int CaDiCaL::Internal::next_decision_variable ( )

Definition at line 44 of file cadical_decide.cpp.

44 {
45 if (use_scores ())
47 else
49}
int next_decision_variable_with_best_score()
int next_decision_variable_on_queue()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ next_decision_variable_on_queue()

int CaDiCaL::Internal::next_decision_variable_on_queue ( )

Definition at line 16 of file cadical_decide.cpp.

16 {
17 int64_t searched = 0;
18 int res = queue.unassigned;
19 while (val (res))
20 res = link (res).prev, searched++;
21 if (searched) {
22 stats.searched += searched;
24 }
25 LOG ("next queue decision variable %d bumped %" PRId64 "", res,
26 bumped (res));
27 return res;
28}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ next_decision_variable_with_best_score()

int CaDiCaL::Internal::next_decision_variable_with_best_score ( )

Definition at line 32 of file cadical_decide.cpp.

32 {
33 int res = 0;
34 for (;;) {
35 res = scores.front ();
36 if (!val (res))
37 break;
38 (void) scores.pop_front ();
39 }
40 LOG ("next decision variable %d with score %g", res, score (res));
41 return res;
42}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ next_factor()

int CaDiCaL::Internal::next_factor ( Factoring & factoring,
unsigned * next_count_ptr )

Definition at line 253 of file cadical_factor.cpp.

253 {
254 Quotient *last_quotient = factoring.quotients.last;
255 CADICAL_assert (last_quotient);
256 vector<Clause *> &last_clauses = last_quotient->qlauses;
257 vector<unsigned> &count = factoring.count;
258 vector<int> &counted = factoring.counted;
259 vector<Clause *> &flauses = factoring.flauses;
260 CADICAL_assert (counted.empty ());
261 CADICAL_assert (flauses.empty ());
262 const int initial = factoring.initial;
263 int64_t ticks = 1 + cache_lines (last_clauses.size (), sizeof (Clause *));
264 for (auto c : last_clauses) {
265 CADICAL_assert (!c->swept);
266 int min_lit = 0;
267 unsigned factors = 0;
268 size_t min_size = 0;
269 ticks++;
270 for (const auto &other : *c) {
271 if (getfact (other, FACTORS)) {
272 if (factors++)
273 break;
274 } else {
275 CADICAL_assert (!getfact (other, QUOTIENT));
276 markfact (other, QUOTIENT);
277 const size_t other_size = occs (other).size ();
278 if (!min_lit || other_size < min_size) {
279 min_lit = other;
280 min_size = other_size;
281 }
282 }
283 }
284 CADICAL_assert (factors);
285 if (factors == 1) {
286 CADICAL_assert (min_lit);
287 const int c_size = c->size;
288 vector<int> &nounted = factoring.nounted;
289 CADICAL_assert (nounted.empty ());
290 ticks += 1 + cache_lines (occs (min_lit).size (), sizeof (Clause *));
291 for (auto d : occs (min_lit)) {
292 if (c == d)
293 continue;
294 ticks++;
295 if (d->swept)
296 continue;
297 if (d->size != c_size)
298 continue;
299 int next = 0;
300 for (const auto &other : *d) {
301 if (getfact (other, QUOTIENT))
302 continue;
303 if (getfact (other, FACTORS))
304 goto CONTINUE_WITH_NEXT_MIN_WATCH;
305 if (getfact (other, NOUNTED))
306 goto CONTINUE_WITH_NEXT_MIN_WATCH;
307 if (next)
308 goto CONTINUE_WITH_NEXT_MIN_WATCH;
309 next = other;
310 }
311 CADICAL_assert (next);
312 if (abs (next) > abs (initial))
313 continue;
314 if (!active (next))
315 continue;
316 CADICAL_assert (!getfact (next, FACTORS));
317 CADICAL_assert (!getfact (next, NOUNTED));
318 markfact (next, NOUNTED);
319 nounted.push_back (next);
320 d->swept = true;
321 flauses.push_back (d);
322 if (!count[vlit (next)])
323 counted.push_back (next);
324 count[vlit (next)]++;
325 CONTINUE_WITH_NEXT_MIN_WATCH:;
326 }
327 clear_nounted (nounted);
328 }
329 for (const auto &other : *c)
330 if (getfact (other, QUOTIENT))
331 unmarkfact (other, QUOTIENT);
332 stats.ticks.factor += ticks;
333 ticks = 0;
334 if (stats.ticks.factor > factoring.limit)
335 break;
336 }
337 clear_flauses (flauses);
338 unsigned next_count = 0;
339 int next = 0;
340 if (stats.ticks.factor <= factoring.limit) {
341 unsigned ties = 0;
342 for (const auto &lit : counted) {
343 const unsigned lit_count = count[vlit (lit)];
344 if (lit_count < next_count)
345 continue;
346 if (lit_count == next_count) {
347 CADICAL_assert (lit_count);
348 ties++;
349 } else {
350 CADICAL_assert (lit_count > next_count);
351 next_count = lit_count;
352 next = lit;
353 ties = 1;
354 }
355 }
356 if (next_count < 2) {
357 LOG ("next factor count %u smaller than 2", next_count);
358 next = 0;
359 } else if (ties > 1) {
360 LOG ("found %u tied next factor candidate literals with count %u",
361 ties, next_count);
362 double next_score = -1;
363 for (const auto &lit : counted) {
364 const unsigned lit_count = count[vlit (lit)];
365 if (lit_count != next_count)
366 continue;
367 double lit_score = tied_next_factor_score (lit);
368 CADICAL_assert (lit_score >= 0);
369 LOG ("score %g of next factor candidate %d", lit_score, lit);
370 if (lit_score <= next_score)
371 continue;
372 next_score = lit_score;
373 next = lit;
374 }
375 CADICAL_assert (next_score >= 0);
376 CADICAL_assert (next);
377 LOG ("best score %g of next factor %d", next_score, next);
378 } else {
379 CADICAL_assert (ties == 1);
380 LOG ("single next factor %d with count %u", next, next_count);
381 }
382 }
383 for (const auto &lit : counted)
384 count[vlit (lit)] = 0;
385 counted.clear ();
386 CADICAL_assert (!next || next_count > 1);
387 *next_count_ptr = next_count;
388 return next;
389}
double tied_next_factor_score(int)
void clear_nounted(vector< int > &)
uint64_t limit
Definition factor.c:58
unsigned initial
Definition factor.c:49
unsigneds nounted
Definition factor.c:56
unsigned * count
Definition factor.c:50
unsigneds counted
Definition factor.c:55
Here is the call graph for this function:
Here is the caller graph for this function:

◆ next_probe()

int CaDiCaL::Internal::next_probe ( )

Definition at line 753 of file cadical_probe.cpp.

753 {
754
755 int generated = 0;
756
757 for (;;) {
758
759 if (probes.empty ()) {
760 if (generated++)
761 return 0;
763 }
764
765 while (!probes.empty ()) {
766
767 int probe = probes.back ();
768 probes.pop_back ();
769
770 // Eliminated or assigned.
771 //
772 if (!active (probe))
773 continue;
774
775 // There is now new unit since the last time we propagated this probe,
776 // thus we propagated it before without obtaining a conflict and
777 // nothing changed since then. Thus there is no need to propagate it
778 // again. This observation was independently made by Partik Simons
779 // et.al. in the context of implementing 'smodels' (see for instance
780 // Alg. 4 in his JAIR article from 2002) and it has also been
781 // contributed to the thesis work of Yacine Boufkhad.
782 //
783 if (propfixed (probe) >= stats.all.fixed)
784 continue;
785
786 return probe;
787 }
788 }
789}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ next_scheduled()

int CaDiCaL::Internal::next_scheduled ( Sweeper & sweeper)

Definition at line 1008 of file cadical_sweep.cpp.

1008 {
1009 int res = sweeper.last;
1010 if (res == 0) {
1011 LOG ("no more scheduled variables left");
1012 return 0;
1013 }
1014 CADICAL_assert (res > 0);
1015 LOG ("dequeuing next scheduled %d", res);
1016 const unsigned prev = sweeper.prev[res];
1017 CADICAL_assert (sweeper.next[res] == 0);
1018 sweeper.prev[res] = 0;
1019 if (prev == 0) {
1020 CADICAL_assert (sweeper.first == res);
1021 sweeper.first = 0;
1022 } else {
1023 CADICAL_assert (sweeper.next[prev] == res);
1024 sweeper.next[prev] = 0;
1025 }
1026 sweeper.last = prev;
1027 return res;
1028}
Here is the caller graph for this function:

◆ noccs()

int64_t & CaDiCaL::Internal::noccs ( int lit)
inline

Definition at line 466 of file internal.hpp.

466{ return ntab[vlit (lit)]; }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ notify_assignments()

void CaDiCaL::Internal::notify_assignments ( )

Definition at line 932 of file cadical_external_propagate.cpp.

932 {
934 return;
935
936 const size_t end_of_trail = trail.size ();
937
938 if (notified >= end_of_trail)
939 return;
940
941 LOG ("notify external propagator about new assignments");
942 std::vector<int> assigned;
943
944 while (notified < end_of_trail) {
945 int ilit = trail[notified++];
946 if (!observed (ilit))
947 continue;
948
949 int elit = externalize (ilit); // TODO: double-check tainting
950 CADICAL_assert (elit);
951 if (external->ervars[abs (elit)])
952 continue;
953 // Fixed variables might get mapped (during compact) to another
954 // non-observed but fixed variable.
955 // This happens on root level, so notification about their assignment is
956 // already done.
957 CADICAL_assert (external->observed (elit) ||
958 (fixed (ilit) && !external->ervars[abs (elit)]));
959 assigned.push_back (elit);
960 }
961
962 external->propagator->notify_assignment (assigned);
963 return;
964}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ notify_backtrack()

void CaDiCaL::Internal::notify_backtrack ( size_t new_level)

Definition at line 987 of file cadical_external_propagate.cpp.

987 {
989 return;
990 external->propagator->notify_backtrack (new_level);
991}
Here is the caller graph for this function:

◆ notify_decision()

void CaDiCaL::Internal::notify_decision ( )

Definition at line 977 of file cadical_external_propagate.cpp.

977 {
979 return;
980 external->propagator->notify_new_decision_level ();
981}
Here is the caller graph for this function:

◆ observed()

bool CaDiCaL::Internal::observed ( int ilit) const

Definition at line 72 of file cadical_external_propagate.cpp.

72 {
73 CADICAL_assert ((size_t) vidx (ilit) < relevanttab.size ());
74 return relevanttab[vidx (ilit)] > 0;
75}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ occs()

Occs & CaDiCaL::Internal::occs ( int lit)
inline

Definition at line 465 of file internal.hpp.

465{ return otab[vlit (lit)]; }
Here is the call graph for this function:

◆ occurring()

bool CaDiCaL::Internal::occurring ( ) const
inline

Definition at line 461 of file internal.hpp.

461{ return !otab.empty (); }
Here is the caller graph for this function:

◆ on_the_fly_strengthen()

Clause * CaDiCaL::Internal::on_the_fly_strengthen ( Clause * conflict,
int lit )

Definition at line 773 of file cadical_analyze.cpp.

773 {
774 CADICAL_assert (new_conflict);
775 CADICAL_assert (new_conflict->size > 2);
776 LOG (new_conflict, "applying OTFS on lit %d", uip);
777 auto sorted = std::vector<int> ();
778 sorted.reserve (new_conflict->size);
779 CADICAL_assert (sorted.empty ());
780 ++stats.otfs.strengthened;
781
782 int *lits = new_conflict->literals;
783
784 CADICAL_assert (lits[0] == uip || lits[1] == uip);
785 const int other_init = lits[0] ^ lits[1] ^ uip;
786
787 CADICAL_assert (mini_chain.empty ());
788
789 const int old_size = new_conflict->size;
790 int new_size = 0;
791 for (int i = 0; i < old_size; ++i) {
792 const int other = lits[i];
793 sorted.push_back (other);
794 if (var (other).level)
795 lits[new_size++] = other;
796 }
797
798 LOG (new_conflict, "removing all units in");
799
800 CADICAL_assert (lits[0] == uip || lits[1] == uip);
801 const int other = lits[0] ^ lits[1] ^ uip;
802 lits[0] = other;
803 lits[1] = lits[--new_size];
804 LOG (new_conflict, "putting uip at pos 1");
805
806 if (other_init != other)
807 remove_watch (watches (other_init), new_conflict);
808 remove_watch (watches (uip), new_conflict);
809
810 CADICAL_assert (!lrat || lrat_chain.back () == new_conflict->id);
811 if (lrat) {
812 CADICAL_assert (!lrat_chain.empty ());
813 for (const auto &id : unit_chain) {
814 mini_chain.push_back (id);
815 }
816 const auto end = lrat_chain.rend ();
817 const auto begin = lrat_chain.rbegin ();
818 for (auto i = begin; i != end; i++) {
819 const auto id = *i;
820 mini_chain.push_back (id);
821 }
822 lrat_chain.clear ();
824 unit_chain.clear ();
825 }
826 CADICAL_assert (unit_analyzed.empty ());
827 // sort the clause
828 {
829 int highest_pos = 0;
830 int highest_level = 0;
831 for (int i = 1; i < new_size; i++) {
832 const unsigned other = lits[i];
833 CADICAL_assert (val (other) < 0);
834 const int level = var (other).level;
836 LOG ("checking %d", other);
837 if (level <= highest_level)
838 continue;
839 highest_pos = i;
840 highest_level = level;
841 }
842 LOG ("highest lit is %d", lits[highest_pos]);
843 if (highest_pos != 1)
844 swap (lits[1], lits[highest_pos]);
845 LOG ("removing %d literals", new_conflict->size - new_size);
846
847 if (new_size == 1) {
848 LOG (new_conflict, "new size = 1, so interrupting");
849 CADICAL_assert (!opts.exteagerreasons);
850 return 0;
851 } else {
852 otfs_strengthen_clause (new_conflict, uip, new_size, sorted);
853 CADICAL_assert (new_size == new_conflict->size);
854 }
855 }
856
857 if (other_init != other)
858 watch_literal (other, lits[1], new_conflict);
859 else {
860 update_watch_size (watches (other), lits[1], new_conflict);
861 }
862 watch_literal (lits[1], other, new_conflict);
863
864 LOG (new_conflict, "strengthened clause by OTFS");
865 sorted.clear ();
866
867 return new_conflict;
868}
void otfs_strengthen_clause(Clause *, int, int, const std::vector< int > &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ otfs_find_backtrack_level()

int CaDiCaL::Internal::otfs_find_backtrack_level ( int & forced)
inline

Definition at line 551 of file cadical_analyze.cpp.

551 {
552 CADICAL_assert (opts.otfs);
553 int res = 0;
554
555 for (const auto &lit : *conflict) {
556 const int tmp = var (lit).level;
557 if (tmp == level) {
558 forced = lit;
559 } else if (tmp > res) {
560 res = tmp;
561 LOG ("bt level is now %d due to %d", res, lit);
562 }
563 }
564 return res;
565}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ otfs_strengthen_clause()

void CaDiCaL::Internal::otfs_strengthen_clause ( Clause * c,
int lit,
int new_size,
const std::vector< int > & old )

Definition at line 903 of file cadical_analyze.cpp.

904 {
905 stats.strengthened++;
906 CADICAL_assert (c->size > 2);
907 (void) shrink_clause (c, new_size);
908 if (proof) {
909 proof->otfs_strengthen_clause (c, old, mini_chain);
910 }
911 if (!c->redundant) {
913 }
914 mini_chain.clear ();
915 c->used = true;
916 LOG (c, "strengthened");
917 external->check_shrunken_clause (c);
918}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ otfs_subsume_clause()

void CaDiCaL::Internal::otfs_subsume_clause ( Clause * subsuming,
Clause * subsumed )
inline

Definition at line 871 of file cadical_analyze.cpp.

872 {
873 stats.subsumed++;
874 CADICAL_assert (subsuming->size <= subsumed->size);
875 LOG (subsumed, "subsumed");
876 if (subsumed->redundant)
877 stats.subred++;
878 else
879 stats.subirr++;
880 if (subsumed->redundant || !subsuming->redundant) {
881 mark_garbage (subsumed);
882 return;
883 }
884 LOG ("turning redundant subsuming clause into irredundant clause");
885 subsuming->redundant = false;
886 if (proof)
887 proof->strengthen (subsuming->id);
888 mark_garbage (subsumed);
889 stats.current.irredundant++;
890 stats.added.irredundant++;
891 stats.irrlits += subsuming->size;
892 CADICAL_assert (stats.current.redundant > 0);
893 stats.current.redundant--;
894 CADICAL_assert (stats.added.redundant > 0);
895 stats.added.redundant--;
896 // ... and keep 'stats.added.total'.
897}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_dimacs() [1/2]

const char * CaDiCaL::Internal::parse_dimacs ( const char * )

◆ parse_dimacs() [2/2]

const char * CaDiCaL::Internal::parse_dimacs ( FILE * )

◆ parse_solution()

const char * CaDiCaL::Internal::parse_solution ( const char * )

◆ phase()

void CaDiCaL::Internal::phase ( int lit)

Definition at line 23 of file cadical_phases.cpp.

23 {
24 const int idx = vidx (lit);
25 signed char old_forced_phase = phases.forced[idx];
26 signed char new_forced_phase = sign (lit);
27 if (old_forced_phase == new_forced_phase) {
28 LOG ("forced phase remains at %d", old_forced_phase * idx);
29 return;
30 }
31 if (old_forced_phase)
32 LOG ("overwriting old forced phase %d", old_forced_phase * idx);
33 LOG ("new forced phase %d", new_forced_phase * idx);
34 phases.forced[idx] = new_forced_phase;
35}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ positive_horn_satisfiable()

int CaDiCaL::Internal::positive_horn_satisfiable ( )

Definition at line 264 of file cadical_lucky.cpp.

264 {
265 LOG ("checking that all clauses are positive horn satisfiable");
267 CADICAL_assert (assumptions.empty ());
268 for (const auto &c : clauses) {
270 return unlucky (-1);
271 if (c->garbage)
272 continue;
273 if (c->redundant)
274 continue;
275 int positive_literal = 0;
276 bool satisfied = false;
277 for (const auto &lit : *c) {
278 const signed char tmp = val (lit);
279 if (tmp > 0) {
280 satisfied = true;
281 break;
282 }
283 if (tmp < 0)
284 continue;
285 if (lit < 0)
286 continue;
287 positive_literal = lit;
288 break;
289 }
290 if (satisfied)
291 continue;
292 if (!positive_literal) {
293 LOG (c, "no positive unassigned literal in");
294 return unlucky (0);
295 }
296 CADICAL_assert (positive_literal > 0);
297 LOG (c, "found positive literal %d in", positive_literal);
298 search_assume_decision (positive_literal);
299 if (propagate ())
300 continue;
301 LOG ("propagation of positive literal %d leads to conflict",
302 positive_literal);
303 return unlucky (0);
304 }
305 for (auto idx : vars) {
307 return unlucky (-1);
308 if (val (idx))
309 continue;
311 if (propagate ())
312 continue;
313 LOG ("propagation of remaining literal %d leads to conflict", -idx);
314 return unlucky (0);
315 }
316 VERBOSE (1, "clauses are positive horn satisfied");
319 stats.lucky.horn.positive++;
320 return 10;
321}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ preprocess()

int CaDiCaL::Internal::preprocess ( )

Definition at line 740 of file cadical_internal.cpp.

740 {
742 for (int i = 0; i < lim.preprocessing; i++)
743 if (!preprocess_round (i))
744 break;
745 if (unsat)
746 return 20;
747 return 0;
748}
bool preprocess_round(int round)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ preprocess_quickly()

void CaDiCaL::Internal::preprocess_quickly ( )

Definition at line 696 of file cadical_internal.cpp.

696 {
697 if (unsat)
698 return;
699 if (!max_var)
700 return;
701 if (!opts.preprocesslight)
702 return;
704 struct {
705 int64_t vars, clauses;
706 } before, after;
707 before.vars = active ();
708 before.clauses = stats.current.irredundant;
709 // stats.preprocessings++;
711 preprocessing = true;
712 PHASE ("preprocessing", stats.preprocessings,
713 "starting with %" PRId64 " variables and %" PRId64 " clauses",
714 before.vars, before.clauses);
715
716 if (extract_gates ())
717 decompose ();
718
719 if (sweep ())
720 decompose ();
721
722 if (opts.factor)
723 factor ();
724
725 if (opts.fastelim)
726 elimfast ();
727 // if (opts.condition)
728 // condition (false);
729 after.vars = active ();
730 after.clauses = stats.current.irredundant;
732 preprocessing = false;
733 PHASE ("preprocessing", stats.preprocessings,
734 "finished with %" PRId64 " variables and %" PRId64 " clauses",
735 after.vars, after.clauses);
737 report ('P');
738}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ preprocess_round()

bool CaDiCaL::Internal::preprocess_round ( int round)

Definition at line 649 of file cadical_internal.cpp.

649 {
650 (void) round;
651 if (unsat)
652 return false;
653 if (!max_var)
654 return false;
656 struct {
657 int64_t vars, clauses;
658 } before, after;
659 before.vars = active ();
660 before.clauses = stats.current.irredundant;
661 stats.preprocessings++;
663 preprocessing = true;
664 PHASE ("preprocessing", stats.preprocessings,
665 "starting round %d with %" PRId64 " variables and %" PRId64
666 " clauses",
667 round, before.vars, before.clauses);
668 int old_elimbound = lim.elimbound;
669 if (opts.inprobing)
670 inprobe (false);
671 if (opts.elim)
672 elim (false);
673 if (opts.condition)
674 condition (false);
675
676 after.vars = active ();
677 after.clauses = stats.current.irredundant;
679 preprocessing = false;
680 PHASE ("preprocessing", stats.preprocessings,
681 "finished round %d with %" PRId64 " variables and %" PRId64
682 " clauses",
683 round, after.vars, after.clauses);
685 report ('P');
686 if (unsat)
687 return false;
688 if (after.vars < before.vars)
689 return true;
690 if (old_elimbound < lim.elimbound)
691 return true;
692 return false;
693}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ print_resource_usage()

void CaDiCaL::Internal::print_resource_usage ( )

Definition at line 756 of file cadical_stats.cpp.

756 {
757#ifndef CADICAL_QUIET
758 SECTION ("resources");
759 uint64_t m = maximum_resident_set_size ();
760 MSG ("total process time since initialization: %12.2f seconds",
761 internal->process_time ());
762 MSG ("total real time since initialization: %12.2f seconds",
763 internal->real_time ());
764 MSG ("maximum resident set size of process: %12.2f MB",
765 m / (double) (1l << 20));
766#endif
767}
#define SECTION(...)
Definition message.hpp:55
uint64_t maximum_resident_set_size()
Here is the call graph for this function:

◆ print_statistics()

void CaDiCaL::Internal::print_statistics ( )

Definition at line 1098 of file cadical_internal.cpp.

1098 {
1099 stats.print (this);
1100 for (auto &st : stat_tracers)
1101 st->print_stats ();
1102}

◆ probe()

bool CaDiCaL::Internal::probe ( )

Definition at line 791 of file cadical_probe.cpp.

791 {
792
793 if (!opts.probe)
794 return false;
795 if (unsat)
796 return false;
798 return false;
799
801
803 stats.probingrounds++;
804
805 // Probing is limited in terms of non-probing propagations
806 // 'stats.propagations'. We allow a certain percentage 'opts.probeeffort'
807 // (say %5) of probing propagations in each probing with a lower bound of
808 // 'opts.probmineff'.
809 //
810
811 PHASE ("probe-round", stats.probingrounds,
812 "probing limit of %" PRId64 " propagations ", limit);
813
814 int old_failed = stats.failed;
815#ifndef CADICAL_QUIET
816 int64_t old_probed = stats.probed;
817#endif
818 int64_t old_hbrs = stats.hbrs;
819
820 if (!probes.empty ())
821 flush_probes ();
822
823 // We reset 'propfixed' since there was at least another conflict thus
824 // a new learned clause, which might produce new propagations (and hyper
825 // binary resolvents). During 'generate_probes' we keep the old value.
826 //
827 for (auto idx : vars)
828 propfixed (idx) = propfixed (-idx) = -1;
829
830 CADICAL_assert (unsat || propagated == trail.size ());
831 propagated = propagated2 = trail.size ();
832
833 int probe;
835 while (!unsat && !terminated_asynchronously () &&
836 stats.ticks.probe < limit && (probe = next_probe ())) {
837 stats.probed++;
838 LOG ("probing %d", probe);
840 if (probe_propagate ())
841 backtrack ();
842 else
845 }
846
847 if (unsat)
848 LOG ("probing derived empty clause");
849 else if (propagated < trail.size ()) {
850 LOG ("probing produced %zd units",
851 (size_t) (trail.size () - propagated));
852 if (!propagate ()) {
853 LOG ("propagating units after probing results in empty clause");
855 } else
856 sort_watches ();
857 }
858
859 int failed = stats.failed - old_failed;
860#ifndef CADICAL_QUIET
861 int64_t probed = stats.probed - old_probed;
862#endif
863 int64_t hbrs = stats.hbrs - old_hbrs;
864
865 PHASE ("probe-round", stats.probingrounds,
866 "probed %" PRId64 " and found %d failed literals", probed, failed);
867
868 if (hbrs)
869 PHASE ("probe-round", stats.probingrounds,
870 "found %" PRId64 " hyper binary resolvents", hbrs);
871
873
874 report ('p', !opts.reportall && !(unsat + failed + hbrs));
875
876 return !unsat && failed;
877}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ probe_assign()

void CaDiCaL::Internal::probe_assign ( int lit,
int parent )
inline

Definition at line 296 of file cadical_probe.cpp.

296 {
298 int idx = vidx (lit);
299 CADICAL_assert (!val (idx));
300 CADICAL_assert (!flags (idx).eliminated () || !parent);
301 CADICAL_assert (!parent || val (parent) > 0);
302 Var &v = var (idx);
303 v.level = level;
304 v.trail = (int) trail.size ();
306 num_assigned++;
307 v.reason = level ? probe_reason : 0;
308 probe_reason = 0;
310 if (!level)
312 else
313 CADICAL_assert (level == 1);
314 const signed char tmp = sign (lit);
315 set_val (idx, tmp);
316 CADICAL_assert (val (lit) > 0);
317 CADICAL_assert (val (-lit) < 0);
318 trail.push_back (lit);
319
320 // Do not save the current phase during inprocessing but remember the
321 // number of units on the trail of the last time this literal was
322 // assigned. This allows us to avoid some redundant failed literal
323 // probing attempts. Search for 'propfixed' in 'probe.cpp' for details.
324 //
325 if (level)
326 propfixed (lit) = stats.all.fixed;
327
328 if (parent)
329 LOG ("probe assign %d parent %d", lit, parent);
330 else if (level)
331 LOG ("probe assign %d probe", lit);
332 else
333 LOG ("probe assign %d negated failed literal UIP", lit);
334}
void set_parent_reason_literal(int lit, int reason)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ probe_assign_decision()

void CaDiCaL::Internal::probe_assign_decision ( int lit)

Definition at line 336 of file cadical_probe.cpp.

336 {
339 CADICAL_assert (propagated == trail.size ());
340 level++;
341 control.push_back (Level (lit, trail.size ()));
342 probe_assign (lit, 0);
343}
void probe_assign(int lit, int parent)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ probe_assign_unit()

void CaDiCaL::Internal::probe_assign_unit ( int lit)

Definition at line 345 of file cadical_probe.cpp.

345 {
349 probe_assign (lit, 0);
350}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ probe_dominator()

int CaDiCaL::Internal::probe_dominator ( int a,
int b )

Definition at line 154 of file cadical_probe.cpp.

154 {
156 int l = a, k = b;
157 Var *u = &var (l), *v = &var (k);
158 CADICAL_assert (val (l) > 0), CADICAL_assert (val (k) > 0);
159 CADICAL_assert (u->level == 1), CADICAL_assert (v->level == 1);
160 while (l != k) {
161 if (u->trail > v->trail)
162 swap (l, k), swap (u, v);
164 return l;
165 int parent = get_parent_reason_literal (k);
166 CADICAL_assert (parent), CADICAL_assert (val (parent) > 0);
167 v = &var (k = parent);
168 CADICAL_assert (v->level == 1);
169 }
170 LOG ("dominator %d of %d and %d", l, a, b);
171 CADICAL_assert (val (l) > 0);
172 return l;
173}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ probe_dominator_lrat()

void CaDiCaL::Internal::probe_dominator_lrat ( int dom,
Clause * reason )

Definition at line 117 of file cadical_probe.cpp.

117 {
118 if (!lrat || !dom)
119 return;
120 LOG (reason, "probe dominator LRAT for %d from", dom);
121 for (const auto lit : *reason) {
122 if (val (lit) >= 0)
123 continue;
124 const auto other = -lit;
125 if (other == dom)
126 continue;
127 Flags &f = flags (other);
128 if (f.seen)
129 continue;
130 f.seen = true;
131 analyzed.push_back (other);
132 Var u = var (other);
133 if (u.level) {
134 if (!u.reason) {
135 LOG ("this may be a problem %d", other);
136 continue;
137 }
138 probe_dominator_lrat (dom, u.reason);
139 continue;
140 }
141 int64_t id = unit_id (other);
142 lrat_chain.push_back (id);
143 }
144 lrat_chain.push_back (reason->id);
145}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ probe_lrat_for_units()

void CaDiCaL::Internal::probe_lrat_for_units ( int lit)
inline

Definition at line 356 of file cadical_probe.cpp.

356 {
357 if (!lrat)
358 return;
359 if (level)
360 return; // not decision level 0
361 LOG ("building chain for units");
362 CADICAL_assert (lrat_chain.empty ());
364 for (auto &reason_lit : *probe_reason) {
365 if (lit == reason_lit)
366 continue;
367 CADICAL_assert (val (reason_lit));
368 if (!val (reason_lit))
369 continue;
370 const int signed_reason_lit = val (reason_lit) * reason_lit;
371 int64_t id = unit_id (signed_reason_lit);
372 lrat_chain.push_back (id);
373 }
374 lrat_chain.push_back (probe_reason->id);
375}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ probe_post_dominator_lrat()

void CaDiCaL::Internal::probe_post_dominator_lrat ( vector< Clause * > & ,
int ,
int  )
Here is the call graph for this function:

◆ probe_propagate()

bool CaDiCaL::Internal::probe_propagate ( )

Definition at line 416 of file cadical_probe.cpp.

416 {
420 int64_t before = propagated2 = propagated;
421 int64_t &ticks = stats.ticks.probe;
422 while (!conflict) {
423 if (propagated2 != trail.size ())
425 else if (propagated != trail.size ()) {
426 const int lit = -trail[propagated++];
427 LOG ("probe propagating %d over large clauses", -lit);
428 Watches &ws = watches (lit);
429 ticks += 1 + cache_lines (ws.size (),
430 sizeof (sizeof (const_watch_iterator *)));
431 size_t i = 0, j = 0;
432 while (i != ws.size ()) {
433 const Watch w = ws[j++] = ws[i++];
434 if (w.binary ())
435 continue;
436 const signed char b = val (w.blit);
437 if (b > 0)
438 continue;
439 ticks++;
440 if (w.clause->garbage)
441 continue;
442 const literal_iterator lits = w.clause->begin ();
443 const int other = lits[0] ^ lits[1] ^ lit;
444 // lits[0] = other, lits[1] = lit;
445 const signed char u = val (other);
446 if (u > 0)
447 ws[j - 1].blit = other;
448 else {
449 const int size = w.clause->size;
450 const const_literal_iterator end = lits + size;
451 const literal_iterator middle = lits + w.clause->pos;
452 literal_iterator k = middle;
453 int r = 0;
454 signed char v = -1;
455 while (k != end && (v = val (r = *k)) < 0)
456 k++;
457 if (v < 0) {
458 k = lits + 2;
459 CADICAL_assert (w.clause->pos <= size);
460 while (k != middle && (v = val (r = *k)) < 0)
461 k++;
462 }
463 w.clause->pos = k - lits;
464 CADICAL_assert (lits + 2 <= k), CADICAL_assert (k <= w.clause->end ());
465 if (v > 0)
466 ws[j - 1].blit = r;
467 else if (!v) {
468 ticks++;
469 LOG (w.clause, "unwatch %d in", r);
470 *k = lit;
471 lits[0] = other;
472 lits[1] = r;
473 watch_literal (r, lit, w.clause);
474 j--;
475 } else if (!u) {
476 ticks++;
477 if (level == 1) {
478 lits[0] = other, lits[1] = lit;
479 CADICAL_assert (lrat_chain.empty ());
481 int dom = hyper_binary_resolve (w.clause);
482 probe_assign (other, dom);
483 } else {
484 ticks++;
485 CADICAL_assert (lrat_chain.empty ());
487 probe_reason = w.clause;
488 probe_lrat_for_units (other);
489 probe_assign_unit (other);
490 lrat_chain.clear ();
491 }
493 } else
494 conflict = w.clause;
495 }
496 }
497 if (j != i) {
498 while (i != ws.size ())
499 ws[j++] = ws[i++];
500 ws.resize (j);
501 }
502 } else
503 break;
504 }
505 int64_t delta = propagated2 - before;
506 stats.propagations.probe += delta;
507 if (conflict)
508 LOG (conflict, "conflict");
509 STOP (propagate);
510 return !conflict;
511}
void probe_lrat_for_units(int lit)
int hyper_binary_resolve(Clause *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ probe_propagate2()

void CaDiCaL::Internal::probe_propagate2 ( )
inline

Definition at line 387 of file cadical_probe.cpp.

387 {
389 int64_t &ticks = stats.ticks.probe;
390 while (propagated2 != trail.size ()) {
391 const int lit = -trail[propagated2++];
392 LOG ("probe propagating %d over binary clauses", -lit);
393 Watches &ws = watches (lit);
394 ticks += 1 + cache_lines (ws.size (), sizeof (const_watch_iterator *));
395 for (const auto &w : ws) {
396 if (!w.binary ())
397 continue;
398 const signed char b = val (w.blit);
399 if (b > 0)
400 continue;
401 ticks++;
402 if (b < 0)
403 conflict = w.clause; // but continue
404 else {
405 CADICAL_assert (lrat_chain.empty ());
407 probe_reason = w.clause;
408 probe_lrat_for_units (w.blit);
409 probe_assign (w.blit, -lit);
410 lrat_chain.clear ();
411 }
412 }
413 }
414}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_time()

double CaDiCaL::Internal::process_time ( ) const

Definition at line 105 of file cadical_resources.cpp.

105 {
106 return absolute_process_time () - stats.time.process;
107}
double absolute_process_time()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ produce_failed_assumptions()

void CaDiCaL::Internal::produce_failed_assumptions ( )

Definition at line 796 of file cadical_internal.cpp.

796 {
797 LOG ("producing failed assumptions");
799 CADICAL_assert (!assumptions.empty ());
800 while (!unsat) {
803 if (decide ())
804 break;
805 while (!unsat && !propagate ())
806 analyze ();
807 }
809 if (unsat)
810 LOG ("formula is actually unsatisfiable unconditionally");
811 else
812 LOG ("assumptions indeed failing");
813}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ promote_clause()

void CaDiCaL::Internal::promote_clause ( Clause * c,
int new_glue )

Definition at line 152 of file cadical_clause.cpp.

152 {
153 CADICAL_assert (c->redundant);
154 const int tier1limit = tier1[false];
155 const int tier2limit = max (tier1limit, tier2[false]);
156 if (!c->redundant)
157 return;
158 if (c->hyper)
159 return;
160 int old_glue = c->glue;
161 if (new_glue >= old_glue)
162 return;
163 if (old_glue > tier1limit && new_glue <= tier1limit) {
164 LOG (c, "promoting with new glue %d to tier1", new_glue);
165 stats.promoted1++;
166 c->used = max_used;
167 } else if (old_glue > tier2limit && new_glue <= tier2limit) {
168 LOG (c, "promoting with new glue %d to tier2", new_glue);
169 stats.promoted2++;
170 } else if (old_glue <= tier2limit)
171 LOG (c, "keeping with new glue %d in tier2", new_glue);
172 else
173 LOG (c, "keeping with new glue %d in tier3", new_glue);
174 stats.improvedglue++;
175 c->glue = new_glue;
176}
Here is the caller graph for this function:

◆ promote_clause_glue_only()

void CaDiCaL::Internal::promote_clause_glue_only ( Clause * c,
int new_glue )

Definition at line 179 of file cadical_clause.cpp.

179 {
180 CADICAL_assert (c->redundant);
181 if (c->hyper)
182 return;
183 int old_glue = c->glue;
184 const int tier1limit = tier1[false];
185 const int tier2limit = max (tier1limit, tier2[false]);
186 if (new_glue >= old_glue)
187 return;
188 if (new_glue <= tier1limit) {
189 LOG (c, "promoting with new glue %d to tier1", new_glue);
190 stats.promoted1++;
191 c->used = max_used;
192 } else if (old_glue > tier2limit && new_glue <= tier2limit) {
193 LOG (c, "promoting with new glue %d to tier2", new_glue);
194 stats.promoted2++;
195 } else if (old_glue <= tier2limit)
196 LOG (c, "keeping with new glue %d in tier2", new_glue);
197 else
198 LOG (c, "keeping with new glue %d in tier3", new_glue);
199 stats.improvedglue++;
200 c->glue = new_glue;
201}
Here is the caller graph for this function:

◆ propagate()

bool CaDiCaL::Internal::propagate ( )

Definition at line 232 of file cadical_propagate.cpp.

232 {
233
234 if (level)
237 LOG ("starting propagate");
239
240 // Updating statistics counter in the propagation loops is costly so we
241 // delay until propagation ran to completion.
242 //
243 int64_t before = propagated;
244 int64_t ticks = 0;
245
246 while (!conflict && propagated != trail.size ()) {
247
248 const int lit = -trail[propagated++];
249 LOG ("propagating %d", -lit);
250 Watches &ws = watches (lit);
251
252 const const_watch_iterator eow = ws.end ();
253 watch_iterator j = ws.begin ();
255 ticks += 1 + cache_lines (ws.size (), sizeof *i);
256
257 while (i != eow) {
258
259 const Watch w = *j++ = *i++;
260 const signed char b = val (w.blit);
261 LOG (w.clause, "checking");
262
263 if (b > 0)
264 continue; // blocking literal satisfied
265
266 if (w.binary ()) {
267
268 // CADICAL_assert (w.clause->redundant || !w.clause->garbage);
269
270 // In principle we can ignore garbage binary clauses too, but that
271 // would require to dereference the clause pointer all the time with
272 //
273 // if (w.clause->garbage) { j--; continue; } // (*)
274 //
275 // This is too costly. It is however necessary to produce correct
276 // proof traces if binary clauses are traced to be deleted ('d ...'
277 // line) immediately as soon they are marked as garbage. Actually
278 // finding instances where this happens is pretty difficult (six
279 // parallel fuzzing jobs in parallel took an hour), but it does
280 // occur. Our strategy to avoid generating incorrect proofs now is
281 // to delay tracing the deletion of binary clauses marked as garbage
282 // until they are really deleted from memory. For large clauses
283 // this is not necessary since we have to access the clause anyhow.
284 //
285 // Thanks go to Mathias Fleury, who wanted me to explain why the
286 // line '(*)' above was in the code. Removing it actually really
287 // improved running times and thus I tried to find concrete
288 // instances where this happens (which I found), and then
289 // implemented the described fix.
290
291 // Binary clauses are treated separately since they do not require
292 // to access the clause at all (only during conflict analysis, and
293 // there also only to simplify the code).
294
295 if (b < 0)
296 conflict = w.clause; // but continue ...
297 else {
298 build_chain_for_units (w.blit, w.clause, 0);
299 search_assign (w.blit, w.clause);
300 // lrat_chain.clear (); done in search_assign
301 ticks++;
302 }
303
304 } else {
305 CADICAL_assert (w.clause->size > 2);
306
307 if (conflict)
308 break; // Stop if there was a binary conflict already.
309
310 // The cache line with the clause data is forced to be loaded here
311 // and thus this first memory access below is the real hot-spot of
312 // the solver. Note, that this check is positive very rarely and
313 // thus branch prediction should be almost perfect here.
314
315 ticks++;
316
317 if (w.clause->garbage) {
318 j--;
319 continue;
320 }
321
322 literal_iterator lits = w.clause->begin ();
323
324 // Simplify code by forcing 'lit' to be the second literal in the
325 // clause. This goes back to MiniSAT. We use a branch-less version
326 // for conditionally swapping the first two literals, since it
327 // turned out to be substantially faster than this one
328 //
329 // if (lits[0] == lit) swap (lits[0], lits[1]);
330 //
331 // which achieves the same effect, but needs a branch.
332 //
333 const int other = lits[0] ^ lits[1] ^ lit;
334 const signed char u = val (other); // value of the other watch
335
336 if (u > 0)
337 j[-1].blit = other; // satisfied, just replace blit
338 else {
339
340 // This follows Ian Gent's (JAIR'13) idea of saving the position
341 // of the last watch replacement. In essence it needs two copies
342 // of the default search for a watch replacement (in essence the
343 // code in the 'if (v < 0) { ... }' block below), one starting at
344 // the saved position until the end of the clause and then if that
345 // one failed to find a replacement another one starting at the
346 // first non-watched literal until the saved position.
347
348 const int size = w.clause->size;
349 const literal_iterator middle = lits + w.clause->pos;
350 const const_literal_iterator end = lits + size;
351 literal_iterator k = middle;
352
353 // Find replacement watch 'r' at position 'k' with value 'v'.
354
355 int r = 0;
356 signed char v = -1;
357
358 while (k != end && (v = val (r = *k)) < 0)
359 k++;
360
361 if (v < 0) { // need second search starting at the head?
362
363 k = lits + 2;
364 CADICAL_assert (w.clause->pos <= size);
365 while (k != middle && (v = val (r = *k)) < 0)
366 k++;
367 }
368
369 w.clause->pos = k - lits; // always save position
370
371 CADICAL_assert (lits + 2 <= k), CADICAL_assert (k <= w.clause->end ());
372
373 if (v > 0) {
374
375 // Replacement satisfied, so just replace 'blit'.
376
377 j[-1].blit = r;
378
379 } else if (!v) {
380
381 // Found new unassigned replacement literal to be watched.
382
383 LOG (w.clause, "unwatch %d in", lit);
384
385 lits[0] = other;
386 lits[1] = r;
387 *k = lit;
388
389 watch_literal (r, lit, w.clause);
390
391 j--; // Drop this watch from the watch list of 'lit'.
392
393 ticks++;
394
395 } else if (!u) {
396
397 CADICAL_assert (v < 0);
398
399 // The other watch is unassigned ('!u') and all other literals
400 // assigned to false (still 'v < 0'), thus we found a unit.
401 //
402 build_chain_for_units (other, w.clause, 0);
403 search_assign (other, w.clause);
404 // lrat_chain.clear (); done in search_assign
405 ticks++;
406
407 // Similar code is in the implementation of the SAT'18 paper on
408 // chronological backtracking but in our experience, this code
409 // first does not really seem to be necessary for correctness,
410 // and further does not improve running time either.
411 //
412 if (opts.chrono > 1) {
413
414 const int other_level = var (other).level;
415
416 if (other_level > var (lit).level) {
417
418 // The assignment level of the new unit 'other' is larger
419 // than the assignment level of 'lit'. Thus we should find
420 // another literal in the clause at that higher assignment
421 // level and watch that instead of 'lit'.
422
423 CADICAL_assert (size > 2);
424
425 int pos, s = 0;
426
427 for (pos = 2; pos < size; pos++)
428 if (var (s = lits[pos]).level == other_level)
429 break;
430
431 CADICAL_assert (s);
432 CADICAL_assert (pos < size);
433
434 LOG (w.clause, "unwatch %d in", lit);
435 lits[pos] = lit;
436 lits[0] = other;
437 lits[1] = s;
438 watch_literal (s, lit, w.clause);
439
440 j--; // Drop this watch from the watch list of 'lit'.
441 }
442 }
443 } else {
444
445 CADICAL_assert (u < 0);
446 CADICAL_assert (v < 0);
447
448 // The other watch is assigned false ('u < 0') and all other
449 // literals as well (still 'v < 0'), thus we found a conflict.
450
451 conflict = w.clause;
452 break;
453 }
454 }
455 }
456 }
457
458 if (j != i) {
459
460 while (i != eow)
461 *j++ = *i++;
462
463 ws.resize (j - ws.begin ());
464 }
465 }
466
468
469 if (conflict)
470 LOG (conflict, "ignoring lucky conflict");
471
472 } else {
473
474 // Avoid updating stats eagerly in the hot-spot of the solver.
475 //
476 stats.propagations.search += propagated - before;
477 stats.ticks.search[stable] += ticks;
478
479 if (!conflict)
481 else {
482
483 if (stable)
484 stats.stabconflicts++;
485 stats.conflicts++;
486
487 LOG (conflict, "conflict");
488
489 // The trail before the current decision level was conflict free.
490 //
492 }
493 }
494
495 STOP (propagate);
496
497 return !conflict;
498}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ propagate_assumptions()

int CaDiCaL::Internal::propagate_assumptions ( )

Definition at line 347 of file cadical_internal.cpp.

347 {
348 if (proof)
349 proof->solve_query ();
350 if (opts.ilb) {
351 if (opts.ilbassumptions)
353 stats.ilbtriggers++;
354 stats.ilbsuccess += (level > 0);
355 stats.levelsreused += level;
356 if (level) {
357 CADICAL_assert (control.size () > 1);
358 stats.literalsreused += num_assigned - control[1].trail;
359 }
360 }
363
364 int res = already_solved (); // root-level propagation is done here
365
366 int last_assumption_level = assumptions.size ();
367 if (constraint.size ())
368 last_assumption_level++;
369
370 if (!res) {
372 while (!res) {
373 if (unsat)
374 res = 20;
375 else if (unsat_constraint)
376 res = 20;
377 else if (!propagate ()) {
378 // let analyze run to get failed assumptions
379 analyze ();
380 } else if (!external_propagate () || unsat) { // external propagation
381 if (unsat)
382 continue;
383 else
384 analyze ();
385 } else if (satisfied ()) { // found model
386 if (!external_check_solution () || unsat) {
387 if (unsat)
388 continue;
389 else
390 analyze ();
391 } else if (satisfied ())
392 res = 10;
393 } else if (search_limits_hit ())
394 break; // decision or conflict limit
395 else if (terminated_asynchronously ()) // externally terminated
396 break;
397 else {
398 if (level >= last_assumption_level)
399 break;
400 res = decide ();
401 }
402 }
403 }
404
405 if (unsat || unsat_constraint)
406 res = 20;
407
408 if (!res && satisfied ())
409 res = 10;
410
411 finalize (res);
412 reset_solving ();
413 report_solving (res);
414
415 return res;
416}
Here is the call graph for this function:

◆ propagate_out_of_order_units()

bool CaDiCaL::Internal::propagate_out_of_order_units ( )

Definition at line 176 of file cadical_reduce.cpp.

176 {
177 if (!level)
178 return true;
179 int oou = 0;
180 for (size_t i = control[1].trail; !oou && i < trail.size (); i++) {
181 const int lit = trail[i];
182 CADICAL_assert (val (lit) > 0);
183 if (var (lit).level)
184 continue;
185 LOG ("found out-of-order assigned unit %d", oou);
186 oou = lit;
187 }
188 if (!oou)
189 return true;
191 backtrack (0);
192 if (propagate ())
193 return true;
195 return false;
196}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ propergate()

void CaDiCaL::Internal::propergate ( )

Definition at line 502 of file cadical_propagate.cpp.

502 {
503
505 CADICAL_assert (propagated == trail.size ());
506
507 while (propergated != trail.size ()) {
508
509 const int lit = -trail[propergated++];
510 LOG ("propergating %d", -lit);
511 Watches &ws = watches (lit);
512
513 const const_watch_iterator eow = ws.end ();
514 watch_iterator j = ws.begin ();
516
517 while (i != eow) {
518
519 const Watch w = *j++ = *i++;
520
521 if (w.binary ()) {
522 CADICAL_assert (val (w.blit) > 0);
523 continue;
524 }
525 if (w.clause->garbage) {
526 j--;
527 continue;
528 }
529
530 literal_iterator lits = w.clause->begin ();
531
532 const int other = lits[0] ^ lits[1] ^ lit;
533 const signed char u = val (other);
534
535 // TODO: check if u == 0 can happen.
536 if (u > 0)
537 continue;
538 CADICAL_assert (u < 0);
539
540 const int size = w.clause->size;
541 const literal_iterator middle = lits + w.clause->pos;
542 const const_literal_iterator end = lits + size;
543 literal_iterator k = middle;
544
545 int r = 0;
546 signed char v = -1;
547
548 while (k != end && (v = val (r = *k)) < 0)
549 k++;
550
551 if (v < 0) {
552 k = lits + 2;
553 CADICAL_assert (w.clause->pos <= size);
554 while (k != middle && (v = val (r = *k)) < 0)
555 k++;
556 }
557
558 CADICAL_assert (lits + 2 <= k), CADICAL_assert (k <= w.clause->end ());
559 w.clause->pos = k - lits;
560
561 CADICAL_assert (v > 0);
562
563 LOG (w.clause, "unwatch %d in", lit);
564
565 lits[0] = other;
566 lits[1] = r;
567 *k = lit;
568
569 watch_literal (r, lit, w.clause);
570
571 j--;
572 }
573
574 if (j != i) {
575
576 while (i != eow)
577 *j++ = *i++;
578
579 ws.resize (j - ws.begin ());
580 }
581 }
582}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ propfixed()

int & CaDiCaL::Internal::propfixed ( int lit)
inline

Definition at line 456 of file internal.hpp.

456{ return ptab[vlit (lit)]; }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ protect_reasons()

void CaDiCaL::Internal::protect_reasons ( )

Definition at line 107 of file cadical_collect.cpp.

107 {
108 LOG ("protecting reason clauses of all assigned variables on trail");
110#ifdef LOGGING
111 size_t count = 0;
112#endif
113 for (const auto &lit : trail) {
114 if (!active (lit))
115 continue;
117 Var &v = var (lit);
118 CADICAL_assert (v.level > 0);
119 Clause *reason = v.reason;
120 if (!reason)
121 continue;
122 if (reason == external_reason)
123 continue;
124 LOG (reason, "protecting assigned %d reason %p", lit, (void *) reason);
125 CADICAL_assert (!reason->reason);
126 reason->reason = true;
127#ifdef LOGGING
128 count++;
129#endif
130 }
131 LOG ("protected %zd reason clauses referenced on trail", count);
132 protected_reasons = true;
133}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ push_literals_of_block()

void CaDiCaL::Internal::push_literals_of_block ( const std::vector< int >::reverse_iterator & rbegin_block,
const std::vector< int >::reverse_iterator & rend_block,
int blevel,
unsigned max_trail )

Definition at line 185 of file cadical_shrink.cpp.

188 {
189 CADICAL_assert (rbegin_block < rend_block);
190 for (auto p = rbegin_block; p != rend_block; ++p) {
191 CADICAL_assert (p != clause.rend () - 1);
192 CADICAL_assert (!flags (*p).keep);
193 const int lit = *p;
194 LOG ("pushing lit %i of blevel %i", lit, var (lit).level);
195#ifndef CADICAL_NDEBUG
196 int tmp =
197#endif
198 shrink_literal (lit, blevel, max_trail);
199 CADICAL_assert (tmp > 0);
200 }
201}
int shrink_literal(int, int, unsigned)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reactivate()

void CaDiCaL::Internal::reactivate ( int lit)

Definition at line 93 of file cadical_flags.cpp.

93 {
95 Flags &f = flags (lit);
96 CADICAL_assert (f.status != Flags::FIXED);
97 CADICAL_assert (f.status != Flags::UNUSED);
98#ifdef LOGGING
99 const char *msg = 0;
100#endif
101 switch (f.status) {
102 default:
104 CADICAL_assert (f.status == Flags::ELIMINATED);
105 CADICAL_assert (stats.now.eliminated > 0);
106 stats.now.eliminated--;
107#ifdef LOGGING
108 msg = "eliminated";
109#endif
110 break;
112#ifdef LOGGING
113 msg = "substituted";
114#endif
115 CADICAL_assert (stats.now.substituted > 0);
116 stats.now.substituted--;
117 break;
118 case Flags::PURE:
119#ifdef LOGGING
120 msg = "pure literal";
121#endif
122 CADICAL_assert (stats.now.pure > 0);
123 stats.now.pure--;
124 break;
125 }
126#ifdef LOGGING
127 CADICAL_assert (msg);
128 LOG ("reactivate previously %s %d", msg, abs (lit));
129#endif
130 f.status = Flags::ACTIVE;
131 f.sweep = false;
133 stats.reactivated++;
134 CADICAL_assert (stats.inactive > 0);
135 stats.inactive--;
136 stats.active++;
137}
Here is the call graph for this function:

◆ real_time()

double CaDiCaL::Internal::real_time ( ) const

Definition at line 101 of file cadical_resources.cpp.

101 {
102 return absolute_real_time () - stats.time.real;
103}
double absolute_real_time()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ recompute_glue()

int CaDiCaL::Internal::recompute_glue ( Clause * c)

Definition at line 210 of file cadical_analyze.cpp.

210 {
211 int res = 0;
212 const int64_t stamp = ++stats.recomputed;
213 for (const auto &lit : *c) {
214 int level = var (lit).level;
215 CADICAL_assert (gtab[level] <= stamp);
216 if (gtab[level] == stamp)
217 continue;
218 gtab[level] = stamp;
219 res++;
220 }
221 return res;
222}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ recompute_tier()

void CaDiCaL::Internal::recompute_tier ( )

Definition at line 9 of file cadical_tier.cpp.

9 {
10 if (!opts.recomputetier)
11 return;
12
13 ++stats.tierecomputed;
14 const int64_t delta =
15 stats.tierecomputed >= 16 ? 1u << 16 : (1u << stats.tierecomputed);
16 lim.recompute_tier = stats.conflicts + delta;
17 LOG ("rescheduling in %zd at %zd (conflicts at %zd)", delta,
18 lim.recompute_tier, stats.conflicts);
19#ifndef CADICAL_NDEBUG
20 uint64_t total_used = 0;
21 for (auto u : stats.used[stable])
22 total_used += u;
23 CADICAL_assert (total_used == stats.bump_used[stable]);
24#endif
25
26 if (!stats.bump_used[stable]) {
27 tier1[stable] = opts.reducetier1glue;
28 tier2[stable] = opts.reducetier2glue;
29 LOG ("tier1 limit = %d", tier1[stable]);
30 LOG ("tier2 limit = %d", tier2[stable]);
31 return;
32 } else {
33 uint64_t accumulated_tier1_limit =
34 stats.bump_used[stable] * opts.tier1limit / 100;
35 uint64_t accumulated_tier2_limit =
36 stats.bump_used[stable] * opts.tier2limit / 100;
37 uint64_t accumulated_used = 0;
38 for (size_t glue = 0; glue < stats.used[stable].size (); ++glue) {
39 const uint64_t u = stats.used[stable][glue];
40 accumulated_used += u;
41 if (accumulated_used <= accumulated_tier1_limit) {
42 tier1[stable] = glue;
43 }
44 if (accumulated_used >= accumulated_tier2_limit) {
45 tier2[stable] = glue;
46 break;
47 }
48 }
49 }
50
51 LOG ("tier1 limit = %d in %s mode", tier1[stable],
52 stable ? "stable" : "focused");
53 LOG ("tier2 limit = %d in %s mode", tier2[stable],
54 stable ? "stable" : "focused");
55}
Here is the caller graph for this function:

◆ reduce()

void CaDiCaL::Internal::reduce ( )

Definition at line 217 of file cadical_reduce.cpp.

217 {
218 START (reduce);
219
220 stats.reductions++;
221 report ('.', 1);
222
223 bool flush = flushing ();
224 if (flush)
225 stats.flush.count++;
226
228 goto DONE;
229
232 if (flush)
234 else
237
238 {
239 int64_t delta = opts.reduceint;
240 double factor = stats.reductions + 1;
241 if (opts.reduceopt ==
242 0) // adjust delta such this is the same as reduceopt=1
243 delta = delta * delta / 2;
244 else if (opts.reduceopt == 1) {
245 // this is the same as reduceopt=0 if reduceint = sqrt (reduceint) =
246 // 17
247 factor = sqrt ((double) stats.conflicts);
248 } else if (opts.reduceopt == 2)
249 // log scaling instead
250 factor = log ((double) stats.conflicts);
251 if (factor < 1)
252 factor = 1;
253 delta = delta * factor;
254 if (irredundant () > 1e5) {
255 delta *= log (irredundant () / 1e4) / log (10);
256 }
257 if (delta < 1)
258 delta = 1;
259 lim.reduce = stats.conflicts + delta;
260 PHASE ("reduce", stats.reductions,
261 "new reduce limit %" PRId64 " after %" PRId64 " conflicts",
262 lim.reduce, delta);
263 }
264
265 if (flush) {
266 PHASE ("flush", stats.flush.count, "new flush increment %" PRId64 "",
267 inc.flush);
268 inc.flush *= opts.flushfactor;
269 lim.flush = stats.conflicts + inc.flush;
270 PHASE ("flush", stats.flush.count, "new flush limit %" PRId64 "",
271 lim.flush);
272 }
273
274 last.reduce.conflicts = stats.conflicts;
275
276DONE:
277
278 report (flush ? 'f' : '-');
279 STOP (reduce);
280}
bool propagate_out_of_order_units()
void mark_useless_redundant_clauses_as_garbage()
void mark_clauses_to_be_flushed()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reducing()

bool CaDiCaL::Internal::reducing ( )

Definition at line 18 of file cadical_reduce.cpp.

18 {
19 if (!opts.reduce)
20 return false;
21 if (!stats.current.redundant)
22 return false;
23 return stats.conflicts >= lim.reduce;
24}
Here is the caller graph for this function:

◆ redundant()

int64_t CaDiCaL::Internal::redundant ( ) const
inline

Definition at line 381 of file internal.hpp.

381{ return stats.current.redundant; }
Here is the caller graph for this function:

◆ release_quotients()

void CaDiCaL::Internal::release_quotients ( Factoring & factoring)

Definition at line 173 of file cadical_factor.cpp.

173 {
174 for (Quotient *q = factoring.quotients.first, *next; q; q = next) {
175 next = q->next;
176 int factor = q->factor;
179 delete q;
180 }
182}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ release_sweeper()

void CaDiCaL::Internal::release_sweeper ( Sweeper & sweeper)

Definition at line 275 of file cadical_sweep.cpp.

275 {
276
278 delete[] sweeper.reprs;
279
287 erase_vector (sweeper.prev_units);
288 for (unsigned i = 0; i < 2; i++)
290
292 citten = 0;
293 stats.ticks.sweep += sweeper.current_ticks;
295 return;
296}
void cadical_kitten_release(cadical_kitten *cadical_kitten)
unsigneds clause
Definition sweep.c:30
Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove_falsified_literals()

void CaDiCaL::Internal::remove_falsified_literals ( Clause * c)

Definition at line 44 of file cadical_collect.cpp.

44 {
45 const const_literal_iterator end = c->end ();
47 int num_non_false = 0;
48 for (i = c->begin (); num_non_false < 2 && i != end; i++)
49 if (fixed (*i) >= 0)
50 num_non_false++;
51 if (num_non_false < 2)
52 return;
53 if (proof) {
54 // Flush changes the clause id, external forgettables need to be
55 // marked here (or the new id could be used instead of old one)
56 if (opts.check && is_external_forgettable (c->id))
58 proof->flush_clause (c);
59 }
60 literal_iterator j = c->begin ();
61 for (i = j; i != end; i++) {
62 const int lit = *j++ = *i, tmp = fixed (lit);
63 CADICAL_assert (tmp <= 0);
64 if (tmp >= 0)
65 continue;
66 LOG ("flushing %d", lit);
67 j--;
68 }
69 stats.collected += shrink_clause (c, j - c->begin ());
70}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove_garbage_binaries()

void CaDiCaL::Internal::remove_garbage_binaries ( )

Definition at line 477 of file cadical_collect.cpp.

477 {
478 if (unsat)
479 return;
480 START (collect);
481
484 int backtrack_level = level + 1;
485 Watches saved;
486 for (auto v : vars) {
487 for (auto lit : {-v, v}) {
488 CADICAL_assert (saved.empty ());
489 Watches &ws = watches (lit);
490 const const_watch_iterator end = ws.end ();
491 watch_iterator j = ws.begin ();
493 for (i = j; i != end; i++) {
494 Watch w = *i;
495 *j++ = w;
496 Clause *c = w.clause;
497 COVER (!w.binary () && c->size == 2);
498 if (!w.binary ())
499 continue;
500 if (c->reason && c->garbage) {
501 COVER (true);
502 CADICAL_assert (c->size == 2);
503 backtrack_level =
504 min (backtrack_level, var (c->literals[0]).level);
505 LOG ("need to backtrack to before level %d", backtrack_level);
506 --j;
507 continue;
508 }
509 if (!c->collect ())
510 continue;
511 LOG (c, "removing from watch list");
512 --j;
513 }
514 ws.resize (j - ws.begin ());
515 shrink_vector (ws);
516 }
517 }
520 if (backtrack_level - 1 < level)
521 backtrack (backtrack_level - 1);
522 STOP (collect);
523}
Here is the call graph for this function:

◆ remove_observed_var()

void CaDiCaL::Internal::remove_observed_var ( int ilit)

Definition at line 45 of file cadical_external_propagate.cpp.

45 {
46 if (!fixed (ilit) && level) {
47 backtrack ();
48 }
49
50 CADICAL_assert (fixed (ilit) || !level);
51
52 const int idx = vidx (ilit);
53 CADICAL_assert ((size_t) idx < relevanttab.size ());
54 unsigned &ref = relevanttab[idx];
55 CADICAL_assert (fixed (ilit) || ref > 0);
56 if (fixed (ilit))
57 ref = 0;
58 else if (ref < UINT_MAX) {
59 if (!--ref) {
60 LOG ("variable %d is not observed anymore", idx);
61 } else
62 LOG ("variable %d is unobserved once but remains observed %u times",
63 ilit, ref);
64 } else
65 LOG ("variable %d remains observed forever", idx);
66}
Here is the call graph for this function:

◆ renotify_full_trail()

void CaDiCaL::Internal::renotify_full_trail ( )

Definition at line 130 of file cadical_external_propagate.cpp.

130 {
131 const size_t end_of_trail = trail.size ();
132 if (level) {
133 notified = 0; // TODO: save the last notified root-level position
134 // somewhere and use it here
136 }
137 std::vector<int> assigned;
138
139 int prev_max_level = 0;
140 int current_level = 0;
141 int propagator_level = 0;
142
143 while (notified < end_of_trail) {
144 int ilit = trail[notified++];
145 // In theory, 0 ilit can happen due to pseudo-decision levels
146 if (!ilit)
147 current_level = prev_max_level + 1;
148 else
149 current_level = var (ilit).level;
150
151 if (current_level > propagator_level) {
152 if (assigned.size ())
153 external->propagator->notify_assignment (assigned);
154 while (current_level > propagator_level) {
155 external->propagator->notify_new_decision_level ();
156 propagator_level++;
157 }
158 assigned.clear ();
159 }
160 // Current level can be smaller than prev_max_level due to chrono
161 if (current_level > prev_max_level)
162 prev_max_level = current_level;
163
164 if (!observed (ilit))
165 continue;
166
167 int elit = externalize (ilit); // TODO: double-check tainting
168 CADICAL_assert (elit);
169 // Fixed variables might get mapped (during compact) to another
170 // non-observed but fixed variable.
171 // This happens on root level, so notification about their assignment is
172 // already done.
173 CADICAL_assert (external->observed (elit) || fixed (ilit));
174 if (!external->ervars[abs (elit)])
175 assigned.push_back (elit);
176 }
177 if (assigned.size ())
178 external->propagator->notify_assignment (assigned);
179 assigned.clear ();
180
181 // In case there are some left over empty levels on the top of the trail,
182 // the external propagtor must be notified about them so the levels are
183 // synced
184 while (level > propagator_level) {
185 external->propagator->notify_new_decision_level ();
186 propagator_level++;
187 }
188
189 return;
190}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ renotify_trail_after_ilb()

void CaDiCaL::Internal::renotify_trail_after_ilb ( )

Definition at line 101 of file cadical_external_propagate.cpp.

101 {
102 if (!external_prop || external_prop_is_lazy || !trail.size () ||
103 !opts.ilb) {
104 return;
105 }
106 LOG ("notify external propagator about new assignments (after ilb)");
107#ifndef CADICAL_NDEBUG
108 LOG ("(decision level: %d, trail size: %zd, notified %zd)", level,
109 trail.size (), notified);
110#endif
112}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ renotify_trail_after_local_search()

void CaDiCaL::Internal::renotify_trail_after_local_search ( )

Definition at line 114 of file cadical_external_propagate.cpp.

114 {
115 if (!external_prop || external_prop_is_lazy || !trail.size ()) {
116 return;
117 }
118 LOG ("notify external propagator about new assignments (after local "
119 "search)");
120#ifndef CADICAL_NDEBUG
121 LOG ("(decision level: %d, trail size: %zd, notified %zd)", level,
122 trail.size (), notified);
123#endif
125}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rephase()

void CaDiCaL::Internal::rephase ( )

Definition at line 108 of file cadical_rephase.cpp.

108 {
109
110 stats.rephased.total++;
111 PHASE ("rephase", stats.rephased.total,
112 "reached rephase limit %" PRId64 " after %" PRId64 " conflicts",
113 lim.rephase, stats.conflicts);
114
115 // Report current 'target' and 'best' and then set 'rephased' below, which
116 // will trigger reporting the new 'target' and 'best' after updating it in
117 // the next 'update_target_and_best' called from the next 'backtrack'.
118 //
119 report ('~', 1);
120
121 backtrack ();
122 clear_phases (phases.target);
123 target_assigned = 0;
124
125 size_t count = lim.rephased[stable]++;
126 bool single;
127 char type;
128
129 if (opts.stabilize && opts.stabilizeonly)
130 single = true;
131 else
132 single = !opts.stabilize;
133
134 if (single && !opts.walk) {
135 // (inverted,best,flipping,best,random,best,original,best)^\omega
136 switch (count % 8) {
137 case 0:
139 break;
140 case 1:
141 type = rephase_best ();
142 break;
143 case 2:
145 break;
146 case 3:
147 type = rephase_best ();
148 break;
149 case 4:
150 type = rephase_random ();
151 break;
152 case 5:
153 type = rephase_best ();
154 break;
155 case 6:
157 break;
158 case 7:
159 type = rephase_best ();
160 break;
161 default:
162 type = 0;
163 break;
164 }
165 } else if (single && opts.walk) {
166 // (inverted,best,walk,
167 // flipping,best,walk,
168 // random,best,walk,
169 // original,best,walk)^\omega
170 switch (count % 12) {
171 case 0:
173 break;
174 case 1:
175 type = rephase_best ();
176 break;
177 case 2:
178 type = rephase_walk ();
179 break;
180 case 3:
182 break;
183 case 4:
184 type = rephase_best ();
185 break;
186 case 5:
187 type = rephase_walk ();
188 break;
189 case 6:
190 type = rephase_random ();
191 break;
192 case 7:
193 type = rephase_best ();
194 break;
195 case 8:
196 type = rephase_walk ();
197 break;
198 case 9:
200 break;
201 case 10:
202 type = rephase_best ();
203 break;
204 case 11:
205 type = rephase_walk ();
206 break;
207 default:
208 type = 0;
209 break;
210 }
211 } else if (stable && !opts.walk) {
212 // original,inverted,(best,original,best,inverted)^\omega
213 if (!count)
215 else if (count == 1)
217 else
218 switch ((count - 2) % 4) {
219 case 0:
220 type = rephase_best ();
221 break;
222 case 1:
224 break;
225 case 2:
226 type = rephase_best ();
227 break;
228 case 3:
230 break;
231 default:
232 type = 0;
233 break;
234 }
235 } else if (stable && opts.walk) {
236 // original,inverted,(best,walk,original,best,walk,inverted)^\omega
237 if (!count)
239 else if (count == 1)
241 else
242 switch ((count - 2) % 6) {
243 case 0:
244 type = rephase_best ();
245 break;
246 case 1:
247 type = rephase_walk ();
248 break;
249 case 2:
251 break;
252 case 3:
253 type = rephase_best ();
254 break;
255 case 4:
256 type = rephase_walk ();
257 break;
258 case 5:
260 break;
261 default:
262 type = 0;
263 break;
264 }
265 } else if (!stable && (!opts.walk || !opts.walknonstable)) {
266 // flipping,(random,best,flipping,best)^\omega
267 if (!count)
269 else
270 switch ((count - 1) % 4) {
271 case 0:
272 type = rephase_random ();
273 break;
274 case 1:
275 type = rephase_best ();
276 break;
277 case 2:
279 break;
280 case 3:
281 type = rephase_best ();
282 break;
283 default:
284 type = 0;
285 break;
286 }
287 } else {
288 CADICAL_assert (!stable && opts.walk && opts.walknonstable);
289 // flipping,(random,best,walk,flipping,best,walk)^\omega
290 if (!count)
292 else
293 switch ((count - 1) % 6) {
294 case 0:
295 type = rephase_random ();
296 break;
297 case 1:
298 type = rephase_best ();
299 break;
300 case 2:
301 type = rephase_walk ();
302 break;
303 case 3:
305 break;
306 case 4:
307 type = rephase_best ();
308 break;
309 case 5:
310 type = rephase_walk ();
311 break;
312 default:
313 type = 0;
314 break;
315 }
316 }
318
319 int64_t delta = opts.rephaseint * (stats.rephased.total + 1);
320 lim.rephase = stats.conflicts + delta;
321
322 PHASE ("rephase", stats.rephased.total,
323 "new rephase limit %" PRId64 " after %" PRId64 " conflicts",
324 lim.rephase, delta);
325
326 // This will trigger to report the effect of this new set of phases at the
327 // 'backtrack' (actually 'update_target_and_best') after the next
328 // conflict, as well as resetting 'best_assigned' then to allow to compute
329 // a new "best" assignment at that point.
330 //
331 last.rephase.conflicts = stats.conflicts;
332 rephased = type;
333
334 if (stable)
336 else
337 shuffle_queue ();
338}
type
CUBE COVER and CUBE typedefs ///.
Definition exor.h:90
void clear_phases(vector< signed char > &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rephase_best()

char CaDiCaL::Internal::rephase_best ( )

Definition at line 85 of file cadical_rephase.cpp.

85 {
86 stats.rephased.best++;
87 PHASE ("rephase", stats.rephased.total,
88 "overwriting saved phases by best phases");
89 signed char val;
90 for (auto idx : vars)
91 if ((val = phases.best[idx]))
92 phases.saved[idx] = val;
93 return 'B';
94}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rephase_flipping()

char CaDiCaL::Internal::rephase_flipping ( )

Definition at line 61 of file cadical_rephase.cpp.

61 {
62 stats.rephased.flipped++;
63 PHASE ("rephase", stats.rephased.total,
64 "flipping all phases individually");
65 for (auto idx : vars)
66 phases.saved[idx] *= -1;
67 return 'F';
68}
Here is the caller graph for this function:

◆ rephase_inverted()

char CaDiCaL::Internal::rephase_inverted ( )

Definition at line 49 of file cadical_rephase.cpp.

49 {
50 stats.rephased.inverted++;
51 signed char val = opts.phase ? -1 : 1; // original = -initial
52 PHASE ("rephase", stats.rephased.total,
53 "switching to inverted original phase %d", val);
54 for (auto idx : vars)
55 phases.saved[idx] = val;
56 return 'I';
57}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rephase_original()

char CaDiCaL::Internal::rephase_original ( )

Definition at line 37 of file cadical_rephase.cpp.

37 {
38 stats.rephased.original++;
39 signed char val = opts.phase ? 1 : -1; // original = initial
40 PHASE ("rephase", stats.rephased.total, "switching to original phase %d",
41 val);
42 for (auto idx : vars)
43 phases.saved[idx] = val;
44 return 'O';
45}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rephase_random()

char CaDiCaL::Internal::rephase_random ( )

Definition at line 72 of file cadical_rephase.cpp.

72 {
73 stats.rephased.random++;
74 PHASE ("rephase", stats.rephased.total, "resetting all phases randomly");
75 Random random (opts.seed); // global seed
76 random += stats.rephased.random; // different every time
77 for (auto idx : vars)
78 phases.saved[idx] = random.generate_bool () ? -1 : 1;
79 return '#';
80}
long random()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rephase_walk()

char CaDiCaL::Internal::rephase_walk ( )

Definition at line 98 of file cadical_rephase.cpp.

98 {
99 stats.rephased.walk++;
100 PHASE ("rephase", stats.rephased.total,
101 "starting local search to improve current phase");
102 walk ();
103 return 'W';
104}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rephasing()

bool CaDiCaL::Internal::rephasing ( )

Definition at line 25 of file cadical_rephase.cpp.

25 {
26 if (!opts.rephase)
27 return false;
28 if (opts.forcephase)
29 return false;
30 return stats.conflicts > lim.rephase;
31}
Here is the caller graph for this function:

◆ report()

void CaDiCaL::Internal::report ( char type,
int verbose_level = 0 )

Definition at line 296 of file cadical_report.cpp.

296{}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ report_solving()

void CaDiCaL::Internal::report_solving ( int res)

Definition at line 959 of file cadical_internal.cpp.

959 {
960 if (res == 10)
961 report ('1');
962 else if (res == 20)
963 report ('0');
964 else
965 report ('?');
966}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ require_mode()

void CaDiCaL::Internal::require_mode ( Mode m) const
inline

Definition at line 173 of file internal.hpp.

173{ CADICAL_assert (mode & m), (void) m; }
Here is the caller graph for this function:

◆ rescale_variable_scores()

void CaDiCaL::Internal::rescale_variable_scores ( )

Definition at line 89 of file cadical_analyze.cpp.

89 {
90 stats.rescored++;
91 double divider = score_inc;
92 for (auto idx : vars) {
93 const double tmp = stab[idx];
94 if (tmp > divider)
95 divider = tmp;
96 }
97 PHASE ("rescore", stats.rescored, "rescoring %d variable scores by 1/%g",
98 max_var, divider);
99 CADICAL_assert (divider > 0);
100 double factor = 1.0 / divider;
101 for (auto idx : vars)
102 stab[idx] *= factor;
103 score_inc *= factor;
104 PHASE ("rescore", stats.rescored,
105 "new score increment %g after %" PRId64 " conflicts", score_inc,
106 stats.conflicts);
107}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reschedule_previously_remaining()

unsigned CaDiCaL::Internal::reschedule_previously_remaining ( Sweeper & sweeper)

Definition at line 1773 of file cadical_sweep.cpp.

1773 {
1774 unsigned rescheduled = 0;
1775 for (const auto &idx : sweep_schedule) {
1776 Flags &f = flags (idx);
1777 if (!f.active ())
1778 continue;
1779 if (scheduled_variable (sweeper, idx))
1780 continue;
1781 size_t occ;
1782 if (!scheduable_variable (sweeper, idx, &occ)) {
1783 f.sweep = false;
1784 continue;
1785 }
1786 schedule_inner (sweeper, idx);
1787 rescheduled++;
1788 }
1789 sweep_schedule.clear ();
1790 return rescheduled;
1791}
bool scheduled_variable(Sweeper &sweeper, int idx)
bool scheduable_variable(Sweeper &sweeper, int idx, size_t *occ_ptr)
void schedule_inner(Sweeper &sweeper, int idx)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reserve_ids()

void CaDiCaL::Internal::reserve_ids ( int number)

Definition at line 233 of file cadical_internal.cpp.

233 {
234 // return;
235 LOG ("reserving %d ids", number);
236 CADICAL_assert (number >= 0);
238 clause_id = reserved_ids = number;
239 if (proof)
240 proof->begin_proof (reserved_ids);
241}

◆ reset_assumptions()

void CaDiCaL::Internal::reset_assumptions ( )

Definition at line 502 of file cadical_assume.cpp.

502 {
503 for (const auto &lit : assumptions) {
504 Flags &f = flags (lit);
505 const unsigned char bit = bign (lit);
506 f.assumed &= ~bit;
507 f.failed &= ~bit;
508 melt (lit);
509 }
510 LOG ("cleared %zd assumptions", assumptions.size ());
511 assumptions.clear ();
512 marked_failed = true;
513}
void melt(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_bins()

void CaDiCaL::Internal::reset_bins ( )

Definition at line 20 of file cadical_bins.cpp.

20 {
21 CADICAL_assert (!big.empty ());
23 LOG ("reset binary implication graph");
24}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_citten()

void CaDiCaL::Internal::reset_citten ( )

Definition at line 1011 of file cadical_elim.cpp.

1011 {
1012 if (citten) {
1014 citten = 0;
1015 }
1016}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_concluded()

void CaDiCaL::Internal::reset_concluded ( )

Definition at line 485 of file cadical_assume.cpp.

485 {
486 if (proof)
487 proof->reset_assumptions ();
488 if (concluded) {
489 LOG ("reset concluded");
490 concluded = false;
491 }
492 if (conflict_id) {
493 CADICAL_assert (conclusion.size () == 1);
494 return;
495 }
496 conclusion.clear ();
497}

◆ reset_constraint()

void CaDiCaL::Internal::reset_constraint ( )

Definition at line 59 of file cadical_constrain.cpp.

59 {
60 for (auto lit : constraint)
61 melt (lit);
62 LOG ("cleared %zd constraint literals", constraint.size ());
63 constraint.clear ();
64 unsat_constraint = false;
65 marked_failed = true;
66}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_factor_mode()

void CaDiCaL::Internal::reset_factor_mode ( )

Definition at line 111 of file cadical_factor.cpp.

111 {
112 reset_occs ();
113 init_watches ();
115}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_limits()

void CaDiCaL::Internal::reset_limits ( )

Definition at line 124 of file cadical_limit.cpp.

124 {
125 LOG ("reset limits");
126 limit_terminate (0);
127 limit_conflicts (-1);
128 limit_decisions (-1);
131}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_mode()

void CaDiCaL::Internal::reset_mode ( Mode m)
inline

Definition at line 169 of file internal.hpp.

169 {
170 CADICAL_assert (mode & m);
171 mode &= ~m;
172 }
Here is the caller graph for this function:

◆ reset_noccs()

void CaDiCaL::Internal::reset_noccs ( )

Definition at line 50 of file cadical_occs.cpp.

50 {
51 CADICAL_assert (!max_var || !ntab.empty ());
53 LOG ("reset two-sided occurrence counters");
54}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_occs()

void CaDiCaL::Internal::reset_occs ( )

Definition at line 19 of file cadical_occs.cpp.

19 {
22 LOG ("reset occurrence lists");
23}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_shrinkable()

void CaDiCaL::Internal::reset_shrinkable ( )

Definition at line 10 of file cadical_shrink.cpp.

10 {
11#ifdef LOGGING
12 size_t reset = 0;
13#endif
14 for (const auto &lit : shrinkable) {
15 LOG ("resetting lit %i", lit);
16 Flags &f = flags (lit);
17 CADICAL_assert (f.shrinkable);
18 f.shrinkable = false;
19#ifdef LOGGING
20 ++reset;
21#endif
22 }
23 LOG ("resetting %zu shrinkable variables", reset);
24}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_solving()

void CaDiCaL::Internal::reset_solving ( )

Definition at line 968 of file cadical_internal.cpp.

968 {
969 if (termination_forced) {
970
971 // TODO this leads potentially to a data race if the external
972 // user is calling 'terminate' twice within one 'solve' call.
973 // A proper solution would be to guard / protect setting the
974 // 'termination_forced' flag and only allow it during solving and
975 // ignore it otherwise thus also the second time it is called during a
976 // 'solve' call. We could move resetting it also the start of
977 // 'solve'.
978 //
979 termination_forced = false;
980
981 LOG ("reset forced termination");
982 }
983}
Here is the caller graph for this function:

◆ reset_subsume_bits()

void CaDiCaL::Internal::reset_subsume_bits ( )

Definition at line 9 of file cadical_var.cpp.

9 {
10 LOG ("marking all variables as not subsume");
11 for (auto idx : vars)
12 flags (idx).subsume = false;
13}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_watches()

void CaDiCaL::Internal::reset_watches ( )

Definition at line 21 of file cadical_watch.cpp.

21 {
22 CADICAL_assert (!wtab.empty ());
24 LOG ("reset watcher tables");
25}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resize_factoring()

void CaDiCaL::Internal::resize_factoring ( Factoring & factoring,
int lit )

Definition at line 472 of file cadical_factor.cpp.

472 {
473 CADICAL_assert (lit > 0);
474 size_t new_var_size = lit + 1;
475 size_t new_lit_size = 2 * new_var_size;
476 enlarge_zero (factoring.count, new_lit_size);
477}
Here is the caller graph for this function:

◆ resize_unit_clauses_idx()

void CaDiCaL::Internal::resize_unit_clauses_idx ( )

Definition at line 22 of file cadical_proof.cpp.

22 {
23 size_t new_vsize = vsize ? 2 * vsize : 1 + (size_t) max_var;
24 unit_clauses_idx.resize (2 * new_vsize, 0);
25}
Here is the caller graph for this function:

◆ resolve_clauses()

bool CaDiCaL::Internal::resolve_clauses ( Eliminator & eliminator,
Clause * c,
int pivot,
Clause * d,
bool propagate_eagerly )

Definition at line 269 of file cadical_elim.cpp.

271 {
272
273 CADICAL_assert (!c->redundant);
274 CADICAL_assert (!d->redundant);
275
276 stats.elimres++;
277
278 if (c->garbage || d->garbage)
279 return false;
280 if (c->size > d->size) {
281 pivot = -pivot;
282 swap (c, d);
283 }
284
286 CADICAL_assert (clause.empty ());
287
288 int satisfied = 0; // Contains this satisfying literal.
289 int tautological = 0; // Clashing literal if tautological.
290
291 int s = 0; // Actual literals from 'c'.
292 int t = 0; // Actual literals from 'd'.
293
294 // First determine whether the first antecedent is satisfied, add its
295 // literals to 'clause' and mark them (except for 'pivot').
296 //
297 for (const auto &lit : *c) {
298 if (lit == pivot) {
299 s++;
300 continue;
301 }
302 CADICAL_assert (lit != -pivot);
303 const signed char tmp = val (lit);
304 if (tmp > 0) {
305 satisfied = lit;
306 break;
307 } else if (tmp < 0) {
308 if (!lrat)
309 continue;
310 Flags &f = flags (lit);
311 if (f.seen)
312 continue;
313 analyzed.push_back (lit);
314 f.seen = true;
315 int64_t id = unit_id (-lit);
316 lrat_chain.push_back (id);
317 continue;
318 } else
319 mark (lit), clause.push_back (lit), s++;
320 }
321 if (satisfied) {
322 LOG (c, "satisfied by %d antecedent", satisfied);
323 elim_update_removed_clause (eliminator, c, satisfied);
324 mark_garbage (c);
325 clause.clear ();
326 lrat_chain.clear ();
328 unmark (c);
329 return false;
330 }
331
332 // Then determine whether the second antecedent is satisfied, add its
333 // literal to 'clause' and check whether a clashing literal is found, such
334 // that the resolvent would be tautological.
335 //
336 for (const auto &lit : *d) {
337 if (lit == -pivot) {
338 t++;
339 continue;
340 }
341 CADICAL_assert (lit != pivot);
342 signed char tmp = val (lit);
343 if (tmp > 0) {
344 satisfied = lit;
345 break;
346 } else if (tmp < 0) {
347 if (!lrat)
348 continue;
349 Flags &f = flags (lit);
350 if (f.seen)
351 continue;
352 analyzed.push_back (lit);
353 f.seen = true;
354 int64_t id = unit_id (-lit);
355 lrat_chain.push_back (id);
356 continue;
357 } else if ((tmp = marked (lit)) < 0) {
358 tautological = lit;
359 break;
360 } else if (!tmp)
361 clause.push_back (lit), t++;
362 else
363 CADICAL_assert (tmp > 0), t++;
364 }
365
367 unmark (c);
368 const int64_t size = clause.size ();
369
370 if (lrat) {
371 lrat_chain.push_back (d->id);
372 lrat_chain.push_back (c->id);
373 }
374
375 if (satisfied) {
376 LOG (d, "satisfied by %d antecedent", satisfied);
377 elim_update_removed_clause (eliminator, d, satisfied);
378 mark_garbage (d);
379 clause.clear ();
380 lrat_chain.clear ();
381 return false;
382 }
383
384 LOG (c, "first antecedent");
385 LOG (d, "second antecedent");
386
387 if (tautological) {
388 clause.clear ();
389 LOG ("resolvent tautological on %d", tautological);
390 lrat_chain.clear ();
391 return false;
392 }
393
394 if (!size) {
395 clause.clear ();
396 LOG ("empty resolvent");
397 learn_empty_clause (); // already clears lrat_chain.
398 return false;
399 }
400
401 if (size == 1) {
402 int unit = clause[0];
403 LOG ("unit resolvent %d", unit);
404 clause.clear ();
405 assign_unit (unit); // already clears lrat_chain.
406 if (propagate_eagerly)
407 elim_propagate (eliminator, unit);
408 return false;
409 }
410
411 LOG (clause, "resolvent");
412 CADICAL_assert (!lrat || !lrat_chain.empty ());
413
414 // Double self-subsuming resolution. The clauses 'c' and 'd' are
415 // identical except for the pivot which occurs in different phase. The
416 // resolvent subsumes both antecedents.
417
418 if (s > size && t > size) {
419 CADICAL_assert (s == size + 1);
420 CADICAL_assert (t == size + 1);
421 clause.clear ();
422 // LRAT is c + d (+ eventual units)
423 elim_on_the_fly_self_subsumption (eliminator, c, pivot);
424 LOG (d, "double pivot %d on-the-fly self-subsuming resolution", -pivot);
425 stats.elimotfsub++;
426 stats.subsumed++;
427 elim_update_removed_clause (eliminator, d, -pivot);
428 mark_garbage (d);
429 return false;
430 }
431
432 // Single self-subsuming resolution: The pivot can be removed from 'c',
433 // which is implemented by adding a clause which is the same as 'c' but
434 // with 'pivot' removed and then marking 'c' as garbage.
435
436 if (s > size) {
437 CADICAL_assert (s == size + 1);
438 clause.clear ();
439 // LRAT is c + d (+ eventual units)
440 elim_on_the_fly_self_subsumption (eliminator, c, pivot);
441 return false;
442 }
443
444 // Same single self-subsuming resolution situation, but only for 'd'.
445
446 if (t > size) {
447 CADICAL_assert (t == size + 1);
448 clause.clear ();
449 // LRAT is c + d (+ eventual units) -> same.
450 elim_on_the_fly_self_subsumption (eliminator, d, -pivot);
451 return false;
452 }
453 if (propagate_eagerly)
454 lrat_chain.clear ();
455 return true;
456}
void elim_on_the_fly_self_subsumption(Eliminator &, Clause *, int)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ restart()

void CaDiCaL::Internal::restart ( )

Definition at line 147 of file cadical_restart.cpp.

147 {
148 START (restart);
149 stats.restarts++;
150 stats.restartlevels += level;
151 if (stable)
152 stats.restartstable++;
153 LOG ("restart %" PRId64 "", stats.restarts);
155
156 lim.restart = stats.conflicts + opts.restartint;
157 LOG ("new restart limit at %" PRId64 " conflicts", lim.restart);
158
159 report ('R', 2);
160 STOP (restart);
161}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ restarting()

bool CaDiCaL::Internal::restarting ( )

Definition at line 89 of file cadical_restart.cpp.

89 {
90 if (!opts.restart)
91 return false;
92 if ((size_t) level < assumptions.size () + 2)
93 return false;
94 if (stabilizing ())
95 return reluctant;
96 if (stats.conflicts <= lim.restart)
97 return false;
98 double f = averages.current.glue.fast;
99 double margin = (100.0 + opts.restartmargin) / 100.0;
100 double s = averages.current.glue.slow, l = margin * s;
101 LOG ("EMA glue slow %.2f fast %.2f limit %.2f", s, f, l);
102 return l <= f;
103}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ restore_clauses()

int CaDiCaL::Internal::restore_clauses ( )

Definition at line 985 of file cadical_internal.cpp.

985 {
986 int res = 0;
987 if (opts.restoreall <= 1 && external->tainted.empty ()) {
988 LOG ("no tainted literals and nothing to restore");
989 report ('*');
990 } else {
991 report ('+');
992 // remove_garbage_binaries ();
993 external->restore_clauses ();
994 internal->report ('r');
995 if (!unsat && !level && !propagate ()) {
996 LOG ("root level propagation after restore produces conflict");
998 res = 20;
999 }
1000 }
1001 return res;
1002}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reuse_trail()

int CaDiCaL::Internal::reuse_trail ( )

Definition at line 110 of file cadical_restart.cpp.

110 {
111 const int trivial_decisions =
112 assumptions.size ()
113 // Plus 1 if the constraint is satisfied via implications of
114 // assumptions and a pseudo-decision level was introduced.
115 + !control[assumptions.size () + 1].decision;
116 if (!opts.restartreusetrail)
117 return trivial_decisions;
118 int next_decision = next_decision_variable ();
119 CADICAL_assert (1 <= next_decision);
120 int res = trivial_decisions;
121 if (use_scores ()) {
122 while (res < level) {
123 int decision = control[res + 1].decision;
124 if (decision && score_smaller (this) (abs (decision), next_decision))
125 break;
126 res++;
127 }
128 } else {
129 int64_t limit = bumped (next_decision);
130 while (res < level) {
131 int decision = control[res + 1].decision;
132 if (decision && bumped (decision) < limit)
133 break;
134 res++;
135 }
136 }
137 int reused = res - trivial_decisions;
138 if (reused > 0) {
139 stats.reused++;
140 stats.reusedlevels += reused;
141 if (stable)
142 stats.reusedstable++;
143 }
144 return res;
145}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_factorization()

bool CaDiCaL::Internal::run_factorization ( int64_t limit)

Definition at line 772 of file cadical_factor.cpp.

772 {
773 Factoring factoring = Factoring (this, limit);
775 bool done = false;
776#ifndef CADICAL_QUIET
777 unsigned factored = 0;
778#endif
779 int64_t *ticks = &stats.ticks.factor;
780 VERBOSE (3, "factorization limit of %" PRIu64 " ticks", limit - *ticks);
781
782 while (!unsat && !done && !factoring.schedule.empty ()) {
783 const unsigned ufirst = factoring.schedule.pop_front ();
784 LOG ("next factor candidate %d", ufirst);
785 const int first = u2i (ufirst);
786 const int first_idx = vidx (first);
787 if (!active (first_idx))
788 continue;
789 if (!occs (first).size ()) {
790 factoring.schedule.clear ();
791 break;
792 }
793 if (*ticks > limit) {
794 VERBOSE (2, "factorization ticks limit hit");
795 break;
796 }
798 break;
799 Flags &f = flags (first_idx);
800 const unsigned bit = 1u << (first < 0);
801 if (!(f.factor & bit))
802 continue;
803 f.factor &= ~bit;
804 const size_t first_count = first_factor (factoring, first);
805 if (first_count > 1) {
806 for (;;) {
807 unsigned next_count;
808 const int next = next_factor (factoring, &next_count);
809 if (next == 0)
810 break;
811 CADICAL_assert (next_count > 1);
812 if (next_count < 2)
813 break;
814 factorize_next (factoring, next, next_count);
815 }
816 size_t reduction;
817 Quotient *q = best_quotient (factoring, &reduction);
818 if (q && (int) reduction > factoring.bound) {
819 if (apply_factoring (factoring, q)) {
820#ifndef CADICAL_QUIET
821 factored++;
822#endif
823 } else
824 done = true;
825 }
826 }
828 }
829
830 // since we cannot remove elements from the heap we check wether the
831 // first element in the heap has occurences
832 bool completed = factoring.schedule.empty ();
833 if (!completed) {
834 const unsigned idx = factoring.schedule.front ();
835 completed = occs (u2i (idx)).empty ();
836 }
837 // kissat initializes scores for new variables at this point, however
838 // this is actually done already during resize of internal
839#ifndef CADICAL_QUIET
840 report ('f', !factored);
841#endif
842 return completed;
843}
size_t first_factor(Factoring &, int)
Quotient * best_quotient(Factoring &, size_t *)
void factorize_next(Factoring &, int, unsigned)
bool apply_factoring(Factoring &factoring, Quotient *q)
void schedule_factorization(Factoring &)
int next_factor(Factoring &, unsigned *)
void release_quotients(Factoring &)
unsigned bound
Definition factor.c:53
heap schedule
Definition factor.c:62
Here is the call graph for this function:
Here is the caller graph for this function:

◆ satisfied()

bool CaDiCaL::Internal::satisfied ( )

Definition at line 102 of file cadical_decide.cpp.

102 {
103 if ((size_t) level < assumptions.size () + (!!constraint.size ()))
104 return false;
105 if (num_assigned < (size_t) max_var)
106 return false;
107 CADICAL_assert (num_assigned == (size_t) max_var);
108 if (propagated < trail.size ())
109 return false;
110 size_t assigned = num_assigned;
111 return (assigned == (size_t) max_var);
112}
Here is the caller graph for this function:

◆ save_add_clear_core()

void CaDiCaL::Internal::save_add_clear_core ( Sweeper & sweeper)

Definition at line 626 of file cadical_sweep.cpp.

626 {
627 save_core (sweeper, 0);
628 add_core (sweeper, 0);
629 clear_core (sweeper, 0);
630}
void save_core(Sweeper &sweeper, unsigned core)
void clear_core(Sweeper &sweeper, unsigned core_idx)
void add_core(Sweeper &sweeper, unsigned core_idx)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ save_core()

void CaDiCaL::Internal::save_core ( Sweeper & sweeper,
unsigned core )

Definition at line 599 of file cadical_sweep.cpp.

599 {
600 LOG ("saving extracted core[%u] lemmas", core);
601 CADICAL_assert (core == 0 || core == 1);
602 CADICAL_assert (sweeper.core[core].empty ());
603 sweeper.save = core;
605 if (lrat)
606 cadical_kitten_trace_core (citten, &sweeper, save_core_clause_with_lrat);
607 else
609 save_core_clause);
610}
void cadical_kitten_traverse_core_clauses_with_id(cadical_kitten *cadical_kitten, void *state, void(*traverse)(void *state, unsigned, bool learned, size_t, const unsigned *))
unsigned save
Definition sweep.c:27
Here is the call graph for this function:
Here is the caller graph for this function:

◆ scale()

double CaDiCaL::Internal::scale ( double v) const

Definition at line 13 of file cadical_limit.cpp.

13 {
14 const double ratio = clause_variable_ratio ();
15 const double factor = (ratio <= 2) ? 1.0 : log (ratio) / log (2);
16 double res = factor * v;
17 if (res < 1)
18 res = 1;
19 return res;
20}
double clause_variable_ratio() const
Definition internal.hpp:385
Here is the call graph for this function:
Here is the caller graph for this function:

◆ scheduable_variable()

bool CaDiCaL::Internal::scheduable_variable ( Sweeper & sweeper,
int idx,
size_t * occ_ptr )

Definition at line 1726 of file cadical_sweep.cpp.

1727 {
1728 const int lit = idx;
1729 const size_t pos = noccs (lit);
1730 if (!pos)
1731 return false;
1732 const unsigned max_occurrences = sweeper.limit.clauses;
1733 if (pos > max_occurrences)
1734 return false;
1735 const int not_lit = -lit;
1736 const size_t neg = noccs (not_lit);
1737 if (!neg)
1738 return false;
1739 if (neg > max_occurrences)
1740 return false;
1741 *occ_ptr = pos + neg;
1742 return true;
1743}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ schedule_all_other_not_scheduled_yet()

unsigned CaDiCaL::Internal::schedule_all_other_not_scheduled_yet ( Sweeper & sweeper)

Definition at line 1745 of file cadical_sweep.cpp.

1745 {
1747 for (const auto &idx : vars) {
1748 Flags &f = flags (idx);
1749 if (!f.active ())
1750 continue;
1751 if (sweep_incomplete && !f.sweep)
1752 continue;
1753 if (scheduled_variable (sweeper, idx))
1754 continue;
1755 size_t occ;
1756 if (!scheduable_variable (sweeper, idx, &occ)) {
1757 f.sweep = false;
1758 continue;
1759 }
1760 sweep_candidate cand;
1761 cand.rank = occ;
1762 cand.idx = idx;
1763 fresh.push_back (cand);
1764 }
1765 const size_t size = fresh.size ();
1766 CADICAL_assert (size <= UINT_MAX);
1767 sort (fresh.begin (), fresh.end (), rank_sweep_candidate ());
1768 for (auto &cand : fresh)
1769 schedule_outer (sweeper, cand.idx);
1770 return size;
1771}
void sort(T *array, int size, LessThan lt)
Definition Sort.h:58
void schedule_outer(Sweeper &sweeper, int idx)
unsigned rank
Definition sweep.c:1468
unsigned idx
Definition sweep.c:1469
struct sweep_candidate sweep_candidate
Definition sweep.c:1465
Here is the call graph for this function:
Here is the caller graph for this function:

◆ schedule_factorization()

void CaDiCaL::Internal::schedule_factorization ( Factoring & factoring)

Definition at line 753 of file cadical_factor.cpp.

753 {
754 for (const auto &idx : vars) {
755 if (active (idx)) {
756 Flags &f = flags (idx);
757 const int lit = idx;
758 const int not_lit = -lit;
759 if (f.factor & 1)
761 if (f.factor & 2)
763 }
764 }
765#ifndef CADICAL_QUIET
766 size_t size_cands = factoring.schedule.size ();
767 VERBOSE (2, "scheduled %zu factorization candidate literals %.0f %%",
768 size_cands, percent (size_cands, max_var));
769#endif
770}
void update_factor_candidate(Factoring &, int)
unsigned size
Definition heap.h:22
Here is the call graph for this function:
Here is the caller graph for this function:

◆ schedule_inner()

void CaDiCaL::Internal::schedule_inner ( Sweeper & sweeper,
int idx )

Definition at line 946 of file cadical_sweep.cpp.

946 {
947 CADICAL_assert (idx);
948 if (!active (idx))
949 return;
950 const int next = sweeper.next[idx];
951 if (next != 0) {
952 LOG ("rescheduling inner %d as last", idx);
953 const unsigned prev = sweeper.prev[idx];
954 CADICAL_assert (sweeper.prev[next] == idx);
955 sweeper.prev[next] = prev;
956 if (prev == 0) {
958 sweeper.first = next;
959 } else {
960 CADICAL_assert (sweeper.next[prev] == idx);
961 sweeper.next[prev] = next;
962 }
963 const unsigned last = sweeper.last;
964 if (last == 0) {
966 sweeper.first = idx;
967 } else {
969 sweeper.next[last] = idx;
970 }
971 sweeper.prev[idx] = last;
972 sweeper.next[idx] = 0;
973 sweeper.last = idx;
974 } else if (sweeper.last != idx) {
975 LOG ("scheduling inner %d as last", idx);
976 const unsigned last = sweeper.last;
977 if (last == 0) {
979 sweeper.first = idx;
980 } else {
982 sweeper.next[last] = idx;
983 }
984 CADICAL_assert (sweeper.next[idx] == 0);
985 sweeper.prev[idx] = last;
986 sweeper.last = idx;
987 } else
988 LOG ("keeping inner %d scheduled as last", idx);
989}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ schedule_outer()

void CaDiCaL::Internal::schedule_outer ( Sweeper & sweeper,
int idx )

Definition at line 991 of file cadical_sweep.cpp.

991 {
993 CADICAL_assert (active (idx));
994 const int first = sweeper.first;
995 if (first == 0) {
997 sweeper.last = idx;
998 } else {
999 CADICAL_assert (sweeper.prev[first] == 0);
1000 sweeper.prev[first] = idx;
1001 }
1002 CADICAL_assert (sweeper.prev[idx] == 0);
1003 sweeper.next[idx] = first;
1004 sweeper.first = idx;
1005 LOG ("scheduling outer %d as first", idx);
1006}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ schedule_sweeping()

unsigned CaDiCaL::Internal::schedule_sweeping ( Sweeper & sweeper)

Definition at line 1822 of file cadical_sweep.cpp.

1822 {
1823 const unsigned rescheduled = reschedule_previously_remaining (sweeper);
1824 const unsigned fresh = schedule_all_other_not_scheduled_yet (sweeper);
1825 const unsigned scheduled = fresh + rescheduled;
1826 const unsigned incomplete = incomplete_variables ();
1827#ifndef CADICAL_QUIET
1828 PHASE ("sweep", stats.sweep,
1829 "scheduled %u variables %.0f%% "
1830 "(%u rescheduled %.0f%%, %u incomplete %.0f%%)",
1831 scheduled, percent (scheduled, active ()), rescheduled,
1832 percent (rescheduled, scheduled), incomplete,
1833 percent (incomplete, scheduled));
1834#endif
1835 if (incomplete)
1837 else {
1838 if (sweep_incomplete)
1839 stats.sweep_completed++;
1841 }
1842 return scheduled;
1843}
unsigned schedule_all_other_not_scheduled_yet(Sweeper &sweeper)
unsigned incomplete_variables()
unsigned reschedule_previously_remaining(Sweeper &sweeper)
void mark_incomplete(Sweeper &sweeper)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ scheduled_variable()

bool CaDiCaL::Internal::scheduled_variable ( Sweeper & sweeper,
int idx )

Definition at line 942 of file cadical_sweep.cpp.

942 {
943 return sweeper.prev[idx] != 0 || sweeper.first == idx;
944}
Here is the caller graph for this function:

◆ score()

double & CaDiCaL::Internal::score ( int lit)
inline

Definition at line 457 of file internal.hpp.

457{ return stab[vidx (lit)]; }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ search_assign()

void CaDiCaL::Internal::search_assign ( int lit,
Clause * reason )
inline

Definition at line 106 of file cadical_propagate.cpp.

106 {
107
108 if (level)
110
111 const int idx = vidx (lit);
112 const bool from_external = reason == external_reason;
113 CADICAL_assert (!val (idx));
114 CADICAL_assert (!flags (idx).eliminated () || reason == decision_reason ||
115 reason == external_reason);
116 Var &v = var (idx);
117 int lit_level;
118 CADICAL_assert (!lrat || level || reason == external_reason ||
119 reason == decision_reason || !lrat_chain.empty ());
120 // The following cases are explained in the two comments above before
121 // 'decision_reason' and 'assignment_level'.
122 //
123 // External decision reason means that the propagation was done by
124 // an external propagation and the reason clause not known (yet).
125 // In that case it is assumed that the propagation is NOT out of
126 // order (i.e. lit_level = level), because due to lazy explanation,
127 // we can not calculate the real assignment level.
128 // The function assignment_level () will also assign the current level
129 // to literals with external reason.
130 if (!reason)
131 lit_level = 0; // unit
132 else if (reason == decision_reason)
133 lit_level = level, reason = 0;
134 else if (opts.chrono)
135 lit_level = assignment_level (lit, reason);
136 else
137 lit_level = level;
138 if (!lit_level)
139 reason = 0;
140
141 v.level = lit_level;
142 v.trail = trail.size ();
143 v.reason = reason;
145 CADICAL_assert (num_assigned == trail.size ());
146 num_assigned++;
147 if (!lit_level && !from_external)
148 learn_unit_clause (lit); // increases 'stats.fixed'
149 CADICAL_assert (lit_level || !from_external);
150 const signed char tmp = sign (lit);
151 set_val (idx, tmp);
152 CADICAL_assert (val (lit) > 0); // Just a bit paranoid but useful.
153 CADICAL_assert (val (-lit) < 0); // Ditto.
155 phases.saved[idx] = tmp; // phase saving during search
156 trail.push_back (lit);
157#ifdef LOGGING
158 if (!lit_level)
159 LOG ("root-level unit assign %d @ 0", lit);
160 else
161 LOG (reason, "search assign %d @ %d", lit, lit_level);
162#endif
163
164 if (watching ()) {
165 const Watches &ws = watches (-lit);
166 if (!ws.empty ()) {
167 const Watch &w = ws[0];
168#ifndef WIN32
169 __builtin_prefetch (&w, 0, 1);
170#endif
171 }
172 }
173 lrat_chain.clear ();
174}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ search_assign_driving()

void CaDiCaL::Internal::search_assign_driving ( int lit,
Clause * reason )

Definition at line 201 of file cadical_propagate.cpp.

201 {
203 search_assign (lit, c);
205}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ search_assign_external()

void CaDiCaL::Internal::search_assign_external ( int lit)

Definition at line 207 of file cadical_propagate.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ search_assume_decision()

void CaDiCaL::Internal::search_assume_decision ( int decision)

Definition at line 192 of file cadical_propagate.cpp.

192 {
194 CADICAL_assert (propagated == trail.size ());
197 LOG ("search decide %d", lit);
198 search_assign (lit, decision_reason);
199}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ search_limits_hit()

bool CaDiCaL::Internal::search_limits_hit ( )
inline

Definition at line 1843 of file internal.hpp.

1843 {
1846
1847 if (lim.conflicts >= 0 && stats.conflicts >= lim.conflicts) {
1848 LOG ("conflict limit %" PRId64 " reached", lim.conflicts);
1849 return true;
1850 }
1851
1852 if (lim.decisions >= 0 && stats.decisions >= lim.decisions) {
1853 LOG ("decision limit %" PRId64 " reached", lim.decisions);
1854 return true;
1855 }
1856
1857 return false;
1858}
Here is the caller graph for this function:

◆ second_literal_in_binary_clause()

int CaDiCaL::Internal::second_literal_in_binary_clause ( Eliminator & eliminator,
Clause * c,
int first )

Definition at line 24 of file cadical_gates.cpp.

25 {
26 CADICAL_assert (!c->garbage);
27 int second = 0;
28 for (const auto &lit : *c) {
29 if (lit == first)
30 continue;
31 const signed char tmp = val (lit);
32 if (tmp < 0)
33 continue;
34 if (tmp > 0) {
35 mark_garbage (c);
36 elim_update_removed_clause (eliminator, c);
37 return 0;
38 }
39 if (second) {
40 second = INT_MIN;
41 break;
42 }
43 second = lit;
44 }
45 if (!second)
46 return 0;
47 if (second == INT_MIN)
48 return 0;
49 CADICAL_assert (active (second));
50#ifdef LOGGING
51 if (c->size == 2)
52 LOG (c, "found binary");
53 else
54 LOG (c, "found actual binary %d %d", first, second);
55#endif
56 return second;
57}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ second_literal_in_binary_clause_lrat()

int CaDiCaL::Internal::second_literal_in_binary_clause_lrat ( Clause * c,
int first )

Definition at line 63 of file cadical_gates.cpp.

63 {
64 if (c->garbage)
65 return 0;
66 int second = 0;
67 for (const auto &lit : *c) {
68 if (lit == first)
69 continue;
70 const signed char tmp = val (lit);
71 if (tmp < 0)
72 continue;
73 if (tmp > 0)
74 return 0;
75 if (!tmp) {
76 if (second) {
77 second = INT_MIN;
78 break;
79 }
80 second = lit;
81 }
82 }
83 if (!second)
84 return 0;
85 if (second == INT_MIN)
86 return 0;
87 return second;
88}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ self_subsuming_factor()

bool CaDiCaL::Internal::self_subsuming_factor ( Quotient * q)

Definition at line 566 of file cadical_factor.cpp.

566 {
567 Quotient *x = 0, *y = 0;
568 bool found = false;
569 for (Quotient *p = q; p; p = p->prev) {
570 const int factor = p->factor;
571 Flags &f = flags (factor);
572 if (f.seen) {
573 CADICAL_assert (std::find (analyzed.begin (), analyzed.end (), -factor) !=
574 analyzed.end ());
575 found = true;
576 x = p;
577 for (Quotient *r = q; r; r = r->prev) {
578 if (r->factor != -factor)
579 continue;
580 y = r;
581 break;
582 }
583 break;
584 }
585 analyzed.push_back (factor);
586 f.seen = true;
587 }
588 CADICAL_assert (!found || (x && y));
590 if (found) {
592 return true;
593 }
594 return false;
595}
void add_self_subsuming_factor(Quotient *, Quotient *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_mode()

void CaDiCaL::Internal::set_mode ( Mode m)
inline

Definition at line 165 of file internal.hpp.

165 {
166 CADICAL_assert (!(mode & m));
167 mode |= m;
168 }
Here is the caller graph for this function:

◆ set_parent_reason_literal()

void CaDiCaL::Internal::set_parent_reason_literal ( int lit,
int reason )
inline

Definition at line 42 of file cadical_probe.cpp.

42 {
43 const int idx = vidx (lit);
44 if (lit < 0)
45 reason = -reason;
46 parents[idx] = reason;
47}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_probehbr_lrat()

void CaDiCaL::Internal::set_probehbr_lrat ( int lit,
int uip )

Definition at line 104 of file cadical_probe.cpp.

104 {
105 if (!lrat || opts.probehbr)
106 return;
108 CADICAL_assert (lrat_chain.size ());
109 CADICAL_assert (probehbr_chains[vlit (lit)][vlit (uip)].empty ());
111 lrat_chain.clear ();
112}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_tainted_literal()

void CaDiCaL::Internal::set_tainted_literal ( )

Definition at line 81 of file cadical_external_propagate.cpp.

81 {
82 if (!opts.ilb) {
83 return;
84 }
85 for (auto idx : vars) {
86 if (!val (idx))
87 continue;
88 if (var (idx).reason != external_reason)
89 continue;
90 if (!tainted_literal) {
91 tainted_literal = idx;
92 continue;
93 }
95 if (var (idx).level < var (tainted_literal).level) {
96 tainted_literal = idx;
97 }
98 }
99}
Here is the call graph for this function:

◆ set_val()

void CaDiCaL::Internal::set_val ( int lit,
signed char val )
inline

Definition at line 1528 of file internal.hpp.

1528 {
1529 CADICAL_assert (-1 <= val);
1530 CADICAL_assert (val <= 1);
1534 vals[lit] = val;
1535 vals[-lit] = -val;
1536 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setbit()

void CaDiCaL::Internal::setbit ( int lit,
int bit )
inline

Definition at line 540 of file internal.hpp.

540 {
541 CADICAL_assert (0 <= bit), CADICAL_assert (bit < 6);
542 CADICAL_assert (!getbit (lit, bit));
543 marks[vidx (lit)] |= (1 << bit);
544 CADICAL_assert (getbit (lit, bit));
545 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shrink_along_reason()

unsigned CaDiCaL::Internal::shrink_along_reason ( int uip,
int blevel,
bool resolve_large_clauses,
bool & failed_ptr,
unsigned max_trail )
inline

Definition at line 234 of file cadical_shrink.cpp.

237 {
238 LOG ("shrinking along the reason of lit %i", uip);
239 unsigned open = 0;
240#ifndef CADICAL_NDEBUG
241 const Flags &f = flags (uip);
242#endif
243 const Var &v = var (uip);
244
245 CADICAL_assert (f.shrinkable);
246 CADICAL_assert (v.level == blevel);
247 CADICAL_assert (v.reason);
248
249 if (opts.minimizeticks)
250 stats.ticks.search[stable]++;
251
252 if (resolve_large_clauses || v.reason->size == 2) {
253 const Clause &c = *v.reason;
254 LOG (v.reason, "resolving with reason");
255 for (int lit : c) {
256 if (lit == uip)
257 continue;
258 CADICAL_assert (val (lit) < 0);
259 int tmp = shrink_literal (lit, blevel, max_trail);
260 if (tmp < 0) {
261 failed_ptr = true;
262 break;
263 }
264 if (tmp > 0) {
265 ++open;
266 }
267 }
268 } else {
269 failed_ptr = true;
270 }
271 return open;
272}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shrink_and_minimize_clause()

void CaDiCaL::Internal::shrink_and_minimize_clause ( )

Definition at line 430 of file cadical_shrink.cpp.

430 {
431 CADICAL_assert (opts.minimize || opts.shrink > 0);
432 LOG (clause, "shrink first UIP clause");
433
434 START (shrink);
435 external->check_learned_clause (); // check 1st UIP learned clause first
436 MSORT (opts.radixsortlim, clause.begin (), clause.end (),
437 shrink_trail_negative_rank (this), shrink_trail_larger (this));
438 unsigned total_shrunken = 0;
439 unsigned total_minimized = 0;
440
441 LOG (clause, "shrink first UIP clause (CADICAL_asserting lit: %i)", clause[0]);
442
443 auto rend_lits = clause.rend () - 1;
444 auto rend_block = clause.rbegin ();
445 const int uip0 = clause[0];
446
447 // for direct LRAT we remember how the clause used to look
448 vector<int> old_clause_lrat;
450 if (lrat)
451 for (auto &i : clause)
452 old_clause_lrat.push_back (i);
453
454 while (rend_block != rend_lits) {
455 rend_block = minimize_and_shrink_block (rend_block, total_shrunken,
456 total_minimized, uip0);
457 }
458
459 LOG (clause,
460 "post shrink pass (with uips, not removed) first UIP clause");
461 LOG (old_clause_lrat, "(used for lratdirect) before shrink: clause");
462#if defined(LOGGING) || !defined(CADICAL_NDEBUG)
463 const unsigned old_size = clause.size ();
464#endif
465 std::vector<int> stack;
466 {
467 std::vector<int>::size_type i = 1;
468 for (std::vector<int>::size_type j = 1; j < clause.size (); ++j) {
469 CADICAL_assert (i <= j);
470 clause[i] = clause[j];
471 if (lrat) {
472 CADICAL_assert (j < old_clause_lrat.size ());
473 CADICAL_assert (mini_chain.empty ());
474 if (clause[j] != old_clause_lrat[j]) {
475 calculate_minimize_chain (-old_clause_lrat[j], stack);
476 for (auto p : mini_chain) {
477 minimize_chain.push_back (p);
478 }
479 mini_chain.clear ();
480 }
481 }
482 if (clause[j] == uip0) {
483 continue;
484 }
485 CADICAL_assert (flags (clause[i]).keep);
486 ++i;
487 LOG ("keeping literal %i", clause[j]);
488 }
489 clause.resize (i);
490 }
491 CADICAL_assert (old_size ==
492 (unsigned) clause.size () + total_shrunken + total_minimized);
493 LOG (clause, "after shrinking first UIP clause");
494 LOG ("clause shrunken by %zd literals (including %u minimized)",
495 old_size - clause.size (), total_minimized);
496
497 stats.shrunken += total_shrunken;
498 stats.minishrunken += total_minimized;
499 STOP (shrink);
500
501 START (minimize);
503 for (auto p = minimize_chain.rbegin (); p != minimize_chain.rend ();
504 p++) {
505 lrat_chain.push_back (*p);
506 }
507 minimize_chain.clear ();
508 STOP (minimize);
509}
std::vector< int >::reverse_iterator minimize_and_shrink_block(std::vector< int >::reverse_iterator &, unsigned int &, unsigned int &, const int)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shrink_block()

unsigned CaDiCaL::Internal::shrink_block ( std::vector< int >::reverse_iterator & rbegin_lits,
std::vector< int >::reverse_iterator & rend_block,
int blevel,
unsigned & open,
unsigned & block_minimized,
const int uip0,
unsigned max_trail )

Definition at line 275 of file cadical_shrink.cpp.

279 {
280 CADICAL_assert (shrinkable.empty ());
281 CADICAL_assert (blevel <= this->level);
282 CADICAL_assert (open < clause.size ());
283 CADICAL_assert (rbegin_lits >= clause.rbegin ());
284 CADICAL_assert (rend_block < clause.rend ());
285 CADICAL_assert (rbegin_lits < rend_block);
286 CADICAL_assert (opts.shrink);
287
288#ifdef LOGGING
289
290 LOG ("trying to shrink %u literals on level %u", open, blevel);
291
292 const auto &t = &trail;
293
294 LOG ("maximum trail position %zd on level %u", t->size (), blevel);
295 if (opts.shrinkreap)
296 LOG ("shrinking up to %u", max_trail);
297#endif
298
299 const bool resolve_large_clauses = (opts.shrink > 1);
300 bool failed = false;
301 unsigned block_shrunken = 0;
302 std::vector<int>::size_type minimized_start = minimized.size ();
303 int uip = uip0;
304 unsigned max_trail2 = max_trail;
305
306 if (!failed) {
307 push_literals_of_block (rbegin_lits, rend_block, blevel, max_trail);
308 CADICAL_assert (!opts.shrinkreap || reap.size () == open);
309
310 CADICAL_assert (open > 0);
311 while (!failed) {
312 CADICAL_assert (!opts.shrinkreap || reap.size () == open);
313 uip = shrink_next (blevel, open, max_trail);
314 if (open == 0) {
315 break;
316 }
317 open += shrink_along_reason (uip, blevel, resolve_large_clauses,
318 failed, max_trail2);
319 CADICAL_assert (open >= 1);
320 }
321
322 if (!failed)
323 LOG ("shrinking found UIP %i on level %i (open: %d)", uip, blevel,
324 open);
325 else
326 LOG ("shrinking failed on level %i", blevel);
327 }
328
329 if (failed)
330 reset_shrinkable (), shrunken_block_no_uip (rbegin_lits, rend_block,
331 block_minimized, uip0);
332 else
333 block_shrunken = shrunken_block_uip (uip, blevel, rbegin_lits,
334 rend_block, minimized_start, uip0);
335
336 if (opts.shrinkreap)
337 reap.clear ();
338 shrinkable.clear ();
339 return block_shrunken;
340}
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_along_reason(int, int, bool, bool &, unsigned)
unsigned shrink_next(int, unsigned &, unsigned &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shrink_clause()

size_t CaDiCaL::Internal::shrink_clause ( Clause * c,
int new_size )

Definition at line 213 of file cadical_clause.cpp.

213 {
214 if (opts.check && is_external_forgettable (c->id))
216 CADICAL_assert (new_size >= 2);
217 int old_size = c->size;
218 CADICAL_assert (new_size < old_size);
219#ifndef CADICAL_NDEBUG
220 for (int i = c->size; i < new_size; i++)
221 c->literals[i] = 0;
222#endif
223
224 if (c->pos >= new_size)
225 c->pos = 2;
226
227 size_t old_bytes = c->bytes ();
228 c->size = new_size;
229 size_t new_bytes = c->bytes ();
230 size_t res = old_bytes - new_bytes;
231
232 if (c->redundant)
233 promote_clause_glue_only (c, min (c->size - 1, c->glue));
234 else {
235 int delta_size = old_size - new_size;
236 CADICAL_assert (stats.irrlits >= delta_size);
237 stats.irrlits -= delta_size;
238 }
239
241 mark_added (c);
242
243 return res;
244}
void promote_clause_glue_only(Clause *, int new_glue)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shrink_literal()

int CaDiCaL::Internal::shrink_literal ( int lit,
int blevel,
unsigned max_trail )
inline

Definition at line 70 of file cadical_shrink.cpp.

71 {
72 CADICAL_assert (val (lit) < 0);
73
74 Flags &f = flags (lit);
75 Var &v = var (lit);
76 CADICAL_assert (v.level <= blevel);
77
78 if (!v.level) {
79 LOG ("skipping root level assigned %d", (lit));
80 return 0;
81 }
82
83 if (v.reason == external_reason) {
84 CADICAL_assert (!opts.exteagerreasons);
85 v.reason = learn_external_reason_clause (-lit, 0, true);
86 if (!v.reason) {
87 CADICAL_assert (!v.level);
88 return 0;
89 }
90 }
91 CADICAL_assert (v.reason != external_reason);
92 if (f.shrinkable) {
93 LOG ("skipping already shrinkable literal %d", (lit));
94 return 0;
95 }
96
97 if (v.level < blevel) {
98 if (f.removable) {
99 LOG ("skipping removable thus shrinkable %d", (lit));
100 return 0;
101 }
102 const bool always_minimize_on_lower_blevel = (opts.shrink > 2);
103 if (always_minimize_on_lower_blevel && minimize_literal (-lit, 1)) {
104 LOG ("minimized thus shrinkable %d", (lit));
105 return 0;
106 }
107 LOG ("literal %d on lower blevel %u < %u not removable/shrinkable",
108 (lit), v.level, blevel);
109 return -1;
110 }
111
112 LOG ("marking %d as shrinkable", lit);
113 f.shrinkable = true;
114 f.poison = false;
115 shrinkable.push_back (lit);
116 if (opts.shrinkreap) {
117 CADICAL_assert (max_trail < trail.size ());
118 const unsigned dist = max_trail - v.trail;
119 reap.push (dist);
120 }
121 return 1;
122}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shrink_next()

unsigned CaDiCaL::Internal::shrink_next ( int blevel,
unsigned & open,
unsigned & max_trail )
inline

Definition at line 203 of file cadical_shrink.cpp.

204 {
205 const auto &t = &trail;
206 if (opts.shrinkreap) {
207 CADICAL_assert (!reap.empty ());
208 const unsigned dist = reap.pop ();
209 --open;
210 CADICAL_assert (dist <= max_trail);
211 const unsigned pos = max_trail - dist;
212 CADICAL_assert (pos < t->size ());
213 const int uip = (*t)[pos];
214 CADICAL_assert (val (uip) > 0);
215 LOG ("trying to shrink literal %d at trail[%u] and level %d", uip, pos,
216 blevel);
217 return uip;
218 } else {
219 int uip;
220#ifndef CADICAL_NDEBUG
221 unsigned init_max_trail = max_trail;
222#endif
223 do {
224 CADICAL_assert (max_trail <= init_max_trail);
225 uip = (*t)[max_trail--];
226 } while (!flags (uip).shrinkable);
227 --open;
228 LOG ("open is now %d, uip = %d, level %d", open, uip, blevel);
229 return uip;
230 }
231 (void) blevel;
232}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shrunken_block_no_uip()

void CaDiCaL::Internal::shrunken_block_no_uip ( const std::vector< int >::reverse_iterator & rbegin_block,
const std::vector< int >::reverse_iterator & rend_block,
unsigned & block_minimized,
const int uip0 )
inline

Definition at line 161 of file cadical_shrink.cpp.

164 {
165 STOP (shrink);
166 START (minimize);
167 CADICAL_assert (rend_block > rbegin_block);
168 LOG ("no UIP found, now minimizing");
169 for (auto p = rbegin_block; p != rend_block; ++p) {
170 CADICAL_assert (p != clause.rend () - 1);
171 const int lit = *p;
172 if (opts.minimize && minimize_literal (-lit)) {
173 CADICAL_assert (!flags (lit).keep);
174 ++block_minimized;
175 *p = uip0;
176 } else {
177 flags (lit).keep = true;
178 CADICAL_assert (flags (lit).keep);
179 }
180 }
181 STOP (minimize);
182 START (shrink);
183}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shrunken_block_uip()

unsigned CaDiCaL::Internal::shrunken_block_uip ( int uip,
int blevel,
std::vector< int >::reverse_iterator & rbegin_block,
std::vector< int >::reverse_iterator & rend_block,
std::vector< int >::size_type minimized_start,
const int uip0 )

Definition at line 124 of file cadical_shrink.cpp.

127 {
128 CADICAL_assert (clause[0] == uip0);
129
130 LOG ("UIP on level %u, uip: %i (replacing by %i)", blevel, uip, uip0);
131 CADICAL_assert (rend_block > rbegin_block);
132 CADICAL_assert (rend_block < clause.rend ());
133 unsigned block_shrunken = 0;
134 *rbegin_block = -uip;
135 Var &v = var (-uip);
136 Level &l = control[v.level];
137 l.seen.trail = v.trail;
138 l.seen.count = 1;
139
140 Flags &f = flags (-uip);
141 if (!f.seen) {
142 analyzed.push_back (-uip);
143 f.seen = true;
144 }
145
146 flags (-uip).keep = true;
147 for (auto p = rbegin_block + 1; p != rend_block; ++p) {
148 const int lit = *p;
149 if (lit == -uip0)
150 continue;
151 *p = uip0;
152 // if (lit == -uip) continue;
153 ++block_shrunken;
154 CADICAL_assert (clause[0] == uip0);
155 }
156 mark_shrinkable_as_removable (blevel, minimized_start);
157 CADICAL_assert (clause[0] == uip0);
158 return block_shrunken;
159}
void mark_shrinkable_as_removable(int, std::vector< int >::size_type)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shuffle_queue()

void CaDiCaL::Internal::shuffle_queue ( )

Definition at line 64 of file cadical_queue.cpp.

64 {
65 if (!opts.shuffle)
66 return;
67 if (!opts.shufflequeue)
68 return;
69 stats.shuffled++;
70 LOG ("shuffling queue");
71 vector<int> shuffle;
72 if (opts.shufflerandom) {
73 for (int idx = max_var; idx; idx--)
74 shuffle.push_back (idx);
75 Random random (opts.seed); // global seed
76 random += stats.shuffled; // different every time
77 for (int i = 0; i <= max_var - 2; i++) {
78 const int j = random.pick_int (i, max_var - 1);
79 swap (shuffle[i], shuffle[j]);
80 }
81 } else {
82 for (int idx = queue.last; idx; idx = links[idx].prev)
83 shuffle.push_back (idx);
84 }
85 queue.first = queue.last = 0;
86 for (const int idx : shuffle)
87 queue.enqueue (links, idx);
88 int64_t bumped = queue.bumped;
89 for (int idx = queue.last; idx; idx = links[idx].prev)
90 btab[idx] = bumped--;
91 queue.unassigned = queue.last;
92}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shuffle_scores()

void CaDiCaL::Internal::shuffle_scores ( )

Definition at line 22 of file cadical_score.cpp.

22 {
23 if (!opts.shuffle)
24 return;
25 if (!opts.shufflescores)
26 return;
28 stats.shuffled++;
29 LOG ("shuffling scores");
30 vector<int> shuffle;
31 if (opts.shufflerandom) {
32 scores.erase ();
33 for (int idx = max_var; idx; idx--)
34 shuffle.push_back (idx);
35 Random random (opts.seed); // global seed
36 random += stats.shuffled; // different every time
37 for (int i = 0; i <= max_var - 2; i++) {
38 const int j = random.pick_int (i, max_var - 1);
39 swap (shuffle[i], shuffle[j]);
40 }
41 } else {
42 while (!scores.empty ()) {
43 int idx = scores.front ();
44 (void) scores.pop_front ();
45 shuffle.push_back (idx);
46 }
47 }
48 score_inc = 0;
49 for (const auto &idx : shuffle) {
50 stab[idx] = score_inc++;
51 scores.push_back (idx);
52 }
53}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ solve()

int CaDiCaL::Internal::solve ( bool preprocess_only = false)

Definition at line 884 of file cadical_internal.cpp.

884 {
885 CADICAL_assert (clause.empty ());
886 START (solve);
887 if (proof)
888 proof->solve_query ();
889 if (opts.ilb) {
890 if (opts.ilbassumptions)
892 stats.ilbtriggers++;
893 stats.ilbsuccess += (level > 0);
894 stats.levelsreused += level;
895 if (level) {
896 CADICAL_assert (control.size () > 1);
897 stats.literalsreused += num_assigned - control[1].trail;
898 }
899 if (external->propagator)
901 }
902 if (preprocess_only)
903 LOG ("internal solving in preprocessing only mode");
904 else
905 LOG ("internal solving in full mode");
907 int res = already_solved ();
908 if (!res && preprocess_only && level)
909 backtrack ();
910 if (!res)
911 res = restore_clauses ();
912 if (!res || (res == 10 && external_prop)) {
914 if (!preprocess_only)
916 }
917 if (!preprocess_only) {
918 if (!res && !level)
919 res = local_search ();
920 }
921 if (!res && !level)
922 res = preprocess ();
923 if (!preprocess_only) {
924 if (!res && !level)
925 res = local_search ();
926 if (!res && !level)
927 res = lucky_phases ();
928 if (!res || (res == 10 && external_prop)) {
929 if (res == 10 && external_prop && level)
930 backtrack ();
932 }
933 }
934 finalize (res);
935 reset_solving ();
936 report_solving (res);
937 STOP (solve);
938 return res;
939}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ solve_time()

double CaDiCaL::Internal::solve_time ( )

◆ sort_and_reuse_assumptions()

void CaDiCaL::Internal::sort_and_reuse_assumptions ( )

Definition at line 554 of file cadical_assume.cpp.

554 {
555 CADICAL_assert (opts.ilbassumptions);
556 if (assumptions.empty ())
557 return;
558 MSORT (opts.radixsortlim, assumptions.begin (), assumptions.end (),
559 sort_assumptions_positive_rank (this),
560 sort_assumptions_smaller (this));
561
562 unsigned max_level = 0;
563 // assumptions are sorted by level, with unset at the end
564 for (auto lit : assumptions) {
565 if (val (lit))
566 max_level = var (lit).level;
567 else
568 break;
569 }
570
571 const unsigned size = min (level + 1u, max_level + 1);
572 CADICAL_assert ((size_t) level == control.size () - 1);
573 LOG (assumptions, "sorted assumptions");
574 int target = 0;
575 for (unsigned i = 1, j = 0; i < size;) {
576 const Level &l = control[i];
577 const int lit = l.decision;
578 const int alit = assumptions[j];
579 const int lev = i;
580 target = lev;
581 if (val (alit) > 0 &&
582 var (alit).level < lev) { // we can ignore propagated assumptions
583 LOG ("ILB skipping propagation %d", alit);
584 ++j;
585 continue;
586 }
587 if (!lit) { // skip fake decisions
588 target = lev - 1;
589 break;
590 }
591 ++i, ++j;
592 CADICAL_assert (var (lit).level == lev);
593 if (l.decision == alit) {
594 continue;
595 }
596 target = lev - 1;
597 LOG ("first different literal %d on the trail and %d from the "
598 "assumptions",
599 lit, alit);
600 break;
601 }
602 if (target < level)
603 backtrack (target);
604 LOG ("assumptions allow for reuse of trail up to level %d", level);
605 // COVER (target > 1);
606 if ((size_t) level > assumptions.size ())
607 stats.assumptionsreused += assumptions.size ();
608 else
609 stats.assumptionsreused += level;
610}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sort_watches()

void CaDiCaL::Internal::sort_watches ( )

Definition at line 103 of file cadical_watch.cpp.

103 {
105 LOG ("sorting watches");
106 Watches saved;
107 for (auto lit : lits) {
108 Watches &ws = watches (lit);
109
110 const const_watch_iterator end = ws.end ();
111 watch_iterator j = ws.begin ();
113
114 CADICAL_assert (saved.empty ());
115
116 for (i = j; i != end; i++) {
117 const Watch w = *i;
118 if (w.binary ())
119 *j++ = w;
120 else
121 saved.push_back (w);
122 }
123
124 std::copy (saved.cbegin (), saved.cend (), j);
125
126 saved.clear ();
127 }
128}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ stabilizing()

bool CaDiCaL::Internal::stabilizing ( )

Definition at line 22 of file cadical_restart.cpp.

22 {
23 if (!opts.stabilize)
24 return false;
25 if (stable && opts.stabilizeonly)
26 return true;
27 if (!inc.stabilize) {
29 if (stats.conflicts <= lim.stabilize)
30 return false;
31 } else if (stats.ticks.search[stable] <= lim.stabilize)
32 return stable;
33 report (stable ? ']' : '}');
34 if (stable)
35 STOP (stable);
36 else
37 STOP (unstable);
38 const int64_t delta_conflicts =
39 stats.conflicts - last.stabilize.conflicts;
40 const int64_t delta_ticks =
41 stats.ticks.search[stable] - last.stabilize.ticks;
42 const char *current_mode = stable ? "stable" : "unstable";
43 const char *next_mode = stable ? "unstable" : "stable";
44 PHASE ("stabilizing", stats.stabphases,
45 "reached %s stabilization limit %" PRId64 " after %" PRId64
46 " conflicts and %" PRId64 " ticks at %" PRId64
47 " conflicts and %" PRId64 " ticks",
48 current_mode, lim.stabilize, delta_conflicts, delta_ticks,
49 stats.conflicts, stats.ticks.search[stable]);
50 if (!inc.stabilize)
51 inc.stabilize = delta_ticks;
52 if (!inc.stabilize) // rare occurence in incremental calls requiring no
53 // ticks
54 inc.stabilize = 1;
55
56 stable = !stable; // Switch!!!!!
57
58 int64_t next_delta_ticks = inc.stabilize;
59 int64_t stabphases = stats.stabphases + 1;
60 next_delta_ticks *= stabphases * stabphases;
61
62 lim.stabilize = stats.ticks.search[stable] + next_delta_ticks;
63 if (lim.stabilize <= stats.ticks.search[stable])
64 lim.stabilize = stats.ticks.search[stable] + 1;
65
66 if (stable)
67 stats.stabphases++;
68
70 PHASE ("stabilizing", stats.stabphases,
71 "next %s stabilization limit %" PRId64
72 " at ticks interval %" PRId64,
73 next_mode, lim.stabilize, next_delta_ticks);
74 report (stable ? '[' : '{');
75 if (stable)
76 START (stable);
77 else
78 START (unstable);
79 return stable;
80}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ strengthen_clause()

void CaDiCaL::Internal::strengthen_clause ( Clause * c,
int lit )

Definition at line 160 of file cadical_subsume.cpp.

160 {
161 if (opts.check && is_external_forgettable (c->id))
163 stats.strengthened++;
164 CADICAL_assert (c->size > 2);
165 LOG (c, "removing %d in", lit);
166 if (proof) {
167 LOG (lrat_chain, "strengthening clause with chain");
168 proof->strengthen_clause (c, lit, lrat_chain);
169 }
170 if (!c->redundant)
172 auto new_end = remove (c->begin (), c->end (), lit);
173 CADICAL_assert (new_end + 1 == c->end ()), (void) new_end;
174 (void) shrink_clause (c, c->size - 1);
175 // bump_clause2 (c);
176 LOG (c, "strengthened");
177 external->check_shrunken_clause (c);
178}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ substitute_connected_clauses()

void CaDiCaL::Internal::substitute_connected_clauses ( Sweeper & sweeper,
int lit,
int other,
int64_t id )

Definition at line 1051 of file cadical_sweep.cpp.

1052 {
1053 if (unsat)
1054 return;
1055 if (val (lit))
1056 return;
1057 if (val (repr))
1058 return;
1059 LOG ("substituting %d with %d in all irredundant clauses", lit, repr);
1060
1061 CADICAL_assert (lit != repr);
1062 CADICAL_assert (lit != -repr);
1063
1065 CADICAL_assert (active (repr));
1066
1067 uint64_t &ticks = sweeper.current_ticks;
1068
1069 {
1070 ticks += 1 + cache_lines (occs (lit).size (), sizeof (Clause *));
1071 Occs &ns = occs (lit);
1072 auto const begin = ns.begin ();
1073 const auto end = ns.end ();
1074 auto q = begin;
1075 auto p = q;
1076 while (p != end) {
1077 Clause *c = *q++ = *p++;
1078 ticks++;
1079 if (c->garbage)
1080 continue;
1081 CADICAL_assert (clause.empty ());
1082 bool satisfied = false;
1083 bool repr_already_watched = false;
1084 const int not_repr = -repr;
1085#ifndef CADICAL_NDEBUG
1086 bool found = false;
1087#endif
1088 for (const auto &other : *c) {
1089 if (other == lit) {
1090#ifndef CADICAL_NDEBUG
1091 CADICAL_assert (!found);
1092 found = true;
1093#endif
1094 clause.push_back (repr);
1095 continue;
1096 }
1097 CADICAL_assert (other != -lit);
1098 if (other == repr) {
1099 CADICAL_assert (!repr_already_watched);
1100 repr_already_watched = true;
1101 continue;
1102 }
1103 if (other == not_repr) {
1104 satisfied = true;
1105 break;
1106 }
1107 const signed char tmp = val (other);
1108 if (tmp < 0)
1109 continue;
1110 if (tmp > 0) {
1111 satisfied = true;
1112 break;
1113 }
1114 clause.push_back (other);
1115 }
1116 if (satisfied) {
1117 clause.clear ();
1118 mark_garbage (c);
1120 continue;
1121 }
1122 CADICAL_assert (found);
1123 const unsigned new_size = clause.size ();
1124 sweep_substitute_lrat (c, id);
1125 if (new_size == 0) {
1126 LOG (c, "substituted empty clause");
1129 break;
1130 }
1131 ticks++;
1132 if (new_size == 1) {
1133 LOG (c, "reduces to unit");
1134 const int unit = clause[0];
1135 clause.clear ();
1136 assign_unit (unit);
1137 sweeper.propagate.push_back (unit);
1138 mark_garbage (c);
1140 stats.sweep_units++;
1141 break;
1142 }
1143 CADICAL_assert (c->size >= 2);
1144 if (!c->redundant)
1145 mark_removed (c);
1146 uint64_t new_id = ++clause_id;
1147 if (proof) {
1148 proof->add_derived_clause (new_id, c->redundant, clause,
1149 lrat_chain);
1150 proof->delete_clause (c);
1151 }
1152 c->id = new_id;
1153 lrat_chain.clear ();
1154 size_t l;
1155 int *literals = c->literals;
1156 for (l = 0; l < clause.size (); l++)
1157 literals[l] = clause[l];
1158 int flushed = c->size - (int) l;
1159 if (flushed) {
1160 LOG ("flushed %d literals", flushed);
1161 (void) shrink_clause (c, l);
1162 } else if (likely_to_be_kept_clause (c))
1163 mark_added (c);
1164 LOG (c, "substituted");
1165 if (!repr_already_watched) {
1166 occs (repr).push_back (c);
1167 noccs (repr)++;
1168 }
1169 clause.clear ();
1170 q--;
1171 }
1172 while (p != end)
1173 *q++ = *p++;
1174 ns.resize (q - ns.begin ());
1175 }
1176}
void sweep_update_noccs(Clause *c)
void sweep_substitute_lrat(Clause *c, int64_t id)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ subsume()

void CaDiCaL::Internal::subsume ( )

Definition at line 611 of file cadical_subsume.cpp.

611 {
612
613 if (!stats.current.redundant && !stats.current.irredundant)
614 return;
615
616 if (unsat)
617 return;
618
619 backtrack ();
620 if (!propagate ()) {
622 return;
623 }
624
625 stats.subsumephases++;
626
627 if (external_prop) {
629 private_steps = true;
630 }
631
632 if (opts.subsume) {
633 reset_watches ();
634 subsume_round ();
635 init_watches ();
637 if (!unsat && !propagate ()) {
638 LOG ("propagation after subsume rounds results in inconsistency");
640 }
641 }
642
643 transred ();
644 if (external_prop) {
646 private_steps = false;
647 }
648}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ subsume_check()

int CaDiCaL::Internal::subsume_check ( Clause * subsuming,
Clause * subsumed )
inline

Definition at line 78 of file cadical_subsume.cpp.

78 {
79#ifdef CADICAL_NDEBUG
80 (void) subsumed;
81#endif
82 // Only use 'subsumed' for these following CADICAL_assertion checks. Otherwise we
83 // only require that 'subsumed' has all its literals marked.
84 //
85 CADICAL_assert (!subsumed->garbage);
86 CADICAL_assert (!subsuming->garbage);
87 CADICAL_assert (subsuming != subsumed);
88 CADICAL_assert (subsuming->size <= subsumed->size);
89
90 stats.subchecks++;
91 if (subsuming->size == 2)
92 stats.subchecks2++;
93
94 int flipped = 0, prev = 0;
95 bool failed = false;
96 const auto eoc = subsuming->end ();
97 for (auto i = subsuming->begin (); !failed && i != eoc; i++) {
98 int lit = *i;
99 *i = prev;
100 prev = lit;
101 const int tmp = marked (lit);
102 if (!tmp)
103 failed = true;
104 else if (tmp > 0)
105 continue;
106 else if (flipped)
107 failed = true;
108 else
109 flipped = lit;
110 }
111 CADICAL_assert (prev);
112 CADICAL_assert (!subsuming->literals[0]);
113 subsuming->literals[0] = prev;
114 if (failed)
115 return 0;
116
117 if (!flipped)
118 return INT_MIN; // subsumed!!
119 else if (!opts.subsumestr)
120 return 0;
121 else
122 return flipped; // strengthen!!
123}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ subsume_clause()

void CaDiCaL::Internal::subsume_clause ( Clause * subsuming,
Clause * subsumed )
inline

Definition at line 129 of file cadical_subsume.cpp.

129 {
130 stats.subsumed++;
131 CADICAL_assert (subsuming->size <= subsumed->size);
132 LOG (subsumed, "subsumed");
133 if (subsumed->redundant)
134 stats.subred++;
135 else
136 stats.subirr++;
137 if (subsumed->redundant || !subsuming->redundant) {
138 mark_garbage (subsumed);
139 return;
140 }
141 LOG ("turning redundant subsuming clause into irredundant clause");
142 subsuming->redundant = false;
143 if (proof)
144 proof->strengthen (subsuming->id);
145 mark_garbage (subsumed);
146 stats.current.irredundant++;
147 stats.added.irredundant++;
148 stats.irrlits += subsuming->size;
149 CADICAL_assert (stats.current.redundant > 0);
150 stats.current.redundant--;
151 CADICAL_assert (stats.added.redundant > 0);
152 stats.added.redundant--;
153 // ... and keep 'stats.added.total'.
154}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ subsume_round()

bool CaDiCaL::Internal::subsume_round ( )

Definition at line 340 of file cadical_subsume.cpp.

340 {
341
342 if (!opts.subsume)
343 return false;
344 if (unsat)
345 return false;
347 return false;
348 if (!stats.current.redundant && !stats.current.irredundant)
349 return false;
350
352 stats.subsumerounds++;
353
354 int64_t check_limit;
355 if (opts.subsumelimited) {
356 int64_t delta = stats.propagations.search;
357 delta *= 1e-3 * opts.subsumeeffort;
358 if (delta < opts.subsumemineff)
359 delta = opts.subsumemineff;
360 if (delta > opts.subsumemaxeff)
361 delta = opts.subsumemaxeff;
362 delta = max (delta, (int64_t) 2l * active ());
363
364 PHASE ("subsume-round", stats.subsumerounds,
365 "limit of %" PRId64 " subsumption checks", delta);
366
367 check_limit = stats.subchecks + delta;
368 } else {
369 PHASE ("subsume-round", stats.subsumerounds,
370 "unlimited subsumption checks");
371 check_limit = LONG_MAX;
372 }
373
374 int old_marked_candidate_variables_for_elimination = stats.mark.elim;
375
377
378 // Allocate schedule and occurrence lists.
379 //
380 vector<ClauseSize> schedule;
381 init_noccs ();
382
383 // Determine candidate clauses and sort them by size.
384 //
385 int64_t left_over_from_last_subsumption_round = 0;
386
387 for (auto c : clauses) {
388
389 if (c->garbage)
390 continue;
391 if (c->size > opts.subsumeclslim)
392 continue;
394 continue;
395
396 bool fixed = false;
397 int subsume = 0;
398 for (const auto &lit : *c)
399 if (val (lit))
400 fixed = true;
401 else if (flags (lit).subsume)
402 subsume++;
403
404 // If the clause contains a root level assigned (fixed) literal we will
405 // not work on it. This simplifies the code substantially since we do
406 // not have to care about assignments at all. Strengthening becomes
407 // much simpler too.
408 //
409 if (fixed) {
410 LOG (c, "skipping (fixed literal)");
411 continue;
412 }
413
414 // Further, if less than two variables in the clause were added since
415 // the last subsumption round, the clause is ignored too.
416 //
417 if (subsume < 2) {
418 LOG (c, "skipping (only %d added literals)", subsume);
419 continue;
420 }
421
422 if (c->subsume)
423 left_over_from_last_subsumption_round++;
424 schedule.push_back (ClauseSize (c->size, c));
425 for (const auto &lit : *c)
426 noccs (lit)++;
427 }
428 shrink_vector (schedule);
429
430 // Smaller clauses are checked and connected first.
431 //
432 rsort (schedule.begin (), schedule.end (), smaller_clause_size_rank ());
433
434 if (!left_over_from_last_subsumption_round)
435 for (auto cs : schedule)
436 if (cs.clause->size > 2)
437 cs.clause->subsume = true;
438
439#ifndef CADICAL_QUIET
440 int64_t scheduled = schedule.size ();
441 int64_t total = stats.current.irredundant + stats.current.redundant;
442 PHASE ("subsume-round", stats.subsumerounds,
443 "scheduled %" PRId64 " clauses %.0f%% out of %" PRId64 " clauses",
444 scheduled, percent (scheduled, total), total);
445#endif
446
447 // Now go over the scheduled clauses in the order of increasing size and
448 // try to forward subsume and strengthen them. Forward subsumption tries
449 // to find smaller or same size clauses which subsume or might strengthen
450 // the candidate. After the candidate has been processed connect one
451 // of its literals (with smallest number of occurrences at this point) in
452 // a one-watched scheme.
453
454 int64_t subsumed = 0, strengthened = 0, checked = 0;
455
456 vector<Clause *> shrunken;
457 init_occs ();
458 init_bins ();
459
460 for (const auto &s : schedule) {
461
463 break;
464 if (stats.subchecks >= check_limit)
465 break;
466
467 Clause *c = s.clause;
468 CADICAL_assert (!c->garbage);
469
470 checked++;
471
472 // First try to subsume or strengthen this candidate clause. For binary
473 // clauses this could be done much faster by hashing and is costly due
474 // to a usually large number of binary clauses. There is further the
475 // issue, that strengthening binary clauses (through double
476 // self-subsuming resolution) would produce units, which needs much more
477 // care. In the same (lazy) spirit we also ignore clauses with fixed
478 // literals (false or true).
479 //
480 if (c->size > 2 && c->subsume) {
481 c->subsume = false;
482 const int tmp = try_to_subsume_clause (c, shrunken);
483 if (tmp > 0) {
484 subsumed++;
485 continue;
486 }
487 if (tmp < 0)
488 strengthened++;
489 }
490
491 // If not subsumed connect smallest occurring literal, where occurring
492 // means the number of times it was used to connect (as a one-watch) a
493 // previous smaller or equal sized clause. This minimizes the length of
494 // the occurrence lists traversed during 'try_to_subsume_clause'. Also
495 // note that this number is usually way smaller than the number of
496 // occurrences computed before and stored in 'noccs'.
497 //
498 int minlit = 0;
499 int64_t minoccs = 0;
500 size_t minsize = 0;
501 bool subsume = true;
502 bool binary = (c->size == 2 && !c->redundant);
503
504 for (const auto &lit : *c) {
505
506 if (!flags (lit).subsume)
507 subsume = false;
508 const size_t size = binary ? bins (lit).size () : occs (lit).size ();
509 if (minlit && minsize <= size)
510 continue;
511 const int64_t tmp = noccs (lit);
512 if (minlit && minsize == size && tmp <= minoccs)
513 continue;
514 minlit = lit, minsize = size, minoccs = tmp;
515 }
516
517 // If there is a variable in a clause different from is not 'subsume'
518 // (has been added since the last subsumption round), then this clause
519 // can not serve to strengthen or subsume another clause, since all
520 // shrunken or added clauses mark all their variables as 'subsume'.
521 //
522 if (!subsume)
523 continue;
524
525 if (!binary) {
526
527 // If smallest occurring literal occurs too often do not connect.
528 //
529 if (minsize > (size_t) opts.subsumeocclim)
530 continue;
531
532 LOG (c,
533 "watching %d with %zd current and total %" PRId64 " occurrences",
534 minlit, minsize, minoccs);
535
536 occs (minlit).push_back (c);
537
538 // This sorting should give faster failures for assumption checks
539 // since the less occurring variables are put first in a clause and
540 // thus will make it more likely to be found as witness for a clause
541 // not to be subsuming. One could in principle (see also the
542 // discussion on 'subsumption' in our 'Splatz' solver) replace marking
543 // by a kind of merge sort, as also suggested by Bayardo. It would
544 // avoid 'marked' calls and thus might be slightly faster but could
545 // not take benefit of this sorting optimization.
546 //
547 sort (c->begin (), c->end (), subsume_less_noccs (this));
548
549 } else {
550
551 // If smallest occurring literal occurs too often do not connect.
552 //
553 if (minsize > (size_t) opts.subsumebinlim)
554 continue;
555
556 LOG (c,
557 "watching %d with %zd current binary and total %" PRId64
558 " occurrences",
559 minlit, minsize, minoccs);
560
561 const int minlit_pos = (c->literals[1] == minlit);
562 const int other = c->literals[!minlit_pos];
563 bins (minlit).push_back (Bin{other, c->id});
564 }
565 }
566
567 PHASE ("subsume-round", stats.subsumerounds,
568 "subsumed %" PRId64 " and strengthened %" PRId64 " out of %" PRId64
569 " clauses %.0f%%",
570 subsumed, strengthened, scheduled,
571 percent (subsumed + strengthened, scheduled));
572
573 const int64_t remain = schedule.size () - checked;
574 const bool completed = !remain;
575
576 if (completed)
577 PHASE ("subsume-round", stats.subsumerounds,
578 "checked all %" PRId64 " scheduled clauses", checked);
579 else
580 PHASE ("subsume-round", stats.subsumerounds,
581 "checked %" PRId64 " clauses %.0f%% of scheduled (%" PRId64
582 " remain)",
583 checked, percent (checked, scheduled), remain);
584
585 // Release occurrence lists and schedule.
586 //
587 erase_vector (schedule);
588 reset_noccs ();
589 reset_occs ();
590 reset_bins ();
591
592 // Reset all old 'added' flags and mark variables in shrunken
593 // clauses as 'added' for the next subsumption round.
594 //
595 if (completed)
597
598 for (const auto &c : shrunken)
599 mark_added (c);
600 erase_vector (shrunken);
601
602 report ('s', !opts.reportall && !(subsumed + strengthened));
603
605
606 return old_marked_candidate_variables_for_elimination < stats.mark.elim;
607}
int try_to_subsume_clause(Clause *, vector< Clause * > &shrunken)
Bins & bins(int lit)
Definition internal.hpp:464
void reset_subsume_bits()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ swap_averages()

void CaDiCaL::Internal::swap_averages ( )

Definition at line 28 of file cadical_averages.cpp.

28 {
29 LOG ("saving current averages");
30 swap (averages.current, averages.saved);
31 if (!averages.swapped)
33 else
34 LOG ("swapping in previously saved averages");
35 averages.swapped++;
36}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep()

bool CaDiCaL::Internal::sweep ( )

Definition at line 1875 of file cadical_sweep.cpp.

1875 {
1876 if (!opts.sweep)
1877 return false;
1878 if (unsat)
1879 return false;
1881 return false;
1882 if (delaying_sweep.bumpreasons.delay ()) { // TODO need to fix Delay
1883 last.sweep.ticks = stats.ticks.search[0] + stats.ticks.search[1];
1884 return false;
1885 }
1886 delaying_sweep.bumpreasons.bypass_delay ();
1887 SET_EFFORT_LIMIT (tickslimit, sweep, !opts.sweepcomplete);
1888 delaying_sweep.bumpreasons.unbypass_delay ();
1889
1892 stats.sweep++;
1893 uint64_t equivalences = stats.sweep_equivalences;
1894 uint64_t units = stats.sweep_units;
1895 Sweeper sweeper = Sweeper (this);
1896 if (opts.sweepcomplete)
1897 sweeper.limit.ticks = INT64_MAX;
1898 else
1899 sweeper.limit.ticks = tickslimit - stats.ticks.sweep;
1901 const unsigned scheduled = schedule_sweeping (sweeper);
1902 uint64_t swept = 0, limit = 10;
1903 for (;;) {
1904 if (unsat)
1905 break;
1907 break;
1908 if (cadical_kitten_ticks_limit_hit (sweeper, "sweeping loop"))
1909 break;
1910 int idx = next_scheduled (sweeper);
1911 if (idx == 0)
1912 break;
1913 flags (idx).sweep = false;
1914#ifndef CADICAL_QUIET
1915 const char *res =
1916#endif
1917 sweep_variable (sweeper, idx);
1918 VERBOSE (2, "swept[%" PRIu64 "] external variable %d %s", swept,
1919 externalize (idx), res);
1920 if (++swept == limit) {
1921 VERBOSE (2,
1922 "found %" PRIu64 " equivalences and %" PRIu64
1923 " units after sweeping %" PRIu64 " variables ",
1924 stats.sweep_equivalences - equivalences,
1925 stats.sweep_units - units, swept);
1926 limit *= 10;
1927 }
1928 }
1929 VERBOSE (2, "swept %" PRIu64 " variables", swept);
1930 equivalences = stats.sweep_equivalences - equivalences,
1931 units = stats.sweep_units - units;
1932 PHASE ("sweep", stats.sweep,
1933 "found %" PRIu64 " equivalences and %" PRIu64 " units",
1934 equivalences, units);
1935 unschedule_sweeping (sweeper, swept, scheduled);
1937
1938 if (!unsat) {
1939 propagated = 0;
1940 if (!propagate ()) {
1942 }
1943 }
1944
1945 uint64_t eliminated = equivalences + units;
1946 report ('=', !eliminated);
1947
1948 if (relative (eliminated, swept) < 0.001) {
1949 delaying_sweep.bumpreasons.bump_delay ();
1950 } else {
1951 delaying_sweep.bumpreasons.reduce_delay ();
1952 }
1954 return eliminated;
1955}
void unschedule_sweeping(Sweeper &sweeper, unsigned swept, unsigned scheduled)
int next_scheduled(Sweeper &sweeper)
unsigned schedule_sweeping(Sweeper &sweeper)
void release_sweeper(Sweeper &sweeper)
const char * sweep_variable(Sweeper &sweeper, int idx)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_add_clause()

void CaDiCaL::Internal::sweep_add_clause ( Sweeper & sweeper,
unsigned depth )

Definition at line 358 of file cadical_sweep.cpp.

358 {
359 // TODO: CADICAL_assertion fails, check if this an issue or can be avoided
360 // CADICAL_assert (sweeper.clause.size () > 1);
361 for (const auto &lit : sweeper.clause)
364 sweeper.clause.size (), sweeper.clause.data ());
365 sweeper.clause.clear ();
366 if (opts.sweepcountbinary || sweeper.clause.size () > 2)
368}
void citten_clause_with_id(cadical_kitten *cadical_kitten, unsigned id, size_t size, int *elits)
void add_literal_to_environment(Sweeper &sweeper, unsigned depth, int)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_backbone_candidate()

bool CaDiCaL::Internal::sweep_backbone_candidate ( Sweeper & sweeper,
int lit )

Definition at line 843 of file cadical_sweep.cpp.

843 {
844 LOG ("trying backbone candidate %d", lit);
846 if (value) {
847 stats.sweep_fixed_backbone++;
848 CADICAL_assert (value > 0);
849 if (val (lit) <= 0) {
851 } else
852 LOG ("literal %d already fixed", lit);
853 return false;
854 }
855
856 int res = cadical_kitten_status (citten);
857 if (res != 10) {
858 LOG ("not flipping due to status %d != 10", res);
859 }
860 stats.sweep_flip_backbone++;
861 if (res == 10 && sweep_flip (lit)) {
862 stats.sweep_flipped_backbone++;
863 LOG ("flipping %d succeeded", lit);
864 // LOGBACKBONE ("refined backbone candidates");
865 return false;
866 }
867
868 LOG ("flipping %d failed", lit);
869 const int not_lit = -lit;
870 stats.sweep_solved_backbone++;
872 res = sweep_solve ();
873 if (res == 10) {
874 LOG ("sweeping backbone candidate %d failed", lit);
876 stats.sweep_sat_backbone++;
877 return false;
878 }
879
880 if (res == 20) {
881 LOG ("sweep unit %d", lit);
884 stats.sweep_unsat_backbone++;
885 return true;
886 }
887
888 stats.sweep_unknown_backbone++;
889
890 LOG ("sweeping backbone candidate %d failed", lit);
891 return false;
892}
void cadical_kitten_assume_signed(cadical_kitten *cadical_kitten, int elit)
ABC_NAMESPACE_IMPL_START typedef signed char value
signed char cadical_kitten_fixed_signed(cadical_kitten *cadical_kitten, int elit)
void save_add_clear_core(Sweeper &sweeper)
bool sweep_extract_fixed(Sweeper &sweeper, int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_clause()

void CaDiCaL::Internal::sweep_clause ( Sweeper & sweeper,
unsigned depth,
Clause * c )

Definition at line 370 of file cadical_sweep.cpp.

370 {
371 if (c->swept)
372 return;
374 LOG (c, "sweeping[%u]", depth);
375 CADICAL_assert (sweeper.clause.empty ());
376 for (const auto &lit : *c) {
377 const signed char tmp = val (lit);
378 if (tmp > 0) {
379 mark_garbage (c);
381 sweeper.clause.clear ();
382 return;
383 }
384 if (tmp < 0) {
385 if (lrat)
386 sweeper.prev_units[abs (lit)] = true;
387 continue;
388 }
389 sweeper.clause.push_back (lit);
390 }
391 c->swept = true;
392 sweep_add_clause (sweeper, depth);
393 sweeper.clauses.push_back (c);
394}
void sweep_add_clause(Sweeper &sweeper, unsigned depth)
bool can_sweep_clause(Clause *c)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_dense_mode_and_watch_irredundant()

void CaDiCaL::Internal::sweep_dense_mode_and_watch_irredundant ( )

Definition at line 77 of file cadical_sweep.cpp.

77 {
79
80 init_noccs ();
81
82 // mark satisfied irredundant clauses as garbage
83 for (const auto &c : clauses) {
84 if (!can_sweep_clause (c))
85 continue;
86 bool satisfied = false;
87 for (const auto &lit : *c) {
88 const signed char tmp = val (lit);
89 if (tmp <= 0)
90 continue;
91 if (tmp > 0) {
92 satisfied = true;
93 break;
94 }
95 }
96 if (satisfied)
97 mark_garbage (c); // forces more precise counts
98 else {
99 for (const auto &lit : *c)
100 noccs (lit)++;
101 }
102 }
103
104 init_occs ();
105
106 // Connect irredundant clauses.
107 //
108 for (const auto &c : clauses) {
109 if (!c->garbage) {
110 for (const auto &lit : *c)
111 if (active (lit))
112 occs (lit).push_back (c);
113 } else if (c->size == 2) {
114 if (!c->flushed) {
115 if (proof) {
116 c->flushed = true;
117 proof->delete_clause (c);
118 }
119 }
120 }
121 }
122}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_dense_propagate()

void CaDiCaL::Internal::sweep_dense_propagate ( Sweeper & sweeper)

Definition at line 133 of file cadical_sweep.cpp.

133 {
134 vector<int> &work = sweeper.propagate;
135 size_t i = 0;
136 uint64_t &ticks = sweeper.current_ticks;
137 while (i < work.size ()) {
138 int lit = work[i++];
139 LOG ("sweeping propagation of %d", lit);
140 CADICAL_assert (val (lit) > 0);
141 ticks += 1 + cache_lines (occs (-lit).size (), sizeof (Clause *));
142 const Occs &ns = occs (-lit);
143 for (const auto &c : ns) {
144 ticks++;
145 if (!can_sweep_clause (c))
146 continue;
147 int unit = 0, satisfied = 0;
148 for (const auto &other : *c) {
149 const signed char tmp = val (other);
150 if (tmp < 0)
151 continue;
152 if (tmp > 0) {
153 satisfied = other;
154 break;
155 }
156 if (unit)
157 unit = INT_MIN;
158 else
159 unit = other;
160 }
161 if (satisfied) {
162 LOG (c, "sweeping propagation of %d finds %d satisfied", lit,
163 satisfied);
164 mark_garbage (c);
166 } else if (!unit) {
167 LOG ("empty clause during sweeping propagation of %d", lit);
168 // need to set conflict = c for lrat
169 conflict = c;
171 conflict = 0;
172 break;
173 } else if (unit != INT_MIN) {
174 LOG ("new unit %d during sweeping propagation of %d", unit, lit);
175 build_chain_for_units (unit, c, 0);
176 assign_unit (unit);
177 work.push_back (unit);
178 ticks++;
179 }
180 }
181 if (unsat)
182 break;
183
184 // not necessary but should help
185 ticks += 1 + cache_lines (occs (lit).size (), sizeof (Clause *));
186 const Occs &ps = occs (lit);
187 for (const auto &c : ps) {
188 ticks++;
189 if (c->garbage)
190 continue;
191 // if (c->redundant) // TODO I assume it does not hurt to mark
192 // everything here continue;
193 LOG (c, "sweeping propagation of %d produces satisfied", lit);
194 mark_garbage (c);
196 }
197 }
198 work.clear ();
199}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_empty_clause()

void CaDiCaL::Internal::sweep_empty_clause ( Sweeper & sweeper)

Definition at line 654 of file cadical_sweep.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_equivalence_candidates()

bool CaDiCaL::Internal::sweep_equivalence_candidates ( Sweeper & sweeper,
int lit,
int other )

Definition at line 1341 of file cadical_sweep.cpp.

1342 {
1343 LOG ("trying equivalence candidates %d = %d", lit, other);
1344 const auto begin = sweeper.partition.begin ();
1345 auto const end = sweeper.partition.end ();
1346 CADICAL_assert (begin + 3 <= end);
1347 CADICAL_assert (end[-3] == lit);
1348 CADICAL_assert (end[-2] == other);
1349 const int third = (end - begin == 3) ? 0 : end[-4];
1350 int res = cadical_kitten_status (citten);
1351 if (res == 10) {
1352 stats.sweep_flip_equivalences++;
1353 if (sweep_flip (lit)) {
1354 stats.sweep_flipped_equivalences++;
1355 LOG ("flipping %d succeeded", lit);
1356 if (third == 0) {
1357 LOG ("squashing equivalence class of %d", lit);
1358 sweeper.partition.resize (sweeper.partition.size () - 3);
1359 } else {
1360 LOG ("removing %d from equivalence class of %d", lit, other);
1361 end[-3] = other;
1362 end[-2] = 0;
1363 sweeper.partition.resize (sweeper.partition.size () - 1);
1364 }
1365 return false;
1366 }
1367 stats.sweep_flip_equivalences++;
1368 if (sweep_flip (other)) {
1369 stats.sweep_flipped_equivalences++;
1370 LOG ("flipping %d succeeded", other);
1371 if (third == 0) {
1372 LOG ("squashing equivalence class of %d", lit);
1373 sweeper.partition.resize (sweeper.partition.size () - 3);
1374 } else {
1375 LOG ("removing %d from equivalence class of %d", other, lit);
1376 end[-2] = 0;
1377 sweeper.partition.resize (sweeper.partition.size () - 1);
1378 }
1379 return false;
1380 }
1381 }
1382 // frozen variables are not allowed to be eliminated.
1383 // It might still be beneficial to learn the binaries, if they
1384 // really are equivalent, but we avoid the issue by not trying
1385 // for equivalence at all if the non-representative is frozen.
1386 // i.e., the higher absolute value
1387 if (abs (lit) > abs (other) && frozen (lit)) {
1388 if (third == 0) {
1389 LOG ("squashing equivalence class of %d", lit);
1390 sweeper.partition.resize (sweeper.partition.size () - 3);
1391 } else {
1392 LOG ("removing %d from equivalence class of %d", lit, other);
1393 end[-3] = other;
1394 end[-2] = 0;
1395 sweeper.partition.resize (sweeper.partition.size () - 1);
1396 }
1397 return false;
1398 } else if (abs (other) > abs (lit) && frozen (other)) {
1399 if (third == 0) {
1400 LOG ("squashing equivalence class of %d", lit);
1401 sweeper.partition.resize (sweeper.partition.size () - 3);
1402 } else {
1403 LOG ("removing %d from equivalence class of %d", lit, other);
1404 end[-2] = 0;
1405 sweeper.partition.resize (sweeper.partition.size () - 1);
1406 }
1407 return false;
1408 }
1409
1410 const int not_other = -other;
1411 const int not_lit = -lit;
1412 LOG ("flipping %d and %d both failed", lit, other);
1415 stats.sweep_solved_equivalences++;
1416 res = sweep_solve ();
1417 if (res == 10) {
1418 stats.sweep_sat_equivalences++;
1419 LOG ("first sweeping implication %d -> %d failed", other, lit);
1421 } else if (!res) {
1422 stats.sweep_unknown_equivalences++;
1423 LOG ("first sweeping implication %d -> %d hit ticks limit", other, lit);
1424 }
1425
1426 if (res != 20)
1427 return false;
1428
1429 stats.sweep_unsat_equivalences++;
1430 LOG ("first sweeping implication %d -> %d succeeded", other, lit);
1431
1432 save_core (sweeper, 0);
1433
1436 res = sweep_solve ();
1437 stats.sweep_solved_equivalences++;
1438 if (res == 10) {
1439 stats.sweep_sat_equivalences++;
1440 LOG ("second sweeping implication %d <- %d failed", other, lit);
1442 } else if (!res) {
1443 stats.sweep_unknown_equivalences++;
1444 LOG ("second sweeping implication %d <- %d hit ticks limit", other,
1445 lit);
1446 }
1447
1448 if (res != 20) {
1449 sweeper.core[0].clear ();
1450 return false;
1451 }
1452
1453 CADICAL_assert (res == 20);
1454
1455 stats.sweep_unsat_equivalences++;
1456 LOG ("second sweeping implication %d <- %d succeeded too", other, lit);
1457
1458 save_core (sweeper, 1);
1459
1460 LOG ("sweep equivalence %d = %d", lit, other);
1461
1462 // If cadical_kitten behaves as expected, the two binaries of the equivalence
1463 // should be stored at sweeper.core[i].back () for i in {0, 1}.
1464 // We pick the smaller absolute valued literal as representative and
1465 // store the equivalence .
1466 add_core (sweeper, 0);
1467 add_core (sweeper, 1);
1468 if (!val (lit) && !val (other)) {
1469 CADICAL_assert (sweeper.core[0].size ());
1470 CADICAL_assert (sweeper.core[1].size ());
1471 stats.sweep_equivalences++;
1472 sweep_binary bin1;
1473 sweep_binary bin2;
1474 if (abs (lit) > abs (other)) {
1475 bin1.lit = lit;
1476 bin1.other = not_other;
1477 bin2.lit = not_lit;
1478 bin2.other = other;
1479 bin1.id = add_sweep_binary (sweeper.core[0].back (), lit, not_other);
1480 bin2.id = add_sweep_binary (sweeper.core[1].back (), not_lit, other);
1481 } else {
1482 bin1.lit = not_other;
1483 bin1.other = lit;
1484 bin2.lit = other;
1485 bin2.other = not_lit;
1486 bin1.id = add_sweep_binary (sweeper.core[0].back (), not_other, lit);
1487 bin2.id = add_sweep_binary (sweeper.core[1].back (), other, not_lit);
1488 }
1489 if (bin1.id && bin2.id) {
1490 sweeper.binaries.push_back (bin1);
1491 sweeper.binaries.push_back (bin2);
1492 }
1493 }
1494
1495 int repr;
1496 if (abs (lit) < abs (other)) {
1497 repr = sweeper.reprs[other] = lit;
1498 sweeper.reprs[not_other] = not_lit;
1499 sweep_remove (sweeper, other);
1500 } else {
1501 repr = sweeper.reprs[lit] = other;
1502 sweeper.reprs[not_lit] = not_other;
1504 }
1505 clear_core (sweeper, 0);
1506 clear_core (sweeper, 1);
1507
1508 const int repr_idx = abs (repr);
1509 schedule_inner (sweeper, repr_idx);
1510
1511 return true;
1512}
void sweep_remove(Sweeper &sweeper, int lit)
int64_t add_sweep_binary(sweep_proof_clause, int lit, int other)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_extract_fixed()

bool CaDiCaL::Internal::sweep_extract_fixed ( Sweeper & sweeper,
int lit )

Definition at line 827 of file cadical_sweep.cpp.

827 {
828 const int not_lit = -lit;
829 stats.sweep_solved_backbone++;
831 int res = sweep_solve ();
832 if (!res) {
833 stats.sweep_unknown_backbone++;
834 return false;
835 }
836 CADICAL_assert (res == 20);
837 LOG ("sweep unit %d", lit);
839 stats.sweep_unsat_backbone++;
840 return true;
841}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_flip()

bool CaDiCaL::Internal::sweep_flip ( int lit)

Definition at line 37 of file cadical_sweep.cpp.

37 {
38 START (sweepflip);
40 STOP (sweepflip);
41 return res;
42}
bool cadical_kitten_flip_signed_literal(cadical_kitten *cadical_kitten, int elit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_flip_and_implicant()

int CaDiCaL::Internal::sweep_flip_and_implicant ( int lit)

Definition at line 44 of file cadical_sweep.cpp.

44 {
45 START (sweepimplicant);
47 STOP (sweepimplicant);
48 return res;
49}
int cadical_kitten_flip_and_implicant_for_signed_literal(cadical_kitten *cadical_kitten, int elit)
Here is the call graph for this function:

◆ sweep_refine()

void CaDiCaL::Internal::sweep_refine ( Sweeper & sweeper)

Definition at line 762 of file cadical_sweep.cpp.

762 {
764 if (sweeper.backbone.empty ())
765 LOG ("no need to refine empty backbone candidates");
766 else
768 if (sweeper.partition.empty ())
769 LOG ("no need to refine empty partition candidates");
770 else
772}
void sweep_refine_backbone(Sweeper &sweeper)
void sweep_refine_partition(Sweeper &sweeper)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_refine_backbone()

void CaDiCaL::Internal::sweep_refine_backbone ( Sweeper & sweeper)

Definition at line 745 of file cadical_sweep.cpp.

745 {
746 LOG ("refining backbone candidates");
747 const auto end = sweeper.backbone.end ();
748 auto q = sweeper.backbone.begin ();
749 for (auto p = q; p != end; p++) {
750 const int lit = *p;
751 if (val (lit))
752 continue;
754 if (!value)
755 LOG ("dropping sub-solver unassigned %d", lit);
756 else if (value > 0)
757 *q++ = lit;
758 }
759 sweeper.backbone.resize (q - sweeper.backbone.begin ());
760}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_refine_partition()

void CaDiCaL::Internal::sweep_refine_partition ( Sweeper & sweeper)

Definition at line 660 of file cadical_sweep.cpp.

660 {
661 LOG ("refining partition");
662 vector<int> &old_partition = sweeper.partition;
663 vector<int> new_partition;
664 auto old_begin = old_partition.begin ();
665 const auto old_end = old_partition.end ();
666#ifdef LOGGING
667 unsigned old_classes = 0;
668 unsigned new_classes = 0;
669#endif
670 for (auto p = old_begin, q = p; p != old_end; p = q + 1) {
671 unsigned assigned_true = 0;
672 int other;
673 for (q = p; (other = *q) != 0; q++) {
674 if (sweep_repr (sweeper, other) != other)
675 continue;
676 if (val (other))
677 continue;
678 signed char value = cadical_kitten_signed_value (citten, other);
679 if (!value)
680 LOG ("dropping sub-solver unassigned %d", other);
681 else if (value > 0) {
682 new_partition.push_back (other);
683 assigned_true++;
684 }
685 }
686#ifdef LOGGING
687 LOG ("refining class %u of size %zu", old_classes, (size_t) (q - p));
688 old_classes++;
689#endif
690 if (assigned_true == 0)
691 LOG ("no positive literal in class");
692 else if (assigned_true == 1) {
693#ifdef LOGGING
694 other =
695#else
696 (void)
697#endif
698 new_partition.back ();
699 new_partition.pop_back ();
700 LOG ("dropping singleton class %d", other);
701 } else {
702 LOG ("%u positive literal in class", assigned_true);
703 new_partition.push_back (0);
704#ifdef LOGGING
705 new_classes++;
706#endif
707 }
708
709 unsigned assigned_false = 0;
710 for (q = p; (other = *q) != 0; q++) {
711 if (sweep_repr (sweeper, other) != other)
712 continue;
713 if (val (other))
714 continue;
715 signed char value = cadical_kitten_signed_value (citten, other);
716 if (value < 0) {
717 new_partition.push_back (other);
718 assigned_false++;
719 }
720 }
721
722 if (assigned_false == 0)
723 LOG ("no negative literal in class");
724 else if (assigned_false == 1) {
725#ifdef LOGGING
726 other =
727#else
728 (void)
729#endif
730 new_partition.back ();
731 new_partition.pop_back ();
732 LOG ("dropping singleton class %d", other);
733 } else {
734 LOG ("%u negative literal in class", assigned_false);
735 new_partition.push_back (0);
736#ifdef LOGGING
737 new_classes++;
738#endif
739 }
740 }
741 old_partition.swap (new_partition);
742 LOG ("refined %u classes into %u", old_classes, new_classes);
743}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_remove()

void CaDiCaL::Internal::sweep_remove ( Sweeper & sweeper,
int lit )

Definition at line 1242 of file cadical_sweep.cpp.

1242 {
1244 vector<int> &partition = sweeper.partition;
1245 const auto begin_partition = partition.begin ();
1246 auto p = begin_partition;
1247 const auto end_partition = partition.end ();
1248 for (; *p != lit; p++)
1249 CADICAL_assert (p + 1 != end_partition);
1250 auto begin_class = p;
1251 while (begin_class != begin_partition && begin_class[-1] != 0)
1252 begin_class--;
1253 auto end_class = p;
1254 while (*end_class != 0)
1255 end_class++;
1256 const unsigned size = end_class - begin_class;
1257 LOG ("removing non-representative %d from equivalence class of size %u",
1258 lit, size);
1259 CADICAL_assert (size > 1);
1260 auto q = begin_class;
1261 if (size == 2) {
1262 LOG ("completely squashing equivalence class of %d", lit);
1263 for (auto r = end_class + 1; r != end_partition; r++)
1264 *q++ = *r;
1265 } else {
1266 for (auto r = begin_class; r != end_partition; r++)
1267 if (r != p)
1268 *q++ = *r;
1269 }
1270 partition.resize (q - partition.begin ());
1271}
Here is the caller graph for this function:

◆ sweep_repr()

int CaDiCaL::Internal::sweep_repr ( Sweeper & sweeper,
int lit )

Definition at line 319 of file cadical_sweep.cpp.

319 {
320 int res;
321 {
322 int prev = lit;
323 while ((res = sweeper.reprs[prev]) != prev)
324 prev = res;
325 }
326 if (res == lit)
327 return res;
328 LOG ("sweeping repr[%d] = %d", lit, res);
329 {
330 const int not_res = -res;
331 int next, prev = lit;
332 while ((next = sweeper.reprs[prev]) != res) {
333 const int not_prev = -prev;
334 sweeper.reprs[not_prev] = not_res;
335 sweeper.reprs[prev] = res;
336 prev = next;
337 }
338 CADICAL_assert (sweeper.reprs[-prev] == not_res);
339 }
340 return res;
341}
Here is the caller graph for this function:

◆ sweep_set_cadical_kitten_ticks_limit()

void CaDiCaL::Internal::sweep_set_cadical_kitten_ticks_limit ( Sweeper & sweeper)

Definition at line 51 of file cadical_sweep.cpp.

51 {
52 uint64_t remaining = 0;
53 const uint64_t current = sweeper.current_ticks;
54 if (current < sweeper.limit.ticks)
55 remaining = sweeper.limit.ticks - current;
56 LOG ("'cadical_kitten_ticks' remaining %" PRIu64, remaining);
58}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_solve()

int CaDiCaL::Internal::sweep_solve ( )

Definition at line 24 of file cadical_sweep.cpp.

24 {
25 START (sweepsolve);
27 stats.sweep_solved++;
28 int res = cadical_kitten_solve (citten);
29 if (res == 10)
30 stats.sweep_sat++;
31 if (res == 20)
32 stats.sweep_unsat++;
33 STOP (sweepsolve);
34 return res;
35}
void cadical_kitten_randomize_phases(cadical_kitten *cadical_kitten)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_sparse_mode()

void CaDiCaL::Internal::sweep_sparse_mode ( )

Definition at line 125 of file cadical_sweep.cpp.

125 {
126 reset_occs ();
127 reset_noccs ();
128 init_watches ();
130}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_substitute_lrat()

void CaDiCaL::Internal::sweep_substitute_lrat ( Clause * c,
int64_t id )

Definition at line 1030 of file cadical_sweep.cpp.

1030 {
1031 if (!lrat)
1032 return;
1033 for (const auto &lit : *c) {
1034 CADICAL_assert (val (lit) <= 0);
1035 if (val (lit) < 0) {
1036 int64_t id = unit_id (-lit);
1037 lrat_chain.push_back (id);
1038 }
1039 }
1040 lrat_chain.push_back (id);
1041 lrat_chain.push_back (c->id);
1042}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_substitute_new_equivalences()

void CaDiCaL::Internal::sweep_substitute_new_equivalences ( Sweeper & sweeper)

Definition at line 1181 of file cadical_sweep.cpp.

1181 {
1182 if (unsat)
1183 return;
1184
1185 unsigned count = 0;
1186 CADICAL_assert (lrat_chain.empty ());
1187
1188 for (const auto &sb : sweeper.binaries) {
1189 count++;
1190 const auto lit = sb.lit;
1191 const auto other = sb.other;
1192 if (abs (lit) < abs (other)) {
1193 substitute_connected_clauses (sweeper, -other, lit, sb.id);
1194 } else {
1195 substitute_connected_clauses (sweeper, -lit, other, sb.id);
1196 }
1197 CADICAL_assert (lrat_chain.empty ());
1198 if (val (lit) < 0) {
1199 if (lrat) {
1200 const int64_t lid = unit_id (-lit);
1201 lrat_chain.push_back (lid);
1202 }
1203 if (!val (other)) {
1204 if (lrat)
1205 lrat_chain.push_back (sb.id);
1206 assign_unit (other);
1207 } else if (val (other) < 0) {
1208 if (lrat) {
1209 const int64_t oid = unit_id (-other);
1210 lrat_chain.push_back (oid);
1211 lrat_chain.push_back (sb.id);
1212 }
1214 return;
1215 }
1216 } else if (val (other) < 0) {
1217 if (!val (lit)) {
1218 if (lrat) {
1219 const int64_t oid = unit_id (-other);
1220 lrat_chain.push_back (oid);
1221 lrat_chain.push_back (sb.id);
1222 }
1223 assign_unit (lit);
1224 } else
1225 CADICAL_assert (val (lit) > 0);
1226 }
1227 lrat_chain.clear ();
1229 if (count == 2) {
1230 if (!val (lit) && !val (other)) {
1231 const auto idx = abs (lit) < abs (other) ? abs (other) : abs (lit);
1232 if (!flags (idx).fixed ())
1233 mark_substituted (idx);
1234 }
1235 count = 0;
1236 }
1237 CADICAL_assert (lrat_chain.empty ());
1238 }
1239 sweeper.binaries.clear ();
1240}
void substitute_connected_clauses(Sweeper &sweeper, int lit, int other, int64_t id)
void delete_sweep_binary(const sweep_binary &sb)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_update_noccs()

void CaDiCaL::Internal::sweep_update_noccs ( Clause * c)

Definition at line 60 of file cadical_sweep.cpp.

60 {
61 if (c->redundant)
62 return;
63 for (const auto &lit : *c) {
64 noccs (lit)--;
65 }
66}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_variable()

const char * CaDiCaL::Internal::sweep_variable ( Sweeper & sweeper,
int idx )

Definition at line 1514 of file cadical_sweep.cpp.

1514 {
1516 if (!active (idx))
1517 return "inactive variable";
1518 const int start = idx;
1519 if (sweeper.reprs[start] != start)
1520 return "non-representative variable";
1521 CADICAL_assert (sweeper.vars.empty ());
1522 CADICAL_assert (sweeper.clauses.empty ());
1523 CADICAL_assert (sweeper.backbone.empty ());
1524 CADICAL_assert (sweeper.partition.empty ());
1526
1527 stats.sweep_variables++;
1528
1529 LOG ("sweeping %d", idx);
1530 CADICAL_assert (!val (start));
1531 LOG ("starting sweeping[0]");
1533 LOG ("finished sweeping[0]");
1534 LOG ("starting sweeping[1]");
1535
1536 bool limit_reached = false;
1537 size_t expand = 0, next = 1;
1538 bool success = false;
1539 unsigned depth = 1;
1540
1541 uint64_t &ticks = sweeper.current_ticks;
1542 while (!limit_reached) {
1544 LOG ("environment clause limit reached");
1545 limit_reached = true;
1546 break;
1547 }
1548 if (expand == next) {
1549 LOG ("finished sweeping[%u]", depth);
1550 if (depth >= sweeper.limit.depth) {
1551 LOG ("environment depth limit reached");
1552 break;
1553 }
1554 next = sweeper.vars.size ();
1555 if (expand == next) {
1556 LOG ("completely copied all clauses");
1557 break;
1558 }
1559 depth++;
1560 LOG ("starting sweeping[%u]", depth);
1561 }
1562 const unsigned choices = next - expand;
1563 if (opts.sweeprand && choices > 1) {
1564 const unsigned swaps = sweeper.random.pick_int (0, choices - 1);
1565 if (swaps) {
1566 CADICAL_assert (expand + swaps < sweeper.vars.size ());
1567 swap (sweeper.vars[expand], sweeper.vars[expand + swaps]);
1568 }
1569 }
1570 const int idx = sweeper.vars[expand];
1571 LOG ("traversing and adding clauses of %d", idx);
1572 for (unsigned sign = 0; sign < 2; sign++) {
1573 const int lit = sign ? -idx : idx;
1574 ticks += 1 + cache_lines (occs (lit).size (), sizeof (Clause *));
1575 Occs &ns = occs (lit);
1576 for (auto c : ns) {
1577 ticks++;
1578 if (!can_sweep_clause (c))
1579 continue;
1580 sweep_clause (sweeper, depth, c);
1581 if (sweeper.vars.size () >= sweeper.limit.vars) {
1582 LOG ("environment variable limit reached");
1583 limit_reached = true;
1584 break;
1585 }
1586 }
1587 if (limit_reached)
1588 break;
1589 }
1590 expand++;
1591 }
1592 stats.sweep_depth += depth;
1593 stats.sweep_clauses += sweeper.encoded;
1594 stats.sweep_environment += sweeper.vars.size ();
1595 VERBOSE (3,
1596 "sweeping variable %d environment of "
1597 "%zu variables %u clauses depth %u",
1598 externalize (idx), sweeper.vars.size (), sweeper.encoded, depth);
1599
1600 int res;
1601 if (sweeper.vars.size () == 1) {
1602 LOG ("not sweeping literal %d with environment size 1", idx);
1603 goto DONE;
1604 }
1605 res = sweep_solve ();
1606 LOG ("sub-solver returns '%d'", res);
1607 if (res == 10) {
1609#ifndef CADICAL_QUIET
1610 uint64_t units = stats.sweep_units;
1611 uint64_t solved = stats.sweep_solved;
1612#endif
1613 START (sweepbackbone);
1614 while (sweeper.backbone.size ()) {
1615 if (unsat || terminated_asynchronously () ||
1616 cadical_kitten_ticks_limit_hit (sweeper, "backbone refinement")) {
1617 limit_reached = true;
1618 STOP_SWEEP_BACKBONE:
1619 STOP (sweepbackbone);
1620 goto DONE;
1621 }
1624 cadical_kitten_ticks_limit_hit (sweeper, "backbone refinement")) {
1625 limit_reached = true;
1626 goto STOP_SWEEP_BACKBONE;
1627 }
1628 if (sweeper.backbone.empty ())
1629 break;
1630 const int lit = sweeper.backbone.back ();
1631 sweeper.backbone.pop_back ();
1632 if (!active (lit))
1633 continue;
1635 success = true;
1636 }
1637 STOP (sweepbackbone);
1638#ifndef CADICAL_QUIET
1639 units = stats.sweep_units - units;
1640 solved = stats.sweep_solved - solved;
1641#endif
1642 VERBOSE (3,
1643 "complete swept variable %d backbone with %" PRIu64
1644 " units in %" PRIu64 " solver calls",
1645 externalize (idx), units, solved);
1646 CADICAL_assert (sweeper.backbone.empty ());
1647#ifndef CADICAL_QUIET
1648 uint64_t equivalences = stats.sweep_equivalences;
1649 solved = stats.sweep_solved;
1650#endif
1651 START (sweepequivalences);
1652 while (sweeper.partition.size ()) {
1653 if (unsat || terminated_asynchronously () ||
1654 cadical_kitten_ticks_limit_hit (sweeper, "partition refinement")) {
1655 limit_reached = true;
1656 STOP_SWEEP_EQUIVALENCES:
1657 STOP (sweepequivalences);
1658 goto DONE;
1659 }
1662 cadical_kitten_ticks_limit_hit (sweeper, "backbone refinement")) {
1663 limit_reached = true;
1664 goto STOP_SWEEP_EQUIVALENCES;
1665 }
1666 if (sweeper.partition.empty ())
1667 break;
1668 if (sweeper.partition.size () > 2) {
1669 const auto end = sweeper.partition.end ();
1670 CADICAL_assert (end[-1] == 0);
1671 int lit = end[-3];
1672 int other = end[-2];
1674 success = true;
1675 } else
1676 sweeper.partition.clear ();
1677 }
1678 STOP (sweepequivalences);
1679#ifndef CADICAL_QUIET
1680 equivalences = stats.sweep_equivalences - equivalences;
1681 solved = stats.sweep_solved - solved;
1682 if (equivalences)
1683 VERBOSE (3,
1684 "complete swept variable %d partition with %" PRIu64
1685 " equivalences in %" PRIu64 " solver calls",
1686 externalize (idx), equivalences, solved);
1687#endif
1688 } else if (res == 20)
1690
1691DONE:
1693
1694 if (!unsat)
1696 if (!unsat)
1698
1699 if (success && limit_reached)
1700 return "successfully despite reaching limit";
1701 if (!success && !limit_reached)
1702 return "unsuccessfully without reaching limit";
1703 else if (success && !limit_reached)
1704 return "successfully without reaching limit";
1705 CADICAL_assert (!success && limit_reached);
1706 return "unsuccessfully and reached limit";
1707}
pcover expand()
void sweep_dense_propagate(Sweeper &sweeper)
void clear_sweeper(Sweeper &sweeper)
void sweep_empty_clause(Sweeper &sweeper)
void sweep_substitute_new_equivalences(Sweeper &sweeper)
void init_backbone_and_partition(Sweeper &sweeper)
void flip_backbone_literals(struct Sweeper &sweeper)
void sweep_clause(Sweeper &sweeper, unsigned depth, Clause *)
void flip_partition_literals(struct Sweeper &sweeper)
bool sweep_backbone_candidate(Sweeper &sweeper, int lit)
bool sweep_equivalence_candidates(Sweeper &sweeper, int lit, int other)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ terminate()

void CaDiCaL::Internal::terminate ( )
inline

Definition at line 878 of file internal.hpp.

878 {
879 LOG ("forcing asynchronous termination");
880 termination_forced = true;
881 }

◆ terminated_asynchronously()

bool CaDiCaL::Internal::terminated_asynchronously ( int factor = 1)
inline

Definition at line 1789 of file internal.hpp.

1789 {
1790 // First way of asynchronous termination is through 'terminate' which sets
1791 // the 'termination_forced' flag directly. The second way is through a
1792 // call back to a 'terminator' if it is non-zero, which however is costly.
1793 //
1794 if (termination_forced) {
1795 LOG ("termination asynchronously forced");
1796 return true;
1797 }
1798
1799 // This is only for testing and debugging asynchronous termination calls.
1800 // In production code this could be removed but then should not be costly
1801 // and keeping it will allow to test correctness of asynchronous
1802 // termination on the production platform too. After this triggers we
1803 // have to set the 'termination_forced' flag, such that subsequent calls
1804 // to this function do not check this again.
1805 //
1806 if (lim.terminate.forced) {
1807 CADICAL_assert (lim.terminate.forced > 0);
1808 if (lim.terminate.forced-- == 1) {
1809 LOG ("internally forcing termination");
1810 termination_forced = true;
1811 return true;
1812 }
1813 LOG ("decremented internal forced termination limit to %d",
1814 lim.terminate.forced);
1815 }
1816
1817 // The second way of asynchronous termination is through registering and
1818 // calling an external 'Terminator' object. This is of course more costly
1819 // than just checking a (volatile though) boolean flag, particularly in
1820 // tight loops. To avoid this cost we only call the terminator in
1821 // intervals of 'opts.terminateint', which in addition can be scaled up by
1822 // the argument 'factor'. If the terminator returns 'true' we set the
1823 // 'termination_forced' flag to 'true' in order to remember the
1824 // termination status and to avoid the terminator again. Setting this
1825 // flag leads to the first test above to succeed in subsequent calls.
1826 //
1827 if (external->terminator && !lim.terminate.check--) {
1828 CADICAL_assert (factor > 0);
1829 CADICAL_assert (INT_MAX / factor > opts.terminateint);
1830 lim.terminate.check = factor * opts.terminateint;
1831 if (external->terminator->terminate ()) {
1832 termination_forced = true; // Cache it.
1833 LOG ("connected terminator forces termination");
1834 return true;
1835 }
1836 }
1837
1838 return false;
1839}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ terminating_asked()

bool CaDiCaL::Internal::terminating_asked ( )

Definition at line 267 of file cadical_lookahead.cpp.

267 {
268
269 if (external->terminator && external->terminator->terminate ()) {
270 MSG ("connected terminator forces termination");
271 return true;
272 }
273
274 if (termination_forced) {
275 MSG ("termination forced");
276 return true;
277 }
278 return false;
279}
Here is the caller graph for this function:

◆ ternary()

bool CaDiCaL::Internal::ternary ( )

Definition at line 361 of file cadical_ternary.cpp.

361 {
362
363 if (!opts.ternary)
364 return false;
365 if (unsat)
366 return false;
368 return false;
369
370 // No new ternary clauses added since last time?
371 //
372 if (last.ternary.marked == stats.mark.ternary)
373 return false;
374
376
378 stats.ternary++;
379
381
383 if (watching ())
384 reset_watches ();
385
386 // The number of clauses derived through ternary resolution can grow
387 // substantially, particularly for random formulas. Thus we limit the
388 // number of added clauses too (actually the number of 'htrs').
389 //
390 int64_t htrs_limit = stats.current.redundant + stats.current.irredundant;
391 htrs_limit *= opts.ternarymaxadd;
392 htrs_limit /= 100;
393
394 // approximation of ternary ticks.
395 // TODO: count with ternary.ticks directly.
396 int64_t steps_limit = stats.ticks.ternary - limit;
397 stats.ticks.ternary = limit;
398
399 // With 'stats.ternary' we actually count the number of calls to
400 // 'ternary_round' and not the number of calls to 'ternary'. But before
401 // the first round we want to show the limit on the number of steps and
402 // thus we increase counter for the first round here and skip increasing
403 // it in the loop below.
404 //
405 PHASE ("ternary", stats.ternary,
406 "will run a maximum of %d rounds "
407 "limited to %" PRId64 " steps and %" PRId64 " clauses",
408 opts.ternaryrounds, steps_limit, htrs_limit);
409
410 bool resolved_binary_clause = false;
411 bool completed = false;
412
413 for (int round = 0;
414 !terminated_asynchronously () && round < opts.ternaryrounds;
415 round++) {
416 if (htrs_limit < 0)
417 break;
418 if (steps_limit < 0)
419 break;
420 if (round)
421 stats.ternary++;
422 int old_htrs2 = stats.htrs2;
423 int old_htrs3 = stats.htrs3;
424 completed = ternary_round (steps_limit, htrs_limit);
425 int delta_htrs2 = stats.htrs2 - old_htrs2;
426 int delta_htrs3 = stats.htrs3 - old_htrs3;
427 PHASE ("ternary", stats.ternary,
428 "derived %d ternary and %d binary resolvents", delta_htrs3,
429 delta_htrs2);
430 report ('3', !opts.reportall && !(delta_htrs2 + delta_htrs2));
431 if (delta_htrs2)
432 resolved_binary_clause = true;
433 if (!delta_htrs3)
434 break;
435 }
436
439 init_watches ();
441 if (!propagate ()) {
442 LOG ("propagation after connecting watches results in inconsistency");
444 }
445
446 if (completed)
447 last.ternary.marked = stats.mark.ternary;
448
450
451 return resolved_binary_clause;
452}
bool ternary_round(int64_t &steps, int64_t &htrs)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ternary_find_binary_clause()

bool CaDiCaL::Internal::ternary_find_binary_clause ( int a,
int b )

Definition at line 29 of file cadical_ternary.cpp.

29 {
33 size_t s = occs (a).size ();
34 size_t t = occs (b).size ();
35 int lit = s < t ? a : b;
36 if (opts.ternaryocclim < (int) occs (lit).size ())
37 return true;
38 for (const auto &c : occs (lit)) {
39 if (c->size != 2)
40 continue;
41 const int *lits = c->literals;
42 if (lits[0] == a && lits[1] == b)
43 return true;
44 if (lits[0] == b && lits[1] == a)
45 return true;
46 }
47 return false;
48}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ternary_find_ternary_clause()

bool CaDiCaL::Internal::ternary_find_ternary_clause ( int a,
int b,
int c )

Definition at line 55 of file cadical_ternary.cpp.

55 {
60 size_t r = occs (a).size ();
61 size_t s = occs (b).size ();
62 size_t t = occs (c).size ();
63 int lit;
64 if (r < s)
65 lit = (t < r) ? c : a;
66 else
67 lit = (t < s) ? c : b;
68 if (opts.ternaryocclim < (int) occs (lit).size ())
69 return true;
70 for (const auto &d : occs (lit)) {
71 const int *lits = d->literals;
72 if (d->size == 2) {
73 if (lits[0] == a && lits[1] == b)
74 return true;
75 if (lits[0] == b && lits[1] == a)
76 return true;
77 if (lits[0] == a && lits[1] == c)
78 return true;
79 if (lits[0] == c && lits[1] == a)
80 return true;
81 if (lits[0] == b && lits[1] == c)
82 return true;
83 if (lits[0] == c && lits[1] == b)
84 return true;
85 } else {
86 CADICAL_assert (d->size == 3);
87 if (lits[0] == a && lits[1] == b && lits[2] == c)
88 return true;
89 if (lits[0] == a && lits[1] == c && lits[2] == b)
90 return true;
91 if (lits[0] == b && lits[1] == a && lits[2] == c)
92 return true;
93 if (lits[0] == b && lits[1] == c && lits[2] == a)
94 return true;
95 if (lits[0] == c && lits[1] == a && lits[2] == b)
96 return true;
97 if (lits[0] == c && lits[1] == b && lits[2] == a)
98 return true;
99 }
100 }
101 return false;
102}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ternary_idx()

void CaDiCaL::Internal::ternary_idx ( int idx,
int64_t & steps,
int64_t & htrs )

Definition at line 241 of file cadical_ternary.cpp.

241 {
242 CADICAL_assert (0 < idx);
243 CADICAL_assert (idx <= max_var);
244 steps -= 3;
245 if (!active (idx))
246 return;
247 if (!flags (idx).ternary)
248 return;
249 int pos = occs (idx).size ();
250 int neg = occs (-idx).size ();
251 if (pos <= opts.ternaryocclim && neg <= opts.ternaryocclim) {
252 LOG ("index %d has %zd positive and %zd negative occurrences", idx,
253 occs (idx).size (), occs (-idx).size ());
254 int pivot = (neg < pos ? -idx : idx);
255 ternary_lit (pivot, steps, htrs);
256 }
257 flags (idx).ternary = false;
258}
void ternary_lit(int pivot, int64_t &steps, int64_t &htrs)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ternary_lit()

void CaDiCaL::Internal::ternary_lit ( int pivot,
int64_t & steps,
int64_t & htrs )

Definition at line 156 of file cadical_ternary.cpp.

156 {
157 LOG ("starting hyper ternary resolutions on pivot %d", pivot);
158 steps -= 1 + cache_lines (occs (pivot).size (), sizeof (Clause *));
159 for (const auto &c : occs (pivot)) {
160 if (steps < 0)
161 break;
162 if (htrs < 0)
163 break;
164 if (c->garbage)
165 continue;
166 if (c->size != 3) {
167 CADICAL_assert (c->size == 2);
168 continue;
169 }
170 if (--steps < 0)
171 break;
172 bool assigned = false;
173 for (const auto &lit : *c)
174 if (val (lit)) {
175 assigned = true;
176 break;
177 }
178 if (assigned)
179 continue;
180 steps -= 1 + cache_lines (occs (-pivot).size (), sizeof (Clause *));
181 for (const auto &d : occs (-pivot)) {
182 if (htrs < 0)
183 break;
184 if (--steps < 0)
185 break;
186 if (d->garbage)
187 continue;
188 if (d->size != 3) {
189 CADICAL_assert (d->size == 2);
190 continue;
191 }
192 for (const auto &lit : *d)
193 if (val (lit)) {
194 assigned = true;
195 break;
196 }
197 if (assigned)
198 continue;
199 CADICAL_assert (clause.empty ());
200 htrs--;
201 if (hyper_ternary_resolve (c, pivot, d)) {
202 size_t size = clause.size ();
203 bool red = (size == 3 || (c->redundant && d->redundant));
204 if (lrat) {
205 CADICAL_assert (lrat_chain.empty ());
206 lrat_chain.push_back (c->id);
207 lrat_chain.push_back (d->id);
208 }
209 Clause *r = new_hyper_ternary_resolved_clause (red);
210 if (red)
211 r->hyper = true;
212 lrat_chain.clear ();
213 clause.clear ();
214 LOG (r, "hyper ternary resolved");
215 stats.htrs++;
216 for (const auto &lit : *r)
217 occs (lit).push_back (r);
218 if (size == 2) {
219 LOG ("hyper ternary resolvent subsumes both antecedents");
220 mark_garbage (c);
221 mark_garbage (d);
222 stats.htrs2++;
223 break;
224 } else {
225 CADICAL_assert (r->size == 3);
226 stats.htrs3++;
227 }
228 } else {
229 LOG (clause, "ignoring size %zd resolvent", clause.size ());
230 clause.clear ();
231 }
232 }
233 }
234}
Clause * new_hyper_ternary_resolved_clause(bool red)
bool hyper_ternary_resolve(Clause *, int, Clause *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ternary_round()

bool CaDiCaL::Internal::ternary_round ( int64_t & steps,
int64_t & htrs )

Definition at line 271 of file cadical_ternary.cpp.

271 {
272
274
275#ifndef CADICAL_QUIET
276 int64_t bincon = 0;
277 int64_t terncon = 0;
278#endif
279
280 init_occs ();
281
282 steps_limit -= 1 + cache_lines (clauses.size (), sizeof (Clause *));
283 for (const auto &c : clauses) {
284 steps_limit--;
285 if (c->garbage)
286 continue;
287 if (c->size > 3)
288 continue;
289 bool assigned = false, marked = false;
290 for (const auto &lit : *c) {
291 if (val (lit)) {
292 assigned = true;
293 break;
294 }
295 if (flags (lit).ternary)
296 marked = true;
297 }
298 if (assigned)
299 continue;
300 if (c->size == 2) {
301#ifndef CADICAL_QUIET
302 bincon++;
303#endif
304 } else {
305 CADICAL_assert (c->size == 3);
306 if (!marked)
307 continue;
308#ifndef CADICAL_QUIET
309 terncon++;
310#endif
311 }
312
313 for (const auto &lit : *c)
314 occs (lit).push_back (c);
315 }
316
317 PHASE ("ternary", stats.ternary,
318 "connected %" PRId64 " ternary %.0f%% "
319 "and %" PRId64 " binary clauses %.0f%%",
320 terncon, percent (terncon, clauses.size ()), bincon,
321 percent (bincon, clauses.size ()));
322
323 // Try ternary resolution on all variables once.
324 //
325 for (auto idx : vars) {
327 break;
328 if (steps_limit < 0)
329 break;
330 if (htrs_limit < 0)
331 break;
332 ternary_idx (idx, steps_limit, htrs_limit);
333 }
334
335 // Gather some statistics for the verbose messages below and also
336 // determine whether new variables have been marked and it would make
337 // sense to run another round of ternary resolution over those variables.
338 //
339 int remain = 0;
340 for (auto idx : vars) {
341 if (!active (idx))
342 continue;
343 if (!flags (idx).ternary)
344 continue;
345 remain++;
346 }
347 if (remain)
348 PHASE ("ternary", stats.ternary, "%d variables remain %.0f%%", remain,
349 percent (remain, max_var));
350 else
351 PHASE ("ternary", stats.ternary, "completed hyper ternary resolution");
352
353 reset_occs ();
355
356 return remain; // Are there variables that should be tried again?
357}
void ternary_idx(int idx, int64_t &steps, int64_t &htrs)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tied_next_factor_score()

double CaDiCaL::Internal::tied_next_factor_score ( int lit)

Definition at line 135 of file cadical_factor.cpp.

135 {
136 double res = occs (lit).size ();
137 LOG ("watches score %g of %d", res, lit);
138 return res;
139}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ time()

double CaDiCaL::Internal::time ( )
inline

Definition at line 1660 of file internal.hpp.

1660{ return opts.realtime ? real_time () : process_time (); }
double process_time() const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ trace()

void CaDiCaL::Internal::trace ( File * file)

Definition at line 126 of file cadical_proof.cpp.

126 {
127 if (opts.veripb) {
128 LOG ("PROOF connecting VeriPB tracer");
129 bool antecedents = opts.veripb == 1 || opts.veripb == 2;
130 bool deletions = opts.veripb == 2 || opts.veripb == 4;
131 FileTracer *ft =
132 new VeripbTracer (this, file, opts.binary, antecedents, deletions);
133 connect_proof_tracer (ft, antecedents);
134 } else if (opts.frat) {
135 LOG ("PROOF connecting FRAT tracer");
136 bool antecedents = opts.frat == 1;
138 FileTracer *ft =
139 new FratTracer (this, file, opts.binary, opts.frat == 1);
140 connect_proof_tracer (ft, antecedents, true);
141 } else if (opts.lrat) {
142 LOG ("PROOF connecting LRAT tracer");
143 FileTracer *ft = new LratTracer (this, file, opts.binary);
144 connect_proof_tracer (ft, true);
145 } else if (opts.idrup) {
146 LOG ("PROOF connecting IDRUP tracer");
147 FileTracer *ft = new IdrupTracer (this, file, opts.binary);
148 connect_proof_tracer (ft, true);
149 } else if (opts.lidrup) {
150 LOG ("PROOF connecting LIDRUP tracer");
151 FileTracer *ft = new LidrupTracer (this, file, opts.binary);
152 connect_proof_tracer (ft, true);
153 } else {
154 LOG ("PROOF connecting DRAT tracer");
155 FileTracer *ft = new DratTracer (this, file, opts.binary);
156 connect_proof_tracer (ft, false);
157 }
158}
struct file file
Definition file.h:21
void connect_proof_tracer(Tracer *tracer, bool antecedents, bool finalize_clauses=false)
Here is the call graph for this function:

◆ transred()

void CaDiCaL::Internal::transred ( )

Definition at line 15 of file cadical_transred.cpp.

15 {
16 if (!opts.transred)
17 return;
18 if (unsat)
19 return;
21 return;
22 if (!stats.current.redundant && !stats.current.irredundant)
23 return;
24
25 CADICAL_assert (opts.transred);
27
29 stats.transreds++;
30
31 // Transitive reduction can not be run to completion for larger formulas
32 // with many binary clauses. We bound it in the same way as 'probe_core'.
33 //
34 int64_t limit = stats.propagations.search;
35 limit -= last.transred.propagations;
36 limit *= 1e-3 * opts.transredeffort;
37 if (limit < opts.transredmineff)
38 limit = opts.transredmineff;
39 if (limit > opts.transredmaxeff)
40 limit = opts.transredmaxeff;
41
42 PHASE ("transred", stats.transreds,
43 "transitive reduction limit of %" PRId64 " propagations", limit);
44
45 const auto end = clauses.end ();
46 auto i = clauses.begin ();
47
48 // Find first clause not checked for being transitive yet.
49 //
50 for (; i != end; i++) {
51 Clause *c = *i;
52 if (c->garbage)
53 continue;
54 if (c->size != 2)
55 continue;
56 if (c->redundant && c->hyper)
57 continue;
58 if (!c->transred)
59 break;
60 }
61
62 // If all candidate clauses have been checked reschedule all.
63 //
64 if (i == end) {
65
66 PHASE ("transred", stats.transreds,
67 "rescheduling all clauses since no clauses to check left");
68 for (i = clauses.begin (); i != end; i++) {
69 Clause *c = *i;
70 if (c->transred)
71 c->transred = false;
72 }
73 i = clauses.begin ();
74 }
75
76 // Move watches of binary clauses to the front. Thus we can stop iterating
77 // watches as soon a long clause is found during watch traversal.
78 //
79 sort_watches ();
80
81 // This working stack plays the same role as the 'trail' during standard
82 // propagation.
83 //
84 vector<int> work;
85
86 int64_t propagations = 0, units = 0, removed = 0;
87
88 while (!unsat && i != end && !terminated_asynchronously () &&
89 propagations < limit) {
90 Clause *c = *i++;
91
92 // A clause is a candidate for being transitive if it is binary, and not
93 // the result of hyper binary resolution. The reason for excluding
94 // those, is that they come in large numbers, most of them are reduced
95 // away anyhow and further are non-transitive at the point they are
96 // added (see the code in 'hyper_binary_resolve' in 'prope.cpp' and
97 // also check out our CPAIOR paper on tree-based look ahead).
98 //
99 if (c->garbage)
100 continue;
101 if (c->size != 2)
102 continue;
103 if (c->redundant && c->hyper)
104 continue;
105 if (c->transred)
106 continue; // checked before?
107 c->transred = true; // marked as checked
108
109 LOG (c, "checking transitive reduction of");
110
111 // Find a different path from 'src' to 'dst' in the binary implication
112 // graph, not using 'c'. Since this is the same as checking whether
113 // there is a path from '-dst' to '-src', we can do the reverse search
114 // if the number of watches of '-dst' is larger than those of 'src'.
115 //
116 int src = -c->literals[0];
117 int dst = c->literals[1];
118 if (val (src) || val (dst))
119 continue;
120 if (watches (-src).size () < watches (dst).size ()) {
121 int tmp = dst;
122 dst = -src;
123 src = -tmp;
124 }
125
126 LOG ("searching path from %d to %d", src, dst);
127
128 // If the candidate clause is irredundant then we can not use redundant
129 // binary clauses in the implication graph. See our inprocessing rules
130 // paper, why this restriction is required.
131 //
132 const bool irredundant = !c->redundant;
133
134 CADICAL_assert (work.empty ());
135 mark (src);
136 work.push_back (src);
137 LOG ("transred assign %d", src);
138
139 bool transitive = false; // found path from 'src' to 'dst'?
140 bool failed = false; // 'src' failed literal?
141
142 size_t j = 0; // 'propagated' in BFS
143
144 CADICAL_assert (lrat_chain.empty ());
145 CADICAL_assert (mini_chain.empty ());
146 vector<int> parents;
147
148 while (!transitive && !failed && j < work.size ()) {
149 const int lit = work[j++];
150 CADICAL_assert (marked (lit) > 0);
151 LOG ("transred propagating %d", lit);
152 propagations++;
153 const Watches &ws = watches (-lit);
154 const const_watch_iterator eow = ws.end ();
156 for (k = ws.begin (); !transitive && !failed && k != eow; k++) {
157 const Watch &w = *k;
158 if (!w.binary ())
159 break; // since we sorted watches above
160 Clause *d = w.clause;
161 if (d == c)
162 continue;
163 if (irredundant && d->redundant)
164 continue;
165 if (d->garbage)
166 continue;
167 const int other = w.blit;
168 if (other == dst)
169 transitive = true; // 'dst' reached
170 else {
171 const int tmp = marked (other);
172 if (tmp > 0)
173 continue;
174 else if (tmp < 0) {
175 if (lrat) {
176 parents.push_back (lit);
177 mini_chain.push_back (d->id);
178 work.push_back (other);
179 }
180 LOG ("found both %d and %d reachable", -other, other);
181 failed = true;
182 } else {
183 if (lrat) {
184 parents.push_back (lit);
185 mini_chain.push_back (d->id);
186 }
187 mark (other);
188 work.push_back (other);
189 LOG ("transred assign %d", other);
190 }
191 }
192 }
193 }
194
195 int failed_lit = work.back ();
196 int next_pos = 0;
197 int next_neg = 0;
198
199 // Unassign all assigned literals (same as '[bp]acktrack').
200 //
201 while (!work.empty ()) {
202 const int lit = work.back ();
203 work.pop_back ();
204 if (lrat && failed && !work.empty ()) {
205 CADICAL_assert (!parents.empty () && !mini_chain.empty ());
206 LOG ("transred LRAT current lit %d next pos %d next neg %d", lit,
207 next_pos, next_neg);
208 if (lit == failed_lit || lit == next_pos) {
209 lrat_chain.push_back (mini_chain.back ());
210 next_pos = parents.back ();
211 } else if (lit == -failed_lit || lit == next_neg) {
212 lrat_chain.push_back (mini_chain.back ());
213 next_neg = parents.back ();
214 }
215 parents.pop_back ();
216 mini_chain.pop_back ();
217 }
218 unmark (lit);
219 }
220 mini_chain.clear ();
221 CADICAL_assert (mini_chain.empty ());
222 if (lrat && failed) {
223 reverse (lrat_chain.begin (), lrat_chain.end ());
224 }
225
226 if (transitive) {
227 removed++;
228 stats.transitive++;
229 LOG (c, "transitive redundant");
230 mark_garbage (c);
231 } else if (failed) {
232 units++;
233 LOG ("found failed literal %d during transitive reduction", src);
234 stats.failed++;
235 stats.transredunits++;
236 assign_unit (-src);
237 if (!propagate ()) {
238 VERBOSE (1, "propagating new unit results in conflict");
240 }
241 }
242 lrat_chain.clear ();
243 }
244
245 last.transred.propagations = stats.propagations.search;
246 stats.propagations.transred += propagations;
247 erase_vector (work);
248
249 PHASE ("transred", stats.transreds,
250 "removed %" PRId64 " transitive clauses, found %" PRId64 " units",
251 removed, units);
252
254 report ('t', !opts.reportall && !(removed + units));
255}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ traverse_clauses()

bool CaDiCaL::Internal::traverse_clauses ( ClauseIterator & it)

Definition at line 1166 of file cadical_internal.cpp.

1166 {
1167 vector<int> eclause;
1168 if (unsat)
1169 return it.clause (eclause);
1170 for (const auto &c : clauses) {
1171 if (c->garbage)
1172 continue;
1173 if (c->redundant)
1174 continue;
1175 bool satisfied = false;
1176 for (const auto &ilit : *c) {
1177 const int tmp = fixed (ilit);
1178 if (tmp > 0) {
1179 satisfied = true;
1180 break;
1181 }
1182 if (tmp < 0)
1183 continue;
1184 const int elit = externalize (ilit);
1185 eclause.push_back (elit);
1186 }
1187 if (!satisfied && !it.clause (eclause))
1188 return false;
1189 eclause.clear ();
1190 }
1191 return true;
1192}
Here is the call graph for this function:

◆ traverse_constraint()

bool CaDiCaL::Internal::traverse_constraint ( ClauseIterator & it)

Definition at line 1138 of file cadical_internal.cpp.

1138 {
1139 if (constraint.empty () && !unsat_constraint)
1140 return true;
1141
1142 vector<int> eclause;
1143 if (unsat)
1144 return it.clause (eclause);
1145
1146 LOG (constraint, "traversing constraint");
1147 bool satisfied = false;
1148 for (auto ilit : constraint) {
1149 const int tmp = fixed (ilit);
1150 if (tmp > 0) {
1151 satisfied = true;
1152 break;
1153 }
1154 if (tmp < 0)
1155 continue;
1156 const int elit = externalize (ilit);
1157 eclause.push_back (elit);
1158 }
1159 if (!satisfied && !it.clause (eclause))
1160 return false;
1161
1162 return true;
1163}
Here is the call graph for this function:

◆ trivially_false_satisfiable()

int CaDiCaL::Internal::trivially_false_satisfiable ( )

Definition at line 34 of file cadical_lucky.cpp.

34 {
35 LOG ("checking that all clauses contain a negative literal");
37 CADICAL_assert (assumptions.empty ());
38 for (const auto &c : clauses) {
40 return unlucky (-1);
41 if (c->garbage)
42 continue;
43 if (c->redundant)
44 continue;
45 bool satisfied = false, found_negative_literal = false;
46 for (const auto &lit : *c) {
47 const signed char tmp = val (lit);
48 if (tmp > 0) {
49 satisfied = true;
50 break;
51 }
52 if (tmp < 0)
53 continue;
54 if (lit > 0)
55 continue;
56 found_negative_literal = true;
57 break;
58 }
59 if (satisfied || found_negative_literal)
60 continue;
61 LOG (c, "found purely positively");
62 return unlucky (0);
63 }
64 VERBOSE (1, "all clauses contain a negative literal");
65 for (auto idx : vars) {
67 return unlucky (-1);
68 if (val (idx))
69 continue;
71 if (propagate ())
72 continue;
74 LOG ("propagation failed including redundant clauses");
75 return unlucky (0);
76 }
77 stats.lucky.constant.zero++;
78 return 10;
79}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ trivially_true_satisfiable()

int CaDiCaL::Internal::trivially_true_satisfiable ( )

Definition at line 81 of file cadical_lucky.cpp.

81 {
82 LOG ("checking that all clauses contain a positive literal");
84 CADICAL_assert (assumptions.empty ());
85 for (const auto &c : clauses) {
87 return unlucky (-1);
88 if (c->garbage)
89 continue;
90 if (c->redundant)
91 continue;
92 bool satisfied = false, found_positive_literal = false;
93 for (const auto &lit : *c) {
94 const signed char tmp = val (lit);
95 if (tmp > 0) {
96 satisfied = true;
97 break;
98 }
99 if (tmp < 0)
100 continue;
101 if (lit < 0)
102 continue;
103 found_positive_literal = true;
104 break;
105 }
106 if (satisfied || found_positive_literal)
107 continue;
108 LOG (c, "found purely negatively");
109 return unlucky (0);
110 }
111 VERBOSE (1, "all clauses contain a positive literal");
112 for (auto idx : vars) {
114 return unlucky (-1);
115 if (val (idx))
116 continue;
118 if (propagate ())
119 continue;
120 CADICAL_assert (level > 0);
121 LOG ("propagation failed including redundant clauses");
122 return unlucky (0);
123 }
124 stats.lucky.constant.one++;
125 return 10;
126}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_to_eliminate_variable()

void CaDiCaL::Internal::try_to_eliminate_variable ( Eliminator & eliminator,
int pivot,
bool & deleted_binary_clause )

Definition at line 681 of file cadical_elim.cpp.

682 {
683
684 if (!active (pivot))
685 return;
686 CADICAL_assert (!frozen (pivot));
687
688 // First flush garbage clauses.
689 //
690 int64_t pos = flush_occs (pivot);
691 int64_t neg = flush_occs (-pivot);
692
693 if (pos > neg) {
694 pivot = -pivot;
695 swap (pos, neg);
696 }
697 LOG ("pivot %d occurs positively %" PRId64
698 " times and negatively %" PRId64 " times",
699 pivot, pos, neg);
700 CADICAL_assert (!eliminator.schedule.contains (abs (pivot)));
701 CADICAL_assert (pos <= neg);
702
703 if (pos && neg > opts.elimocclim) {
704 LOG ("too many occurrences thus not eliminated %d", pivot);
705 CADICAL_assert (!eliminator.schedule.contains (abs (pivot)));
706 return;
707 }
708
709 LOG ("trying to eliminate %d", pivot);
710 CADICAL_assert (!flags (pivot).eliminated ());
711
712 // Sort occurrence lists, such that shorter clauses come first.
713 Occs &ps = occs (pivot);
714 stable_sort (ps.begin (), ps.end (), clause_smaller_size ());
715 Occs &ns = occs (-pivot);
716 stable_sort (ns.begin (), ns.end (), clause_smaller_size ());
717
718 if (pos)
719 find_gate_clauses (eliminator, pivot);
720
721 if (!unsat && !val (pivot)) {
722 if (elim_resolvents_are_bounded (eliminator, pivot)) {
723 LOG ("number of resolvents on %d are bounded", pivot);
724 elim_add_resolvents (eliminator, pivot);
725 if (!unsat)
726 mark_eliminated_clauses_as_garbage (eliminator, pivot,
727 deleted_binary_clause);
728 if (active (pivot))
729 mark_eliminated (pivot);
730 } else {
731 LOG ("too many resolvents on %d so not eliminated", pivot);
732 }
733 }
734
735 unmark_gate_clauses (eliminator);
736 elim_backward_clauses (eliminator);
737}
void find_gate_clauses(Eliminator &, int pivot)
void mark_eliminated(int)
void unmark_gate_clauses(Eliminator &)
void elim_backward_clauses(Eliminator &)
void mark_eliminated_clauses_as_garbage(Eliminator &, int pivot, bool &)
bool elim_resolvents_are_bounded(Eliminator &, int pivot)
void elim_add_resolvents(Eliminator &, int pivot)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_to_fasteliminate_variable()

void CaDiCaL::Internal::try_to_fasteliminate_variable ( Eliminator & eliminator,
int pivot,
bool & deleted_binary_clause )

Definition at line 189 of file cadical_elimfast.cpp.

191 {
192
193 if (!active (pivot))
194 return;
195 CADICAL_assert (!frozen (pivot));
196
197 // First flush garbage clauses and check limits.
198
199 int64_t bound = opts.fastelimbound;
200
201 int64_t pos = flush_elimfast_occs (pivot);
202 if (pos > bound) {
203 LOG ("too many occurrences thus not eliminated %d", pivot);
204 CADICAL_assert (!eliminator.schedule.contains (abs (pivot)));
205 return;
206 }
207
208 int64_t neg = flush_elimfast_occs (-pivot);
209 if (neg > bound) {
210 LOG ("too many occurrences thus not eliminated %d", -pivot);
211 CADICAL_assert (!eliminator.schedule.contains (abs (pivot)));
212 return;
213 }
214
215 const int64_t product = pos * neg;
216 const int64_t sum = pos + neg;
217 if (bound > sum)
218 bound = sum;
219
220 if (pos > neg) {
221 pivot = -pivot;
222 swap (pos, neg);
223 }
224
225 LOG ("pivot %d occurs positively %" PRId64
226 " times and negatively %" PRId64 " times",
227 pivot, pos, neg);
228
229 CADICAL_assert (!eliminator.schedule.contains (abs (pivot)));
230 CADICAL_assert (pos <= neg);
231
232 LOG ("trying to eliminate %d", pivot);
233 CADICAL_assert (!flags (pivot).eliminated ());
234
235 // Sort occurrence lists, such that shorter clauses come first.
236 Occs &ps = occs (pivot);
237 stable_sort (ps.begin (), ps.end (), clause_smaller_size ());
238 Occs &ns = occs (-pivot);
239 stable_sort (ns.begin (), ns.end (), clause_smaller_size ());
240
241 if (!unsat && !val (pivot)) {
242 if (product <= bound ||
243 elimfast_resolvents_are_bounded (eliminator, pivot)) {
244 LOG ("number of resolvents on %d are bounded", pivot);
245 elimfast_add_resolvents (eliminator, pivot);
246 if (!unsat)
247 mark_eliminated_clauses_as_garbage (eliminator, pivot,
248 deleted_binary_clause);
249 if (active (pivot))
250 mark_eliminated (pivot);
251 } else {
252 LOG ("too many resolvents on %d so not eliminated", pivot);
253 }
254 }
255
256 unmark_gate_clauses (eliminator);
257 elim_backward_clauses (eliminator);
258}
void elimfast_add_resolvents(Eliminator &, int pivot)
int64_t flush_elimfast_occs(int lit)
bool elimfast_resolvents_are_bounded(Eliminator &, int pivot)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_to_satisfy_formula_by_saved_phases()

int CaDiCaL::Internal::try_to_satisfy_formula_by_saved_phases ( )

Definition at line 752 of file cadical_internal.cpp.

752 {
753 LOG ("satisfying formula by saved phases");
756 CADICAL_assert (propagated == trail.size ());
757 force_saved_phase = true;
758 if (external_prop) {
760 LOG ("external notifications are turned off during preprocessing.");
761 private_steps = true;
762 }
763 int res = 0;
764 while (!res) {
765 if (satisfied ()) {
766 LOG ("formula indeed satisfied by saved phases");
767 res = 10;
768 } else if (decide ()) {
769 LOG ("inconsistent assumptions with redundant clauses and phases");
770 res = 20;
771 } else if (!propagate ()) {
772 LOG ("saved phases do not satisfy redundant clauses");
773 CADICAL_assert (level > 0);
774 backtrack ();
775 conflict = 0; // ignore conflict
776 CADICAL_assert (!res);
777 break;
778 }
779 }
781 force_saved_phase = false;
782 if (external_prop) {
783 private_steps = false;
784 LOG ("external notifications are turned back on.");
785 if (!level)
786 notify_assignments (); // In case fixed assignments were found.
787 else {
789 }
790 }
791 return res;
792}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_to_subsume_clause()

int CaDiCaL::Internal::try_to_subsume_clause ( Clause * c,
vector< Clause * > & shrunken )
inline

Definition at line 188 of file cadical_subsume.cpp.

189 {
190
191 stats.subtried++;
193 LOG (c, "trying to subsume");
194
195 mark (c); // signed!
196
197 Clause *d = 0;
198 int flipped = 0;
199
200 for (const auto &lit : *c) {
201
202 // Only clauses which have a variable which has recently been added are
203 // checked for being subsumed. The idea is that all these newly added
204 // clauses are candidates for subsuming the clause. Then we also only
205 // need to check occurrences of these variables. The occurrence lists
206 // of other literal do not have to be checked.
207 //
208 if (!flags (lit).subsume)
209 continue;
210
211 for (int sign = -1; !d && sign <= 1; sign += 2) {
212
213 // First we check against all binary clauses. The other literals of
214 // all binary clauses of 'sign*lit' are stored in one consecutive
215 // array, which is way faster than storing clause pointers and
216 // dereferencing them. Since this binary clause array is also not
217 // shrunken, we also can bail out earlier if subsumption or
218 // strengthening is determined.
219
220 // In both cases the (self-)subsuming clause is stored in 'd', which
221 // makes it nonzero and forces aborting both the outer and inner loop.
222 // If the binary clause can strengthen the candidate clause 'c'
223 // (through self-subsuming resolution), then 'filled' is set to the
224 // literal which can be removed in 'c', otherwise to 'INT_MIN' which
225 // is a non-valid literal.
226
227 for (const auto &bin : bins (sign * lit)) {
228 const auto &other = bin.lit;
229 const int tmp = marked (other);
230 if (!tmp)
231 continue;
232 if (tmp < 0 && sign < 0)
233 continue;
234 if (tmp < 0) {
235 if (sign < 0)
236 continue; // tautological resolvent
237 dummy_binary->literals[0] = lit;
238 dummy_binary->literals[1] = other;
239 flipped = other;
240 } else {
241 dummy_binary->literals[0] = sign * lit;
242 dummy_binary->literals[1] = other;
243 flipped = (sign < 0) ? -lit : INT_MIN;
244 }
245
246 // This dummy binary clauses is initialized in 'Internal::Internal'
247 // and only changes it literals in the lines above. By using such
248 // a faked binary clause we can simply reuse 'subsume_clause' as
249 // well as the code around 'strengthen_clause' uniform for both real
250 // clauses and this special case for binary clauses
251
252 dummy_binary->id = bin.id;
253 d = dummy_binary;
254
255 break;
256 }
257
258 if (d)
259 break;
260
261 // In this second loop we check for larger than binary clauses to
262 // subsume or strengthen the candidate clause. This is more costly,
263 // and needs a call to 'subsume_check'. Otherwise the same contract
264 // as above for communicating 'subsumption' or 'strengthening' to the
265 // code after the loop is used.
266 //
267 const Occs &os = occs (sign * lit);
268 for (const auto &e : os) {
269 CADICAL_assert (!e->garbage); // sanity check
270 if (e->garbage)
271 continue; // defensive: not needed
272 flipped = subsume_check (e, c);
273 if (!flipped)
274 continue;
275 d = e; // leave also outer loop
276 break;
277 }
278 }
279
280 if (d)
281 break;
282 }
283
284 unmark (c);
285
286 if (flipped == INT_MIN) {
287 LOG (d, "subsuming");
288 subsume_clause (d, c);
289 return 1;
290 }
291
292 if (flipped) {
293 LOG (d, "strengthening");
294 if (lrat) {
295 CADICAL_assert (lrat_chain.empty ());
296 lrat_chain.push_back (c->id);
297 lrat_chain.push_back (d->id);
298 }
299 if (d->used > c->used)
300 c->used = d->used;
301 strengthen_clause (c, -flipped);
302 lrat_chain.clear ();
304 shrunken.push_back (c);
305 return -1;
306 }
307
308 return 0;
309}
void subsume_clause(Clause *subsuming, Clause *subsumed)
int subsume_check(Clause *subsuming, Clause *subsumed)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ u2i()

int CaDiCaL::Internal::u2i ( unsigned u)
inline

Definition at line 412 of file internal.hpp.

412 {
413 CADICAL_assert (u > 1);
414 int res = u / 2;
415 CADICAL_assert (res <= max_var);
416 if (u & 1)
417 res = -res;
418 return res;
419 }
Here is the caller graph for this function:

◆ unassign()

void CaDiCaL::Internal::unassign ( int lit)
inline

Definition at line 14 of file cadical_backtrack.cpp.

14 {
15 CADICAL_assert (val (lit) > 0);
16 set_val (lit, 0);
17
18 int idx = vidx (lit);
19 LOG ("unassign %d @ %d", lit, var (idx).level);
21
22 // In the standard EVSIDS variable decision heuristic of MiniSAT, we need
23 // to push variables which become unassigned back to the heap.
24 //
25 if (!scores.contains (idx))
26 scores.push_back (idx);
27
28 // For VMTF we need to update the 'queue.unassigned' pointer in case this
29 // variable sits after the variable to which 'queue.unassigned' currently
30 // points. See our SAT'15 paper for more details on this aspect.
31 //
32 if (queue.bumped < btab[idx])
34}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unit_clauses()

int64_t & CaDiCaL::Internal::unit_clauses ( int uidx)
inline

Definition at line 443 of file internal.hpp.

443 {
445 CADICAL_assert (uidx > 0);
446 CADICAL_assert ((size_t) uidx < unit_clauses_idx.size ());
447 return unit_clauses_idx[uidx];
448 }
Here is the caller graph for this function:

◆ unit_id()

int64_t CaDiCaL::Internal::unit_id ( int lit) const
inline

Definition at line 434 of file internal.hpp.

434 {
436 CADICAL_assert (val (lit) > 0);
437 const unsigned uidx = vlit (lit);
438 int64_t id = unit_clauses_idx[uidx];
439 CADICAL_assert (id);
440 return id;
441 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unlucky()

int CaDiCaL::Internal::unlucky ( int res)

Definition at line 26 of file cadical_lucky.cpp.

26 {
27 if (level > 0)
28 backtrack ();
29 if (conflict)
30 conflict = 0;
31 return res;
32}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unmark() [1/3]

void CaDiCaL::Internal::unmark ( Clause * c)

Definition at line 23 of file cadical_clause.cpp.

23 {
24 for (const auto &lit : *c)
25 unmark (lit);
26}
Here is the call graph for this function:

◆ unmark() [2/3]

void CaDiCaL::Internal::unmark ( int lit)
inline

Definition at line 490 of file internal.hpp.

490 {
491 marks[vidx (lit)] = 0;
493 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unmark() [3/3]

void CaDiCaL::Internal::unmark ( vector< int > & lits)
inline

Definition at line 527 of file internal.hpp.

527 {
528 for (const auto &lit : lits)
529 unmark (lit);
530 }
Here is the call graph for this function:

◆ unmark67()

void CaDiCaL::Internal::unmark67 ( int lit)
inline

Definition at line 517 of file internal.hpp.

517 {
518 signed char &m = marks[vidx (lit)];
519 const signed char mask = 0x3f;
520#ifndef CADICAL_NDEBUG
521 const signed bits = m & mask;
522#endif
523 m &= mask;
524 CADICAL_assert ((m & mask) == bits);
525 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unmark_as_conditional_literal()

void CaDiCaL::Internal::unmark_as_conditional_literal ( int lit)
inline

Definition at line 117 of file cadical_condition.cpp.

117 {
118 LOG ("unmarking %d as conditional literal", lit);
120 unsetbit (lit, 0);
121}
void unsetbit(int lit, int bit)
Definition internal.hpp:546
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unmark_binary_literals()

void CaDiCaL::Internal::unmark_binary_literals ( Eliminator & eliminator)

Definition at line 192 of file cadical_gates.cpp.

192 {
193 LOG ("unmarking %zd literals", eliminator.marked.size ());
194 for (const auto &lit : eliminator.marked)
195 unmark (lit);
196 eliminator.marked.clear ();
197}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unmark_block()

void CaDiCaL::Internal::unmark_block ( int lit)
inline

Definition at line 1094 of file internal.hpp.

1094 {
1095 Flags &f = flags (lit);
1096 const unsigned bit = bign (lit);
1097 f.block &= ~bit;
1098 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unmark_clause()

void CaDiCaL::Internal::unmark_clause ( )

Definition at line 33 of file cadical_clause.cpp.

33 {
34 for (const auto &lit : clause)
35 unmark (lit);
36}
Here is the call graph for this function:

◆ unmark_decomposed()

void CaDiCaL::Internal::unmark_decomposed ( int lit)
inline

Definition at line 1126 of file internal.hpp.

1126 {
1127 Flags &f = flags (lit);
1128 const unsigned bit = bign (lit);
1129 f.marked_signed &= ~bit;
1130 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unmark_gate_clauses()

void CaDiCaL::Internal::unmark_gate_clauses ( Eliminator & eliminator)

Definition at line 758 of file cadical_gates.cpp.

758 {
759 LOG ("unmarking %zd gate clauses", eliminator.gates.size ());
760 for (const auto &c : eliminator.gates) {
761 CADICAL_assert (c->gate);
762 c->gate = false;
763 }
764 eliminator.gates.clear ();
765 eliminator.definition_unit = 0;
766}
Here is the caller graph for this function:

◆ unmark_in_candidate_clause()

void CaDiCaL::Internal::unmark_in_candidate_clause ( int lit)
inline

Definition at line 141 of file cadical_condition.cpp.

141 {
142 LOG ("unmarking %d as literal of the candidate clause", lit);
144 unmark67 (lit);
145}
void unmark67(int lit)
Definition internal.hpp:517
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unmarkfact()

void CaDiCaL::Internal::unmarkfact ( int lit,
int fact )
inline

Definition at line 599 of file internal.hpp.

599 {
600 CADICAL_assert (fact == 1 || fact == 2 || fact == 4);
601 CADICAL_assert (getfact (lit, fact));
602 int res = marks[vidx (lit)];
603 if (lit < 0) {
604 res &= ~(fact << 3);
605 } else {
606 res &= ~fact;
607 }
608 marks[vidx (lit)] = res;
609 CADICAL_assert (!getfact (lit, fact));
610 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unphase()

void CaDiCaL::Internal::unphase ( int lit)

Definition at line 37 of file cadical_phases.cpp.

37 {
38 const int idx = vidx (lit);
39 signed char old_forced_phase = phases.forced[idx];
40 if (!old_forced_phase) {
41 LOG ("forced phase of %d already reset", lit);
42 return;
43 }
44 LOG ("clearing old forced phase %d", old_forced_phase * idx);
45 phases.forced[idx] = 0;
46}
Here is the call graph for this function:

◆ unprotect_reasons()

void CaDiCaL::Internal::unprotect_reasons ( )

Definition at line 140 of file cadical_collect.cpp.

140 {
141 LOG ("unprotecting reasons clauses of all assigned variables on trail");
143#ifdef LOGGING
144 size_t count = 0;
145#endif
146 for (const auto &lit : trail) {
147 if (!active (lit))
148 continue;
150 Var &v = var (lit);
151 CADICAL_assert (v.level > 0);
152 Clause *reason = v.reason;
153 if (!reason)
154 continue;
155 if (reason == external_reason)
156 continue;
157 LOG (reason, "unprotecting assigned %d reason %p", lit,
158 (void *) reason);
159 CADICAL_assert (reason->reason);
160 reason->reason = false;
161#ifdef LOGGING
162 count++;
163#endif
164 }
165 LOG ("unprotected %zd reason clauses referenced on trail", count);
166 protected_reasons = false;
167}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unschedule_sweeping()

void CaDiCaL::Internal::unschedule_sweeping ( Sweeper & sweeper,
unsigned swept,
unsigned scheduled )

Definition at line 1845 of file cadical_sweep.cpp.

1846 {
1847#ifdef CADICAL_QUIET
1848 (void) scheduled, (void) swept;
1849#endif
1850 CADICAL_assert (sweep_schedule.empty ());
1852 for (all_scheduled (idx))
1853 if (active (idx)) {
1854 sweep_schedule.push_back (idx);
1855 LOG ("untried scheduled %d", idx);
1856 }
1857#ifndef CADICAL_QUIET
1858 const unsigned retained = sweep_schedule.size ();
1859#endif
1860 VERBOSE (3, "retained %u variables %.0f%% to be swept next time",
1861 retained, percent (retained, active ()));
1862 const unsigned incomplete = incomplete_variables ();
1863 if (incomplete)
1864 VERBOSE (3, "need to sweep %u more variables %.0f%% for completion",
1865 incomplete, percent (incomplete, active ()));
1866 else {
1867 VERBOSE (3, "no more variables needed to complete sweep");
1868 sweep_incomplete = false;
1869 stats.sweep_completed++;
1870 }
1871 PHASE ("sweep", stats.sweep, "swept %u variables (%u remain %.0f%%)",
1872 swept, incomplete, percent (incomplete, scheduled));
1873}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unsetbit()

void CaDiCaL::Internal::unsetbit ( int lit,
int bit )
inline

Definition at line 546 of file internal.hpp.

546 {
547 CADICAL_assert (0 <= bit), CADICAL_assert (bit < 6);
548 CADICAL_assert (getbit (lit, bit));
549 marks[vidx (lit)] &= ~(1 << bit);
550 CADICAL_assert (!getbit (lit, bit));
551 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unwatch_clause()

void CaDiCaL::Internal::unwatch_clause ( Clause * c)
inline

Definition at line 640 of file internal.hpp.

640 {
641 const int l0 = c->literals[0];
642 const int l1 = c->literals[1];
643 remove_watch (watches (l0), c);
644 remove_watch (watches (l1), c);
645 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_decision_rate_average()

void CaDiCaL::Internal::update_decision_rate_average ( )

Definition at line 927 of file cadical_analyze.cpp.

927 {
928 int64_t current = stats.decisions;
929 int64_t decisions = current - saved_decisions;
930 UPDATE_AVERAGE (averages.current.decisions, decisions);
931 saved_decisions = current;
932}
Here is the caller graph for this function:

◆ update_factor_candidate()

void CaDiCaL::Internal::update_factor_candidate ( Factoring & factoring,
int lit )

Definition at line 742 of file cadical_factor.cpp.

742 {
744 const size_t size = occs (lit).size ();
745 const unsigned idx = vlit (lit);
746 if (schedule.contains (idx))
747 schedule.update (idx);
748 else if (size > 1) {
749 schedule.push_back (idx);
750 }
751}
heap< factor_occs_size > FactorSchedule
Definition factor.hpp:33
Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_factored()

void CaDiCaL::Internal::update_factored ( Factoring & factoring,
Quotient * q )

Definition at line 701 of file cadical_factor.cpp.

701 {
702 const int factor = q->factor;
705 for (auto c : q->qlauses) {
706 LOG (c, "deleting unfactored");
707 for (const auto &lit : *c)
708 if (lit != factor)
710 }
711}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_queue_unassigned()

void CaDiCaL::Internal::update_queue_unassigned ( int idx)
inline

Definition at line 652 of file internal.hpp.

652 {
653 CADICAL_assert (0 < idx);
654 CADICAL_assert (idx <= max_var);
655 queue.unassigned = idx;
656 queue.bumped = btab[idx];
657 LOG ("queue unassigned now %d bumped %" PRId64 "", idx, btab[idx]);
658 }
Here is the caller graph for this function:

◆ update_reason_references()

void CaDiCaL::Internal::update_reason_references ( )

Definition at line 246 of file cadical_collect.cpp.

246 {
247 LOG ("update assigned reason references");
248#ifdef LOGGING
249 size_t count = 0;
250#endif
251 for (auto &lit : trail) {
252 if (!active (lit))
253 continue;
254 Var &v = var (lit);
255 Clause *c = v.reason;
256 if (!c)
257 continue;
258 if (c == external_reason)
259 continue;
260 LOG (c, "updating assigned %d reason", lit);
261 CADICAL_assert (c->reason);
262 CADICAL_assert (c->moved);
263 Clause *d = c->copy;
264 v.reason = d;
265#ifdef LOGGING
266 count++;
267#endif
268 }
269 LOG ("updated %zd assigned reason references", count);
270}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_target_and_best()

void CaDiCaL::Internal::update_target_and_best ( )

Definition at line 50 of file cadical_backtrack.cpp.

50 {
51
52 bool reset = (rephased && stats.conflicts > last.rephase.conflicts);
53
54 if (reset) {
56 if (rephased == 'B')
57 best_assigned = 0; // update it again
58 }
59
61 copy_phases (phases.target);
63 LOG ("new target trail level %zu", target_assigned);
64 }
65
67 copy_phases (phases.best);
69 LOG ("new best trail level %zu", best_assigned);
70 }
71
72 if (reset) {
74 rephased = 0;
75 }
76}
void copy_phases(vector< signed char > &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ use_scores()

bool CaDiCaL::Internal::use_scores ( ) const
inline

Definition at line 471 of file internal.hpp.

471{ return opts.score && stable; }
Here is the caller graph for this function:

◆ val()

signed char CaDiCaL::Internal::val ( int lit) const
inline

Definition at line 1518 of file internal.hpp.

1518 {
1522 return vals[lit];
1523 }

◆ var()

Var & CaDiCaL::Internal::var ( int lit)
inline

Definition at line 452 of file internal.hpp.

452{ return vtab[vidx (lit)]; }
Here is the call graph for this function:

◆ verror()

void CaDiCaL::Internal::verror ( const char * fmt,
va_list & ap )

Definition at line 175 of file cadical_message.cpp.

175 {
177 vfprintf (stderr, fmt, ap);
179}
void void error_message_start()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vidx()

int CaDiCaL::Internal::vidx ( int lit) const
inline

Definition at line 395 of file internal.hpp.

395 {
396 int idx;
398 CADICAL_assert (lit != INT_MIN);
399 idx = abs (lit);
400 CADICAL_assert (idx <= max_var);
401 return idx;
402 }
Here is the caller graph for this function:

◆ vivify()

bool CaDiCaL::Internal::vivify ( )

Definition at line 1804 of file cadical_vivify.cpp.

1804 {
1805
1806 if (unsat)
1807 return false;
1809 return false;
1810 if (!opts.vivify)
1811 return false;
1812 if (!stats.current.irredundant)
1813 return false;
1814 if (level)
1815 backtrack ();
1816 CADICAL_assert (opts.vivify);
1818
1819 SET_EFFORT_LIMIT (totallimit, vivify, true);
1820
1821 private_steps = true;
1822
1824 stats.vivifications++;
1825
1826 // the effort is normalized by dividing by sumeffort below, hence no need
1827 // to multiply by 1e-3 (also making the precision better)
1828 double tier1effort = !opts.vivifytier1 ? 0 : (double) opts.vivifytier1eff;
1829 double tier2effort = !opts.vivifytier2 ? 0 : (double) opts.vivifytier2eff;
1830 double tier3effort = !opts.vivifytier3 ? 0 : (double) opts.vivifytier3eff;
1831 double irreffort =
1832 delaying_vivify_irredundant.bumpreasons.delay () || !opts.vivifyirred
1833 ? 0
1834 : (double) opts.vivifyirredeff;
1835 double sumeffort = tier1effort + tier2effort + tier3effort + irreffort;
1836 if (!stats.current.redundant)
1837 tier1effort = tier2effort = tier3effort = 0;
1838 if (!sumeffort)
1839 sumeffort = irreffort = 1;
1840 int64_t total = totallimit - stats.ticks.vivify;
1841
1842 PHASE ("vivify", stats.vivifications,
1843 "vivification limit of %" PRId64 " ticks", total);
1844 Vivifier vivifier (Vivify_Mode::TIER1);
1846
1847 if (vivifier.tier1_limit == vivifier.tier2_limit) {
1848 tier1effort += tier2effort;
1849 tier2effort = 0;
1850 LOG ("vivification tier1 matches tier2 "
1851 "thus using tier2 budget for tier1");
1852 }
1853 int64_t init_ticks = 0;
1854
1855 // Refill the schedule every time. Unchecked clauses are 'saved' by
1856 // setting their 'vivify' bit, such that they can be tried next time.
1857 //
1858 // TODO: count against ticks.vivify directly instead of this unholy
1859 // shifting.
1860 vivify_initialize (vivifier, init_ticks);
1861 stats.ticks.vivify += init_ticks;
1862 int64_t limit = stats.ticks.vivify;
1863 const double shared_effort = (double) init_ticks / 4.0;
1864 if (opts.vivifytier1) {
1866 if (limit < stats.ticks.vivify)
1867 limit = stats.ticks.vivify;
1868 const double effort = (total * tier1effort) / sumeffort;
1869 CADICAL_assert (std::numeric_limits<int64_t>::max () - (int64_t) effort >=
1870 limit);
1871 limit += effort;
1872 if (limit - shared_effort > stats.ticks.vivify) {
1873 limit -= shared_effort;
1874 CADICAL_assert (limit >= 0);
1876 } else {
1877 LOG ("building the schedule already used our entire ticks budget for "
1878 "tier1");
1879 }
1880 }
1881
1882 if (!unsat && tier2effort) {
1883 erase_vector (
1884 vivifier.schedule_tier1); // save memory (well, not really as we
1885 // already reached the peak memory)
1886 if (limit < stats.ticks.vivify)
1887 limit = stats.ticks.vivify;
1888 const double effort = (total * tier2effort) / sumeffort;
1889 CADICAL_assert (std::numeric_limits<int64_t>::max () - (int64_t) effort >=
1890 limit);
1891 limit += effort;
1892 if (limit - shared_effort > stats.ticks.vivify) {
1893 limit -= shared_effort;
1894 CADICAL_assert (limit >= 0);
1897 } else {
1898 LOG ("building the schedule already used our entire ticks budget for "
1899 "tier2");
1900 }
1901 }
1902
1903 if (!unsat && tier3effort) {
1904 erase_vector (vivifier.schedule_tier2);
1905 if (limit < stats.ticks.vivify)
1906 limit = stats.ticks.vivify;
1907 const double effort = (total * tier3effort) / sumeffort;
1908 CADICAL_assert (std::numeric_limits<int64_t>::max () - (int64_t) effort >=
1909 limit);
1910 limit += effort;
1911 if (limit - shared_effort > stats.ticks.vivify) {
1912 limit -= shared_effort;
1913 CADICAL_assert (limit >= 0);
1916 } else {
1917 LOG ("building the schedule already used our entire ticks budget for "
1918 "tier3");
1919 }
1920 }
1921
1922 if (!unsat && irreffort) {
1923 erase_vector (vivifier.schedule_tier3);
1924 if (limit < stats.ticks.vivify)
1925 limit = stats.ticks.vivify;
1926 const double effort = (total * irreffort) / sumeffort;
1927 CADICAL_assert (std::numeric_limits<int64_t>::max () - (int64_t) effort >=
1928 limit);
1929 limit += effort;
1930 if (limit - shared_effort > stats.ticks.vivify) {
1931 limit -= shared_effort;
1932 CADICAL_assert (limit >= 0);
1934 const int old = stats.vivifystrirr;
1935 const int old_tried = stats.vivifychecks;
1937 if (stats.vivifychecks - old_tried == 0 ||
1938 (float) (stats.vivifystrirr - old) /
1939 (float) (stats.vivifychecks - old_tried) <
1940 0.01) {
1941 delaying_vivify_irredundant.bumpreasons.bump_delay ();
1942 } else {
1943 delaying_vivify_irredundant.bumpreasons.reduce_delay ();
1944 }
1945 } else {
1946 delaying_vivify_irredundant.bumpreasons.bump_delay ();
1947 LOG ("building the schedule already used our entire ticks budget for "
1948 "irredundant");
1949 }
1950 }
1951
1952 reset_noccs ();
1954
1955 private_steps = false;
1956
1957 return true;
1958}
void set_vivifier_mode(Vivifier &vivifier, Vivify_Mode tier)
void vivify_round(Vivifier &, int64_t delta)
Delay delaying_vivify_irredundant
Definition internal.hpp:291
void vivify_initialize(Vivifier &vivifier, int64_t &ticks)
void compute_tier_limits(Vivifier &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_analyze()

void CaDiCaL::Internal::vivify_analyze ( Clause * start,
bool & subsumes,
Clause ** subsuming,
const Clause * const candidate,
int implied,
bool & redundant )

Definition at line 652 of file cadical_vivify.cpp.

655 {
656 const auto &t = &trail; // normal trail, so next_trail is wrong
657 int i = t->size (); // Start at end-of-trail.
658 Clause *reason = start;
659 CADICAL_assert (reason);
660 CADICAL_assert (!trail.empty ());
661 int uip = trail.back ();
662 bool mark_implied = (implied);
663
664 while (i >= 0) {
665 if (reason) {
666 redundant = (redundant || reason->redundant);
667 subsumes = (start != reason && reason->size <= start->size);
668 LOG (reason, "resolving on %d with", uip);
669 for (auto other : *reason) {
670 const Var v = var (other);
671 Flags &f = flags (other);
672 if (!marked2 (other) && v.level) {
673 LOG ("not subsuming due to lit %d", other);
674 subsumes = false;
675 }
676 if (!val (other)) {
677 LOG ("skipping unset lit %d", other);
678 continue;
679 }
680 if (other == uip) {
681 continue;
682 }
683 if (!v.level) {
684 if (f.seen || !lrat || reason == start)
685 continue;
686 LOG ("unit reason for %d", other);
687 int64_t id = unit_id (-other);
688 LOG ("adding unit reason %zd for %d", id, other);
689 unit_chain.push_back (id);
690 f.seen = true;
691 analyzed.push_back (other);
692 continue;
693 }
694 if (mark_implied && other != implied) {
695 LOG ("skipping non-implied literal %d on current level", other);
696 continue;
697 }
698
699 CADICAL_assert (val (other));
700 if (f.seen)
701 continue;
702 LOG ("pushing lit %d", other);
703 analyzed.push_back (other);
704 f.seen = true;
705 }
706 if (start->redundant) {
707 const int new_glue = recompute_glue (start);
708 promote_clause (start, new_glue);
709 }
710 if (subsumes) {
711 CADICAL_assert (reason);
712 LOG (reason, "clause found subsuming");
713 LOG (candidate, "clause found subsumed");
714 *subsuming = reason;
715 return;
716 }
717 } else {
718 LOG ("vivify analyzed decision %d", uip);
719 clause.push_back (-uip);
720 }
721 mark_implied = false;
722
723 uip = 0;
724 while (!uip && i > 0) {
725 CADICAL_assert (i > 0);
726 const int lit = (*t)[--i];
727 if (!var (lit).level)
728 continue;
729 if (flags (lit).seen)
730 uip = lit;
731 }
732 if (!uip)
733 break;
734 LOG ("uip is %d", uip);
735 Var &w = var (uip);
736 reason = w.reason;
737 if (lrat && reason)
738 lrat_chain.push_back (reason->id);
739 }
740 (void) candidate;
741}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_analyze_redundant()

void CaDiCaL::Internal::vivify_analyze_redundant ( Vivifier & ,
Clause * start,
bool &  )
Here is the call graph for this function:

◆ vivify_assign()

void CaDiCaL::Internal::vivify_assign ( int lit,
Clause * reason )
inline

Definition at line 146 of file cadical_vivify.cpp.

146 {
148 const int idx = vidx (lit);
149 CADICAL_assert (!vals[idx]);
150 CADICAL_assert (!flags (idx).eliminated () || !reason);
151 Var &v = var (idx);
152 v.level = level; // required to reuse decisions
153 v.trail = (int) trail.size (); // used in 'vivify_better_watch'
155 num_assigned++;
156 v.reason = level ? reason : 0; // for conflict analysis
157 if (!level)
159 const signed char tmp = sign (lit);
160 vals[idx] = tmp;
161 vals[-idx] = -tmp;
162 CADICAL_assert (val (lit) > 0);
163 CADICAL_assert (val (-lit) < 0);
164 trail.push_back (lit);
165 LOG (reason, "vivify assign %d", lit);
166}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_assume()

void CaDiCaL::Internal::vivify_assume ( int lit)

Definition at line 170 of file cadical_vivify.cpp.

170 {
172 level++;
173 control.push_back (Level (lit, trail.size ()));
174 LOG ("vivify decide %d", lit);
175 CADICAL_assert (level > 0);
176 CADICAL_assert (propagated == trail.size ());
177 vivify_assign (lit, 0);
178}
void vivify_assign(int lit, Clause *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_build_lrat()

void CaDiCaL::Internal::vivify_build_lrat ( int lit,
Clause * reason,
std::vector< std::tuple< int, Clause *, bool > > & stack )

Definition at line 1257 of file cadical_vivify.cpp.

1259 {
1260 CADICAL_assert (stack.empty ());
1261 stack.push_back ({lit, reason, false});
1262 while (!stack.empty ()) {
1263 int lit;
1264 Clause *reason;
1265 bool finished;
1266 std::tie (lit, reason, finished) = stack.back ();
1267 LOG ("VIVIFY LRAT justifying %d", lit);
1268 stack.pop_back ();
1269 if (lit && flags (lit).seen) {
1270 LOG ("skipping already justified");
1271 continue;
1272 }
1273 if (finished) {
1274 lrat_chain.push_back (reason->id);
1275 if (lit && reason) {
1276 Flags &f = flags (lit);
1277 f.seen = true;
1278 analyzed.push_back (lit); // CADICAL_assert (val (other) < 0);
1279 CADICAL_assert (flags (lit).seen);
1280 }
1281 continue;
1282 } else
1283 stack.push_back ({lit, reason, true});
1284 for (const auto &other : *reason) {
1285 if (other == lit)
1286 continue;
1287 Var &v = var (other);
1288 Flags &f = flags (other);
1289 if (f.seen)
1290 continue;
1291 if (!v.level) {
1292 const int64_t id = unit_id (-other);
1293 lrat_chain.push_back (id);
1294 f.seen = true;
1295 analyzed.push_back (other);
1296 continue;
1297 }
1298 if (v.reason) { // recursive justification
1299 LOG ("VIVIFY LRAT pushing %d", other);
1300 stack.push_back ({other, v.reason, false});
1301 }
1302 }
1303 }
1304 stack.clear ();
1305}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_chain_for_units()

void CaDiCaL::Internal::vivify_chain_for_units ( int lit,
Clause * reason )
inline

Definition at line 1309 of file cadical_vivify.cpp.

1309 {
1310 if (!lrat)
1311 return;
1312 // LOG ("building chain for units"); bad line for debugging
1313 // equivalence if (opts.chrono && assignment_level (lit, reason)) return;
1314 if (level)
1315 return; // not decision level 0
1316 CADICAL_assert (lrat_chain.empty ());
1317 for (auto &reason_lit : *reason) {
1318 if (lit == reason_lit)
1319 continue;
1320 CADICAL_assert (val (reason_lit));
1321 const int signed_reason_lit = val (reason_lit) * reason_lit;
1322 int64_t id = unit_id (signed_reason_lit);
1323 lrat_chain.push_back (id);
1324 }
1325 lrat_chain.push_back (reason->id);
1326}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_clause()

bool CaDiCaL::Internal::vivify_clause ( Vivifier & vivifier,
Clause * candidate )

Definition at line 947 of file cadical_vivify.cpp.

947 {
948
949 CADICAL_assert (c->size > 2); // see (NO-BINARY) below
950 CADICAL_assert (analyzed.empty ());
951
952 c->vivify = false; // mark as checked / tried
953 c->vivified = true; // and globally remember
954
955 CADICAL_assert (!c->garbage);
956
957 auto &lrat_stack = vivifier.lrat_stack;
958 auto &ticks = vivifier.ticks;
959 ticks++;
960
961 // First check whether the candidate clause is already satisfied and at
962 // the same time copy its non fixed literals to 'sorted'. The literals
963 // in the candidate clause might not be sorted anymore due to replacing
964 // watches during propagation, even though we sorted them initially
965 // while pushing the clause onto the schedule and sorting the schedule.
966 //
967 auto &sorted = vivifier.sorted;
968 sorted.clear ();
969
970 for (const auto &lit : *c) {
971 const int tmp = fixed (lit);
972 if (tmp > 0) {
973 LOG (c, "satisfied by propagated unit %d", lit);
974 mark_garbage (c);
975 return false;
976 } else if (!tmp)
977 sorted.push_back (lit);
978 }
979
980 CADICAL_assert (sorted.size () > 1);
981 if (sorted.size () == 2) {
982 LOG ("skipping actual binary");
983 return false;
984 }
985
986 sort (sorted.begin (), sorted.end (), vivify_more_noccs_kissat (this));
987
988 // The actual vivification checking is performed here, by assuming the
989 // negation of each of the remaining literals of the clause in turn and
990 // propagating it. If a conflict occurs or another literal in the
991 // clause becomes assigned during propagation, we can stop.
992 //
993 LOG (c, "vivification checking");
994 stats.vivifychecks++;
995
996 // If the decision 'level' is non-zero, then we can reuse decisions for
997 // the previous candidate, and avoid re-propagating them. In preliminary
998 // experiments this saved between 30%-50% decisions (and thus
999 // propagations), which in turn lets us also vivify more clauses within
1000 // the same propagation bounds, or terminate earlier if vivify runs to
1001 // completion.
1002 //
1003 if (level) {
1004#ifdef LOGGING
1005 int orig_level = level;
1006#endif
1007 // First check whether this clause is actually a reason for forcing
1008 // one of its literals to true and then backtrack one level before
1009 // that happened. Otherwise this clause might be incorrectly
1010 // considered to be redundant or if this situation is checked then
1011 // redundancy by other clauses using this forced literal becomes
1012 // impossible.
1013 //
1014 int forced = 0;
1015
1016 // This search could be avoided if we would eagerly set the 'reason'
1017 // boolean flag of clauses, which however we do not want to do for
1018 // binary clauses (during propagation) and thus would still require
1019 // a version of 'protect_reason' for binary clauses during 'reduce'
1020 // (well binary clauses are not collected during 'reduce', but again
1021 // this exception from the exception is pretty complex and thus a
1022 // simply search here is probably easier to understand).
1023
1024 for (const auto &lit : *c) {
1025 const signed char tmp = val (lit);
1026 if (tmp < 0)
1027 continue;
1028 if (tmp > 0 && var (lit).reason == c)
1029 forced = lit;
1030 break;
1031 }
1032 if (forced) {
1033 LOG ("clause is reason forcing %d", forced);
1034 CADICAL_assert (var (forced).level);
1036 }
1037
1038 // As long the (remaining) literals of the sorted clause match
1039 // decisions on the trail we just reuse them.
1040 //
1041 if (level) {
1042
1043 int l = 1; // This is the decision level we want to reuse.
1044
1045 for (const auto &lit : sorted) {
1047 const int decision = control[l].decision;
1048 if (-lit == decision) {
1049 LOG ("reusing decision %d at decision level %d", decision, l);
1050 stats.vivifyreused++;
1051 if (++l > level)
1052 break;
1053 } else {
1054 LOG ("literal %d does not match decision %d at decision level %d",
1055 lit, decision, l);
1057 break;
1058 }
1059 }
1060 }
1061
1062 LOG ("reused %d decision levels from %d", level, orig_level);
1063 }
1064
1065 LOG (sorted, "sorted size %zd probing schedule", sorted.size ());
1066
1067 // Make sure to ignore this clause during propagation. This is not that
1068 // easy for binary clauses (NO-BINARY), e.g., ignoring binary clauses,
1069 // without changing 'propagate'. Actually, we do not want to remove binary
1070 // clauses which are subsumed. Those are hyper binary resolvents and
1071 // should be kept as learned clauses instead, unless they are transitive
1072 // in the binary implication graph, which in turn is detected during
1073 // transitive reduction in 'transred'.
1074 //
1075 ignore = c;
1076
1077 int subsume = 0; // determined to be redundant / subsumed
1078
1079 // If the candidate is redundant, i.e., we are in redundant mode, the
1080 // clause is subsumed (in one of the two cases below where 'subsume' is
1081 // assigned) and further all reasons involved are only binary clauses,
1082 // then this redundant clause is what we once called a hidden tautology,
1083 // and even for redundant clauses it makes sense to remove the candidate.
1084 // It does not add anything to propagation power of the formula. This is
1085 // the same argument as removing transitive clauses in the binary
1086 // implication graph during transitive reduction.
1087 //
1088
1089 // Go over the literals in the candidate clause in sorted order.
1090 //
1091 for (const auto &lit : sorted) {
1092
1093 // Exit loop as soon a literal is positively implied (case '@5' below)
1094 // or propagation of the negation of a literal fails ('@6').
1095 //
1096 if (subsume)
1097 break;
1098
1099 // We keep on assigning literals, even though we know already that we
1100 // can remove one (was negatively implied), since we either might run
1101 // into the 'subsume' case above or more false literals become implied.
1102 // In any case this might result in stronger vivified clauses. As a
1103 // consequence continue with this loop even if 'remove' is non-zero.
1104
1105 const signed char tmp = val (lit);
1106
1107 if (tmp) { // literal already assigned
1108
1109 const Var &v = var (lit);
1110 CADICAL_assert (v.level);
1111 if (!v.reason) {
1112 LOG ("skipping decision %d", lit);
1113 continue;
1114 }
1115
1116 if (tmp < 0) {
1117 CADICAL_assert (v.level);
1118 LOG ("literal %d is already false and can be removed", lit);
1119 continue;
1120 }
1121
1122 CADICAL_assert (tmp > 0);
1123 LOG ("subsumed since literal %d already true", lit);
1124 subsume = lit; // will be able to subsume candidate '@5'
1125 break;
1126 }
1127
1128 CADICAL_assert (!tmp);
1129
1130 stats.vivifydecs++;
1131 vivify_assume (-lit);
1132 LOG ("negated decision %d score %" PRId64 "", lit, noccs (lit));
1133
1134 if (!vivify_propagate (ticks)) {
1135 break; // hot-spot
1136 }
1137 }
1138
1139 if (subsume) {
1140 int better_subsume_trail = var (subsume).trail;
1141 for (auto lit : sorted) {
1142 if (val (lit) <= 0)
1143 continue;
1144 const Var v = var (lit);
1145 if (v.trail < better_subsume_trail) {
1146 LOG ("improving subsume from %d at %d to %d at %d", subsume,
1147 better_subsume_trail, lit, v.trail);
1148 better_subsume_trail = v.trail;
1149 subsume = lit;
1150 }
1151 }
1152 }
1153
1154 Clause *subsuming = nullptr;
1155 bool redundant = false;
1156 const int level_after_assumptions = level;
1157 CADICAL_assert (level_after_assumptions);
1158 vivify_deduce (c, conflict, subsume, &subsuming, redundant);
1159
1160 bool res;
1161
1162 // reverse lrat_chain. We could probably work with reversed iterators
1163 // (views) to be more efficient but we would have to distinguish in proof
1164 //
1165 if (lrat) {
1166 for (auto id : unit_chain)
1167 lrat_chain.push_back (id);
1168 unit_chain.clear ();
1169 reverse (lrat_chain.begin (), lrat_chain.end ());
1170 }
1171
1172 if (subsuming) {
1173 CADICAL_assert (c != subsuming);
1174 LOG (c, "deleting subsumed clause");
1175 if (c->redundant && subsuming->redundant && c->glue < subsuming->glue) {
1176 promote_clause (c, c->glue);
1177 }
1178 vivify_subsume_clause (subsuming, c);
1179 res = false;
1180 // stats.vivifysubs++; // already done in vivify_subsume_clause
1181 } else if (vivify_shrinkable (sorted, conflict)) {
1183 LOG ("vivify succeeded, learning new clause");
1185 LOG (lrat_chain, "lrat");
1186 LOG (clause, "learning clause");
1187 conflict = nullptr; // TODO dup from below
1189 res = true;
1190 } else if (subsume && c->redundant) {
1191 LOG (c, "vivification implied");
1192 mark_garbage (c);
1193 ++stats.vivifyimplied;
1194 res = true;
1195 } else if ((conflict || subsume) && !c->redundant && !redundant) {
1196 LOG ("demote clause from irredundant to redundant");
1197 if (opts.vivifydemote) {
1198 demote_clause (c);
1199 const int new_glue = recompute_glue (c);
1200 promote_clause (c, new_glue);
1201 res = false;
1202 } else {
1203 mark_garbage (c);
1204 ++stats.vivifyimplied;
1205 res = true;
1206 }
1207 } else if (subsume) {
1208 LOG (c, "no vivification instantiation with implied literal %d",
1209 subsume);
1210 CADICAL_assert (!c->redundant);
1212 res = false;
1213 ++stats.vivifyimplied;
1214 } else {
1215 CADICAL_assert (level > 2);
1216 CADICAL_assert ((size_t) level == sorted.size ());
1217 LOG (c, "vivification failed on");
1218 lrat_chain.clear ();
1220 if (!subsume && opts.vivifyinst) {
1221 res = vivify_instantiate (sorted, c, lrat_stack, ticks);
1223 } else {
1224 LOG ("cannot apply instantiation");
1225 res = false;
1226 }
1227 }
1228
1229 if (conflict && level == level_after_assumptions) {
1230 LOG ("forcing backtracking at least one level after conflict");
1232 }
1233
1234 clause.clear ();
1235 clear_analyzed_literals (); // TODO why needed?
1236 lrat_chain.clear ();
1237 conflict = nullptr;
1238 return res;
1239}
void vivify_assume(int lit)
void vivify_increment_stats(const Vivifier &vivifier)
void vivify_subsume_clause(Clause *subsuming, Clause *subsumed)
void demote_clause(Clause *)
void vivify_strengthen(Clause *candidate)
void vivify_deduce(Clause *candidate, Clause *conflct, int implied, Clause **, bool &)
bool vivify_propagate(int64_t &)
bool vivify_instantiate(const std::vector< int > &, Clause *, std::vector< std::tuple< int, Clause *, bool > > &lrat_stack, int64_t &ticks)
bool vivify_shrinkable(const std::vector< int > &sorted, Clause *c)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_deduce()

void CaDiCaL::Internal::vivify_deduce ( Clause * candidate,
Clause * conflct,
int implied,
Clause ** subsuming,
bool & redundant )

Definition at line 743 of file cadical_vivify.cpp.

745 {
746 CADICAL_assert (lrat_chain.empty ());
747 bool subsumes;
748 Clause *reason;
749
750 CADICAL_assert (clause.empty ());
751 if (implied) {
752 reason = candidate;
754 const int not_implied = -implied;
755 CADICAL_assert (var (not_implied).level);
756 Flags &f = flags (not_implied);
757 f.seen = true;
758 LOG ("pushing implied lit %d", not_implied);
759 analyzed.push_back (not_implied);
760 clause.push_back (implied);
761 } else {
762 reason = (conflict ? conflict : candidate);
763 CADICAL_assert (reason);
764 CADICAL_assert (!reason->garbage);
766 subsumes = (candidate != reason);
767 redundant = reason->redundant;
768 LOG (reason, "resolving with");
769 if (lrat)
770 lrat_chain.push_back (reason->id);
771 for (auto lit : *reason) {
772 const Var &v = var (lit);
773 Flags &f = flags (lit);
774 CADICAL_assert (val (lit) < 0);
775 if (!v.level) {
776 if (!lrat)
777 continue;
778 LOG ("adding unit %d", lit);
779 if (!f.seen) {
780 // nevertheless we can use var (l) as if l was still assigned
781 // because var is updated lazily
782 int64_t id = unit_id (-lit);
783 LOG ("adding unit reason %zd for %d", id, lit);
784 unit_chain.push_back (id);
785 }
786 f.seen = true;
787 analyzed.push_back (lit);
788 continue;
789 }
790 CADICAL_assert (v.level);
791 if (!marked2 (lit)) {
792 LOG ("lit %d is not marked", lit);
793 subsumes = false;
794 }
795 LOG ("analyzing lit %d", lit);
796 LOG ("pushing lit %d", lit);
797 analyzed.push_back (lit);
798 f.seen = true;
799 }
800 if (reason != candidate && reason->redundant) {
801 const int new_glue = recompute_glue (reason);
802 promote_clause (reason, new_glue);
803 }
804 if (subsumes) {
805 CADICAL_assert (candidate != reason);
806#ifndef CADICAL_NDEBUG
807 int nonfalse_reason = 0;
808 for (auto lit : *reason)
809 if (!fixed (lit))
810 ++nonfalse_reason;
811
812 int nonfalse_candidate = 0;
813 for (auto lit : *candidate)
814 if (!fixed (lit))
815 ++nonfalse_candidate;
816
817 CADICAL_assert (nonfalse_reason <= nonfalse_candidate);
818#endif
819 LOG (candidate, "vivify subsumed 0");
820 LOG (reason, "vivify subsuming 0");
821 *subsuming = reason;
823 if (lrat)
824 lrat_chain.clear ();
825 return;
826 }
827 }
828
829 vivify_analyze (reason, subsumes, subsuming, candidate, implied,
830 redundant);
832 if (subsumes) {
833 CADICAL_assert (*subsuming);
834 LOG (candidate, "vivify subsumed");
835 LOG (*subsuming, "vivify subsuming");
836 if (lrat)
837 lrat_chain.clear ();
838 }
839}
void vivify_analyze(Clause *start, bool &, Clause **, const Clause *const, int implied, bool &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_increment_stats()

void CaDiCaL::Internal::vivify_increment_stats ( const Vivifier & vivifier)
inline

Definition at line 880 of file cadical_vivify.cpp.

880 {
881 switch (vivifier.tier) {
883 ++stats.vivifystred1;
884 break;
886 ++stats.vivifystred2;
887 break;
889 ++stats.vivifystred3;
890 break;
891 default:
893 ++stats.vivifystrirr;
894 break;
895 }
896}
Here is the caller graph for this function:

◆ vivify_initialize()

void CaDiCaL::Internal::vivify_initialize ( Vivifier & vivifier,
int64_t & ticks )

Definition at line 1397 of file cadical_vivify.cpp.

1397 {
1398
1399 const int tier1 = vivifier.tier1_limit;
1400 const int tier2 = vivifier.tier2_limit;
1401 // Count the number of occurrences of literals in all clauses,
1402 // particularly binary clauses, which are usually responsible
1403 // for most of the propagations.
1404 //
1405 init_noccs ();
1406
1407 // Disconnect all watches since we sort literals within clauses.
1408 //
1410#if 0
1411 clear_watches ();
1412#endif
1413
1414 size_t prioritized_irred = 0, prioritized_tier1 = 0,
1415 prioritized_tier2 = 0, prioritized_tier3 = 0;
1416 for (const auto &c : clauses) {
1417 ++ticks;
1418 if (c->size == 2)
1419 continue; // see also (NO-BINARY) above
1421 continue;
1422
1423 // This computes an approximation of the Jeroslow Wang heuristic
1424 // score
1425 //
1426 // nocc (L) = sum 2^(12-|C|)
1427 // L in C in F
1428 //
1429 // but we cap the size at 12, that is all clauses of size 12 and
1430 // larger contribute '1' to the score, which allows us to use 'long'
1431 // numbers. See the example above (search for '@1').
1432 //
1433 const int shift = 12 - c->size;
1434 const int64_t score = shift < 1 ? 1 : (1l << shift); // @4
1435 for (const auto lit : *c) {
1436 noccs (lit) += score;
1437 }
1438 LOG (c, "putting clause in candidates");
1439 if (!c->redundant)
1440 vivifier.schedule_irred.push_back (c),
1441 prioritized_irred += (c->vivify);
1442 else if (c->glue <= tier1)
1443 vivifier.schedule_tier1.push_back (c),
1444 prioritized_tier1 += (c->vivify);
1445 else if (c->glue <= tier2)
1446 vivifier.schedule_tier2.push_back (c),
1447 prioritized_tier2 += (c->vivify);
1448 else
1449 vivifier.schedule_tier3.push_back (c),
1450 prioritized_tier3 += (c->vivify);
1451 ++ticks;
1452 }
1453
1454 vivify_prioritize_leftovers ('x', prioritized_irred,
1455 vivifier.schedule_irred);
1456 vivify_prioritize_leftovers ('u', prioritized_tier1,
1457 vivifier.schedule_tier1);
1458 vivify_prioritize_leftovers ('v', prioritized_tier2,
1459 vivifier.schedule_tier2);
1460 vivify_prioritize_leftovers ('w', prioritized_tier3,
1461 vivifier.schedule_tier3);
1462
1463 if (opts.vivifyflush) {
1464 clear_watches ();
1465 for (auto &sched : vivifier.schedules) {
1466 for (const auto &c : sched) {
1467 // Literals in scheduled clauses are sorted with their highest score
1468 // literals first (as explained above in the example at '@2'). This
1469 // is also needed in the prefix subsumption checking below. We do an
1470 // approximation below that is done only in the vivify_ref structure
1471 // below.
1472 //
1473 sort (c->begin (), c->end (), vivify_more_noccs (this));
1474 }
1475 // Flush clauses subsumed by another clause with the same prefix,
1476 // which also includes flushing syntactically identical clauses.
1477 //
1478 flush_vivification_schedule (sched, ticks);
1479 }
1480 connect_watches (); // watch all relevant clauses
1481 }
1482#if 0
1483 connect_watches (); // watch all relevant clauses
1484 vivify_propagate (ticks);
1485#endif
1486 vivify_propagate (ticks);
1487}
void vivify_prioritize_leftovers(char, size_t prioritized, std::vector< Clause * > &schedule)
void flush_vivification_schedule(std::vector< Clause * > &, int64_t &)
bool consider_to_vivify_clause(Clause *candidate)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_instantiate()

bool CaDiCaL::Internal::vivify_instantiate ( const std::vector< int > & sorted,
Clause * c,
std::vector< std::tuple< int, Clause *, bool > > & lrat_stack,
int64_t & ticks )

Definition at line 901 of file cadical_vivify.cpp.

904 {
905 LOG ("now trying instantiation");
906 conflict = nullptr;
907 const int lit = sorted.back ();
908 LOG ("vivify instantiation");
909 CADICAL_assert (!var (lit).reason);
912 backtrack (level - 1);
913 CADICAL_assert (val (lit) == 0);
914 stats.vivifydecs++;
916 bool ok = vivify_propagate (ticks);
917 if (!ok) {
918 LOG (c, "instantiate success with literal %d in", lit);
919 stats.vivifyinst++;
920 // strengthen clause
921 if (lrat) {
923 CADICAL_assert (lrat_chain.empty ());
924 vivify_build_lrat (0, c, lrat_stack);
925 vivify_build_lrat (0, conflict, lrat_stack);
927 }
928 int remove = lit;
929 conflict = nullptr;
930 unwatch_clause (c);
932 strengthen_clause (c, remove);
934 watch_clause (c);
936 return true;
937 } else {
938 LOG ("vivify instantiation failed");
939 return false;
940 }
941}
void vivify_sort_watched(Clause *c)
void vivify_build_lrat(int, Clause *, std::vector< std::tuple< int, Clause *, bool > > &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_prioritize_leftovers()

void CaDiCaL::Internal::vivify_prioritize_leftovers ( char tag,
size_t prioritized,
std::vector< Clause * > & schedule )
inline

Definition at line 1373 of file cadical_vivify.cpp.

1375 {
1376 if (prioritized) {
1377 PHASE ("vivify", stats.vivifications,
1378 "[phase %c] leftovers of %" PRId64 " clause", tag, prioritized);
1379 } else {
1380 PHASE ("vivify", stats.vivifications,
1381 "[phase %c] prioritizing all clause", tag);
1382 for (auto c : schedule)
1383 c->vivify = true;
1384 }
1385 const size_t max = opts.vivifyschedmax;
1386 if (schedule.size () > max) {
1387 if (prioritized) {
1388 std::partition (begin (schedule), end (schedule),
1389 [] (Clause *c) { return c->vivify; });
1390 }
1391 schedule.resize (max);
1392 }
1393 // let's try to save a bit of memory
1394 shrink_vector (schedule);
1395}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_propagate()

bool CaDiCaL::Internal::vivify_propagate ( int64_t & ticks)

Definition at line 184 of file cadical_vivify.cpp.

184 {
188 int64_t before = propagated2 = propagated;
189 for (;;) {
190 if (propagated2 != trail.size ()) {
191 const int lit = -trail[propagated2++];
192 LOG ("vivify propagating %d over binary clauses", -lit);
193 Watches &ws = watches (lit);
194 ticks +=
195 1 + cache_lines (ws.size (), sizeof (const_watch_iterator *));
196 for (const auto &w : ws) {
197 if (!w.binary ())
198 continue;
199 const signed char b = val (w.blit);
200 if (b > 0)
201 continue;
202 if (b < 0)
203 conflict = w.clause; // but continue
204 else {
205 ticks++;
206 build_chain_for_units (w.blit, w.clause, 0);
207 vivify_assign (w.blit, w.clause);
208 lrat_chain.clear ();
209 }
210 }
211 } else if (!conflict && propagated != trail.size ()) {
212 const int lit = -trail[propagated++];
213 LOG ("vivify propagating %d over large clauses", -lit);
214 Watches &ws = watches (lit);
215 const const_watch_iterator eow = ws.end ();
216 const_watch_iterator i = ws.begin ();
217 ticks += 1 + cache_lines (ws.size (), sizeof (*i));
218 watch_iterator j = ws.begin ();
219 while (i != eow) {
220 const Watch w = *j++ = *i++;
221 if (w.binary ())
222 continue;
223 if (val (w.blit) > 0)
224 continue;
225 ticks++;
226 if (w.clause->garbage) {
227 j--;
228 continue;
229 }
230 literal_iterator lits = w.clause->begin ();
231 const int other = lits[0] ^ lits[1] ^ lit;
232 const signed char u = val (other);
233 if (u > 0)
234 j[-1].blit = other;
235 else {
236 const int size = w.clause->size;
237 const const_literal_iterator end = lits + size;
238 const literal_iterator middle = lits + w.clause->pos;
239 literal_iterator k = middle;
240 signed char v = -1;
241 int r = 0;
242 while (k != end && (v = val (r = *k)) < 0)
243 k++;
244 if (v < 0) {
245 k = lits + 2;
246 CADICAL_assert (w.clause->pos <= size);
247 while (k != middle && (v = val (r = *k)) < 0)
248 k++;
249 }
250 w.clause->pos = k - lits;
251 CADICAL_assert (lits + 2 <= k), CADICAL_assert (k <= w.clause->end ());
252 if (v > 0)
253 j[-1].blit = r;
254 else if (!v) {
255 LOG (w.clause, "unwatch %d in", r);
256 lits[0] = other;
257 lits[1] = r;
258 *k = lit;
259 ticks++;
260 watch_literal (r, lit, w.clause);
261 j--;
262 } else if (!u) {
263 if (w.clause == ignore) {
264 LOG ("ignoring propagation due to clause to vivify");
265 continue;
266 }
267 ticks++;
268 CADICAL_assert (v < 0);
269 vivify_chain_for_units (other, w.clause);
270 vivify_assign (other, w.clause);
271 lrat_chain.clear ();
272 } else {
273 if (w.clause == ignore) {
274 LOG ("ignoring conflict due to clause to vivify");
275 continue;
276 }
277 CADICAL_assert (u < 0);
278 CADICAL_assert (v < 0);
279 conflict = w.clause;
280 break;
281 }
282 }
283 }
284 if (j != i) {
285 while (i != eow)
286 *j++ = *i++;
287 ws.resize (j - ws.begin ());
288 }
289 } else
290 break;
291 }
292 int64_t delta = propagated2 - before;
293 stats.propagations.vivify += delta;
294 if (conflict)
295 LOG (conflict, "conflict");
296 STOP (propagate);
297 return !conflict;
298}
void vivify_chain_for_units(int lit, Clause *reason)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_round()

void CaDiCaL::Internal::vivify_round ( Vivifier & vivifier,
int64_t delta )

Definition at line 1576 of file cadical_vivify.cpp.

1576 {
1577
1578 if (unsat)
1579 return;
1581 return;
1582
1583 PHASE ("vivify", stats.vivifications,
1584 "starting %c vivification round ticks limit %" PRId64 "",
1585 vivifier.tag, ticks_limit);
1586
1587 PHASE ("vivify", stats.vivifications,
1588 "starting %c vivification round ticks limit %" PRId64 "",
1589 vivifier.tag, ticks_limit);
1590
1592
1593 auto &refs_schedule = current_refs_schedule (vivifier);
1594 auto &schedule = current_schedule (vivifier);
1595
1596 int64_t ticks = 1 + schedule.size ();
1597
1598 // Sort candidates, with first to be tried candidate clause last, i.e.,
1599 // many occurrences and high score literals) as in the example explained
1600 // above (search for '@3').
1601 //
1602 if (vivifier.tier != Vivify_Mode::IRREDUNDANT ||
1603 irredundant () / 10 < redundant ()) {
1604 // Literals in scheduled clauses are sorted with their highest score
1605 // literals first (as explained above in the example at '@2'). This is
1606 // also needed in the prefix subsumption checking below. We do an
1607 // approximation below that is done only in the vivify_ref structure
1608 // below.
1609 //
1610
1611 // first build the schedule with vivifier_refs
1612 auto end_schedule = end (schedule);
1613 refs_schedule.resize (schedule.size ());
1614 std::transform (begin (schedule), end_schedule, begin (refs_schedule),
1615 [&] (Clause *c) { return create_ref (this, c); });
1616 // now sort by size
1617 MSORT (opts.radixsortlim, refs_schedule.begin (), refs_schedule.end (),
1618 vivify_inversesize_rank (), vivify_inversesize_smaller ());
1619 // now (stable) sort by number of occurrences
1620 for (int i = 0; i < COUNTREF_COUNTS; ++i) {
1621 const int offset = COUNTREF_COUNTS - 1 - i;
1622 MSORT (opts.radixsortlim, refs_schedule.begin (),
1623 refs_schedule.end (), vivify_refcount_rank (offset),
1624 vivify_refcount_smaller (offset));
1625 }
1626 // force left-overs at the end
1627 std::stable_partition (begin (refs_schedule), end (refs_schedule),
1628 [] (vivify_ref c) { return !c.vivify; });
1629 std::transform (begin (refs_schedule), end (refs_schedule),
1630 begin (schedule),
1631 [] (vivify_ref c) { return c.clause; });
1632 erase_vector (refs_schedule);
1633 LOG ("clause after sorting final:");
1634 } else {
1635 // skip sorting but still put clauses with the vivify tag at the end to
1636 // be done first Kissat does this implicitely by going twice over all
1637 // clauses
1638 std::stable_partition (begin (schedule), end (schedule),
1639 [] (Clause *c) { return !c->vivify; });
1640 }
1641
1642 // Remember old values of counters to summarize after each round with
1643 // verbose messages what happened in that round.
1644 //
1645 int64_t checked = stats.vivifychecks;
1646 int64_t subsumed = stats.vivifysubs;
1647 int64_t strengthened = stats.vivifystrs;
1648 int64_t units = stats.vivifyunits;
1649
1650 int64_t scheduled = schedule.size ();
1651 stats.vivifysched += scheduled;
1652
1653 PHASE ("vivify", stats.vivifications,
1654 "scheduled %" PRId64 " clauses to be vivified %.0f%%", scheduled,
1655 percent (scheduled, stats.current.irredundant));
1656
1657 // Limit the number of propagations during vivification as in 'probe'.
1658 //
1659 const int64_t limit = ticks_limit - stats.ticks.vivify;
1660 CADICAL_assert (limit >= 0);
1661
1662 // the clauses might still contain set literals, so propagation since the
1663 // beginning
1664 propagated2 = propagated = 0;
1665
1666 if (!unsat && !propagate ()) {
1667 LOG ("propagation after connecting watches in inconsistency");
1669 }
1670
1671 vivifier.ticks = ticks;
1672 int retry = 0;
1673 while (!unsat && !terminated_asynchronously () && !schedule.empty () &&
1674 vivifier.ticks < limit) {
1675 Clause *c = schedule.back (); // Next candidate.
1676 schedule.pop_back ();
1677 if (vivify_clause (vivifier, c) && !c->garbage && c->size > 2 &&
1678 retry < opts.vivifyretry) {
1679 ++retry;
1680 schedule.push_back (c);
1681 } else
1682 retry = 0;
1683 }
1684
1685 if (level)
1687
1688 if (!unsat) {
1689 int64_t still_need_to_be_vivified = schedule.size ();
1690#if 0
1691 // in the current round we have new_clauses_to_vivify @ leftovers from previous round There are
1692 // now two possibilities: (i) we consider all clauses as leftovers, or (ii) only the leftovers
1693 // from previous round are considered leftovers.
1694 //
1695 // CaDiCaL had the first version before. If
1696 // commented out we go to the second version.
1697 for (auto c : schedule)
1698 c->vivify = true;
1699#elif 1
1700 // if we have gone through all the leftovers, the current clauses are
1701 // leftovers for the next round
1702 if (!schedule.empty () && !schedule.front ()->vivify &&
1703 schedule.back ()->vivify)
1704 for (auto c : schedule)
1705 c->vivify = true;
1706#else
1707 // do nothing like in kissat and use the candidates for next time.
1708#endif
1709 // Preference clauses scheduled but not vivified yet next time.
1710 //
1711 if (still_need_to_be_vivified)
1712 PHASE ("vivify", stats.vivifications,
1713 "still need to vivify %" PRId64 " clauses %.02f%% of %" PRId64
1714 " scheduled",
1715 still_need_to_be_vivified,
1716 percent (still_need_to_be_vivified, scheduled), scheduled);
1717 else {
1718 PHASE ("vivify", stats.vivifications,
1719 "no previously not yet vivified clause left");
1720 }
1721
1722 erase_vector (schedule); // Reclaim memory early.
1723 }
1724
1725 if (!unsat) {
1726
1727 // Since redundant clause were disconnected during propagating vivified
1728 // units in redundant mode, and further irredundant clauses are
1729 // arbitrarily sorted, we have to propagate all literals again after
1730 // connecting the first two literals in the clauses, in order to
1731 // reestablish the watching invariant.
1732 //
1733 propagated2 = propagated = 0;
1734
1735 if (!propagate ()) {
1736 LOG ("propagating vivified units leads to conflict");
1738 }
1739 }
1740
1741 checked = stats.vivifychecks - checked;
1742 subsumed = stats.vivifysubs - subsumed;
1743 strengthened = stats.vivifystrs - strengthened;
1744 units = stats.vivifyunits - units;
1745
1746 PHASE ("vivify", stats.vivifications,
1747 "checked %" PRId64 " clauses %.02f%% of %" PRId64
1748 " scheduled using %" PRIu64 " ticks",
1749 checked, percent (checked, scheduled), scheduled, vivifier.ticks);
1750 if (units)
1751 PHASE ("vivify", stats.vivifications,
1752 "found %" PRId64 " units %.02f%% of %" PRId64 " checked", units,
1753 percent (units, checked), checked);
1754 if (subsumed)
1755 PHASE ("vivify", stats.vivifications,
1756 "subsumed %" PRId64 " clauses %.02f%% of %" PRId64 " checked",
1757 subsumed, percent (subsumed, checked), checked);
1758 if (strengthened)
1759 PHASE ("vivify", stats.vivifications,
1760 "strengthened %" PRId64 " clauses %.02f%% of %" PRId64
1761 " checked",
1762 strengthened, percent (strengthened, checked), checked);
1763
1764 stats.subsumed += subsumed;
1765 stats.strengthened += strengthened;
1766 stats.ticks.vivify += vivifier.ticks;
1767
1768 bool unsuccessful = !(subsumed + strengthened + units);
1769 report (vivifier.tag, unsuccessful);
1770}
std::vector< vivify_ref > & current_refs_schedule(Vivifier &vivifier)
vivify_ref create_ref(Internal *internal, Clause *c)
std::vector< Clause * > & current_schedule(Vivifier &vivifier)
bool vivify_clause(Vivifier &, Clause *candidate)
#define COUNTREF_COUNTS
Definition vivify.hpp:20
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_shrinkable()

bool CaDiCaL::Internal::vivify_shrinkable ( const std::vector< int > & sorted,
Clause * c )

Definition at line 842 of file cadical_vivify.cpp.

843 {
844
845 unsigned count_implied = 0;
846 for (auto lit : sorted) {
847 const signed char value = val (lit);
848 if (!value) {
849 LOG ("vivification unassigned %d", lit);
850 return true;
851 }
852 if (value > 0) {
853 LOG ("vivification implied satisfied %d", lit);
854 if (conflict)
855 return true;
856 if (count_implied++) {
857 LOG ("at least one implied literal with conflict thus shrinking");
858 return true;
859 }
860 } else {
861 CADICAL_assert (value < 0);
862 const Var &v = var (lit);
863 const Flags &f = flags (lit);
864 if (!v.level)
865 continue;
866 if (!f.seen) {
867 LOG ("vivification non-analyzed %d", lit);
868 return true;
869 }
870 if (v.reason) {
871 LOG ("vivification implied falsified %d", lit);
872 return true;
873 }
874 }
875 }
876 return false;
877}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_sort_watched()

void CaDiCaL::Internal::vivify_sort_watched ( Clause * c)

Definition at line 616 of file cadical_vivify.cpp.

616 {
617
618 sort (c->begin (), c->end (), vivify_better_watch (this));
619
620 int new_level = level;
621
622 const int lit0 = c->literals[0];
623 signed char val0 = val (lit0);
624 if (val0 < 0) {
625 const int level0 = var (lit0).level;
626 LOG ("1st watch %d negative at level %d", lit0, level0);
627 new_level = level0 - 1;
628 }
629
630 const int lit1 = c->literals[1];
631 const signed char val1 = val (lit1);
632 if (val1 < 0 && !(val0 > 0 && var (lit0).level <= var (lit1).level)) {
633 const int level1 = var (lit1).level;
634 LOG ("2nd watch %d negative at level %d", lit1, level1);
635 new_level = level1 - 1;
636 }
637
638 CADICAL_assert (new_level >= 0);
639 if (new_level < level)
640 backtrack (new_level);
641
642 CADICAL_assert (val (lit0) >= 0);
643 CADICAL_assert (val (lit1) >= 0 || (val (lit0) > 0 && val (lit1) < 0 &&
644 var (lit0).level <= var (lit1).level));
645}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_strengthen()

void CaDiCaL::Internal::vivify_strengthen ( Clause * candidate)

Definition at line 555 of file cadical_vivify.cpp.

555 {
556
557 CADICAL_assert (!clause.empty ());
558
559 if (clause.size () == 1) {
560
562 const int unit = clause[0];
563 LOG (c, "vivification shrunken to unit %d", unit);
564 CADICAL_assert (!val (unit));
565 assign_unit (unit);
566 // lrat_chain.clear (); done in search_assign
567 stats.vivifyunits++;
568
569 bool ok = propagate ();
570 if (!ok)
572
573 } else {
574
575 // See explanation before 'vivify_better_watch' above.
576 //
577 sort (clause.begin (), clause.end (), vivify_better_watch (this));
578
579 int new_level = level;
580
581 const int lit0 = clause[0];
582 signed char val0 = val (lit0);
583 if (val0 < 0) {
584 const int level0 = var (lit0).level;
585 LOG ("1st watch %d negative at level %d", lit0, level0);
586 new_level = level0 - 1;
587 }
588
589 const int lit1 = clause[1];
590 const signed char val1 = val (lit1);
591 if (val1 < 0 && !(val0 > 0 && var (lit0).level <= var (lit1).level)) {
592 const int level1 = var (lit1).level;
593 LOG ("2nd watch %d negative at level %d", lit1, level1);
594 new_level = level1 - 1;
595 }
596
597 CADICAL_assert (new_level >= 0);
598 if (new_level < level)
599 backtrack (new_level);
600
601 CADICAL_assert (val (lit0) >= 0);
602 CADICAL_assert (val (lit1) >= 0 || (val (lit0) > 0 && val (lit1) < 0 &&
603 var (lit0).level <= var (lit1).level));
604
605 Clause *d = new_clause_as (c);
606 LOG (c, "before vivification");
607 LOG (d, "after vivification");
608 (void) d;
609 }
610 clause.clear ();
611 mark_garbage (c);
612 lrat_chain.clear ();
613 ++stats.vivifystrs;
614}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vivify_subsume_clause()

void CaDiCaL::Internal::vivify_subsume_clause ( Clause * subsuming,
Clause * subsumed )
inline

Definition at line 53 of file cadical_vivify.cpp.

54 {
55 stats.subsumed++;
56 stats.vivifysubs++;
57#ifndef CADICAL_NDEBUG
58 CADICAL_assert (subsuming);
59 CADICAL_assert (subsumed);
60 CADICAL_assert (subsuming != subsumed);
61 CADICAL_assert (!subsumed->garbage);
62 // size after removeing units;
63 int real_size_subsuming = 0, real_size_subsumed = 0;
64 for (auto lit : *subsuming) {
65 if (!val (lit) || var (lit).level)
66 ++real_size_subsuming;
67 else
68 CADICAL_assert (val (lit) < 0);
69 }
70 for (auto lit : *subsumed) {
71 if (!val (lit) || var (lit).level)
72 ++real_size_subsumed;
73 else
74 CADICAL_assert (val (lit) < 0);
75 }
76 CADICAL_assert (real_size_subsuming <= real_size_subsumed);
77#endif
78 LOG (subsumed, "subsumed");
79 if (subsumed->redundant) {
80 stats.subred++;
81 ++stats.vivifysubred;
82 } else {
83 stats.subirr++;
84 ++stats.vivifysubirr;
85 }
86 if (subsuming->garbage) {
87 CADICAL_assert (subsuming->size == 2);
88 LOG (subsuming,
89 "binary subsuming clause was already deleted, so undeleting");
90 subsuming->garbage = false;
91 subsuming->glue = 1;
92 ++stats.current.total;
93 if (subsuming->redundant)
94 stats.current.redundant++;
95 else
96 stats.current.irredundant++, stats.irrlits += subsuming->size;
97 }
98 if (subsumed->redundant || !subsuming->redundant) {
99 mark_garbage (subsumed);
100 return;
101 }
102 LOG ("turning redundant subsuming clause into irredundant clause");
103 subsuming->redundant = false;
104 if (proof)
105 proof->strengthen (subsuming->id);
106 mark_garbage (subsumed);
107 mark_added (subsuming);
108 stats.current.irredundant++;
109 stats.added.irredundant++;
110 stats.irrlits += subsuming->size;
111 CADICAL_assert (stats.current.redundant > 0);
112 stats.current.redundant--;
113 CADICAL_assert (stats.added.redundant > 0);
114 stats.added.redundant--;
115 // ... and keep 'stats.added.total'.
116}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vlit()

unsigned CaDiCaL::Internal::vlit ( int lit) const
inline

Definition at line 408 of file internal.hpp.

408 {
409 return (lit < 0) + 2u * (unsigned) vidx (lit);
410 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ walk()

void CaDiCaL::Internal::walk ( )

Definition at line 696 of file cadical_walk.cpp.

696 {
698 int64_t limit = stats.propagations.search;
699 limit *= 1e-3 * opts.walkeffort;
700 if (limit < opts.walkmineff)
701 limit = opts.walkmineff;
702 if (limit > opts.walkmaxeff)
703 limit = opts.walkmaxeff;
704 (void) walk_round (limit, false);
706}
#define START_INNER_WALK()
Definition profile.hpp:222
#define STOP_INNER_WALK()
Definition profile.hpp:240
Here is the call graph for this function:
Here is the caller graph for this function:

◆ walk_break_value()

unsigned CaDiCaL::Internal::walk_break_value ( int lit)

Definition at line 117 of file cadical_walk.cpp.

117 {
118
120 CADICAL_assert (val (lit) > 0);
121
122 unsigned res = 0; // The computed break-count of 'lit'.
123
124 for (auto &w : watches (lit)) {
125 CADICAL_assert (w.blit != lit);
126 if (val (w.blit) > 0)
127 continue;
128 if (w.binary ()) {
129 res++;
130 continue;
131 }
132
133 Clause *c = w.clause;
134 CADICAL_assert (lit == c->literals[0]);
135
136 // Now try to find a second satisfied literal starting at 'literals[1]'
137 // shifting all the traversed literals to right by one position in order
138 // to move such a second satisfying literal to 'literals[1]'. This move
139 // to front strategy improves the chances to find the second satisfying
140 // literal earlier in subsequent break-count computations.
141 //
142 auto begin = c->begin () + 1;
143 const auto end = c->end ();
144 auto i = begin;
145 int prev = 0;
146 while (i != end) {
147 const int other = *i;
148 *i++ = prev;
149 prev = other;
150 if (val (other) < 0)
151 continue;
152
153 // Found 'other' as second satisfying literal.
154
155 w.blit = other; // Update 'blit'
156 *begin = other; // and move to front.
157
158 break;
159 }
160
161 if (i != end)
162 continue; // Double satisfied!
163
164 // Otherwise restore literals (undo shift to the right).
165 //
166 while (i != begin) {
167 const int other = *--i;
168 *i = prev;
169 prev = other;
170 }
171
172 res++; // Literal 'lit' single satisfies clause 'c'.
173 }
174
175 return res;
176}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ walk_flip_lit()

void CaDiCaL::Internal::walk_flip_lit ( Walker & walker,
int lit )

Definition at line 244 of file cadical_walk.cpp.

244 {
245
247 LOG ("flipping assign %d", lit);
248 CADICAL_assert (val (lit) < 0);
249
250 // First flip the literal value.
251 //
252 const int tmp = sign (lit);
253 const int idx = abs (lit);
254 set_val (idx, tmp);
255 CADICAL_assert (val (lit) > 0);
256
257 // Then remove 'c' and all other now satisfied (made) clauses.
258 {
259 // Simply go over all unsatisfied (broken) clauses.
260
261 LOG ("trying to make %zd broken clauses", walker.broken.size ());
262
263 // We need to measure (and bound) the memory accesses during traversing
264 // broken clauses in terms of 'propagations'. This is tricky since we
265 // are not actually propagating literals. Instead we use the clause
266 // variable 'ratio' as an approximation to the number of clauses used
267 // during propagating a literal. Note that we use a one-watch scheme.
268 // Accordingly the number of broken clauses traversed divided by that
269 // ratio is an approximation of the number of propagation this would
270 // correspond to (in terms of memory access). To eagerly update these
271 // statistics we simply increment the propagation counter after every
272 // 'ratio' traversed clause. These propagations are particularly
273 // expensive if the number of broken clauses is large which usually
274 // happens initially.
275 //
276 const double ratio = clause_variable_ratio ();
277 const auto eou = walker.broken.end ();
278 auto j = walker.broken.begin (), i = j;
279#ifdef LOGGING
280 int64_t made = 0;
281#endif
282 int64_t count = 0;
283
284 while (i != eou) {
285
286 Clause *d = *j++ = *i++;
287
288 int *literals = d->literals, prev = 0;
289
290 // Find 'lit' in 'd'.
291 //
292 const int size = d->size;
293 for (int i = 0; i < size; i++) {
294 const int other = literals[i];
295 CADICAL_assert (active (other));
296 literals[i] = prev;
297 prev = other;
298 if (other == lit)
299 break;
300 CADICAL_assert (val (other) < 0);
301 }
302
303 // If 'lit' is in 'd' then move it to the front to watch it.
304 //
305 if (prev == lit) {
306 literals[0] = lit;
307 LOG (d, "made");
308 watch_literal (literals[0], literals[1], d);
309#ifdef LOGGING
310 made++;
311#endif
312 j--;
313
314 } else { // Otherwise the clause is not satisfied, undo shift.
315
316 for (int i = size - 1; i >= 0; i--) {
317 int other = literals[i];
318 literals[i] = prev;
319 prev = other;
320 }
321 }
322
323 if (count--)
324 continue;
325
326 // Update these counters eagerly. Otherwise if we delay the update
327 // until all clauses are traversed, interrupting the solver has a high
328 // chance of giving bogus statistics on the number of 'propagations'
329 // in 'walk', if it is interrupted in this loop.
330
331 count = ratio; // Starting counting down again.
332 walker.propagations++;
333 stats.propagations.walk++;
334 }
335 LOG ("made %" PRId64 " clauses by flipping %d", made, lit);
336 walker.broken.resize (j - walker.broken.begin ());
337 }
338
339 // Finally add all new unsatisfied (broken) clauses.
340 {
341 walker.propagations++; // This really corresponds now to one
342 stats.propagations.walk++; // propagation (in a one-watch scheme).
343
344#ifdef LOGGING
345 int64_t broken = 0;
346#endif
347 Watches &ws = watches (-lit);
348
349 LOG ("trying to break %zd watched clauses", ws.size ());
350
351 for (const auto &w : ws) {
352 Clause *d = w.clause;
353 LOG (d, "unwatch %d in", -lit);
354 int *literals = d->literals, replacement = 0, prev = -lit;
355 CADICAL_assert (literals[0] == -lit);
356 const int size = d->size;
357 for (int i = 1; i < size; i++) {
358 const int other = literals[i];
359 CADICAL_assert (active (other));
360 literals[i] = prev; // shift all to right
361 prev = other;
362 const signed char tmp = val (other);
363 if (tmp < 0)
364 continue;
365 replacement = other; // satisfying literal
366 break;
367 }
368 if (replacement) {
369 literals[1] = -lit;
370 literals[0] = replacement;
371 CADICAL_assert (-lit != replacement);
372 watch_literal (replacement, -lit, d);
373 } else {
374 for (int i = size - 1; i > 0; i--) { // undo shift
375 const int other = literals[i];
376 literals[i] = prev;
377 prev = other;
378 }
379 CADICAL_assert (literals[0] == -lit);
380 LOG (d, "broken");
381 walker.broken.push_back (d);
382#ifdef LOGGING
383 broken++;
384#endif
385 }
386 }
387 LOG ("broken %" PRId64 " clauses by flipping %d", broken, lit);
388 ws.clear ();
389 }
390}
struct walker walker
Definition walk.c:19
Here is the call graph for this function:
Here is the caller graph for this function:

◆ walk_pick_clause()

Clause * CaDiCaL::Internal::walk_pick_clause ( Walker & walker)

Definition at line 100 of file cadical_walk.cpp.

100 {
102 CADICAL_assert (!walker.broken.empty ());
103 int64_t size = walker.broken.size ();
104 if (size > INT_MAX)
105 size = INT_MAX;
106 int pos = walker.random.pick_int (0, size - 1);
107 Clause *res = walker.broken[pos];
108 LOG (res, "picking random position %d", pos);
109 return res;
110}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ walk_pick_lit()

int CaDiCaL::Internal::walk_pick_lit ( Walker & walker,
Clause * c )

Definition at line 191 of file cadical_walk.cpp.

191 {
192 LOG ("picking literal by break-count");
193 CADICAL_assert (walker.scores.empty ());
194 double sum = 0;
195 int64_t propagations = 0;
196 for (const auto lit : *c) {
198 if (var (lit).level == 1) {
199 LOG ("skipping assumption %d for scoring", -lit);
200 continue;
201 }
203 propagations++;
204 unsigned tmp = walk_break_value (-lit);
205 double score = walker.score (tmp);
206 LOG ("literal %d break-count %u score %g", lit, tmp, score);
207 walker.scores.push_back (score);
208 sum += score;
209 }
210 LOG ("scored %zd literals", walker.scores.size ());
211 CADICAL_assert (!walker.scores.empty ());
212 walker.propagations += propagations;
213 stats.propagations.walk += propagations;
214 CADICAL_assert (walker.scores.size () <= (size_t) c->size);
215 const double lim = sum * walker.random.generate_double ();
216 LOG ("score sum %g limit %g", sum, lim);
217 const auto end = c->end ();
218 auto i = c->begin ();
219 auto j = walker.scores.begin ();
220 int res;
221 for (;;) {
222 CADICAL_assert (i != end);
223 res = *i++;
224 if (var (res).level > 1)
225 break;
226 LOG ("skipping assumption %d without score", -res);
227 }
228 sum = *j++;
229 while (sum <= lim && i != end) {
230 res = *i++;
231 if (var (res).level == 1) {
232 LOG ("skipping assumption %d without score", -res);
233 continue;
234 }
235 sum += *j++;
236 }
237 walker.scores.clear ();
238 LOG ("picking literal %d by break-count", res);
239 return res;
240}
unsigned walk_break_value(int lit)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ walk_round()

int CaDiCaL::Internal::walk_round ( int64_t limit,
bool prev )

Definition at line 411 of file cadical_walk.cpp.

411 {
412
413 backtrack ();
414 if (propagated < trail.size () && !propagate ()) {
415 LOG ("empty clause after root level propagation");
417 return 20;
418 }
419
420 stats.walk.count++;
421
422 clear_watches ();
423
424 // Remove all fixed variables first (assigned at decision level zero).
425 //
426 if (last.collect.fixed < stats.all.fixed)
428
429#ifndef CADICAL_QUIET
430 // We want to see more messages during initial local search.
431 //
432 if (localsearching) {
433 CADICAL_assert (!force_phase_messages);
434 force_phase_messages = true;
435 }
436#endif
437
438 PHASE ("walk", stats.walk.count,
439 "random walk limit of %" PRId64 " propagations", limit);
440
441 // First compute the average clause size for picking the CB constant.
442 //
443 double size = 0;
444 int64_t n = 0;
445 for (const auto c : clauses) {
446 if (c->garbage)
447 continue;
448 if (c->redundant) {
449 if (!opts.walkredundant)
450 continue;
452 continue;
453 }
454 size += c->size;
455 n++;
456 }
457 double average_size = relative (size, n);
458
459 PHASE ("walk", stats.walk.count,
460 "%" PRId64 " clauses average size %.2f over %d variables", n,
461 average_size, active ());
462
463 // Instantiate data structures for this local search round.
464 //
465 Walker walker (internal, average_size, limit);
466
467 bool failed = false; // Inconsistent assumptions?
468
469 level = 1; // Assumed variables assigned at level 1.
470
471 if (assumptions.empty ()) {
472 LOG ("no assumptions so assigning all variables to decision phase");
473 } else {
474 LOG ("assigning assumptions to their forced phase first");
475 for (const auto lit : assumptions) {
476 signed char tmp = val (lit);
477 if (tmp > 0)
478 continue;
479 if (tmp < 0) {
480 LOG ("inconsistent assumption %d", lit);
481 failed = true;
482 break;
483 }
484 if (!active (lit))
485 continue;
486 tmp = sign (lit);
487 const int idx = abs (lit);
488 LOG ("initial assign %d to assumption phase", tmp < 0 ? -idx : idx);
489 set_val (idx, tmp);
490 CADICAL_assert (level == 1);
491 var (idx).level = 1;
492 }
493 if (!failed)
494 LOG ("now assigning remaining variables to their decision phase");
495 }
496
497 level = 2; // All other non assumed variables assigned at level 2.
498
499 if (!failed) {
500
501 for (auto idx : vars) {
502 if (!active (idx)) {
503 LOG ("skipping inactive variable %d", idx);
504 continue;
505 }
506 if (vals[idx]) {
507 CADICAL_assert (var (idx).level == 1);
508 LOG ("skipping assumed variable %d", idx);
509 continue;
510 }
511 int tmp = 0;
512 if (prev)
513 tmp = phases.prev[idx];
514 if (!tmp)
515 tmp = sign (decide_phase (idx, true));
516 CADICAL_assert (tmp == 1 || tmp == -1);
517 set_val (idx, tmp);
518 CADICAL_assert (level == 2);
519 var (idx).level = 2;
520 LOG ("initial assign %d to decision phase", tmp < 0 ? -idx : idx);
521 }
522
523 LOG ("watching satisfied and registering broken clauses");
524#ifdef LOGGING
525 int64_t watched = 0;
526#endif
527 for (const auto c : clauses) {
528
529 if (c->garbage)
530 continue;
531 if (c->redundant) {
532 if (!opts.walkredundant)
533 continue;
535 continue;
536 }
537
538 bool satisfiable = false; // contains not only assumptions
539 int satisfied = 0; // clause satisfied?
540
541 int *lits = c->literals;
542 const int size = c->size;
543
544 // Move to front satisfied literals and determine whether there
545 // is at least one (non-assumed) literal that can be flipped.
546 //
547 for (int i = 0; satisfied < 2 && i < size; i++) {
548 const int lit = lits[i];
549 CADICAL_assert (active (lit)); // Due to garbage collection.
550 if (val (lit) > 0) {
551 swap (lits[satisfied], lits[i]);
552 if (!satisfied++)
553 LOG ("first satisfying literal %d", lit);
554 } else if (!satisfiable && var (lit).level > 1) {
555 LOG ("non-assumption potentially satisfying literal %d", lit);
556 satisfiable = true;
557 }
558 }
559
560 if (!satisfied && !satisfiable) {
561 LOG (c, "due to assumptions unsatisfiable");
562 LOG ("stopping local search since assumptions falsify a clause");
563 failed = true;
564 break;
565 }
566
567 if (satisfied) {
568 watch_literal (lits[0], lits[1], c);
569#ifdef LOGGING
570 watched++;
571#endif
572 } else {
573 CADICAL_assert (satisfiable); // at least one non-assumed variable ...
574 LOG (c, "broken");
575 walker.broken.push_back (c);
576 }
577 }
578#ifdef LOGGING
579 if (!failed) {
580 int64_t broken = walker.broken.size ();
581 int64_t total = watched + broken;
582 LOG ("watching %" PRId64 " clauses %.0f%% "
583 "out of %" PRId64 " (watched and broken)",
584 watched, percent (watched, total), total);
585 }
586#endif
587 }
588
589 int64_t old_global_minimum = stats.walk.minimum;
590
591 int res; // Tells caller to continue with local search.
592
593 if (!failed) {
594
595 int64_t broken = walker.broken.size ();
596
597 PHASE ("walk", stats.walk.count,
598 "starting with %" PRId64 " unsatisfied clauses "
599 "(%.0f%% out of %" PRId64 ")",
600 broken, percent (broken, stats.current.irredundant),
601 stats.current.irredundant);
602
604
605 int64_t minimum = broken;
606#ifndef CADICAL_QUIET
607 int64_t flips = 0;
608#endif
609 while (!terminated_asynchronously () && !walker.broken.empty () &&
610 walker.propagations < walker.limit) {
611#ifndef CADICAL_QUIET
612 flips++;
613#endif
614 stats.walk.flips++;
615 stats.walk.broken += broken;
616 Clause *c = walk_pick_clause (walker);
617 const int lit = walk_pick_lit (walker, c);
619 broken = walker.broken.size ();
620 LOG ("now have %" PRId64 " broken clauses in total", broken);
621 if (broken >= minimum)
622 continue;
623 minimum = broken;
624 VERBOSE (3, "new phase minimum %" PRId64 " after %" PRId64 " flips",
625 minimum, flips);
627 }
628
629 if (minimum < old_global_minimum)
630 PHASE ("walk", stats.walk.count,
631 "%snew global minimum %" PRId64 "%s in %" PRId64 " flips and "
632 "%" PRId64 " propagations",
633 tout.bright_yellow_code (), minimum, tout.normal_code (),
634 flips, walker.propagations);
635 else
636 PHASE ("walk", stats.walk.count,
637 "best phase minimum %" PRId64 " in %" PRId64 " flips and "
638 "%" PRId64 " propagations",
639 minimum, flips, walker.propagations);
640
641 if (opts.profile >= 2) {
642 PHASE ("walk", stats.walk.count,
643 "%.2f million propagations per second",
644 relative (1e-6 * walker.propagations,
645 time () - profiles.walk.started));
646
647 PHASE ("walk", stats.walk.count, "%.2f thousand flips per second",
648 relative (1e-3 * flips, time () - profiles.walk.started));
649
650 } else {
651 PHASE ("walk", stats.walk.count, "%.2f million propagations",
652 1e-6 * walker.propagations);
653
654 PHASE ("walk", stats.walk.count, "%.2f thousand flips", 1e-3 * flips);
655 }
656
657 if (minimum > 0) {
658 LOG ("minimum %" PRId64 " non-zero thus potentially continue",
659 minimum);
660 res = 0;
661 } else {
662 LOG ("minimum is zero thus stop local search");
663 res = 10;
664 }
665
666 } else {
667
668 res = 20;
669
670 PHASE ("walk", stats.walk.count,
671 "aborted due to inconsistent assumptions");
672 }
673
674 copy_phases (phases.prev);
675
676 for (auto idx : vars)
677 if (active (idx))
678 set_val (idx, 0);
679
680 CADICAL_assert (level == 2);
681 level = 0;
682
683 clear_watches ();
685
686#ifndef CADICAL_QUIET
687 if (localsearching) {
688 CADICAL_assert (force_phase_messages);
689 force_phase_messages = false;
690 }
691#endif
692
693 return res;
694}
const char * normal_code()
Definition terminal.hpp:80
const char * bright_yellow_code()
Definition terminal.hpp:75
Clause * walk_pick_clause(Walker &)
void walk_flip_lit(Walker &, int lit)
int walk_pick_lit(Walker &, Clause *)
void walk_save_minimum(Walker &)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ walk_save_minimum()

void CaDiCaL::Internal::walk_save_minimum ( Walker & walker)
inline

Definition at line 396 of file cadical_walk.cpp.

396 {
397 int64_t broken = walker.broken.size ();
398 if (broken >= stats.walk.minimum)
399 return;
400 VERBOSE (3, "new global minimum %" PRId64 "", broken);
401 stats.walk.minimum = broken;
402 for (auto i : vars) {
403 const signed char tmp = vals[i];
404 if (tmp)
405 phases.min[i] = phases.saved[i] = tmp;
406 }
407}
Here is the caller graph for this function:

◆ warning()

void CaDiCaL::Internal::warning ( const char * fmt,
... )

Definition at line 140 of file cadical_message.cpp.

140 {
141 fflush (stdout);
142 terr.bold ();
143 fputs ("cadical: ", stderr);
144 terr.red (1);
145 fputs ("warning:", stderr);
146 terr.normal ();
147 fputc (' ', stderr);
148 va_list ap;
149 va_start (ap, fmt);
150 vfprintf (stderr, fmt, ap);
151 va_end (ap);
152 fputc ('\n', stderr);
153 fflush (stderr);
154}

◆ watch_clause()

void CaDiCaL::Internal::watch_clause ( Clause * c)
inline

Definition at line 633 of file internal.hpp.

633 {
634 const int l0 = c->literals[0];
635 const int l1 = c->literals[1];
636 watch_literal (l0, l1, c);
637 watch_literal (l1, l0, c);
638 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ watch_literal()

void CaDiCaL::Internal::watch_literal ( int lit,
int blit,
Clause * c )
inline

Definition at line 623 of file internal.hpp.

623 {
624 CADICAL_assert (lit != blit);
625 Watches &ws = watches (lit);
626 ws.push_back (Watch (blit, c));
627 LOG (c, "watch %d blit %d in", lit, blit);
628 }
Here is the caller graph for this function:

◆ watches()

Watches & CaDiCaL::Internal::watches ( int lit)
inline

Definition at line 467 of file internal.hpp.

467{ return wtab[vlit (lit)]; }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ watching()

bool CaDiCaL::Internal::watching ( ) const
inline

Definition at line 462 of file internal.hpp.

462{ return !wtab.empty (); }
Here is the caller graph for this function:

◆ wrapped_learn_external_reason_clause()

Clause * CaDiCaL::Internal::wrapped_learn_external_reason_clause ( int lit)

Definition at line 715 of file cadical_external_propagate.cpp.

715 {
716 Clause *res;
717 std::vector<int64_t> chain_tmp{std::move (lrat_chain)};
718 lrat_chain.clear ();
719 if (clause.empty ()) {
720 res = learn_external_reason_clause (ilit, 0, true);
721 } else {
722 std::vector<int> clause_tmp{std::move (clause)};
723 clause.clear ();
724 res = learn_external_reason_clause (ilit, 0, true);
725 // The learn_external_reason clause can leave a literal in clause when
726 // there is a falsified elit arg. Here it is not allowed to
727 // happen.
728 CADICAL_assert (clause.empty ());
729
730 clause = std::move (clause_tmp);
731 clause_tmp.clear ();
732 }
733 CADICAL_assert (lrat_chain.empty ());
734 lrat_chain = std::move (chain_tmp);
735 chain_tmp.clear ();
736 return res;
737}
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ analyzed

vector<int> CaDiCaL::Internal::analyzed

Definition at line 267 of file internal.hpp.

◆ arena

Arena CaDiCaL::Internal::arena

Definition at line 307 of file internal.hpp.

◆ assumptions

vector<int> CaDiCaL::Internal::assumptions

Definition at line 261 of file internal.hpp.

◆ averages

Averages CaDiCaL::Internal::averages

Definition at line 284 of file internal.hpp.

◆ best_assigned

size_t CaDiCaL::Internal::best_assigned

Definition at line 256 of file internal.hpp.

◆ big

vector<Bins> CaDiCaL::Internal::big

Definition at line 240 of file internal.hpp.

◆ btab

vector<int64_t> CaDiCaL::Internal::btab

Definition at line 234 of file internal.hpp.

◆ citten

cadical_kitten* CaDiCaL::Internal::citten

Definition at line 277 of file internal.hpp.

◆ clause

vector<int> CaDiCaL::Internal::clause

Definition at line 260 of file internal.hpp.

◆ clause_id

int64_t CaDiCaL::Internal::clause_id

Definition at line 201 of file internal.hpp.

◆ clauses

vector<Clause *> CaDiCaL::Internal::clauses

Definition at line 283 of file internal.hpp.

◆ concluded

bool CaDiCaL::Internal::concluded

Definition at line 206 of file internal.hpp.

◆ conclusion

vector<int64_t> CaDiCaL::Internal::conclusion

Definition at line 207 of file internal.hpp.

◆ conflict

Clause* CaDiCaL::Internal::conflict

Definition at line 242 of file internal.hpp.

◆ conflict_id

int64_t CaDiCaL::Internal::conflict_id

Definition at line 204 of file internal.hpp.

◆ congruence_delay

Delay CaDiCaL::Internal::congruence_delay

Definition at line 286 of file internal.hpp.

◆ constraint

vector<int> CaDiCaL::Internal::constraint

Definition at line 262 of file internal.hpp.

◆ control

vector<Level> CaDiCaL::Internal::control

Definition at line 282 of file internal.hpp.

◆ delay

Delay CaDiCaL::Internal::delay[2]

Definition at line 285 of file internal.hpp.

◆ delaying_sweep

Delay CaDiCaL::Internal::delaying_sweep

Definition at line 292 of file internal.hpp.

◆ delaying_vivify_irredundant

Delay CaDiCaL::Internal::delaying_vivify_irredundant

Definition at line 291 of file internal.hpp.

◆ did_external_prop

bool CaDiCaL::Internal::did_external_prop

Definition at line 193 of file internal.hpp.

◆ dummy_binary

Clause* CaDiCaL::Internal::dummy_binary

Definition at line 244 of file internal.hpp.

◆ error_message

Format CaDiCaL::Internal::error_message

Definition at line 308 of file internal.hpp.

◆ ext_clause_forgettable

bool CaDiCaL::Internal::ext_clause_forgettable

Definition at line 249 of file internal.hpp.

◆ external

External* CaDiCaL::Internal::external

Definition at line 312 of file internal.hpp.

◆ external_prop

bool CaDiCaL::Internal::external_prop

Definition at line 192 of file internal.hpp.

◆ external_prop_is_lazy

bool CaDiCaL::Internal::external_prop_is_lazy

Definition at line 194 of file internal.hpp.

◆ external_reason

Clause* CaDiCaL::Internal::external_reason

Definition at line 245 of file internal.hpp.

◆ file_tracers

vector<FileTracer *> CaDiCaL::Internal::file_tracers

Definition at line 298 of file internal.hpp.

◆ force_no_backtrack

bool CaDiCaL::Internal::force_no_backtrack

Definition at line 247 of file internal.hpp.

◆ force_saved_phase

bool CaDiCaL::Internal::force_saved_phase

Definition at line 188 of file internal.hpp.

◆ forced_backt_allowed

bool CaDiCaL::Internal::forced_backt_allowed

Definition at line 195 of file internal.hpp.

◆ frat

bool CaDiCaL::Internal::frat

Definition at line 218 of file internal.hpp.

◆ from_propagator

bool CaDiCaL::Internal::from_propagator

Definition at line 248 of file internal.hpp.

◆ frozentab

vector<unsigned> CaDiCaL::Internal::frozentab

Definition at line 223 of file internal.hpp.

◆ ftab

vector<Flags> CaDiCaL::Internal::ftab

Definition at line 233 of file internal.hpp.

◆ gtab

vector<int64_t> CaDiCaL::Internal::gtab

Definition at line 235 of file internal.hpp.

◆ i2e

vector<int> CaDiCaL::Internal::i2e

Definition at line 224 of file internal.hpp.

◆ ignore

Clause* CaDiCaL::Internal::ignore

Definition at line 243 of file internal.hpp.

◆ inc

Inc CaDiCaL::Internal::inc

Definition at line 289 of file internal.hpp.

◆ inst_chain

vector<Clause *> CaDiCaL::Internal::inst_chain

Definition at line 214 of file internal.hpp.

◆ internal

Internal* CaDiCaL::Internal::internal

Definition at line 311 of file internal.hpp.

◆ iterating

bool CaDiCaL::Internal::iterating

Definition at line 183 of file internal.hpp.

◆ last

Last CaDiCaL::Internal::last

Definition at line 288 of file internal.hpp.

◆ level

int CaDiCaL::Internal::level

Definition at line 219 of file internal.hpp.

◆ levels

vector<int> CaDiCaL::Internal::levels

Definition at line 266 of file internal.hpp.

◆ lim

Limit CaDiCaL::Internal::lim

Definition at line 287 of file internal.hpp.

◆ links

Links CaDiCaL::Internal::links

Definition at line 227 of file internal.hpp.

◆ lits

const Sange CaDiCaL::Internal::lits

Definition at line 325 of file internal.hpp.

◆ localsearching

bool CaDiCaL::Internal::localsearching

Definition at line 184 of file internal.hpp.

◆ lookingahead

bool CaDiCaL::Internal::lookingahead

Definition at line 185 of file internal.hpp.

◆ lrat

bool CaDiCaL::Internal::lrat

Definition at line 217 of file internal.hpp.

◆ lrat_chain

vector<int64_t> CaDiCaL::Internal::lrat_chain

Definition at line 210 of file internal.hpp.

◆ marked_failed

bool CaDiCaL::Internal::marked_failed

Definition at line 264 of file internal.hpp.

◆ marks

vector<signed char> CaDiCaL::Internal::marks

Definition at line 222 of file internal.hpp.

◆ max_used

const unsigned CaDiCaL::Internal::max_used = 255

Definition at line 314 of file internal.hpp.

◆ max_var

int CaDiCaL::Internal::max_var

Definition at line 200 of file internal.hpp.

◆ mini_chain

vector<int64_t> CaDiCaL::Internal::mini_chain

Definition at line 211 of file internal.hpp.

◆ minimize_chain

vector<int64_t> CaDiCaL::Internal::minimize_chain

Definition at line 212 of file internal.hpp.

◆ minimized

vector<int> CaDiCaL::Internal::minimized

Definition at line 270 of file internal.hpp.

◆ mode

int CaDiCaL::Internal::mode

Definition at line 177 of file internal.hpp.

◆ newest_clause

Clause* CaDiCaL::Internal::newest_clause

Definition at line 246 of file internal.hpp.

◆ no_conflict_until

size_t CaDiCaL::Internal::no_conflict_until

Definition at line 258 of file internal.hpp.

◆ notified

size_t CaDiCaL::Internal::notified

Definition at line 251 of file internal.hpp.

◆ ntab

vector<int64_t> CaDiCaL::Internal::ntab

Definition at line 239 of file internal.hpp.

◆ num_assigned

size_t CaDiCaL::Internal::num_assigned

Definition at line 279 of file internal.hpp.

◆ opts

Options CaDiCaL::Internal::opts

Definition at line 301 of file internal.hpp.

◆ original

vector<int> CaDiCaL::Internal::original

Definition at line 265 of file internal.hpp.

◆ original_id

int64_t CaDiCaL::Internal::original_id

Definition at line 202 of file internal.hpp.

◆ otab

vector<Occs> CaDiCaL::Internal::otab

Definition at line 236 of file internal.hpp.

◆ parents

vector<int> CaDiCaL::Internal::parents

Definition at line 232 of file internal.hpp.

◆ phases

Phases CaDiCaL::Internal::phases

Definition at line 220 of file internal.hpp.

◆ prefix

string CaDiCaL::Internal::prefix

Definition at line 309 of file internal.hpp.

◆ preprocessing

bool CaDiCaL::Internal::preprocessing

Definition at line 186 of file internal.hpp.

◆ private_steps

bool CaDiCaL::Internal::private_steps

Definition at line 196 of file internal.hpp.

◆ probe_reason

Clause* CaDiCaL::Internal::probe_reason

Definition at line 252 of file internal.hpp.

◆ probehbr_chains

vector<vector<vector<int64_t> > > CaDiCaL::Internal::probehbr_chains

Definition at line 216 of file internal.hpp.

◆ probes

vector<int> CaDiCaL::Internal::probes

Definition at line 281 of file internal.hpp.

◆ proof

Proof* CaDiCaL::Internal::proof

Definition at line 294 of file internal.hpp.

◆ propagated

size_t CaDiCaL::Internal::propagated

Definition at line 253 of file internal.hpp.

◆ propagated2

size_t CaDiCaL::Internal::propagated2

Definition at line 254 of file internal.hpp.

◆ propergated

size_t CaDiCaL::Internal::propergated

Definition at line 255 of file internal.hpp.

◆ protected_reasons

bool CaDiCaL::Internal::protected_reasons

Definition at line 187 of file internal.hpp.

◆ ptab

vector<int> CaDiCaL::Internal::ptab

Definition at line 238 of file internal.hpp.

◆ queue

Queue CaDiCaL::Internal::queue

Definition at line 226 of file internal.hpp.

◆ reap

Reap CaDiCaL::Internal::reap

Definition at line 272 of file internal.hpp.

◆ relevanttab

vector<unsigned> CaDiCaL::Internal::relevanttab

Definition at line 225 of file internal.hpp.

◆ reluctant

Reluctant CaDiCaL::Internal::reluctant

Definition at line 198 of file internal.hpp.

◆ rephased

char CaDiCaL::Internal::rephased

Definition at line 197 of file internal.hpp.

◆ reported

bool CaDiCaL::Internal::reported

Definition at line 191 of file internal.hpp.

◆ reserved_ids

int64_t CaDiCaL::Internal::reserved_ids

Definition at line 203 of file internal.hpp.

◆ rtab

vector<Occs> CaDiCaL::Internal::rtab

Definition at line 237 of file internal.hpp.

◆ saved_decisions

int64_t CaDiCaL::Internal::saved_decisions

Definition at line 205 of file internal.hpp.

◆ score_inc

double CaDiCaL::Internal::score_inc

Definition at line 228 of file internal.hpp.

◆ scores

ScoreSchedule CaDiCaL::Internal::scores

Definition at line 229 of file internal.hpp.

◆ searching_lucky_phases

bool CaDiCaL::Internal::searching_lucky_phases

Definition at line 189 of file internal.hpp.

◆ shrinkable

vector<int> CaDiCaL::Internal::shrinkable

Definition at line 271 of file internal.hpp.

◆ sign_marked

vector<int> CaDiCaL::Internal::sign_marked

Definition at line 269 of file internal.hpp.

◆ stab

vector<double> CaDiCaL::Internal::stab

Definition at line 230 of file internal.hpp.

◆ stable

bool CaDiCaL::Internal::stable

Definition at line 190 of file internal.hpp.

◆ stat_tracers

vector<StatTracer *> CaDiCaL::Internal::stat_tracers

Definition at line 299 of file internal.hpp.

◆ stats

Stats CaDiCaL::Internal::stats

Definition at line 302 of file internal.hpp.

◆ sweep_incomplete

bool CaDiCaL::Internal::sweep_incomplete

Definition at line 275 of file internal.hpp.

◆ sweep_schedule

vector<int> CaDiCaL::Internal::sweep_schedule

Definition at line 274 of file internal.hpp.

◆ tainted_literal

int CaDiCaL::Internal::tainted_literal

Definition at line 250 of file internal.hpp.

◆ target_assigned

size_t CaDiCaL::Internal::target_assigned

Definition at line 257 of file internal.hpp.

◆ termination_forced

volatile bool CaDiCaL::Internal::termination_forced

Definition at line 320 of file internal.hpp.

◆ tier1

int CaDiCaL::Internal::tier1[2]
Initial value:
= {
2, 2}

Definition at line 178 of file internal.hpp.

178 {
179 2, 2}; // tier1 limit for 0=focused, 1=stable; aka tier1[stable]

◆ tier2

int CaDiCaL::Internal::tier2[2]
Initial value:
= {
6, 6}

Definition at line 180 of file internal.hpp.

180 {
181 6, 6}; // tier2 limit for 0=focused, 1=stable; aka tier1[stable]

◆ tracers

vector<Tracer *> CaDiCaL::Internal::tracers

Definition at line 296 of file internal.hpp.

◆ trail

vector<int> CaDiCaL::Internal::trail

Definition at line 259 of file internal.hpp.

◆ unit_analyzed

vector<int> CaDiCaL::Internal::unit_analyzed

Definition at line 268 of file internal.hpp.

◆ unit_chain

vector<int64_t> CaDiCaL::Internal::unit_chain

Definition at line 213 of file internal.hpp.

◆ unit_clauses_idx

vector<int64_t> CaDiCaL::Internal::unit_clauses_idx

Definition at line 209 of file internal.hpp.

◆ unsat

bool CaDiCaL::Internal::unsat

Definition at line 182 of file internal.hpp.

◆ unsat_constraint

bool CaDiCaL::Internal::unsat_constraint

Definition at line 263 of file internal.hpp.

◆ vals

signed char* CaDiCaL::Internal::vals

Definition at line 221 of file internal.hpp.

◆ vars

const Range CaDiCaL::Internal::vars

Definition at line 324 of file internal.hpp.

◆ vsize

size_t CaDiCaL::Internal::vsize

Definition at line 199 of file internal.hpp.

◆ vtab

vector<Var> CaDiCaL::Internal::vtab

Definition at line 231 of file internal.hpp.

◆ wtab

vector<Watches> CaDiCaL::Internal::wtab

Definition at line 241 of file internal.hpp.


The documentation for this struct was generated from the following files: