-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Core conflicts. #59
Comments
@rkaminsk |
I would think a) is fine because it is still "correct". We can document this as a caveat. I hope I am not wrong but I think splitting is not used very often anyway. |
* Add SolveHandle::unsatCore(). When a problem is unsat when solving under assumptions, this function returns a subset of the initial assumption literals that together made the problem unsat.
I implemented a first version in branch issue-59. However, I'm not convinced that this is really useful because without doing any subset minimization, the returned literals are probably just the initial assumptions. |
This is cool. I will put it into Clingo's SolveHandle class like you did. Having the possibility to minimize cores further would of course be nice, too. Having the ones that are already used in the uncore minimization would be nice. But one can also role one's own minimization strategy using multiple solve calls. |
I did a first throw at an implementation. Using the Python API one can write now: >>> import clingo
>>>
>>> ctl = clingo.Control()
>>> ctl.add("base", [], "{a;b;c}. :- a, b.")
>>> ctl.ground([("base", [])])
>>>
>>> assumptions = []
>>> for name in ("a", "b", "c"):
... assumptions.append(ctl.symbolic_atoms[clingo.Function(name)].literal)
...
>>> print(ctl.solve(assumptions=assumptions, on_core=lambda core: print(core)))
[1, 2]
UNSAT There are still some issues though. It looks like for empty cores Another thing is that the core is returned in terms of solver literals. For the interface, I need program literals. I had to write quite some ugly code (that is not even fully working yet) to do the mapping. Would it be possible to get a little help from Can you have a look at the feature/core branch in the clingo repository, please? PS: I additionally added a callback because this is easier to use in Python. There is a |
Ok. My idea was to return nullptr whenever the problem was not "unsat under assumptions" but I guess it makes more sense to only return a nullptr if the problem was not unsat at all.
Probably, I'll look into that. At least for the assumptions, we'll probably always have or can find a corresponding program literal. This is not the case for unsat-core based minimization, though. There, unsat cores nearly completely consist of solver-local aux variables. |
Thanks. Yes, here it should really work because the clingo API only allows for specifying assumptions as program literals. Maybe with a lower level interface it would also make sense to get solver literals. For example, if we had something like the enumerator in the API. |
* Let SolveAlgorithm::unsatCore() return an empty vector instead of a nullptr if problem is unconditionally unsat. * Add LogicProgram::extractCore() for mapping an unsat core of solver literals back to the corresponding program literals. * Add ClaspFacade::Summary::unsatCore().
@rkaminsk I pushed an update to the issue-59 branch. Let me know if you need anything more or if I can close the issue and merge the branch into dev. |
There is the corner case that someone might assume a fact to be false (or assume a false literal to be true). In this case I would expect to get a core with one literal but clasp reports an empty core. This happens, for example, in the snippet below. Can we fix this? #script (python)
import sys
from clingo import Function
def main(prg):
cores = []
prg.ground([("base", [])])
a = prg.symbolic_atoms[Function("a")].literal
prg.solve(assumptions=[-a], on_core=lambda core: cores.append(core))
assert cores[-1] == [-a]
#end.
a. |
That seems to do the trick. I did not thorough testing but my simple tests all go through now. |
* Add SolveHandle::unsatCore(). When a problem is unsat when solving under assumptions, this function returns a subset of the initial assumption literals that together made the problem unsat.
* Let SolveAlgorithm::unsatCore() return an empty vector instead of a nullptr if problem is unconditionally unsat. * Add LogicProgram::extractCore() for mapping an unsat core of solver literals back to the corresponding program literals. * Add ClaspFacade::Summary::unsatCore().
Merged to dev. |
When a problem is unsatisfiable when solving under assumptions, it would be nice if there were an interface to get a conflict clause that is a subset of the assumptions literals. A trivial example would be something like the following:
Program:
Solve call:
The above is not meant to be the final interface.
The text was updated successfully, but these errors were encountered: