-
Notifications
You must be signed in to change notification settings - Fork 84
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
Variables created during propagator initialization are not frozen and might be eliminated by preprocessing. #226
Comments
Could bring it down to
calling with enumerating all models |
I think that this is a bug in clasp. If I run this with valgrind, I get a bug while a conflict is analyzed. @BenKaufmann can you please have a look? The example is luckily tiny:
|
For easy reproduction: #!/usr/bin/bash
j=`grep processor /proc/cpuinfo | wc -l`
git clone https://github.com/potassco/clingo.git --recursive
git clone https://github.com/potassco/clingcon.git
cmake -Hclingo -Bbuild/clingo -DCMAKE_BUILD_TYPE=Debug -DPYCLINGO_USER_INSTALL=Off -DPYCLINGO_USE_INSTALL_PREFIX=On -DCMAKE_INSTALL_PREFIX=install
cmake --build build/clingo --target install -j${j}
cmake -Hclingcon -Bbuild/clingcon -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=install
cmake --build build/clingcon --target install -j${j}
./install/bin/clingcon --conf=jumpy 0 <<EOF
{b;c}.
&sum{a} = 2 :- b.
&sum{a} = 3 :- c.
EOF |
Interesting. Seems to be related to sat-preprocessing.
works fine, while
also results in an assertion. |
This is not really a bug in clasp but more a manifestation of undefined behaviour due to a precondition violation. clingcon adds new variables that are relevant in "theory constraints" but does not explicitly mark these as frozen. clasp's sat-preprocessor otoh assumes that all variables that are not explicitly marked as frozen only occur in the set of currently known clauses and can therefore be eliminated by clause distribution (among other things). Once a variable has been eliminated, it is assumed that it is no longer part of any (explicit or implicit) constraint. One easy fix for this problem would be to change clingo's Potassco::Lit_t addLiteral() override {
auto v = facade_().ctx.addVar(Clasp::Var_t::Atom);
facade_().ctx.setFrozen(v, true);
return Clasp::encodeLit(Clasp::posLit(v));
} Alternatively, one could come up with a more fine-grained approach, e.g. by freezing only those variables for which |
I guess that from a clingcon perspective, we would have to freeze all variables anyway except if we translate all constraints to clauses during propagate init. What do you think about adding a flag to And one more general question. Do you think it is necessary in general that a propagator freezes variables it wants to add constraints over? |
I think an explicit flag is definitely better than some implicit heuristic. But I would only add it if you think that "eagerly translating all constraints up front" is a relevant use-case. Otherwise, I would probably just unconditionally freeze all variables added via PropagateInit.
Yes. However, you only have to freeze variables that are added during initialization (PropagateInit). Solver-local variables added via PropagateControl are not subject to sat-preprocessing. |
In clingcon we have the use case. There are some variables that a solver has to watch and some that are just auxiliary variables that could be resolved away.
We also have propagators that do not add any variables at all but just use variables associated with atoms. I wanted to ask if those variables have to be frozen as well if the propagator wants to add clauses over them? |
Yes. But clasp already marks all variables associated with input atoms as frozen if program updates are enabled via |
I see. In clingo this is atm always enabled. But I was thinking to provide a way to disable program updates because a lot of users were asking for a mode where the library would behave exactly as clasp's single shot solving. What do you think about the following? We freeze variables added during propagator initialization if program updates are enabled and otherwise don't. In the API, I can add a function to freeze variables and to disable program updates. This gives experts the possibility to tune single-shot solving even with propagators and there are fewer pitfalls in the standard case. |
Sounds reasonable to me. |
I think I don't even need your help to implement this. This can all be done in clingo. At least I hope so. I'll let you know if I need anything. Thanks for having a look. |
Thanks guys, this sounds awesome. |
I cannot provide an option to disable program updates because the clingo API needs access to program literals from the logic program in the model callback (and there is no (reasonable) way around this). I will simply provide EDIT: Providing an |
@BenKaufmann I had a look at clasp's facade. Currently EDIT: If none of this is viable, I would simply not provide single-shot solving and leave it at 1a8512c. |
Initializing
Clasp does not freeze "output" atoms and eliminated variables are not part of a solver assignment. However, models are always extended to all variables and hence also contain an assignment for eliminated variables. |
I thought that initializing
This would mean that in mode b) I would also have to adjust the cleanup function because I can no longer assume that a program literal is associated with a valid solver literal. It looks like this feature would require quite a lot of testing on my side. Maybe better skip it. void ClingoControl::cleanup() {
if (!clingoMode_ || !canClean_) {
return;
}
canClean_ = false;
Clasp::Asp::LogicProgram &prg = static_cast<Clasp::Asp::LogicProgram&>(*clasp_->program());
Clasp::Solver &solver = *clasp_->ctx.master();
auto assignment = [&prg, &solver](unsigned uid) {
Potassco::Value_t truth{Potassco::Value_t::Free};
bool external{false};
if (prg.validAtom(uid)) {
external = prg.isExternal(uid);
Clasp::Literal lit = prg.getLiteral(uid);
if (solver.isTrue(lit)) { truth = Potassco::Value_t::True; }
else if (solver.isFalse(lit)) { truth = Potassco::Value_t::False; }
}
return std::make_pair(external, truth);
};
auto stats = out_->simplify(assignment);
LOG << stats.first << " atom" << (stats.first == 1 ? "" : "s") << " became facts" << std::endl;
LOG << stats.second << " atom" << (stats.second == 1 ? "" : "s") << " deleted" << std::endl;
} |
I am keeping it simple. Closing this. |
bug.zip
While calling
clingcon encoding.lp types.lp test.lp --stats 0
gives the expected results
adding any
--conf=XXX
like jumpy results in a segfault.The text was updated successfully, but these errors were encountered: