2023-03-26 19:15:17 +08:00

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