215 lines
5.7 KiB
C
215 lines
5.7 KiB
C
|
#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--;
|
||
|
}
|