cloud-sat/kissat-inc/src/strengthen.c

215 lines
5.7 KiB
C
Raw Normal View History

2022-08-30 15:42:35 +08:00
#include "inline.h"
#include "promote.h"
#include "strengthen.h"
static clause *
large_on_the_fly_strengthen (kissat * solver, clause * c, unsigned lit)
{
assert (solver->antecedent_size > 3);
LOGCLS (c, "large on-the-fly strengthening "
"by removing %s from", LOGLIT (lit));
unsigned *lits = c->lits;
assert (lits[0] == lit || lits[1] == lit);
INC (on_the_fly_strengthened);
#ifndef NDEBUG
clause *old_next = kissat_next_clause (c);
#endif
if (lits[0] == lit)
SWAP (unsigned, lits[0], lits[1]);
assert (lits[1] == lit);
const reference ref = kissat_reference_clause (solver, c);
kissat_unwatch_blocking (solver, lit, ref);
SHRINK_CLAUSE_IN_PROOF (c, lit, lits[0]);
CHECK_SHRINK_CLAUSE (c, lit, lits[0]);
{
const unsigned old_size = c->size;
unsigned new_size = 1;
const bool irredundant = !c->redundant;
for (unsigned i = 2; i < old_size; i++)
{
const unsigned other = lits[i];
assert (VALUE (other) < 0);
if (!LEVEL (other))
continue;
lits[new_size++] = other;
if (irredundant)
kissat_mark_added_literal (solver, other);
}
assert (new_size > 2);
c->size = new_size;
c->searched = 2;
if (c->redundant && c->glue >= new_size)
kissat_promote_clause (solver, c, new_size - 1);
if (!c->shrunken)
{
c->shrunken = true;
lits[old_size - 1] = INVALID_LIT;
}
}
LOGCLS (c, "unsorted on-the-fly strengthened");
{
assert (VALUE (lits[1]) < 0);
unsigned highest_pos = 1;
unsigned highest_level = LEVEL (lits[1]);
const unsigned size = c->size;
for (unsigned i = 2; i < size; i++)
{
const unsigned other = lits[i];
assert (VALUE (other) < 0);
const unsigned level = LEVEL (other);
if (level <= highest_level)
continue;
highest_pos = i;
highest_level = level;
}
if (highest_pos != 1)
SWAP (unsigned, lits[1], lits[highest_pos]);
LOGCLS (c, "sorted on-the-fly strengthened");
kissat_watch_blocking (solver, lits[1], lits[0], ref);
}
{
watches *watches = &WATCHES (lits[0]);
#ifndef NDEBUG
const watch *end_of_watches = END_WATCHES (*watches);
#endif
watch *p = BEGIN_WATCHES (*watches);
assert (solver->watching);
for (;;)
{
assert (p != end_of_watches);
const watch head = *p++;
if (head.type.binary)
continue;
assert (p != end_of_watches);
const watch tail = *p++;
if (tail.large.ref == ref)
break;
}
p[-2].blocking.lit = lits[1];
LOGREF (ref, "updating watching %s now blocking %s in",
LOGLIT (lits[0]), LOGLIT (lits[1]));
}
#ifndef NDEBUG
clause *new_next = kissat_next_clause (c);
assert (old_next == new_next);
#endif
LOGCLS (c, "conflicting");
INC (conflicts);
return c;
}
static clause *
binary_on_the_fly_strengthen (kissat * solver, clause * c, unsigned lit)
{
assert (solver->antecedent_size == 3);
LOGCLS (c, "binary on-the-fly strengthening "
"by removing %s from", LOGLIT (lit));
unsigned first = INVALID_LIT, second = INVALID_LIT;
#ifndef NDEBUG
bool found = false;
#endif
for (all_literals_in_clause (other, c))
{
if (other == lit)
{
#ifndef NDEBUG
assert (!found);
found = true;
#endif
continue;
}
assert (VALUE (other) < 0);
if (!LEVEL (other))
continue;
if (first == INVALID_LIT)
first = other;
else
{
assert (second == INVALID_LIT);
second = other;
#ifndef NDEBUG
break;
#endif
}
}
assert (found);
assert (second != INVALID_LIT);
const bool redundant = c->redundant;
LOGBINARY (first, second, "on-the-fly strengthened");
kissat_new_binary_clause (solver, redundant, first, second);
const reference ref = kissat_reference_clause (solver, c);
kissat_unwatch_blocking (solver, c->lits[0], ref);
kissat_unwatch_blocking (solver, c->lits[1], ref);
kissat_mark_clause_as_garbage (solver, c);
clause *conflict =
kissat_binary_conflict (solver, redundant, first, second);
INC (conflicts);
return conflict;
}
clause *
kissat_on_the_fly_strengthen (kissat * solver, clause * c, unsigned lit)
{
assert (!c->garbage);
assert (solver->antecedent_size > 2);
if (!c->redundant)
kissat_mark_removed_literal (solver, lit);
clause *res;
if (solver->antecedent_size == 3)
res = binary_on_the_fly_strengthen (solver, c, lit);
else
res = large_on_the_fly_strengthen (solver, c, lit);
return res;
}
void
kissat_on_the_fly_subsume (kissat * solver, clause * c, clause * d)
{
LOGCLS (c, "on-the-fly subsuming");
LOGCLS (d, "on-the-fly subsumed");
assert (c != d);
assert (!d->garbage);
assert (c->size > 1);
assert (c->size <= d->size);
kissat_mark_clause_as_garbage (solver, d);
INC (on_the_fly_subsumed);
if (d->redundant)
return;
if (!c->redundant)
return;
if (c->size == 2)
{
assert (c == &solver->conflict);
const unsigned *lits = c->lits;
LOGBINARY (lits[0], lits[1], "turned irredundant");
for (unsigned i = 0; i < 2; i++)
{
const unsigned lit = lits[i];
watches *watches = &WATCHES (lit);
watch *p = LAST_WATCH_POINTER (*watches);
assert (p->type.binary);
assert (p->binary.redundant);
assert (p->binary.lit == lits[!i]);
p->binary.redundant = false;
assert (!p->binary.hyper);
}
}
else
{
c->redundant = false;
LOGCLS (c, "turned");
clause *last_irredundant = kissat_last_irredundant_clause (solver);
if (!last_irredundant || last_irredundant < c)
{
LOGCLS (c, "updating last irredundant clause as");
reference ref = kissat_reference_clause (solver, c);
solver->last_irredundant = ref;
}
}
statistics *statistics = &solver->statistics;
assert (statistics->clauses_irredundant < UINT64_MAX);
statistics->clauses_irredundant++;
assert (statistics->clauses_redundant > 0);
statistics->clauses_redundant--;
}