#include "inline.h" #ifndef HYPER_PROPAGATION static inline void kissat_watch_large_delayed (kissat * solver, unsigneds * delayed) { const unsigned *end_delayed = END_STACK (*delayed); const unsigned *d = BEGIN_STACK (*delayed); watches *all_watches = solver->watches; while (d != end_delayed) { const unsigned lit = *d++; assert (d != end_delayed); const watch watch = {.raw = *d++ }; assert (!watch.type.binary); watches *lit_watches = all_watches + lit; assert (d != end_delayed); const reference ref = *d++; const unsigned blocking = watch.blocking.lit; LOGREF (ref, "watching %s blocking %s in", LOGLIT (lit), LOGLIT (blocking)); kissat_push_blocking_watch (solver, lit_watches, blocking, ref); } CLEAR_STACK (*delayed); } #endif #if defined(HYPER_PROPAGATION) || defined(PROBING_PROPAGATION) static inline void kissat_update_probing_propagation_statistics (kissat * solver, unsigned propagated) { assert (propagated <= solver->propagated); propagated = solver->propagated - propagated; LOG (PROPAGATION_TYPE " propagation took %" PRIu64 " propagations", propagated); LOG (PROPAGATION_TYPE " propagation took %" PRIu64 " ticks", solver->ticks); ADD (propagations, propagated); ADD (probing_ticks, solver->ticks); ADD (probing_propagations, propagated); ADD (ticks, solver->ticks); } #endif static inline void kissat_delay_watching_large (kissat * solver, unsigneds * delayed, unsigned lit, unsigned other, reference ref) { const watch watch = kissat_blocking_watch (other); PUSH_STACK (*delayed, lit); PUSH_STACK (*delayed, watch.raw); PUSH_STACK (*delayed, ref); } static inline clause * PROPAGATE_LITERAL (kissat * solver, #if defined(HYPER_PROPAGATION) || defined(PROBING_PROPAGATION) const clause * ignore, #endif const unsigned lit) { assert (solver->watching); LOG (PROPAGATION_TYPE " propagating %s", LOGLIT (lit)); assert (VALUE (lit) > 0); assert (EMPTY_STACK (solver->delayed)); const word *arena = BEGIN_STACK (solver->arena); assigned *assigned = solver->assigned; value *values = solver->values; const unsigned not_lit = NOT (lit); #ifdef HYPER_PROPAGATION const bool hyper = GET_OPTION (hyper); #endif watches *watches = &WATCHES (not_lit); watch *begin_watches = BEGIN_WATCHES (*watches), *q = begin_watches; const watch *end_watches = END_WATCHES (*watches), *p = q; unsigneds *delayed = &solver->delayed; uint64_t ticks = kissat_cache_lines (watches->size, sizeof (watch)); clause *res = 0; while (p != end_watches) { const watch head = *q++ = *p++; const unsigned blocking = head.blocking.lit; assert (VALID_INTERNAL_LITERAL (blocking)); const value blocking_value = values[blocking]; if (head.type.binary) { if (blocking_value > 0) continue; const bool redundant = head.binary.redundant; if (blocking_value < 0) { res = kissat_binary_conflict (solver, redundant, not_lit, blocking); break; } else { assert (!blocking_value); kissat_assign_binary (solver, values, assigned, redundant, blocking, not_lit); } } else { const watch tail = *q++ = *p++; if (blocking_value > 0) continue; const reference ref = tail.raw; assert (ref < SIZE_STACK (solver->arena)); clause *c = (clause *) (arena + ref); #if defined(HYPER_PROPAGATION) || defined(PROBING_PROPAGATION) if (c == ignore) continue; #endif ticks++; if (c->garbage) { q -= 2; continue; } unsigned *lits = BEGIN_LITS (c); const unsigned other = lits[0] ^ lits[1] ^ not_lit; assert (lits[0] != lits[1]); assert (VALID_INTERNAL_LITERAL (other)); assert (not_lit != other); assert (lit != other); const value other_value = values[other]; if (other_value > 0) q[-2].blocking.lit = other; else { const unsigned *end_lits = lits + c->size; unsigned *searched = lits + c->searched; assert (c->lits + 2 <= searched); assert (searched < end_lits); unsigned *r, replacement = INVALID_LIT; value replacement_value = -1; for (r = searched; r != end_lits; r++) { replacement = *r; assert (VALID_INTERNAL_LITERAL (replacement)); replacement_value = values[replacement]; if (replacement_value >= 0) break; } if (replacement_value < 0) { for (r = lits + 2; r != searched; r++) { replacement = *r; assert (VALID_INTERNAL_LITERAL (replacement)); replacement_value = values[replacement]; if (replacement_value >= 0) break; } } if (replacement_value >= 0) c->searched = r - c->lits; if (replacement_value > 0) { assert (replacement != INVALID_LIT); q[-2].blocking.lit = replacement; } else if (!replacement_value) { assert (replacement != INVALID_LIT); LOGREF (ref, "unwatching %s in", LOGLIT (not_lit)); q -= 2; lits[0] = other; lits[1] = replacement; assert (lits[0] != lits[1]); *r = not_lit; kissat_delay_watching_large (solver, delayed, replacement, other, ref); ticks++; } else if (other_value) { assert (replacement_value < 0); assert (blocking_value < 0); assert (other_value < 0); LOGREF (ref, "conflicting"); res = c; break; } #ifdef HYPER_PROPAGATION else if (hyper) { assert (replacement_value < 0); unsigned dom = kissat_find_dominator (solver, other, c); if (dom != INVALID_LIT) { LOGBINARY (dom, other, "hyper binary resolvent"); INC (hyper_binary_resolved); INC (clauses_added); INC (hyper_binaries); INC (clauses_redundant); CHECK_AND_ADD_BINARY (dom, other); ADD_BINARY_TO_PROOF (dom, other); kissat_assign_binary (solver, values, assigned, true, other, dom); delay_watching_hyper (solver, delayed, dom, other); delay_watching_hyper (solver, delayed, other, dom); kissat_delay_watching_large (solver, delayed, not_lit, other, ref); LOGREF (ref, "unwatching %s in", LOGLIT (not_lit)); q -= 2; } else kissat_assign_reference (solver, values, assigned, other, ref, c); } #endif else { assert (replacement_value < 0); kissat_assign_reference (solver, values, assigned, other, ref, c); } } } } solver->ticks += ticks; solver->dps_ticks += ticks; if (solver->dps == 1 && solver->dps_ticks >= solver->dps_period) { solver->dps_ticks -= solver->dps_period; solver->cbk_start_new_period(solver->issuer); } while (p != end_watches) *q++ = *p++; SET_END_OF_WATCHES (*watches, q); #ifdef HYPER_PROPAGATION watch_hyper_delayed (solver, delayed); #else kissat_watch_large_delayed (solver, delayed); #endif return res; }