sidekick/src/core/external.ml
Guillaume Bury b4d62d6f3b [breaking] Changed if_sat interface
In Plugin, and Theory, if_sat function now has the same type as assume
Additionally, some insertions into the heap have been moved to avoid
some unnecessary operations.
2016-11-16 17:33:10 +01:00

165 lines
4.8 KiB
OCaml

(*
MSAT is free software, using the Apache license, see file LICENSE
Copyright 2016 Guillaume Bury
Copyright 2016 Simon Cruanes
*)
module type S = Solver_intf.S
type ('term, 'form) sat_state = ('term, 'form) Solver_intf.sat_state = {
eval: 'form -> bool;
(** Returns the valuation of a formula in the current state
of the sat solver.
@raise UndecidedLit if the literal is not decided *)
eval_level: 'form -> bool * int;
(** Return the current assignement of the literals, as well as its
decision level. If the level is 0, then it is necessary for
the atom to have this value; otherwise it is due to choices
that can potentially be backtracked.
@raise UndecidedLit if the literal is not decided *)
iter_trail : ('form -> unit) -> ('term -> unit) -> unit;
(** Iter thorugh the formulas and terms in order of decision/propagation
(starting from the first propagation, to the last propagation). *)
model: unit -> ('term * 'term) list;
(** Returns the model found if the formula is satisfiable. *)
}
type ('clause, 'proof) unsat_state = ('clause, 'proof) Solver_intf.unsat_state = {
unsat_conflict : unit -> 'clause;
(** Returns the unsat clause found at the toplevel *)
get_proof : unit -> 'proof;
(** returns a persistent proof of the empty clause from the Unsat result. *)
}
module Make
(St : Solver_types.S)
(Th : Plugin_intf.S with type term = St.term
and type formula = St.formula
and type proof = St.proof)
(Dummy : sig end) = struct
module St = St
module S = Internal.Make(St)(Th)(struct end)
module Proof = S.Proof
exception UndecidedLit = S.UndecidedLit
type atom = St.formula
type clause = St.clause
type proof = Proof.proof
(* Result type *)
type res =
| Sat of (St.term,St.formula) sat_state
| Unsat of (St.clause,Proof.proof) unsat_state
let pp_all lvl =
Log.debugf lvl
"@[<v>Full resume:@,@[<hov 2>Trail:@\n%a@]@,@[<hov 2>Temp:@\n%a@]@,@[<hov 2>Hyps:@\n%a@]@,@[<hov 2>Lemmas:@\n%a@]@,]@."
(fun k -> k
(Vec.print ~sep:"" St.pp) (S.trail ())
(Vec.print ~sep:"" St.pp_clause) (S.temp ())
(Vec.print ~sep:"" St.pp_clause) (S.hyps ())
(Vec.print ~sep:"" St.pp_clause) (S.history ())
)
let mk_sat () : (_,_) sat_state =
pp_all 99;
let t = S.trail () in
let iter f f' =
Vec.iter (function
| St.Atom a -> f a.St.lit
| St.Lit l -> f' l.St.term
) t
in
{
eval = S.eval;
eval_level = S.eval_level;
iter_trail = iter;
model = S.model;
}
let mk_unsat () : (_,_) unsat_state =
pp_all 99;
let unsat_conflict () =
match S.unsat_conflict () with
| None -> assert false
| Some c -> c
in
let get_proof () =
let c = unsat_conflict () in
S.Proof.prove_unsat c
in
{ unsat_conflict; get_proof; }
(* Wrappers around internal functions*)
let assume = S.assume
let solve ?(assumptions=[]) () =
try
S.pop ();
S.push ();
S.local assumptions;
S.solve ();
Sat (mk_sat())
with S.Unsat ->
Unsat (mk_unsat())
let unsat_core = S.Proof.unsat_core
let true_at_level0 a =
try
let b, lev = S.eval_level a in
b && lev = 0
with S.UndecidedLit -> false
let get_tag cl = St.(cl.tag)
let export_dimacs fmt () =
(* Local assertions *)
let tmp = S.temp () in
assert (Vec.for_all (function
| { St.cpremise = St.Local; _} -> true | _ -> false
) tmp);
(* Problem hypothses *)
let hyps = S.hyps () in
assert (Vec.for_all (function
| { St.cpremise = St.Hyp; _} -> true | _ -> false
) hyps);
(* Learnt clauses, then filtered to only keep only
the theory lemmas; all other learnt clauses should be logical
consequences of the rest. *)
let learnt = S.history () in
let lemmas = Vec.make (Vec.size learnt) St.dummy_clause in
Vec.iter (fun c ->
match c.St.cpremise with
| St.Hyp | St.Local -> assert false
| St.Lemma _ -> Vec.push lemmas c
| St.History l ->
begin match l with
| [] -> assert false
| d :: _ ->
begin match d.St.cpremise with
| St.Lemma _ -> Vec.push lemmas d
| St.Hyp | St.Local | St.History _ -> ()
end
end
) learnt;
(* Number of atoms and clauses *)
let n = St.nb_elt () in
let m = Vec.size tmp + Vec.size hyps + Vec.size lemmas in
(* Actual printing *)
let pp s fmt vec =
Format.fprintf fmt "c %s@,%a@," s (Vec.print ~sep:"" St.pp_dimacs) vec
in
Format.fprintf fmt
"@[<v>p cnf %d %d@,%a%a%a@]@."
n m
(pp "Local assumptions") tmp
(pp "Hypotheses") hyps
(pp "Lemmas") lemmas
end