Moved some type def outside Plugins/Theories

This commit is contained in:
Guillaume Bury 2016-07-08 14:29:45 +02:00
parent 46b621269c
commit eb2850caa6
6 changed files with 107 additions and 149 deletions

View file

@ -6,7 +6,9 @@ Copyright 2014 Simon Cruanes
module Make module Make
(St : Solver_types.S) (St : Solver_types.S)
(Th : Plugin_intf.S with type term = St.term and type formula = St.formula and type proof = St.proof) (Plugin : Plugin_intf.S with type term = St.term
and type formula = St.formula
and type proof = St.proof)
(Dummy: sig end) (Dummy: sig end)
= struct = struct
@ -25,7 +27,7 @@ module Make
(* User levels always refer to decision_level 0 *) (* User levels always refer to decision_level 0 *)
ul_elt_lvl : int; (* Number of atoms in trail at decision level 0 *) ul_elt_lvl : int; (* Number of atoms in trail at decision level 0 *)
ul_th_lvl : int; (* Number of atoms known by the theory at decicion level 0 *) ul_th_lvl : int; (* Number of atoms known by the theory at decicion level 0 *)
ul_th_env : Th.level; (* Theory state at level 0 *) ul_th_env : Plugin.level; (* Theory state at level 0 *)
ul_clauses : int; (* number of clauses *) ul_clauses : int; (* number of clauses *)
ul_learnt : int; (* number of learnt clauses *) ul_learnt : int; (* number of learnt clauses *)
} }
@ -48,7 +50,7 @@ module Make
elt_levels : int Vec.t; elt_levels : int Vec.t;
(* decision levels in [trail] *) (* decision levels in [trail] *)
th_levels : Th.level Vec.t; th_levels : Plugin.level Vec.t;
(* theory states corresponding to elt_levels *) (* theory states corresponding to elt_levels *)
user_levels : user_level Vec.t; user_levels : user_level Vec.t;
(* user-defined levels, for {!push} and {!pop} *) (* user-defined levels, for {!push} and {!pop} *)
@ -120,14 +122,14 @@ module Make
elt_queue = Vec.make 601 (of_atom dummy_atom); elt_queue = Vec.make 601 (of_atom dummy_atom);
elt_levels = Vec.make 601 (-1); elt_levels = Vec.make 601 (-1);
th_levels = Vec.make 100 Th.dummy; th_levels = Vec.make 100 Plugin.dummy;
user_levels = Vec.make 20 { user_levels = Vec.make 20 {
ul_elt_lvl = 0; ul_elt_lvl = 0;
ul_th_lvl = 0; ul_th_lvl = 0;
ul_learnt = 0; ul_learnt = 0;
ul_clauses = 0; ul_clauses = 0;
ul_th_env = Th.dummy; ul_th_env = Plugin.dummy;
}; };
order = Iheap.init 0; order = Iheap.init 0;
@ -199,7 +201,7 @@ module Make
let l = Vec.get env.elt_levels 0 in let l = Vec.get env.elt_levels 0 in
l, l l, l
and ul_th_env = and ul_th_env =
if Vec.is_empty env.th_levels then Th.current_level () if Vec.is_empty env.th_levels then Plugin.current_level ()
else Vec.get env.th_levels 0 else Vec.get env.th_levels 0
in in
(* Keep in mind what are the current assumptions. *) (* Keep in mind what are the current assumptions. *)
@ -230,7 +232,7 @@ module Make
List.iter f (Hashtbl.find iter_map v.vid) List.iter f (Hashtbl.find iter_map v.vid)
with Not_found -> with Not_found ->
let l = ref [] in let l = ref [] in
Th.iter_assignable (fun t -> l := add_term t :: !l) v.pa.lit; Plugin.iter_assignable (fun t -> l := add_term t :: !l) v.pa.lit;
Hashtbl.add iter_map v.vid !l; Hashtbl.add iter_map v.vid !l;
List.iter f !l List.iter f !l
@ -397,7 +399,7 @@ module Make
assert (env.th_head = Vec.size env.elt_queue); assert (env.th_head = Vec.size env.elt_queue);
assert (env.elt_head = Vec.size env.elt_queue); assert (env.elt_head = Vec.size env.elt_queue);
Vec.push env.elt_levels (Vec.size env.elt_queue); Vec.push env.elt_levels (Vec.size env.elt_queue);
Vec.push env.th_levels (Th.current_level ()); (* save the current tenv *) Vec.push env.th_levels (Plugin.current_level ()); (* save the current tenv *)
() ()
(* Attach/Detach a clause. (* Attach/Detach a clause.
@ -464,7 +466,7 @@ module Make
end end
done; done;
(* Recover the right theory state. *) (* Recover the right theory state. *)
Th.backtrack (Vec.get env.th_levels lvl); Plugin.backtrack (Vec.get env.th_levels lvl);
(* Resize the vectors according to their new size. *) (* Resize the vectors according to their new size. *)
Vec.shrink env.elt_queue ((Vec.size env.elt_queue) - env.elt_head); Vec.shrink env.elt_queue ((Vec.size env.elt_queue) - env.elt_head);
Vec.shrink env.elt_levels ((Vec.size env.elt_levels) - lvl); Vec.shrink env.elt_levels ((Vec.size env.elt_levels) - lvl);
@ -534,9 +536,9 @@ module Make
let th_eval a = let th_eval a =
if a.is_true || a.neg.is_true then None if a.is_true || a.neg.is_true then None
else match Th.eval a.lit with else match Plugin.eval a.lit with
| Th.Unknown -> None | Plugin_intf.Unknown -> None
| Th.Valued (b, lvl) -> | Plugin_intf.Valued (b, lvl) ->
let atom = if b then a else a.neg in let atom = if b then a else a.neg in
enqueue_bool atom lvl (Semantic lvl); enqueue_bool atom lvl (Semantic lvl);
Some b Some b
@ -812,8 +814,10 @@ module Make
let slice_get i = let slice_get i =
match Vec.get env.elt_queue i with match Vec.get env.elt_queue i with
| Either.Right a -> Th.Lit a.lit, a.var.v_level | Either.Right a ->
| Either.Left {l_level; term; assigned = Some v} -> Th.Assign (term, v), l_level Plugin_intf.Lit a.lit
| Either.Left {l_level; term; assigned = Some v} ->
Plugin_intf.Assign (term, v, l_level)
| Either.Left _ -> assert false | Either.Left _ -> assert false
let slice_push l lemma = let slice_push l lemma =
@ -828,21 +832,21 @@ module Make
Iheap.grow_to_by_double env.order (St.nb_elt ()); Iheap.grow_to_by_double env.order (St.nb_elt ());
enqueue_bool a lvl (Semantic lvl) enqueue_bool a lvl (Semantic lvl)
let current_slice () = Th.({ let current_slice () = {
start = env.th_head; Plugin_intf.start = env.th_head;
length = (Vec.size env.elt_queue) - env.th_head; length = (Vec.size env.elt_queue) - env.th_head;
get = slice_get; get = slice_get;
push = slice_push; push = slice_push;
propagate = slice_propagate; propagate = slice_propagate;
}) }
let full_slice () = Th.({ let full_slice () = {
start = 0; Plugin_intf.start = 0;
length = Vec.size env.elt_queue; length = Vec.size env.elt_queue;
get = slice_get; get = slice_get;
push = slice_push; push = slice_push;
propagate = (fun _ -> assert false); propagate = (fun _ -> assert false);
}) }
let rec theory_propagate () = let rec theory_propagate () =
assert (env.elt_head = Vec.size env.elt_queue); assert (env.elt_head = Vec.size env.elt_queue);
@ -851,10 +855,10 @@ module Make
else begin else begin
let slice = current_slice () in let slice = current_slice () in
env.th_head <- env.elt_head; env.th_head <- env.elt_head;
match Th.assume slice with match Plugin.assume slice with
| Th.Sat -> | Plugin_intf.Sat ->
propagate () propagate ()
| Th.Unsat (l, p) -> | Plugin_intf.Unsat (l, p) ->
let l = List.rev_map new_atom l in let l = List.rev_map new_atom l in
Iheap.grow_to_by_double env.order (St.nb_elt ()); Iheap.grow_to_by_double env.order (St.nb_elt ());
List.iter (fun a -> insert_var_order (elt_of_var a.var)) l; List.iter (fun a -> insert_var_order (elt_of_var a.var)) l;
@ -965,13 +969,13 @@ module Make
if v.v_level >= 0 then begin if v.v_level >= 0 then begin
assert (v.pa.is_true || v.na.is_true); assert (v.pa.is_true || v.na.is_true);
pick_branch_lit () pick_branch_lit ()
end else match Th.eval atom.lit with end else match Plugin.eval atom.lit with
| Th.Unknown -> | Plugin_intf.Unknown ->
env.decisions <- env.decisions + 1; env.decisions <- env.decisions + 1;
new_decision_level(); new_decision_level();
let current_level = decision_level () in let current_level = decision_level () in
enqueue_bool atom current_level Decision enqueue_bool atom current_level Decision
| Th.Valued (b, lvl) -> | Plugin_intf.Valued (b, lvl) ->
let a = if b then atom else atom.neg in let a = if b then atom else atom.neg in
enqueue_bool a lvl (Semantic lvl) enqueue_bool a lvl (Semantic lvl)
@ -987,7 +991,7 @@ module Make
if l.l_level >= 0 then if l.l_level >= 0 then
pick_branch_lit () pick_branch_lit ()
else begin else begin
let value = Th.assign l.term in let value = Plugin.assign l.term in
env.decisions <- env.decisions + 1; env.decisions <- env.decisions + 1;
new_decision_level(); new_decision_level();
let current_level = decision_level () in let current_level = decision_level () in
@ -1064,7 +1068,7 @@ module Make
n_of_conflicts := !n_of_conflicts *. env.restart_inc; n_of_conflicts := !n_of_conflicts *. env.restart_inc;
n_of_learnts := !n_of_learnts *. env.learntsize_inc n_of_learnts := !n_of_learnts *. env.learntsize_inc
| Sat -> | Sat ->
Th.if_sat (full_slice ()); Plugin.if_sat (full_slice ());
if is_unsat () then raise Unsat if is_unsat () then raise Unsat
else if env.elt_head = Vec.size env.elt_queue (* sanity check *) else if env.elt_head = Vec.size env.elt_queue (* sanity check *)
&& env.elt_head = St.nb_elt () (* this is the important test to know if the search is finished *) then && env.elt_head = St.nb_elt () (* this is the important test to know if the search is finished *) then
@ -1148,7 +1152,7 @@ module Make
end end
end end
done; done;
Th.backtrack th_env; (* recover the right theory env *) Plugin.backtrack th_env; (* recover the right theory env *)
Vec.shrink env.elt_queue ((Vec.size env.elt_queue) - env.elt_head); Vec.shrink env.elt_queue ((Vec.size env.elt_queue) - env.elt_head);
Vec.clear env.elt_levels; Vec.clear env.elt_levels;
Vec.clear env.th_levels; Vec.clear env.th_levels;

View file

@ -12,6 +12,39 @@
(* *) (* *)
(**************************************************************************) (**************************************************************************)
type eval_res =
| Valued of bool * int
| Unknown
(** The type of evaluation results, either the given formula cannot be
evaluated, or it can thanks to assignment. In that case, the level
of the evaluation is the maximum of levels of assignemnts needed
to evaluate the given formula. *)
type ('formula, 'proof) res =
| Sat
| Unsat of 'formula list * 'proof
(** Type returned by the theory, either the current set of assumptions is satisfiable,
or it is not, in which case a tautological clause (hopefully minimal) is returned.
Formulas in the unsat clause must come from the current set of assumptions, i.e
must have been encountered in a slice. *)
type ('term, 'formula) assumption =
| Lit of 'formula
| Assign of 'term * 'term * int (* Assign(x, alpha) *)
(** Asusmptions made by the core SAT solver. Can be either a formula, or an assignment.
Assignemnt are given a level. *)
type ('term, 'formula, 'proof) slice = {
start : int;
length : int;
get : int -> ('term, 'formula) assumption;
push : 'formula list -> 'proof -> unit;
propagate : 'formula -> int -> unit;
}
(** The type for a slice of litterals to assume/propagate in the theory.
[get] operations should only be used for integers [ start <= i < start + length].
[push clause proof] allows to add a tautological clause to the sat solver. *)
module type S = sig module type S = sig
(** Signature for theories to be given to the Model Constructing Solver. *) (** Signature for theories to be given to the Model Constructing Solver. *)
@ -24,36 +57,9 @@ module type S = sig
type proof type proof
(** A custom type for the proofs of lemmas produced by the theory. *) (** A custom type for the proofs of lemmas produced by the theory. *)
type assumption =
| Lit of formula
| Assign of term * term (* Assign(x, alpha) *)
type slice = {
start : int;
length : int;
get : int -> assumption * int;
push : formula list -> proof -> unit;
propagate : formula -> int -> unit;
}
(** The type for a slice of litterals to assume/propagate in the theory.
[get] operations should only be used for integers [ start <= i < start + length].
[push clause proof] allows to add a tautological clause to the sat solver. *)
type level type level
(** The type for levels to allow backtracking. *) (** The type for levels to allow backtracking. *)
(** Type returned by the theory, either the current set of assumptions is satisfiable,
or it is not, in which case a tautological clause (hopefully minimal) is returned.
Formulas in the unsat clause must come from the current set of assumptions, i.e
must have been encountered in a slice. *)
type res =
| Sat
| Unsat of formula list * proof
type eval_res =
| Valued of bool * int
| Unknown
val dummy : level val dummy : level
(** A dummy level. *) (** A dummy level. *)
@ -61,7 +67,7 @@ module type S = sig
(** Return the current level of the theory (either the empty/beginning state, or the (** Return the current level of the theory (either the empty/beginning state, or the
last level returned by the [assume] function). *) last level returned by the [assume] function). *)
val assume : slice -> res val assume : (term, formula, proof) slice -> (formula, proof) res
(** Assume the formulas in the slice, possibly pushing new formulas to be propagated, (** Assume the formulas in the slice, possibly pushing new formulas to be propagated,
and returns the result of the new assumptions. *) and returns the result of the new assumptions. *)
@ -78,7 +84,7 @@ module type S = sig
val eval : formula -> eval_res val eval : formula -> eval_res
(** Returns the evaluation of the formula in the current assignment *) (** Returns the evaluation of the formula in the current assignment *)
val if_sat : slice -> unit val if_sat : (term, formula, proof) slice -> unit
(** Called at the end of the search in case a model has been found. If no new clause is (** Called at the end of the search in case a model has been found. If no new clause is
pushed, then 'sat' is returned, else search is resumed. *) pushed, then 'sat' is returned, else search is resumed. *)

View file

@ -12,6 +12,14 @@
(* *) (* *)
(**************************************************************************) (**************************************************************************)
type ('formula, 'proof) res = ('formula, 'proof) Plugin_intf.res =
| Sat
| Unsat of 'formula list * 'proof
(** Type returned by the theory, either the current set of assumptions is satisfiable,
or it is not, in which case a tautological clause (hopefully minimal) is returned.
Formulas in the unsat clause must come from the current set of assumptions, i.e
must have been encountered in a slice. *)
type ('form, 'proof) slice = { type ('form, 'proof) slice = {
start : int; start : int;
length : int; length : int;
@ -34,14 +42,6 @@ module type S = sig
type level type level
(** The type for levels to allow backtracking. *) (** The type for levels to allow backtracking. *)
(** Type returned by the theory, either the current set of assumptions is satisfiable,
or it is not, in which case a tautological clause (hopefully minimal) is returned.
Formulas in the unsat clause must come from the current set of assumptions, i.e
must have been encountered in a slice. *)
type res =
| Sat of level
| Unsat of formula list * proof
val dummy : level val dummy : level
(** A dummy level. *) (** A dummy level. *)
@ -49,7 +49,7 @@ module type S = sig
(** Return the current level of the theory (either the empty/beginning state, or the (** Return the current level of the theory (either the empty/beginning state, or the
last level returned by the [assume] function). *) last level returned by the [assume] function). *)
val assume : (formula, proof) slice -> res val assume : (formula, proof) slice -> (formula, proof) res
(** Assume the formulas in the slice, possibly pushing new formulas to be propagated, (** Assume the formulas in the slice, possibly pushing new formulas to be propagated,
and returns the result of the new assumptions. *) and returns the result of the new assumptions. *)

View file

@ -16,31 +16,11 @@ module Tsmt = struct
type formula = Fsmt.t type formula = Fsmt.t
type proof = unit type proof = unit
type assumption =
| Lit of formula
| Assign of term * term
type slice = {
start : int;
length : int;
get : int -> assumption * int;
push : formula list -> proof -> unit;
propagate : formula -> int -> unit;
}
type level = { type level = {
cc : CC.t; cc : CC.t;
assign : (term * int) M.t; assign : (term * int) M.t;
} }
type res =
| Sat
| Unsat of formula list * proof
type eval_res =
| Valued of bool * int
| Unknown
(* Functions *) (* Functions *)
let dummy = { cc = CC.empty; assign = M.empty; } let dummy = { cc = CC.empty; assign = M.empty; }
@ -60,12 +40,13 @@ module Tsmt = struct
(Fsmt.mk_eq a b) :: (List.rev_map Fsmt.neg (aux [] l)) (Fsmt.mk_eq a b) :: (List.rev_map Fsmt.neg (aux [] l))
let assume s = let assume s =
let open Plugin_intf in
try try
for i = s.start to s.start + s.length - 1 do for i = s.start to s.start + s.length - 1 do
match s.get i with match s.get i with
| (Assign (x, v)), lvl -> | Assign (x, v, lvl) ->
env := { !env with assign = M.add x (v, lvl) !env.assign } env := { !env with assign = M.add x (v, lvl) !env.assign }
| Lit f, _ -> | Lit f ->
Log.debugf 10 "Propagating in th :@ @[%a@]" (fun k->k Fsmt.print f); Log.debugf 10 "Propagating in th :@ @[%a@]" (fun k->k Fsmt.print f);
match f with match f with
| Fsmt.Prop _ -> () | Fsmt.Prop _ -> ()
@ -91,19 +72,23 @@ module Tsmt = struct
let max (a: int) (b: int) = if a < b then b else a let max (a: int) (b: int) = if a < b then b else a
let eval = function let eval = function
| Fsmt.Prop _ -> Unknown | Fsmt.Prop _ -> Plugin_intf.Unknown
| Fsmt.Equal (a, b) -> | Fsmt.Equal (a, b) ->
begin try begin try
let a', lvl_a = M.find a !env.assign in let a', lvl_a = M.find a !env.assign in
let b', lvl_b = M.find b !env.assign in let b', lvl_b = M.find b !env.assign in
Valued (Fsmt.Term.equal a' b', max lvl_a lvl_b) Plugin_intf.Valued (Fsmt.Term.equal a' b', max lvl_a lvl_b)
with Not_found -> Unknown end with Not_found ->
Plugin_intf.Unknown
end
| Fsmt.Distinct (a, b) -> | Fsmt.Distinct (a, b) ->
begin try begin try
let a', lvl_a = M.find a !env.assign in let a', lvl_a = M.find a !env.assign in
let b', lvl_b = M.find b !env.assign in let b', lvl_b = M.find b !env.assign in
Valued (not (Fsmt.Term.equal a' b'), max lvl_a lvl_b) Plugin_intf.Valued (not (Fsmt.Term.equal a' b'), max lvl_a lvl_b)
with Not_found -> Unknown end with Not_found ->
Plugin_intf.Unknown
end
let if_sat _ = () let if_sat _ = ()

View file

@ -5,7 +5,6 @@ Copyright 2014 Simon Cruanes
*) *)
module Fsmt = Expr module Fsmt = Expr
module ThI = Theory_intf
module Tsmt = struct module Tsmt = struct
@ -15,10 +14,6 @@ module Tsmt = struct
type proof = unit type proof = unit
type level = CC.t type level = CC.t
type res =
| Sat of level
| Unsat of formula list * proof
let dummy = CC.empty let dummy = CC.empty
let env = ref dummy let env = ref dummy
@ -37,15 +32,16 @@ module Tsmt = struct
(Fsmt.mk_eq a b) :: (List.rev_map Fsmt.neg (aux [] l)) (Fsmt.mk_eq a b) :: (List.rev_map Fsmt.neg (aux [] l))
let assume s = let assume s =
let open Theory_intf in
try try
for i = s.ThI.start to s.ThI.start + s.ThI.length - 1 do for i = s.start to s.start + s.length - 1 do
Log.debugf 10 "Propagating in th :@ @[%a@]" (fun k->k Fsmt.print (s.ThI.get i)); Log.debugf 10 "Propagating in th :@ @[%a@]" (fun k->k Fsmt.print (s.get i));
match s.ThI.get i with match s.get i with
| Fsmt.Prop _ -> () | Fsmt.Prop _ -> ()
| Fsmt.Equal (i, j) -> env := CC.add_eq !env i j | Fsmt.Equal (i, j) -> env := CC.add_eq !env i j
| Fsmt.Distinct (i, j) -> env := CC.add_neq !env i j | Fsmt.Distinct (i, j) -> env := CC.add_neq !env i j
done; done;
Sat (current_level ()) Sat
with CC.Unsat x -> with CC.Unsat x ->
Log.debug 8 "Making explanation clause..."; Log.debug 8 "Making explanation clause...";
Unsat (to_clause x, ()) Unsat (to_clause x, ())

View file

@ -11,7 +11,6 @@
(**************************************************************************) (**************************************************************************)
module type S = Solver_intf.S module type S = Solver_intf.S
module ThI = Theory_intf
module DummyTheory(F : Formula_intf.S) = struct module DummyTheory(F : Formula_intf.S) = struct
(* We don't have anything to do since the SAT Solver already (* We don't have anything to do since the SAT Solver already
@ -21,20 +20,9 @@ module DummyTheory(F : Formula_intf.S) = struct
type proof = F.proof type proof = F.proof
type level = unit type level = unit
type slice = {
start : int;
length : int;
get : int -> formula;
push : formula list -> proof -> unit;
}
type res =
| Sat of level
| Unsat of formula list * proof
let dummy = () let dummy = ()
let current_level () = () let current_level () = ()
let assume _ = Sat () let assume _ = Theory_intf.Sat
let backtrack _ = () let backtrack _ = ()
end end
@ -44,46 +32,25 @@ module Plugin(E : Formula_intf.S)
type term = E.t type term = E.t
type formula = E.t type formula = E.t
type proof = Th.proof type proof = Th.proof
type assumption =
| Lit of formula
| Assign of term * term
type slice = {
start : int;
length : int;
get : int -> assumption * int;
push : formula list -> proof -> unit;
propagate : formula -> int -> unit;
}
type level = Th.level type level = Th.level
type res =
| Sat
| Unsat of formula list * proof
type eval_res =
| Valued of bool * int
| Unknown
let dummy = Th.dummy let dummy = Th.dummy
let current_level = Th.current_level let current_level = Th.current_level
let assume_get s i = match s.get i with let assume_get s i =
| Lit f, _ -> f | _ -> assert false match s.Plugin_intf.get i with
| Plugin_intf.Lit f -> f
| _ -> assert false
let assume s = let assume s =
match Th.assume { let slice = {
ThI. Theory_intf.start = s.Plugin_intf.start;
start = s.start; length = s.Plugin_intf.length;
length = s.length; get = assume_get s;
get = assume_get s; push = s.Plugin_intf.push;
push = s.push; } in
} with Th.assume slice
| Th.Sat _ -> Sat
| Th.Unsat (l, p) -> Unsat (l, p)
let backtrack = Th.backtrack let backtrack = Th.backtrack
@ -91,7 +58,7 @@ module Plugin(E : Formula_intf.S)
let iter_assignable _ _ = () let iter_assignable _ _ = ()
let eval _ = Unknown let eval _ = Plugin_intf.Unknown
let if_sat _ = () let if_sat _ = ()