-
Notifications
You must be signed in to change notification settings - Fork 33
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
Invalid SAT environment while optimizing #1023
Comments
Another solution (a bit better in terms of performance I guess) consists in using a different kind of guards to protect the environments during the exploration for optimization. These guards won't appear in the |
That is an interesting point! Sounds like we indeed need to Hence I'm not sure there is much value in replaying the decision trail, in which case we can simply use an internal guard for optimization and
Can you expand on that? I don't understand how that would work. |
I agree we don't need to support incremental asserting after optimization.
After consideration, it seems my idea doesn't work in some specific cases. Let's imagine we discover a contradiction after adding three new assertions during the optimization: let env = SAT.empty () in
(* We assert the original problem. *)
SAT.assume ...
...
(* Beginning the optimization in SatML here. *)
try
SAT.push env 1;
SAT.assume env A1;
SAT.unsat env;
SAT.assume env A2;
SAT.unsat env;
SAT.assume env A3;
SAT.unsat env; (* <- We got an exception here. *)
SAT.pop env 1; (* Not called in this example. *)
with Unsat ->
let mdl = env.last_saved_model in
let objs = env.last_saved_objectives in
SAT.pop env 1;
env.last_saved_model <- mdl;
env.last_saved_objectives <- objs The environment The current implementation of the let pop env to_pop =
Util.loop
~f:(fun _n () () ->
SAT.pop env.satml;
let guard_to_neg = Stack.pop env.guards.stack_guard in
let inst = Inst.pop ~guard:guard_to_neg env.inst in
assert (not (Stack.is_empty env.guards.stack_guard));
let b = Stack.top env.guards.stack_guard in
Steps.pop_steps ();
env.last_saved_model <- None;
env.last_saved_objectives <- None;
env.inst <- inst;
env.guards.current_guard <- b
)
~max:to_pop
~elt:()
~init:() In fact, I don't see any good reason to remove the model in this function. If we use |
Are you talking about the example above with
Not sure if it is that ugly, but it's not sufficient in the presence of (Now that I think about it — I believe the needed information should be guaranteed to be in the model after #1019 and #957 and we could stop using the
Is this really true?
|
No, I was talking about an idea in my mind. The example above should work indeed.
Really? I thought the function |
Ok, we have to optimize from scratch after each |
It does restore the state of the trail prior to the |
Uhm, I see :/ |
The current implementation of
unsat_rec_prem
is wrong in presence of optimization if we try to use the SAT API directly. Consider the input problem:This problem is SAT and we expect to be able to reuse the environment after the
(check-sat)
statement. If we use the Dolmen frontend, it's okay because we throw away the previous environment and produce a fresh environment with all the assertions before each(check-sat)
.If we use the imperative SAT API, we want to write:
But the current implementation will raise the exception
Unsat
during the last statement. The reason is simple: inanalyze_unknown_for_objectives
we call again the solver until getting an unsatisfiable context. In other words, in presence of optimization, the environmentenv
after callingSAT.unsat
is alwaysunsatisfiable
. In the previous example, it will contain both the assertionsx <= 10
andx > 10
.A naive solution consists in protecting the penultimate environment by using the push/pop mechanism and retrieve the model and objectives values produced before popping. Notice that we shouldn't produce an environment with extra push levels, otherwise the behaviour of the
pop
statement will be wrong after callingSAT.unsat
.To implement this solution, we can save the new assertions discovered in
analyze_unknown_for_objectives
in a stack, perform a(push 1)
and a(pop 1)
around theassume
andunsat
inunsat_rec_prem
and after getting anunsat
exception, get the tail of the stack and assert it without push/pop around it.If you have a better solution, I'll be glad to implement it ;)
The text was updated successfully, but these errors were encountered: