328 lines
8.8 KiB
C
328 lines
8.8 KiB
C
#define INLINE_SORT
|
|
|
|
#include "dense.h"
|
|
#include "inline.h"
|
|
#include "propsearch.h"
|
|
#include "proprobe.h"
|
|
#include "trail.h"
|
|
|
|
#include "sort.c"
|
|
|
|
static void
|
|
flush_large_watches (kissat * solver,
|
|
litpairs * irredundant, litwatches * redundant)
|
|
{
|
|
assert (!solver->level);
|
|
assert (solver->watching);
|
|
#ifndef LOGGING
|
|
LOG ("flushing large watches");
|
|
if (irredundant)
|
|
LOG ("flushing and saving irredundant binary clauses too");
|
|
else
|
|
LOG ("keep watching irredundant binary clauses");
|
|
if (redundant)
|
|
LOG ("flushing and saving redundant clauses too");
|
|
else
|
|
LOG ("keep watching redundant binary clauses");
|
|
#endif
|
|
const value *values = solver->values;
|
|
size_t flushed = 0, collected = 0;
|
|
watches *all_watches = solver->watches;
|
|
for (all_literals (lit))
|
|
{
|
|
const value lit_value = values[lit];
|
|
watches *watches = all_watches + lit;
|
|
watch *begin = BEGIN_WATCHES (*watches), *q = begin;
|
|
const watch *end_watches = END_WATCHES (*watches), *p = q;
|
|
while (p != end_watches)
|
|
{
|
|
const watch watch = *p++;
|
|
if (watch.type.binary)
|
|
{
|
|
const unsigned other = watch.binary.lit;
|
|
const value other_value = values[other];
|
|
if (!lit_value && !other_value)
|
|
{
|
|
if (irredundant && !watch.binary.redundant)
|
|
{
|
|
const unsigned other = watch.binary.lit;
|
|
if (lit < other)
|
|
{
|
|
const litpair litpair = {.lits = {lit, other} };
|
|
PUSH_STACK (*irredundant, litpair);
|
|
}
|
|
}
|
|
else if (redundant && watch.binary.redundant)
|
|
{
|
|
const unsigned other = watch.binary.lit;
|
|
if (lit < other)
|
|
{
|
|
const litwatch litwatch = { lit, watch };
|
|
PUSH_STACK (*redundant, litwatch);
|
|
}
|
|
}
|
|
else
|
|
*q++ = watch;
|
|
}
|
|
else
|
|
{
|
|
assert (lit_value > 0 || other_value > 0);
|
|
if (lit < other)
|
|
{
|
|
const bool red = watch.binary.redundant;
|
|
const bool hyper = watch.binary.hyper;
|
|
kissat_delete_binary (solver, red, hyper, lit, other);
|
|
collected++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
flushed++;
|
|
p++;
|
|
}
|
|
|
|
}
|
|
SET_END_OF_WATCHES (*watches, q);
|
|
}
|
|
LOG ("flushed %zu large watches", flushed);
|
|
LOG ("collected %zu satisfied binary clauses", collected);
|
|
if (irredundant)
|
|
LOG ("saved %zu irredundant binary clauses", SIZE_STACK (*irredundant));
|
|
if (redundant)
|
|
LOG ("saved %zu redundant binary clauses", SIZE_STACK (*redundant));
|
|
(void) collected;
|
|
(void) flushed;
|
|
}
|
|
|
|
void
|
|
kissat_enter_dense_mode (kissat * solver,
|
|
litpairs * irredundant, litwatches * redundant)
|
|
{
|
|
assert (!solver->level);
|
|
assert (solver->watching);
|
|
assert (solver->propagated == SIZE_STACK (solver->trail));
|
|
LOG ("entering dense mode with full occurrence lists");
|
|
if (irredundant || redundant)
|
|
flush_large_watches (solver, irredundant, redundant);
|
|
else
|
|
kissat_flush_large_watches (solver);
|
|
LOG ("switched to full occurrence lists");
|
|
solver->watching = false;
|
|
}
|
|
|
|
static void
|
|
resume_watching_binaries_after_elimination (kissat * solver,
|
|
litwatches * binaries)
|
|
{
|
|
assert (binaries);
|
|
#ifdef LOGGING
|
|
size_t resumed_watching = 0;
|
|
size_t flushed_eliminated = 0;
|
|
#endif
|
|
const flags *flags = solver->flags;
|
|
watches *all_watches = solver->watches;
|
|
for (all_stack (litwatch, litwatch, *binaries))
|
|
{
|
|
const unsigned first = litwatch.lit;
|
|
watch watch = litwatch.watch;
|
|
const unsigned second = watch.binary.lit;
|
|
const unsigned first_idx = IDX (first);
|
|
const unsigned second_idx = IDX (second);
|
|
if (!flags[first_idx].eliminated && !flags[second_idx].eliminated)
|
|
{
|
|
watches *first_watches = all_watches + first;
|
|
PUSH_WATCHES (*first_watches, watch);
|
|
watches *second_watches = all_watches + second;
|
|
watch.binary.lit = first;
|
|
PUSH_WATCHES (*second_watches, watch);
|
|
#ifdef LOGGING
|
|
resumed_watching++;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
const bool redundant = watch.binary.redundant;
|
|
const bool hyper = watch.binary.hyper;
|
|
kissat_delete_binary (solver, redundant, hyper, first, second);
|
|
#ifdef LOGGING
|
|
flushed_eliminated++;
|
|
#endif
|
|
}
|
|
}
|
|
LOG ("resumed watching %zu binary clauses flushed %zu eliminated",
|
|
resumed_watching, flushed_eliminated);
|
|
}
|
|
|
|
static void
|
|
completely_resume_watching_binaries (kissat * solver, litwatches * binaries)
|
|
{
|
|
assert (binaries);
|
|
#ifdef LOGGING
|
|
size_t resumed_watching = 0;
|
|
#endif
|
|
watches *all_watches = solver->watches;
|
|
for (all_stack (litwatch, litwatch, *binaries))
|
|
{
|
|
const unsigned first = litwatch.lit;
|
|
watch watch = litwatch.watch;
|
|
const unsigned second = watch.binary.lit;
|
|
assert (!ELIMINATED (IDX (first)));
|
|
assert (!ELIMINATED (IDX (second)));
|
|
watches *first_watches = all_watches + first;
|
|
PUSH_WATCHES (*first_watches, watch);
|
|
watches *second_watches = all_watches + second;
|
|
watch.binary.lit = first;
|
|
PUSH_WATCHES (*second_watches, watch);
|
|
#ifdef LOGGING
|
|
resumed_watching++;
|
|
#endif
|
|
}
|
|
LOG ("resumed watching %zu binary clauses", resumed_watching);
|
|
}
|
|
|
|
static void
|
|
resume_watching_irredundant_binaries (kissat * solver, litpairs * binaries)
|
|
{
|
|
assert (binaries);
|
|
#ifdef LOGGING
|
|
size_t resumed_watching = 0;
|
|
#endif
|
|
watches *all_watches = solver->watches;
|
|
for (all_stack (litpair, litpair, *binaries))
|
|
{
|
|
const unsigned first = litpair.lits[0];
|
|
const unsigned second = litpair.lits[1];
|
|
|
|
assert (!ELIMINATED (IDX (first)));
|
|
assert (!ELIMINATED (IDX (second)));
|
|
|
|
watches *first_watches = all_watches + first;
|
|
watch first_watch = kissat_binary_watch (second, false, false);
|
|
PUSH_WATCHES (*first_watches, first_watch);
|
|
|
|
watches *second_watches = all_watches + second;
|
|
watch second_watch = kissat_binary_watch (first, false, false);
|
|
PUSH_WATCHES (*second_watches, second_watch);
|
|
|
|
#ifdef LOGGING
|
|
resumed_watching++;
|
|
#endif
|
|
}
|
|
LOG ("resumed watching %zu binary clauses", resumed_watching);
|
|
}
|
|
|
|
static void
|
|
resume_watching_large_clauses_after_elimination (kissat * solver)
|
|
{
|
|
#ifdef LOGGING
|
|
size_t resumed_watching_redundant = 0;
|
|
size_t resumed_watching_irredundant = 0;
|
|
#endif
|
|
const flags *flags = solver->flags;
|
|
watches *watches = solver->watches;
|
|
const value *values = solver->values;
|
|
const assigned *assigned = solver->assigned;
|
|
const word *arena = BEGIN_STACK (solver->arena);
|
|
|
|
for (all_clauses (c))
|
|
{
|
|
if (c->garbage)
|
|
continue;
|
|
bool collect = false;
|
|
for (all_literals_in_clause (lit, c))
|
|
{
|
|
if (values[lit] > 0)
|
|
{
|
|
LOGCLS (c, "%s satisfied", LOGLIT (lit));
|
|
collect = true;
|
|
break;
|
|
}
|
|
const unsigned idx = IDX (lit);
|
|
if (flags[idx].eliminated)
|
|
{
|
|
LOGCLS (c, "containing eliminated %s", LOGLIT (lit));
|
|
collect = true;
|
|
break;
|
|
}
|
|
}
|
|
if (collect)
|
|
{
|
|
kissat_mark_clause_as_garbage (solver, c);
|
|
continue;
|
|
}
|
|
|
|
assert (c->size > 2);
|
|
|
|
unsigned *lits = c->lits;
|
|
kissat_sort_literals (solver, values, assigned, c->size, lits);
|
|
c->searched = 2;
|
|
|
|
const reference ref = (word *) c - arena;
|
|
const unsigned l0 = lits[0];
|
|
const unsigned l1 = lits[1];
|
|
|
|
kissat_push_blocking_watch (solver, watches + l0, l1, ref);
|
|
kissat_push_blocking_watch (solver, watches + l1, l0, ref);
|
|
|
|
#ifdef LOGGING
|
|
if (c->redundant)
|
|
resumed_watching_redundant++;
|
|
else
|
|
resumed_watching_irredundant++;
|
|
#endif
|
|
}
|
|
LOG ("resumed watching %zu irredundant and %zu redundant large clauses",
|
|
resumed_watching_irredundant, resumed_watching_redundant);
|
|
}
|
|
|
|
void
|
|
kissat_resume_sparse_mode (kissat * solver, bool flush_eliminated,
|
|
litpairs * irredundant, litwatches * redundant)
|
|
{
|
|
assert (!solver->level);
|
|
assert (!solver->watching);
|
|
if (solver->inconsistent)
|
|
return;
|
|
LOG ("resuming sparse mode watching clauses");
|
|
kissat_flush_large_connected (solver);
|
|
LOG ("switched to watching clauses");
|
|
solver->watching = true;
|
|
if (irredundant)
|
|
{
|
|
LOG ("resuming watching %zu irredundant binaries",
|
|
SIZE_STACK (*irredundant));
|
|
resume_watching_irredundant_binaries (solver, irredundant);
|
|
}
|
|
if (redundant)
|
|
{
|
|
LOG ("resuming watching %zu redundant binaries",
|
|
SIZE_STACK (*redundant));
|
|
if (flush_eliminated)
|
|
resume_watching_binaries_after_elimination (solver, redundant);
|
|
else
|
|
completely_resume_watching_binaries (solver, redundant);
|
|
}
|
|
if (flush_eliminated)
|
|
resume_watching_large_clauses_after_elimination (solver);
|
|
else
|
|
kissat_watch_large_clauses (solver);
|
|
LOG ("forcing to propagate units on all clauses");
|
|
solver->propagated = 0;
|
|
|
|
clause *conflict;
|
|
if (solver->probing)
|
|
conflict = kissat_probing_propagate (solver, 0);
|
|
else
|
|
conflict = kissat_search_propagate (solver);
|
|
if (conflict)
|
|
{
|
|
LOG ("conflict during propagation after resuming sparse mode");
|
|
solver->inconsistent = true;
|
|
CHECK_AND_ADD_EMPTY ();
|
|
ADD_EMPTY_TO_PROOF ();
|
|
}
|
|
else if (solver->unflushed)
|
|
kissat_flush_trail (solver);
|
|
}
|