Better interface for Msat.Internal

This commit is contained in:
Guillaume Bury 2016-07-29 15:45:24 +02:00
parent 38a6d8c481
commit 9d6634d621
4 changed files with 73 additions and 55 deletions

View file

@ -48,12 +48,11 @@ module Make
type clause = St.clause type clause = St.clause
type proof = Proof.proof type proof = Proof.proof
(* Result type *)
type res = type res =
| Sat of (St.term,St.formula) sat_state | Sat of (St.term,St.formula) sat_state
| Unsat of (St.clause,Proof.proof) unsat_state | Unsat of (St.clause,Proof.proof) unsat_state
let assume ?tag l = S.assume ?tag l
let mk_sat () : (_,_) sat_state = let mk_sat () : (_,_) sat_state =
{ model=S.model; eval=S.eval; eval_level=S.eval_level } { model=S.model; eval=S.eval; eval_level=S.eval_level }
@ -68,9 +67,18 @@ module Make
in in
{ unsat_conflict; get_proof; } { unsat_conflict; get_proof; }
let solve ?assumptions () = (* Wrappers around internal functions*)
let assume ?tag l =
try try
S.solve ?assumptions (); S.assume ?tag l
with S.Unsat -> ()
let solve ?(assumptions=[]) () =
try
S.pop ();
S.push ();
S.local assumptions;
S.solve ();
Sat (mk_sat()) Sat (mk_sat())
with S.Unsat -> with S.Unsat ->
Unsat (mk_unsat()) Unsat (mk_unsat())

View file

@ -1064,52 +1064,13 @@ module Make
| Atom _ -> acc) | Atom _ -> acc)
[] env.elt_queue [] env.elt_queue
(* push a series of assumptions to the stack *)
let push_assumptions =
List.iter
(fun lit ->
let a = atom lit in
Log.debugf 10 "push assumption %a" (fun k->k pp_atom a);
if a.is_true then ()
else if a.neg.is_true then (
(* conflict between assumptions: UNSAT *)
let c = make_clause (fresh_hname ()) [a] Hyp in
report_unsat c;
) else (
(* make a decision, propagate *)
new_decision_level();
let level = decision_level() in
assert (env.base_level = level-1);
env.base_level <- level;
let c = make_clause (fresh_hname ()) [a] Hyp in
enqueue_bool a ~level (Bcp c);
match propagate () with
| Some confl -> (* Conflict *)
report_unsat confl;
| None -> ()
))
(* clear assumptions *)
let pop_assumptions (): unit =
env.base_level <- 0; (* before the [cancel_until]! *)
cancel_until 0;
()
(* fixpoint of propagation and decisions until a model is found, or a (* fixpoint of propagation and decisions until a model is found, or a
conflict is reached *) conflict is reached *)
let solve ?(assumptions=[]) (): unit = let solve (): unit =
Log.debug 5 "solve"; Log.debug 5 "solve";
if env.base_level > 0 then (
pop_assumptions();
env.unsat_conflict <- None;
);
if is_unsat () then raise Unsat; if is_unsat () then raise Unsat;
let n_of_conflicts = ref (to_float env.restart_first) in let n_of_conflicts = ref (to_float env.restart_first) in
let n_of_learnts = ref ((to_float (nb_clauses())) *. env.learntsize_factor) in let n_of_learnts = ref ((to_float (nb_clauses())) *. env.learntsize_factor) in
(* return to level 0 before pushing assumptions *)
cancel_until 0;
push_assumptions assumptions;
assert (env.base_level <= List.length assumptions);
try try
while true do while true do
begin try begin try
@ -1132,10 +1093,6 @@ module Make
with Sat -> () with Sat -> ()
let assume ?tag cnf = let assume ?tag cnf =
if env.base_level > 0 then (
pop_assumptions ();
env.unsat_conflict <- None;
);
List.iter List.iter
(fun l -> (fun l ->
let atoms = List.rev_map atom l in let atoms = List.rev_map atom l in
@ -1143,6 +1100,52 @@ module Make
Stack.push c env.clauses_to_add) Stack.push c env.clauses_to_add)
cnf cnf
(* create a factice decision level for local assumptions *)
let push (): unit =
cancel_until env.base_level;
begin match propagate () with
| Some confl -> report_unsat confl
| None ->
new_decision_level ();
env.base_level <- env.base_level + 1;
assert (decision_level () = env.base_level)
end
(* pop the last factice decision level *)
let pop (): unit =
if env.base_level = 0 then ()
else begin
assert (env.base_level > 0);
env.unsat_conflict <- None;
env.base_level <- env.base_level - 1; (* before the [cancel_until]! *)
cancel_until env.base_level
end
(* Add local hyps to the current decision level *)
let local l =
let aux lit =
let a = atom lit in
Log.debugf 10 "local assumption: @[%a@]" (fun k->k pp_atom a);
assert (decision_level () = env.base_level);
if a.is_true then ()
else if a.neg.is_true then begin
(* conflict between assumptions: UNSAT *)
let c = make_clause (fresh_hname ()) [a] Hyp in
report_unsat c;
end else begin
(* make a decision, propagate *)
let level = decision_level() in
let c = make_clause (fresh_hname ()) [a] Hyp in
enqueue_bool a ~level (Bcp c);
end
in
assert (env.base_level > 0);
match env.unsat_conflict with
| None ->
cancel_until env.base_level;
List.iter aux l
| Some _ -> ()
let hyps () = env.clauses_hyps let hyps () = env.clauses_hyps
let history () = env.clauses_learnt let history () = env.clauses_learnt

View file

@ -18,14 +18,9 @@ module Make
module Proof : Res.S with module St = St module Proof : Res.S with module St = St
val solve : val solve : unit -> unit
?assumptions:St.formula list ->
unit ->
unit
(** Try and solves the current set of assumptions. (** Try and solves the current set of assumptions.
@return () if the current set of clauses is satisfiable @return () if the current set of clauses is satisfiable
@param assumptions list of additional local assumptions to make,
removed after the callback returns a value
@raise Unsat if a toplevel conflict is found *) @raise Unsat if a toplevel conflict is found *)
val assume : ?tag:int -> St.formula list list -> unit val assume : ?tag:int -> St.formula list list -> unit
@ -33,6 +28,18 @@ module Make
Modifies the sat solver state in place. Modifies the sat solver state in place.
@raise Unsat if a conflict is detect when adding the clauses *) @raise Unsat if a conflict is detect when adding the clauses *)
val push : unit -> unit
(** Create a decision level for local assumptions.
@raise Unsat if a conflict is detected in the current state. *)
val pop : unit -> unit
(** Pop a decision level for local assumptions. *)
val local : St.formula list -> unit
(** Add local assumptions
@param assumptions list of additional local assumptions to make,
removed after the callback returns a value *)
val eval : St.formula -> bool val eval : St.formula -> bool
(** Returns the valuation of a formula in the current state (** Returns the valuation of a formula in the current state
of the sat solver. of the sat solver.

View file

@ -29,7 +29,7 @@ type ('clause, 'proof) unsat_state = {
module type S = sig module type S = sig
(** {2 Internal modules} (** {2 Internal modules}
These are the internal modules used, you should probablynot use them These are the internal modules used, you should probably not use them
if you're not familiar with the internals of mSAT. *) if you're not familiar with the internals of mSAT. *)
module St : Solver_types.S module St : Solver_types.S