sebfisch / incremental-sat-solver

Simple, Incremental SAT Solving as a Haskell Library

Home Page:http://github.com/sebfisch/incremental-sat-solver

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Semantics of assertTrue is not clear

UnkindPartition opened this issue · comments

  1. Can assertTrue return non-deterministic results (i.e. use mplus)? If yes, this is not obvious form the docs. If no, I think it would be better for it to use Maybe instead of arbitrary MonadPlus to emphasize that fact.
  2. If assertTrue does not fail, does it guarantee that solve will not fail?

I've just had a quick look at the source code, and it looks like the monad m is not just a part of the interface, but is actually used for backtracking. That also should be documented, since the choice of m can impact correctness of the algorithm.

How about choosing a particular monad (such as LogicT) and making it abstract?

I am not in favour of picking a particular MonadPlus instance. I left it intentionally unspecified to allow different (for example parallel) implementations. But I take your point that correctness may depend on which instance one choses. This is because the laws for MonadPlus are not agreed upon (e.g. distributivity vs left catch) and I will make more clear, which laws are required for correctness. Currently, I believe it's distributivity.

Regarding your first question: assertTrue does not backtrack, so MonadZero (if it would exist) would be enough. I am hesitant to fix the type to Maybe to allow for different possible implementations. But I will rethink this decision and will at least update the documentation to say that no backtracking is involved.

Regarding your second question: there are formulas where assertTrue does not fail but solve will fail afterwards. This always happens when the solver only finds the failure after backtracking which assertTrue does not use. If you want to make sure that the solver is still in a solvable state, use isSolvable. An example for a formula that requires backtracking is (x && not x) || (y && not y). See an old blog post that discusses the difference between using backtracking and not using it. I will update the documentation to make more clear where backtracking is used and where it isn't.