When theory raises a conflict, it is analysed, and the backtracck clause
that result is added to the solver, however, I didn't find yet a
satisfying answer as to wether the original clause is implied (or not)
by this backtrack clause, so in order not to lose information, we also
add the original conflict clause when it comes from the theory (because
if not, then it comes from a conflict detected during propgation, so the
conflict clause is actually already attached).
In add_clause, a conflcit at level 0 raised Unsat, but was forgotten,
which is obviously incorrect as succesive solving of the same problem
would yield different results.
Indeed, the previous strategy was that late propagations didn't need to
be propagated since they already have been, however that may not be the
case as a conflict might arise during propagation. It manifested as a
bug when the conflict did *not* depend on local hyps, and was tragically
lost during popping.
In Plugin, and Theory, if_sat function now has the same type as assume
Additionally, some insertions into the heap have been moved to avoid
some unnecessary operations.
Previously a fix was introduced to mitigate the fact that some atoms
couldn't be propagated at level 0 because of local assumptions. However
that fix didn't take into account propagation that implicated the
already propagated atom: for instance consider an atom [a] propagted at
level 1 because of some local hyp, and then atoms [b] propagated at
level 1 because [a] is true in a clause [C = not a \/ b]. If we propagte
0 and modify its level in-place as done in the previous fix, then we
should also propagate [b] at level 0, which is hard. Instead of
modifying levels in place, we simply store unit clauses at level 0 in a
stack, which we transfer to the clauses to add when we pop local hyps.
When we enqueue an atom at level 0, we expect it to stay unconditionally
true whatever happens. However, if it happens that the atom is alrady
true at a level strictly greater than 0 (but lower than base_level),
then enqueue_bool would simply do nothing. To fix this, there is a new
function enqueue_root which modifies in place the level and reason of
the propagated atom if it is already true.
Additionally, enqueue_bool now requires that the atom be undecided,
since if it not (i.e if it is propagated while already decided) it is
most likely a bug.
When a new clause with only 1 atom is added with (usually
from simplifying a theory lemma), the usual strategy is to backtrack to
the base level, then propagate the atom. However, when the atom is
already false at base level, Unsat is raised, in which case the
information that the atom must be true is lost. To avoid that, the
single atom clause is simply pushed back in the stack of clauses to add,
so that it will be re-examined later.
Previously, the heap was not grown when adding local assumptions. This
lead to a bug whne backtracking: indeed when a local assumption was
backtracked, it was added to the (too small) heap, which then raised a
Sparse_vec exception.