wip: use submodules of Solver_types to clean up code

This commit is contained in:
Simon Cruanes 2017-12-29 15:29:04 +01:00
parent 06af58e6f3
commit 148c1da3cc
10 changed files with 669 additions and 570 deletions

View file

@ -22,12 +22,11 @@ module Make(S : Res.S)(A : Arg with type hyp := S.clause
and type lemma := S.clause
and type assumption := S.clause) = struct
module M = Map.Make(struct
type t = S.St.atom
let compare a b = compare a.S.St.aid b.S.St.aid
end)
module Atom = S.St.Atom
module Clause = S.St.Clause
module M = Map.Make(S.St.Atom)
let name c = c.S.St.name
let name = S.St.Clause.name
let clause_map c =
let rec aux acc a i =
@ -70,27 +69,26 @@ module Make(S : Res.S)(A : Arg with type hyp := S.clause
)) h1.S.St.atoms
let resolution fmt goal hyp1 hyp2 atom =
let a = S.St.(atom.var.pa) in
let a = Atom.abs atom in
let h1, h2 =
if Array.exists ((==) a) hyp1.S.St.atoms then hyp1, hyp2
else (assert (Array.exists ((==) a) hyp2.S.St.atoms); hyp2, hyp1)
if Array.exists (Atom.equal a) hyp1.S.St.atoms then hyp1, hyp2
else (assert (Array.exists (Atom.equal a) hyp2.S.St.atoms); hyp2, hyp1)
in
(** Print some debug info *)
Format.fprintf fmt
"(* Clausal resolution. Goal : %s ; Hyps : %s, %s *)@\n"
(name goal) (name h1) (name h2);
(** Prove the goal: intro the axioms, then perform resolution *)
if Array.length goal.S.St.atoms = 0 then begin
if Array.length goal.S.St.atoms = 0 then (
let m = M.empty in
Format.fprintf fmt "exact @[<hov 1>(%a)@].@\n" (resolution_aux m a h1 h2) ();
false
end else begin
) else (
let m = clause_map goal in
Format.fprintf fmt "pose proof @[<hov>(fun %a=>@ %a)@ as %s.@]@\n"
(clause_iter m "%s@ ") goal (resolution_aux m a h1 h2) () (name goal);
true
end
)
(* Count uses of hypotheses *)
let incr_use h c =

View file

@ -36,10 +36,10 @@ module Make(St : Solver_types_intf.S)(Dummy: sig end) = struct
(* Dimacs & iCNF export *)
let export_vec name fmt vec =
Format.fprintf fmt "c %s@,%a@," name (Vec.print ~sep:"" St.pp_dimacs) vec
Format.fprintf fmt "c %s@,%a@," name (Vec.print ~sep:"" St.Clause.pp_dimacs) vec
let export_assumption fmt vec =
Format.fprintf fmt "c Local assumptions@,a %a@," St.pp_dimacs vec
Format.fprintf fmt "c Local assumptions@,a %a@," St.Clause.pp_dimacs vec
let export_icnf_aux r name map_filter fmt vec =
let aux fmt _ =
@ -47,28 +47,28 @@ module Make(St : Solver_types_intf.S)(Dummy: sig end) = struct
let x = Vec.get vec i in
match map_filter x with
| None -> ()
| Some _ -> Format.fprintf fmt "%a@," St.pp_dimacs (Vec.get vec i)
| Some _ -> Format.fprintf fmt "%a@," St.Clause.pp_dimacs (Vec.get vec i)
done;
r := Vec.size vec
in
Format.fprintf fmt "c %s@,%a" name aux vec
let map_filter_learnt c =
match c.St.cpremise with
match St.Clause.premise c with
| St.Hyp | St.Local -> assert false
| St.Lemma _ -> Some c
| St.History l ->
begin match l with
| [] -> assert false
| d :: _ ->
begin match d.St.cpremise with
begin match St.Clause.premise d with
| St.Lemma _ -> Some d
| St.Hyp | St.Local | St.History _ -> None
end
end
let filter_vec learnt =
let lemmas = Vec.make (Vec.size learnt) St.dummy_clause in
let lemmas = Vec.make (Vec.size learnt) St.Clause.dummy in
Vec.iter (fun c ->
match map_filter_learnt c with
| None -> ()
@ -77,17 +77,13 @@ module Make(St : Solver_types_intf.S)(Dummy: sig end) = struct
lemmas
let export fmt ~hyps ~history ~local =
assert (Vec.for_all (function
| { St.cpremise = St.Hyp; _} -> true | _ -> false
) hyps);
assert (Vec.for_all (fun c -> St.Clause.premise c = St.Hyp) hyps);
(* Learnt clauses, then filtered to only keep only
the theory lemmas; all other learnt clauses should be logical
consequences of the rest. *)
let lemmas = filter_vec history in
(* Local assertions *)
assert (Vec.for_all (function
| { St.cpremise = St.Local; _} -> true | _ -> false
) local);
assert (Vec.for_all (fun c -> St.Local = St.Clause.premise c) local);
(* Number of atoms and clauses *)
let n = St.nb_elt () in
let m = Vec.size local + Vec.size hyps + Vec.size lemmas in
@ -102,15 +98,16 @@ module Make(St : Solver_types_intf.S)(Dummy: sig end) = struct
let icnf_lemmas = ref 0
let export_icnf fmt ~hyps ~history ~local =
assert (Vec.for_all (function
| { St.cpremise = St.Hyp; _} -> true | _ -> false
) hyps);
assert (Vec.for_all (fun c -> St.Clause.premise c = St.Hyp) hyps);
let lemmas = history in
(* Local assertions *)
let l = List.map (function
| {St.cpremise = St.Local; atoms = [| a |];_ } -> a
| _ -> assert false) (Vec.to_list local) in
let local = St.make_clause "local (tmp)" l St.Local in
let l = List.map
(fun c -> match St.Clause.premise c, St.Clause.atoms c with
| St.Local, [| a |] -> a
| _ -> assert false)
(Vec.to_list local)
in
let local = St.Clause.make l St.Local in
(* Number of atoms and clauses *)
Format.fprintf fmt
"@[<v>%s@,%a%a%a@]@."

View file

@ -31,20 +31,22 @@ module type Arg = sig
end
module Default(S : Res.S) = struct
module Atom = S.St.Atom
module Clause = S.St.Clause
let print_atom = S.St.print_atom
let print_atom = Atom.pp
let hyp_info c =
"hypothesis", Some "LIGHTBLUE",
[ fun fmt () -> Format.fprintf fmt "%s" c.S.St.name]
[ fun fmt () -> Format.fprintf fmt "%s" @@ Clause.name c]
let lemma_info c =
"lemma", Some "BLUE",
[ fun fmt () -> Format.fprintf fmt "%s" c.S.St.name]
[ fun fmt () -> Format.fprintf fmt "%s" @@ Clause.name c]
let assumption_info c =
"assumption", Some "PURPLE",
[ fun fmt () -> Format.fprintf fmt "%s" c.S.St.name]
[ fun fmt () -> Format.fprintf fmt "%s" @@ Clause.name c]
end
@ -53,15 +55,17 @@ module Make(S : Res.S)(A : Arg with type atom := S.atom
and type hyp := S.clause
and type lemma := S.clause
and type assumption := S.clause) = struct
module Atom = S.St.Atom
module Clause = S.St.Clause
let node_id n = n.S.conclusion.S.St.name
let node_id n = Clause.name n.S.conclusion
let res_node_id n = (node_id n) ^ "_res"
let proof_id p = node_id (S.expand p)
let print_clause fmt c =
let v = c.S.St.atoms in
let v = Clause.atoms c in
if Array.length v = 0 then
Format.fprintf fmt ""
else
@ -149,9 +153,11 @@ module Simple(S : Res.S)
and type lemma := S.lemma
and type assumption = S.St.formula) =
Make(S)(struct
module Atom = S.St.Atom
module Clause = S.St.Clause
(* Some helpers *)
let lit a = a.S.St.lit
let lit = Atom.lit
let get_assumption c =
match S.to_list c with
@ -159,13 +165,13 @@ module Simple(S : Res.S)
| _ -> assert false
let get_lemma c =
match c.S.St.cpremise with
match Clause.premise c with
| S.St.Lemma p -> p
| _ -> assert false
(* Actual functions *)
let print_atom fmt a =
A.print_atom fmt a.S.St.lit
A.print_atom fmt (Atom.lit a)
let hyp_info c =
A.hyp_info (List.map lit (S.to_list c))

View file

@ -16,11 +16,11 @@ module Make
open St
module H = Heap.Make(struct
type t = St.elt
let[@inline] cmp i j = get_elt_weight j < get_elt_weight i (* comparison by weight *)
let dummy = elt_of_var St.dummy_var
let idx = get_elt_idx
let set_idx = set_elt_idx
type t = St.Elt.t
let[@inline] cmp i j = Elt.weight j < Elt.weight i (* comparison by weight *)
let dummy = Elt.of_var St.Var.dummy
let idx = Elt.idx
let set_idx = Elt.set_idx
end)
exception Sat
@ -61,9 +61,8 @@ module Make
mutable next_decision : atom option;
(* When the last conflict was a semantic one, this stores the next decision to make *)
elt_queue : t Vec.t;
(* decision stack + propagated elements (atoms or assignments).
Also called "trail" in some solvers. *)
trail : trail_elt Vec.t;
(* decision stack + propagated elements (atoms or assignments). *)
elt_levels : int Vec.t;
(* decision levels in [trail] *)
@ -74,19 +73,19 @@ module Make
(* user levels in [clauses_temp] *)
mutable th_head : int;
(* Start offset in the queue {!elt_queue} of
(* Start offset in the queue {!trail} of
unit facts not yet seen by the theory. *)
mutable elt_head : int;
(* Start offset in the queue {!elt_queue} of
(* Start offset in the queue {!trail} of
unit facts to propagate, within the trail *)
(* invariant:
- during propagation, th_head <= elt_head
- then, once elt_head reaches length elt_queue, Th.assume is
- then, once elt_head reaches length trail, Th.assume is
called so that th_head can catch up with elt_head
- this is repeated until a fixpoint is reached;
- before a decision (and after the fixpoint),
th_head = elt_head = length elt_queue
th_head = elt_head = length trail
*)
@ -139,9 +138,9 @@ module Make
unsat_conflict = None;
next_decision = None;
clauses_hyps = Vec.make 0 dummy_clause;
clauses_learnt = Vec.make 0 dummy_clause;
clauses_temp = Vec.make 0 dummy_clause;
clauses_hyps = Vec.make 0 Clause.dummy;
clauses_learnt = Vec.make 0 Clause.dummy;
clauses_temp = Vec.make 0 Clause.dummy;
clauses_root = Stack.create ();
clauses_to_add = Stack.create ();
@ -149,7 +148,7 @@ module Make
th_head = 0;
elt_head = 0;
elt_queue = Vec.make 601 (of_atom dummy_atom);
trail = Vec.make 601 (Trail_elt.of_atom Atom.dummy);
elt_levels = Vec.make 601 (-1);
th_levels = Vec.make 100 Plugin.dummy;
user_levels = Vec.make 10 (-1);
@ -212,15 +211,18 @@ module Make
(* When we have a new literal,
we need to first create the list of its subterms. *)
let atom (f:St.formula) : atom =
let res = add_atom f in
if St.mcsat then
let res = Atom.make f in
if St.mcsat then (
begin match res.var.v_assignable with
| Some _ -> ()
| None ->
let l = ref [] in
Plugin.iter_assignable (fun t -> l := add_term t :: !l) res.var.pa.lit;
Plugin.iter_assignable
(fun t -> l := Lit.make t :: !l)
res.var.pa.lit;
res.var.v_assignable <- Some !l;
end;
);
res
(* Variable and literal activity.
@ -238,14 +240,14 @@ module Make
end
and insert_subterms_order (v:St.var) : unit =
iter_sub (fun t -> insert_var_order (elt_of_lit t)) v
iter_sub (fun t -> insert_var_order (Elt.of_lit t)) v
(* Add new litterals/atoms on which to decide on, even if there is no
clause that constrains it.
We could maybe check if they have already has been decided before
inserting them into the heap, if it appears that it helps performance. *)
let new_lit t =
let l = add_term t in
let l = Lit.make t in
insert_var_order (E_lit l)
let new_atom p =
@ -264,13 +266,13 @@ module Make
(* increase activity of [v] *)
let var_bump_activity_aux v =
v.v_weight <- v.v_weight +. env.var_incr;
if v.v_weight > 1e100 then begin
if v.v_weight > 1e100 then (
for i = 0 to (St.nb_elt ()) - 1 do
set_elt_weight (St.get_elt i) ((get_elt_weight (St.get_elt i)) *. 1e-100)
Elt.set_weight (St.get_elt i) ((Elt.weight (St.get_elt i)) *. 1e-100)
done;
env.var_incr <- env.var_incr *. 1e-100;
end;
let elt = elt_of_var v in
);
let elt = Elt.of_var v in
if H.in_heap elt then (
H.decrease env.order elt
)
@ -278,13 +280,13 @@ module Make
(* increase activity of literal [l] *)
let lit_bump_activity_aux (l:lit): unit =
l.l_weight <- l.l_weight +. env.var_incr;
if l.l_weight > 1e100 then begin
if l.l_weight > 1e100 then (
for i = 0 to (St.nb_elt ()) - 1 do
set_elt_weight (St.get_elt i) ((get_elt_weight (St.get_elt i)) *. 1e-100)
Elt.set_weight (St.get_elt i) ((Elt.weight (St.get_elt i)) *. 1e-100)
done;
env.var_incr <- env.var_incr *. 1e-100;
end;
let elt = elt_of_lit l in
);
let elt = Elt.of_lit l in
if H.in_heap elt then (
H.decrease env.order elt
)
@ -297,13 +299,13 @@ module Make
(* increase activity of clause [c] *)
let clause_bump_activity (c:clause) : unit =
c.activity <- c.activity +. env.clause_incr;
if c.activity > 1e20 then begin
if c.activity > 1e20 then (
for i = 0 to (Vec.size env.clauses_learnt) - 1 do
(Vec.get env.clauses_learnt i).activity <-
(Vec.get env.clauses_learnt i).activity *. 1e-20;
done;
env.clause_incr <- env.clause_incr *. 1e-20
end
)
(* Simplification of clauses.
@ -329,20 +331,23 @@ module Make
let duplicates = ref [] in
let res = ref [] in
Array.iter (fun a ->
if seen a then duplicates := a :: !duplicates
else (mark a; res := a :: !res)
) clause.atoms;
if Atom.seen a then duplicates := a :: !duplicates
else (
Atom.mark a;
res := a :: !res
))
clause.atoms;
List.iter
(fun a ->
if seen_both a.var then trivial := true;
clear a.var)
if Var.seen_both a.var then trivial := true;
Var.clear a.var)
!res;
if !trivial then
raise Trivial
else if !duplicates = [] then
clause
else
make_clause (fresh_lname ()) !res (History [clause])
Clause.make !res (History [clause])
(* Partition literals for new clauses, into:
- true literals (maybe makes the clause trivial if the lit is proved true at level 0)
@ -353,20 +358,20 @@ module Make
*)
let partition atoms : atom list * clause list =
let rec partition_aux trues unassigned falses history i =
if i >= Array.length atoms then
if i >= Array.length atoms then (
trues @ unassigned @ falses, history
else begin
) else (
let a = atoms.(i) in
if a.is_true then
if a.is_true then (
let l = a.var.v_level in
if l = 0 then
raise Trivial (* A var true at level 0 gives a trivially true clause *)
else
(a :: trues) @ unassigned @ falses @
(arr_to_list atoms (i + 1)), history
else if a.neg.is_true then
) else if a.neg.is_true then (
let l = a.var.v_level in
if l = 0 then begin
if l = 0 then (
match a.var.reason with
| Some (Bcp cl) ->
partition_aux trues unassigned falses (cl :: history) (i + 1)
@ -381,11 +386,13 @@ module Make
| None | Some Decision -> assert false
(* The var must have a reason, and it cannot be a decision/assumption,
since its level is 0. *)
end else
) else (
partition_aux trues unassigned (a::falses) history (i + 1)
else
)
) else (
partition_aux trues (a::unassigned) falses history (i + 1)
end
)
)
in
partition_aux [] [] [] [] 0
@ -398,9 +405,9 @@ module Make
i.e we have indeed reached a propagation fixpoint before making
a new decision *)
let new_decision_level() =
assert (env.th_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);
assert (env.th_head = Vec.size env.trail);
assert (env.elt_head = Vec.size env.trail);
Vec.push env.elt_levels (Vec.size env.trail);
Vec.push env.th_levels (Plugin.current_level ()); (* save the current theory state *)
()
@ -411,11 +418,11 @@ module Make
*)
let attach_clause c =
assert (not c.attached);
Log.debugf debug (fun k -> k "Attaching %a" St.pp_clause c);
assert (not @@ Clause.attached c);
Log.debugf debug (fun k -> k "Attaching %a" Clause.debug c);
Vec.push c.atoms.(0).neg.watched c;
Vec.push c.atoms.(1).neg.watched c;
c.attached <- true;
Clause.set_attached c true;
()
(* Backtracking.
@ -425,9 +432,9 @@ module Make
let cancel_until lvl =
assert (lvl >= base_level ());
(* Nothing to do if we try to backtrack to a non-existent level. *)
if decision_level () <= lvl then
if decision_level () <= lvl then (
Log.debugf debug (fun k -> k "Already at level <= %d" lvl)
else begin
) else (
Log.debugf info (fun k -> k "Backtracking to lvl %d" lvl);
(* We set the head of the solver and theory queue to what it was. *)
let head = ref (Vec.get env.elt_levels lvl) in
@ -435,29 +442,29 @@ module Make
env.th_head <- !head;
(* Now we need to cleanup the vars that are not valid anymore
(i.e to the right of elt_head in the queue. *)
for c = env.elt_head to Vec.size env.elt_queue - 1 do
match (Vec.get env.elt_queue c) with
for c = env.elt_head to Vec.size env.trail - 1 do
match (Vec.get env.trail c) with
(* A literal is unassigned, we nedd to add it back to
the heap of potentially assignable literals, unless it has
a level lower than [lvl], in which case we just move it back. *)
| Lit l ->
if l.l_level <= lvl then begin
Vec.set env.elt_queue !head (of_lit l);
if l.l_level <= lvl then (
Vec.set env.trail !head (Trail_elt.of_lit l);
head := !head + 1
end else begin
) else (
l.assigned <- None;
l.l_level <- -1;
insert_var_order (elt_of_lit l)
end
insert_var_order (Elt.of_lit l)
)
(* A variable is not true/false anymore, one of two things can happen: *)
| Atom a ->
if a.var.v_level <= lvl then begin
if a.var.v_level <= lvl then (
(* It is a late propagation, which has a level
lower than where we backtrack, so we just move it to the head
of the queue, to be propagated again. *)
Vec.set env.elt_queue !head (of_atom a);
Vec.set env.trail !head (Trail_elt.of_atom a);
head := !head + 1
end else begin
) else (
(* it is a result of bolean propagation, or a semantic propagation
with a level higher than the level to which we backtrack,
in that case, we simply unset its value and reinsert it into the heap. *)
@ -465,23 +472,23 @@ module Make
a.neg.is_true <- false;
a.var.v_level <- -1;
a.var.reason <- None;
insert_var_order (elt_of_var a.var)
end
insert_var_order (Elt.of_var a.var)
)
done;
(* Recover the right theory state. *)
Plugin.backtrack (Vec.get env.th_levels lvl);
(* Resize the vectors according to their new size. *)
Vec.shrink env.elt_queue !head;
Vec.shrink env.trail !head;
Vec.shrink env.elt_levels lvl;
Vec.shrink env.th_levels lvl;
end;
);
assert (Vec.size env.elt_levels = Vec.size env.th_levels);
()
(* Unsatisfiability is signaled through an exception, since it can happen
in multiple places (adding new clauses, or solving for instance). *)
let report_unsat confl : _ =
Log.debugf info (fun k -> k "@[Unsat conflict: %a@]" St.pp_clause confl);
Log.debugf info (fun k -> k "@[Unsat conflict: %a@]" Clause.debug confl);
env.unsat_conflict <- Some confl;
raise Unsat
@ -505,18 +512,18 @@ module Make
with only one formula (which is [a]). So we explicitly create that clause
and set it as the cause for the propagation of [a], that way we can
rebuild the whole resolution tree when we want to prove [a]. *)
let c' = make_clause (fresh_lname ()) l (History (cl :: history)) in
let c' = Clause.make l (History (cl :: history)) in
Log.debugf debug
(fun k -> k "Simplified reason: @[<v>%a@,%a@]" St.pp_clause cl St.pp_clause c');
(fun k -> k "Simplified reason: @[<v>%a@,%a@]" Clause.debug cl Clause.debug c');
Bcp c'
)
| _ ->
Log.debugf error
(fun k ->
k "@[<v 2>Failed at reason simplification:@,%a@,%a@]"
(Vec.print ~sep:"" St.pp_atom)
(Vec.from_list l St.dummy_atom)
St.pp_clause cl);
(Vec.print ~sep:"" Atom.debug)
(Vec.from_list l Atom.dummy)
Clause.debug cl);
assert false
end
| r -> r
@ -524,10 +531,10 @@ module Make
(* Boolean propagation.
Wrapper function for adding a new propagated formula. *)
let enqueue_bool a ~level:lvl reason : unit =
if a.neg.is_true then begin
Log.debugf error (fun k->k "Trying to enqueue a false literal: %a" St.pp_atom a);
if a.neg.is_true then (
Log.debugf error (fun k->k "Trying to enqueue a false literal: %a" Atom.debug a);
assert false
end;
);
assert (not a.is_true && a.var.v_level < 0 &&
a.var.reason = None && lvl >= 0);
let reason =
@ -537,34 +544,35 @@ module Make
a.is_true <- true;
a.var.v_level <- lvl;
a.var.reason <- Some reason;
Vec.push env.elt_queue (of_atom a);
Vec.push env.trail (Trail_elt.of_atom a);
Log.debugf debug
(fun k->k "Enqueue (%d): %a" (Vec.size env.elt_queue) pp_atom a)
(fun k->k "Enqueue (%d): %a" (Vec.size env.trail) Atom.debug a);
()
let enqueue_semantic a terms =
if a.is_true then ()
else begin
let l = List.map St.add_term terms in
if not a.is_true then (
let l = List.map Lit.make terms in
let lvl = List.fold_left (fun acc {l_level; _} ->
assert (l_level > 0); max acc l_level) 0 l in
H.grow_to_at_least env.order (St.nb_elt ());
enqueue_bool a ~level:lvl Semantic
end
)
(* MCsat semantic assignment *)
let enqueue_assign l value lvl =
match l.assigned with
| Some _ ->
Log.debugf error
(fun k -> k "Trying to assign an already assigned literal: %a" St.pp_lit l);
(fun k -> k "Trying to assign an already assigned literal: %a" Lit.debug l);
assert false
| None ->
assert (l.l_level < 0);
l.assigned <- Some value;
l.l_level <- lvl;
Vec.push env.elt_queue (of_lit l);
Vec.push env.trail (Trail_elt.of_lit l);
Log.debugf debug
(fun k -> k "Enqueue (%d): %a" (Vec.size env.elt_queue) pp_lit l)
(fun k -> k "Enqueue (%d): %a" (Vec.size env.trail) Lit.debug l);
()
(* swap elements of array *)
let[@inline] swap_arr a i j =
@ -574,11 +582,17 @@ module Make
a.(j) <- tmp;
)
let[@inline] put_high_level_atoms_first (arr:atom array) : unit =
Array.sort
(fun a b -> compare b.var.v_level a.var.v_level)
arr
(* FIXME
(* move atoms assigned at high levels first *)
let[@inline] put_high_level_atoms_first (arr:atom array) : unit =
Array.iteri
(fun i a ->
if i>0 && a.var.v_level > arr.(0).var.v_level then (
if i>0 && Atom.level a > Atom.level arr.(0) then (
(* move first to second, [i]-th to first, second to [i] *)
if i=1 then (
swap_arr arr 0 1;
@ -588,10 +602,11 @@ module Make
arr.(0) <- arr.(i);
arr.(i) <- tmp;
);
) else if i>1 && a.var.v_level > arr.(1).var.v_level then (
) else if i>1 && Atom.level a > Atom.level arr.(1) then (
swap_arr arr 1 i;
))
arr
*)
(* evaluate an atom for MCsat, if it's not assigned
by boolean propagation/decision *)
@ -636,7 +651,7 @@ module Make
}
let get_atom i =
match Vec.get env.elt_queue i with
match Vec.get env.trail i with
| Lit _ -> assert false | Atom x -> x
(* conflict analysis for SAT
@ -650,20 +665,20 @@ module Make
let blevel = ref 0 in
let seen = ref [] in
let c = ref (Some c_clause) in
let tr_ind = ref (Vec.size env.elt_queue - 1) in
let tr_ind = ref (Vec.size env.trail - 1) in
let history = ref [] in
assert (decision_level () > 0);
let conflict_level =
Array.fold_left (fun acc p -> max acc p.var.v_level) 0 c_clause.atoms
in
Log.debugf debug
(fun k -> k "Analyzing conflict (%d): %a" conflict_level St.pp_clause c_clause);
(fun k -> k "Analyzing conflict (%d): %a" conflict_level Clause.debug c_clause);
while !cond do
begin match !c with
| None ->
Log.debug debug " skipping resolution for semantic propagation"
| Some clause ->
Log.debugf debug (fun k->k" Resolving clause: %a" St.pp_clause clause);
Log.debugf debug (fun k->k" Resolving clause: %a" Clause.debug clause);
begin match clause.cpremise with
| History _ -> clause_bump_activity clause
| Hyp | Local | Lemma _ -> ()
@ -673,36 +688,36 @@ module Make
for j = 0 to Array.length clause.atoms - 1 do
let q = clause.atoms.(j) in
assert (q.is_true || q.neg.is_true && q.var.v_level >= 0); (* unsure? *)
if q.var.v_level <= 0 then begin
if q.var.v_level <= 0 then (
assert (q.neg.is_true);
match q.var.reason with
| Some Bcp cl -> history := cl :: !history
| _ -> assert false
end;
if not (seen_both q.var) then (
mark q;
mark q.neg;
);
if not (Var.seen_both q.var) then (
Atom.mark q;
Atom.mark q.neg;
seen := q :: !seen;
if q.var.v_level > 0 then begin
if q.var.v_level > 0 then (
var_bump_activity q.var;
if q.var.v_level >= conflict_level then begin
if q.var.v_level >= conflict_level then (
incr pathC;
end else begin
) else (
learnt := q :: !learnt;
blevel := max !blevel q.var.v_level
end
end
)
)
)
done
end;
(* look for the next node to expand *)
while
let a = Vec.get env.elt_queue !tr_ind in
Log.debugf debug (fun k -> k " looking at: %a" St.pp a);
let a = Vec.get env.trail !tr_ind in
Log.debugf debug (fun k -> k " looking at: %a" Trail_elt.debug a);
match a with
| Atom q ->
(not (seen_both q.var)) ||
(not (Var.seen_both q.var)) ||
(q.var.v_level < conflict_level)
| Lit _ -> true
do
@ -725,7 +740,7 @@ module Make
c := Some cl
| _ -> assert false
done;
List.iter (fun q -> clear q.var) !seen;
List.iter (fun q -> Var.clear q.var) !seen;
let l = List.fast_sort (fun p q -> compare q.var.v_level p.var.v_level) !learnt in
let level, is_uip = backtrack_lvl l in
{ cr_backtrack_lvl = level;
@ -748,26 +763,24 @@ module Make
| [] -> assert false
| [fuip] ->
assert (cr.cr_backtrack_lvl = 0);
if fuip.neg.is_true then
if fuip.neg.is_true then (
report_unsat confl
else begin
let name = fresh_lname () in
let uclause = make_clause name cr.cr_learnt (History cr.cr_history) in
) else (
let uclause = Clause.make cr.cr_learnt (History cr.cr_history) in
Vec.push env.clauses_learnt uclause;
(* no need to attach [uclause], it is true at level 0 *)
enqueue_bool fuip ~level:0 (Bcp uclause)
end
)
| fuip :: _ ->
let name = fresh_lname () in
let lclause = make_clause name cr.cr_learnt (History cr.cr_history) in
let lclause = Clause.make cr.cr_learnt (History cr.cr_history) in
Vec.push env.clauses_learnt lclause;
attach_clause lclause;
clause_bump_activity lclause;
if cr.cr_is_uip then
if cr.cr_is_uip then (
enqueue_bool fuip ~level:cr.cr_backtrack_lvl (Bcp lclause)
else begin
) else (
env.next_decision <- Some fuip.neg
end
)
end;
var_decay_activity ();
clause_decay_activity ()
@ -778,7 +791,7 @@ module Make
- report unsat if conflict at level 0
*)
let add_boolean_conflict (confl:clause): unit =
Log.debugf info (fun k -> k "Boolean conflict: %a" St.pp_clause confl);
Log.debugf info (fun k -> k "Boolean conflict: %a" Clause.debug confl);
env.next_decision <- None;
env.conflicts <- env.conflicts + 1;
assert (decision_level() >= base_level ());
@ -799,14 +812,14 @@ module Make
(* Add a new clause, simplifying, propagating, and backtracking if
the clause is false in the current trail *)
let add_clause (init:clause) : unit =
Log.debugf debug (fun k -> k "Adding clause: @[<hov>%a@]" St.pp_clause init);
Log.debugf debug (fun k -> k "Adding clause: @[<hov>%a@]" Clause.debug init);
(* Insertion of new lits is done before simplification. Indeed, else a lit in a
trivial clause could end up being not decided on, which is a bug. *)
Array.iter (fun x -> insert_var_order (elt_of_var x.var)) init.atoms;
Array.iter (fun x -> insert_var_order (Elt.of_var x.var)) init.atoms;
let vec = clause_vector init in
try
let c = eliminate_doublons init in
Log.debugf debug (fun k -> k "Doublons eliminated: %a" St.pp_clause c);
Log.debugf debug (fun k -> k "Doublons eliminated: %a" Clause.debug c);
let atoms, history = partition c.atoms in
let clause =
if history = []
@ -815,9 +828,9 @@ module Make
List.iteri (fun i a -> c.atoms.(i) <- a) atoms;
c
)
else make_clause (fresh_name ()) atoms (History (c :: history))
else Clause.make atoms (History (c :: history))
in
Log.debugf info (fun k->k "New clause: @[<hov>%a@]" St.pp_clause clause);
Log.debugf info (fun k->k "New clause: @[<hov>%a@]" Clause.debug clause);
match atoms with
| [] ->
(* Report_unsat will raise, and the current clause will be lost if we do not
@ -827,14 +840,14 @@ module Make
report_unsat clause
| [a] ->
cancel_until (base_level ());
if a.neg.is_true then begin
if a.neg.is_true then (
(* Since we cannot propagate the atom [a], in order to not lose
the information that [a] must be true, we add clause to the list
of clauses to add, so that it will be e-examined later. *)
Log.debug debug "Unit clause, adding to clauses to add";
Stack.push clause env.clauses_to_add;
report_unsat clause
end else if a.is_true then begin
) else if a.is_true then (
(* If the atom is already true, then it should be because of a local hyp.
However it means we can't propagate it at level 0. In order to not lose
that information, we store the clause in a stack of clauses that we will
@ -843,30 +856,30 @@ module Make
assert (0 < a.var.v_level && a.var.v_level <= base_level ());
Stack.push clause env.clauses_root;
()
end else begin
Log.debugf debug (fun k->k "Unit clause, propagating: %a" St.pp_atom a);
) else (
Log.debugf debug (fun k->k "Unit clause, propagating: %a" Atom.debug a);
Vec.push vec clause;
enqueue_bool a ~level:0 (Bcp clause)
end
)
| a::b::_ ->
Vec.push vec clause;
if a.neg.is_true then begin
if a.neg.is_true then (
(* Atoms need to be sorted in decreasing order of decision level,
or we might watch the wrong literals. *)
put_high_level_atoms_first clause.atoms;
attach_clause clause;
add_boolean_conflict clause
end else begin
) else (
attach_clause clause;
if b.neg.is_true && not a.is_true && not a.neg.is_true then begin
if b.neg.is_true && not a.is_true && not a.neg.is_true then (
let lvl = List.fold_left (fun m a -> max m a.var.v_level) 0 atoms in
cancel_until (max lvl (base_level ()));
enqueue_bool a ~level:lvl (Bcp clause)
end
end
)
)
with Trivial ->
Vec.push vec init;
Log.debugf info (fun k->k "Trivial clause ignored : @[%a@]" St.pp_clause init)
Log.debugf info (fun k->k "Trivial clause ignored : @[%a@]" Clause.debug init)
let flush_clauses () =
if not (Stack.is_empty env.clauses_to_add) then begin
@ -900,13 +913,13 @@ module Make
atoms.(1) <- first
) else assert (a.neg == atoms.(1));
let first = atoms.(0) in
if first.is_true
if Atom.is_true first
then Watch_kept (* true clause, keep it in watched *)
else (
try (* look for another watch lit *)
for k = 2 to Array.length atoms - 1 do
let ak = atoms.(k) in
if not (ak.neg.is_true) then begin
if not (ak.neg.is_true) then (
(* watch lit found: update and exit *)
atoms.(1) <- ak;
atoms.(k) <- a.neg;
@ -915,22 +928,22 @@ module Make
assert (Vec.get a.watched i == c);
Vec.fast_remove a.watched i;
raise Exit
end
)
done;
(* no watch lit found *)
if first.neg.is_true then begin
if first.neg.is_true then (
(* clause is false *)
env.elt_head <- Vec.size env.elt_queue;
env.elt_head <- Vec.size env.trail;
raise (Conflict c)
end else begin
) else (
match th_eval first with
| None -> (* clause is unit, keep the same watches, but propagate *)
enqueue_bool first ~level:(decision_level ()) (Bcp c)
| Some true -> ()
| Some false ->
env.elt_head <- Vec.size env.elt_queue;
env.elt_head <- Vec.size env.trail;
raise (Conflict c)
end;
);
Watch_kept
with Exit ->
Watch_removed
@ -948,7 +961,7 @@ module Make
if i >= Vec.size watched then ()
else (
let c = Vec.get watched i in
assert c.attached;
assert (Clause.attached c);
let j = match propagate_in_clause a c i with
| Watch_kept -> i+1
| Watch_removed -> i (* clause at this index changed *)
@ -970,7 +983,7 @@ module Make
a
let slice_get i =
match Vec.get env.elt_queue i with
match Vec.get env.trail i with
| Atom a ->
Plugin_intf.Lit a.lit
| Lit {term; assigned = Some v; _} ->
@ -979,8 +992,8 @@ module Make
let slice_push (l:formula list) (lemma:proof): unit =
let atoms = List.rev_map create_atom l in
let c = make_clause (fresh_tname ()) atoms (Lemma lemma) in
Log.debugf info (fun k->k "Pushing clause %a" St.pp_clause c);
let c = Clause.make atoms (Lemma lemma) in
Log.debugf info (fun k->k "Pushing clause %a" Clause.debug c);
Stack.push c env.clauses_to_add
let slice_propagate f = function
@ -989,24 +1002,24 @@ module Make
enqueue_semantic a l
| Plugin_intf.Consequence (causes, proof) ->
let l = List.rev_map atom causes in
if List.for_all (fun a -> a.is_true) l then
if List.for_all (fun a -> a.is_true) l then (
let p = atom f in
let c = make_clause (fresh_tname ())
(p :: List.map (fun a -> a.neg) l) (Lemma proof) in
let c = Clause.make (p :: List.map Atom.neg l) (Lemma proof) in
if p.is_true then ()
else if p.neg.is_true then
else if p.neg.is_true then (
Stack.push c env.clauses_to_add
else begin
) else (
H.grow_to_at_least env.order (St.nb_elt ());
insert_subterms_order p.var;
enqueue_bool p ~level:(decision_level ()) (Bcp c)
end
else
raise (Invalid_argument "Msat.Internal.slice_propagate")
)
) else (
invalid_arg "Msat.Internal.slice_propagate"
)
let current_slice (): (_,_,_) Plugin_intf.slice = {
Plugin_intf.start = env.th_head;
length = (Vec.size env.elt_queue) - env.th_head;
length = (Vec.size env.trail) - env.th_head;
get = slice_get;
push = slice_push;
propagate = slice_propagate;
@ -1015,7 +1028,7 @@ module Make
(* full slice, for [if_sat] final check *)
let full_slice () : (_,_,_) Plugin_intf.slice = {
Plugin_intf.start = 0;
length = Vec.size env.elt_queue;
length = Vec.size env.trail;
get = slice_get;
push = slice_push;
propagate = (fun _ -> assert false);
@ -1025,11 +1038,11 @@ module Make
need to inform the theory of those assumptions, so it can do its job.
@return the conflict clause, if the theory detects unsatisfiability *)
let rec theory_propagate (): clause option =
assert (env.elt_head = Vec.size env.elt_queue);
assert (env.elt_head = Vec.size env.trail);
assert (env.th_head <= env.elt_head);
if env.th_head = env.elt_head then
if env.th_head = env.elt_head then (
None (* fixpoint/no propagation *)
else begin
) else (
let slice = current_slice () in
env.th_head <- env.elt_head; (* catch up *)
match Plugin.assume slice with
@ -1039,10 +1052,10 @@ module Make
(* conflict *)
let l = List.rev_map create_atom l in
H.grow_to_at_least env.order (St.nb_elt ());
List.iter (fun a -> insert_var_order (elt_of_var a.var)) l;
let c = St.make_clause (St.fresh_tname ()) l (Lemma p) in
List.iter (fun a -> insert_var_order (Elt.of_var a.var)) l;
let c = St.Clause.make l (Lemma p) in
Some c
end
)
(* fixpoint between boolean propagation and theory propagation
@return a conflict clause, if any *)
@ -1050,14 +1063,14 @@ module Make
(* First, treat the stack of lemmas added by the theory, if any *)
flush_clauses ();
(* Now, check that the situation is sane *)
assert (env.elt_head <= Vec.size env.elt_queue);
if env.elt_head = Vec.size env.elt_queue then
assert (env.elt_head <= Vec.size env.trail);
if env.elt_head = Vec.size env.trail then
theory_propagate ()
else begin
let num_props = ref 0 in
let res = ref None in
while env.elt_head < Vec.size env.elt_queue do
begin match Vec.get env.elt_queue env.elt_head with
while env.elt_head < Vec.size env.trail do
begin match Vec.get env.trail env.elt_head with
| Lit _ -> ()
| Atom a ->
incr num_props;
@ -1080,10 +1093,10 @@ module Make
(* Decide on a new literal, and enqueue it into the trail *)
let rec pick_branch_aux atom: unit =
let v = atom.var in
if v.v_level >= 0 then begin
if v.v_level >= 0 then (
assert (v.pa.is_true || v.na.is_true);
pick_branch_lit ()
end else match Plugin.eval atom.lit with
) else match Plugin.eval atom.lit with
| Plugin_intf.Unknown ->
env.decisions <- env.decisions + 1;
new_decision_level();
@ -1099,22 +1112,20 @@ module Make
env.next_decision <- None;
pick_branch_aux atom
| None ->
begin try
begin match H.remove_min env.order with
| E_lit l ->
if l.l_level >= 0 then
pick_branch_lit ()
else begin
let value = Plugin.assign l.term in
env.decisions <- env.decisions + 1;
new_decision_level();
let current_level = decision_level () in
enqueue_assign l value current_level
end
| E_var v ->
pick_branch_aux v.pa
end
with Not_found -> raise Sat
begin match H.remove_min env.order with
| E_lit l ->
if Lit.level l >= 0 then
pick_branch_lit ()
else (
let value = Plugin.assign l.term in
env.decisions <- env.decisions + 1;
new_decision_level();
let current_level = decision_level () in
enqueue_assign l value current_level
)
| E_var v ->
pick_branch_aux v.pa
| exception Not_found -> raise Sat
end
(* do some amount of search, until the number of conflicts or clause learnt
@ -1130,32 +1141,32 @@ module Make
might 'forget' the initial conflict clause, and only add the
analyzed backtrack clause. So in those case, we use add_clause
to make sure the initial conflict clause is also added. *)
if confl.attached then
if Clause.attached confl then
add_boolean_conflict confl
else
add_clause confl
| None -> (* No Conflict *)
assert (env.elt_head = Vec.size env.elt_queue);
assert (env.elt_head = Vec.size env.trail);
assert (env.elt_head = env.th_head);
if Vec.size env.elt_queue = St.nb_elt ()
if Vec.size env.trail = St.nb_elt ()
then raise Sat;
if n_of_conflicts > 0 && !conflictC >= n_of_conflicts then begin
if n_of_conflicts > 0 && !conflictC >= n_of_conflicts then (
Log.debug info "Restarting...";
cancel_until (base_level ());
raise Restart
end;
);
(* if decision_level() = 0 then simplify (); *)
if n_of_learnts >= 0 &&
Vec.size env.clauses_learnt - Vec.size env.elt_queue >= n_of_learnts
Vec.size env.clauses_learnt - Vec.size env.trail >= n_of_learnts
then reduce_db();
pick_branch_lit ()
done
let eval_level lit =
let var, negated = make_boolean_var lit in
let var, negated = Var.make lit in
if not var.pa.is_true && not var.na.is_true
then raise UndecidedLit
else assert (var.v_level >= 0);
@ -1176,7 +1187,7 @@ module Make
(fun acc e -> match e with
| Lit v -> (v.term, opt v.assigned) :: acc
| Atom _ -> acc)
[] env.elt_queue
[] env.trail
(* fixpoint of propagation and decisions until a model is found, or a
conflict is reached *)
@ -1194,13 +1205,13 @@ module Make
n_of_conflicts := !n_of_conflicts *. env.restart_inc;
n_of_learnts := !n_of_learnts *. env.learntsize_inc
| Sat ->
assert (env.elt_head = Vec.size env.elt_queue);
assert (env.elt_head = Vec.size env.trail);
begin match Plugin.if_sat (full_slice ()) with
| Plugin_intf.Sat -> ()
| Plugin_intf.Unsat (l, p) ->
let atoms = List.rev_map create_atom l in
let c = make_clause (fresh_tname ()) atoms (Lemma p) in
Log.debugf info (fun k -> k "Theory conflict clause: %a" St.pp_clause c);
let c = Clause.make atoms (Lemma p) in
Log.debugf info (fun k -> k "Theory conflict clause: %a" Clause.debug c);
Stack.push c env.clauses_to_add
end;
if Stack.is_empty env.clauses_to_add then raise Sat
@ -1212,8 +1223,8 @@ module Make
List.iter
(fun l ->
let atoms = List.rev_map atom l in
let c = make_clause ?tag (fresh_hname ()) atoms Hyp in
Log.debugf debug (fun k -> k "Assuming clause: @[<hov 2>%a@]" pp_clause c);
let c = Clause.make ?tag atoms Hyp in
Log.debugf debug (fun k -> k "Assuming clause: @[<hov 2>%a@]" Clause.debug c);
Stack.push c env.clauses_to_add)
cnf
@ -1223,13 +1234,14 @@ module Make
cancel_until (base_level ());
Log.debugf debug
(fun k -> k "@[<v>Status:@,@[<hov 2>trail: %d - %d@,%a@]"
env.elt_head env.th_head (Vec.print ~sep:"" St.pp) env.elt_queue);
env.elt_head env.th_head (Vec.print ~sep:"" Trail_elt.debug) env.trail);
begin match propagate () with
| Some confl ->
report_unsat confl
| None ->
Log.debugf debug
(fun k -> k "@[<v>Current trail:@,@[<hov>%a@]@]" (Vec.print ~sep:"" St.pp) env.elt_queue);
(fun k -> k "@[<v>Current trail:@,@[<hov>%a@]@]"
(Vec.print ~sep:"" Trail_elt.debug) env.trail);
Log.debug info "Creating new user level";
new_decision_level ();
Vec.push env.user_levels (Vec.size env.clauses_temp);
@ -1260,24 +1272,24 @@ module Make
let local l =
let aux lit =
let a = atom lit in
Log.debugf info (fun k-> k "Local assumption: @[%a@]" pp_atom a);
Log.debugf info (fun k-> k "Local assumption: @[%a@]" Atom.debug a);
assert (decision_level () = base_level ());
if a.is_true then ()
else
let c = make_clause (fresh_hname ()) [a] Local in
Log.debugf debug (fun k -> k "Temp clause: @[%a@]" pp_clause c);
if not a.is_true then (
let c = Clause.make [a] Local in
Log.debugf debug (fun k -> k "Temp clause: @[%a@]" Clause.debug c);
Vec.push env.clauses_temp c;
if a.neg.is_true then begin
if a.neg.is_true then (
(* conflict between assumptions: UNSAT *)
report_unsat c;
end else begin
) else (
(* Grow the heap, because when the lit is backtracked,
it will be added to the heap. *)
H.grow_to_at_least env.order (St.nb_elt ());
(* make a decision, propagate *)
let level = decision_level() in
enqueue_bool a ~level (Bcp c);
end
)
)
in
assert (base_level () > 0);
match env.unsat_conflict with
@ -1295,11 +1307,11 @@ module Make
else if a.neg.is_true then false
else raise UndecidedLit) c.atoms in
let res = Array.exists (fun x -> x) tmp in
if not res then begin
if not res then (
Log.debugf debug
(fun k -> k "Clause not satisfied: @[<hov>%a@]" St.pp_clause c);
(fun k -> k "Clause not satisfied: @[<hov>%a@]" Clause.debug c);
false
end else
) else
true
let check_vec v =
@ -1327,7 +1339,7 @@ module Make
let temp () = env.clauses_temp
let trail () = env.elt_queue
let trail () = env.trail
end

View file

@ -92,7 +92,7 @@ module Make
These functions expose some internal data stored by the solver, as such
great care should be taken to ensure not to mess with the values returned. *)
val trail : unit -> St.t Vec.t
val trail : unit -> St.trail_elt Vec.t
(** Returns the current trail.
*DO NOT MUTATE* *)

View file

@ -24,11 +24,10 @@ module Make(St : Solver_types.S) = struct
let info = 10
let debug = 80
(* Misc functions *)
let equal_atoms a b = St.(a.aid) = St.(b.aid)
let compare_atoms a b = Pervasives.compare St.(a.aid) St.(b.aid)
let print_clause = St.pp_clause
let print_clause = St.Clause.pp
let merge = List.merge compare_atoms
@ -52,19 +51,19 @@ module Make(St : Solver_types.S) = struct
resolved, List.rev new_clause
(* Compute the set of doublons of a clause *)
let list c = List.sort compare_atoms (Array.to_list St.(c.atoms))
let list c = List.sort St.Atom.compare (Array.to_list St.(c.atoms))
let analyze cl =
let rec aux duplicates free = function
| [] -> duplicates, free
| [ x ] -> duplicates, x :: free
| x :: ((y :: r) as l) ->
if equal_atoms x y then
if x == y then
count duplicates (x :: free) x [y] r
else
aux duplicates (x :: free) l
and count duplicates free x acc = function
| (y :: r) when equal_atoms x y ->
| (y :: r) when x == y ->
count duplicates free x (y :: acc) r
| l ->
aux (acc :: duplicates) free l
@ -96,7 +95,8 @@ module Make(St : Solver_types.S) = struct
let cmp_cl c d =
let rec aux = function
| [], [] -> 0
| a :: r, a' :: r' -> begin match compare_atoms a a' with
| a :: r, a' :: r' ->
begin match compare_atoms a a' with
| 0 -> aux (r, r')
| x -> x
end
@ -117,32 +117,32 @@ module Make(St : Solver_types.S) = struct
assert St.(a.var.v_level >= 0);
match St.(a.var.reason) with
| Some St.Bcp c ->
Log.debugf debug (fun k->k "Analysing: @[%a@ %a@]" St.pp_atom a St.pp_clause c);
if Array.length c.St.atoms = 1 then begin
Log.debugf debug (fun k -> k "Old reason: @[%a@]" St.pp_atom a);
Log.debugf debug (fun k->k "Analysing: @[%a@ %a@]" St.Atom.debug a St.Clause.debug c);
if Array.length c.St.atoms = 1 then (
Log.debugf debug (fun k -> k "Old reason: @[%a@]" St.Atom.debug a);
c
end else begin
) else (
assert (a.St.neg.St.is_true);
let r = St.History (c :: (Array.fold_left aux [] c.St.atoms)) in
let c' = St.make_clause (fresh_pcl_name ()) [a.St.neg] r in
let c' = St.Clause.make [a.St.neg] r in
a.St.var.St.reason <- Some St.(Bcp c');
Log.debugf debug
(fun k -> k "New reason: @[%a@ %a@]" St.pp_atom a St.pp_clause c');
(fun k -> k "New reason: @[%a@ %a@]" St.Atom.debug a St.Clause.debug c');
c'
end
)
| _ ->
Log.debugf error (fun k -> k "Error while proving atom %a" St.pp_atom a);
Log.debugf error (fun k -> k "Error while proving atom %a" St.Atom.debug a);
raise (Resolution_error "Cannot prove atom")
let prove_unsat conflict =
if Array.length conflict.St.atoms = 0 then conflict
else begin
Log.debugf info (fun k -> k "Proving unsat from: @[%a@]" St.pp_clause conflict);
else (
Log.debugf info (fun k -> k "Proving unsat from: @[%a@]" St.Clause.debug conflict);
let l = Array.fold_left (fun acc a -> set_atom_proof a :: acc) [] conflict.St.atoms in
let res = St.make_clause (fresh_pcl_name ()) [] (St.History (conflict :: l)) in
Log.debugf info (fun k -> k "Proof found: @[%a@]" St.pp_clause res);
let res = St.Clause.make [] (St.History (conflict :: l)) in
Log.debugf info (fun k -> k "Proof found: @[%a@]" St.Clause.debug res);
res
end
)
let prove_atom a =
if St.(a.is_true && a.var.v_level = 0) then
@ -166,27 +166,26 @@ module Make(St : Solver_types.S) = struct
let rec chain_res (c, cl) = function
| d :: r ->
Log.debugf debug
(fun k -> k " Resolving clauses : @[%a@\n%a@]" St.pp_clause c St.pp_clause d);
(fun k -> k " Resolving clauses : @[%a@\n%a@]" St.Clause.debug c St.Clause.debug d);
let dl = to_list d in
begin match resolve (merge cl dl) with
| [ a ], l ->
begin match r with
| [] -> (l, c, d, a)
| _ ->
let new_clause = St.make_clause (fresh_pcl_name ())
l (St.History [c; d]) in
let new_clause = St.Clause.make l (St.History [c; d]) in
chain_res (new_clause, l) r
end
| _ ->
Log.debugf error
(fun k -> k "While resolving clauses:@[<hov>%a@\n%a@]" St.pp_clause c St.pp_clause d);
(fun k -> k "While resolving clauses:@[<hov>%a@\n%a@]" St.Clause.debug c St.Clause.debug d);
raise (Resolution_error "Clause mismatch")
end
| _ ->
raise (Resolution_error "Bad history")
let expand conclusion =
Log.debugf debug (fun k -> k "Expanding : @[%a@]" St.pp_clause conclusion);
Log.debugf debug (fun k -> k "Expanding : @[%a@]" St.Clause.debug conclusion);
match conclusion.St.cpremise with
| St.Lemma l ->
{conclusion; step = Lemma l; }
@ -195,7 +194,7 @@ module Make(St : Solver_types.S) = struct
| St.Local ->
{ conclusion; step = Assumption; }
| St.History [] ->
Log.debugf error (fun k -> k "Empty history for clause: %a" St.pp_clause conclusion);
Log.debugf error (fun k -> k "Empty history for clause: %a" St.Clause.debug conclusion);
raise (Resolution_error "Empty history")
| St.History [ c ] ->
let duplicates, res = analyze (list c) in
@ -240,7 +239,7 @@ module Make(St : Solver_types.S) = struct
let rec aux res acc = function
| [] -> res, acc
| c :: r ->
if not c.St.visited then begin
if not c.St.visited then (
c.St.visited <- true;
match c.St.cpremise with
| St.Hyp | St.Local | St.Lemma _ -> aux (c :: res) acc r
@ -248,8 +247,9 @@ module Make(St : Solver_types.S) = struct
let l = List.fold_left (fun acc c ->
if not c.St.visited then c :: acc else acc) r h in
aux res (c :: acc) l
end else
) else (
aux res acc r
)
in
let res, tmp = aux [] [] [proof] in
List.iter (fun c -> c.St.visited <- false) res;

View file

@ -6,36 +6,7 @@ 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. *)
}
type 'clause export = 'clause Solver_intf.export = {
hyps: 'clause Vec.t;
history: 'clause Vec.t;
local: 'clause Vec.t;
}
open Solver_intf
module Make
(St : Solver_types.S)
@ -65,10 +36,10 @@ module Make
(fun k -> k
"@[<v>%s - Full resume:@,@[<hov 2>Trail:@\n%a@]@,@[<hov 2>Temp:@\n%a@]@,@[<hov 2>Hyps:@\n%a@]@,@[<hov 2>Lemmas:@\n%a@]@,@]@."
status
(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 ())
(Vec.print ~sep:"" St.Trail_elt.debug) (S.trail ())
(Vec.print ~sep:"" St.Clause.debug) (S.temp ())
(Vec.print ~sep:"" St.Clause.debug) (S.hyps ())
(Vec.print ~sep:"" St.Clause.debug) (S.history ())
)
let mk_sat () : (_,_) sat_state =
@ -77,8 +48,8 @@ module Make
let iter f f' =
Vec.iter (function
| St.Atom a -> f a.St.lit
| St.Lit l -> f' l.St.term
) t
| St.Lit l -> f' l.St.term)
t
in
{
eval = S.eval;

View file

@ -73,7 +73,7 @@ module McMake (E : Expr_intf.S)() = struct
}
and clause = {
name : string;
name : int;
tag : int option;
atoms : atom array;
mutable cpremise : premise;
@ -97,8 +97,9 @@ module McMake (E : Expr_intf.S)() = struct
| E_lit of lit
| E_var of var
(* Dummy values *)
let dummy_lit = E.Formula.dummy
type trail_elt =
| Lit of lit
| Atom of atom
let rec dummy_var =
{ vid = -101;
@ -113,7 +114,7 @@ module McMake (E : Expr_intf.S)() = struct
}
and dummy_atom =
{ var = dummy_var;
lit = dummy_lit;
lit = E.Formula.dummy;
watched = Obj.magic 0;
(* should be [Vec.make_empty dummy_clause]
but we have to break the cycle *)
@ -121,7 +122,7 @@ module McMake (E : Expr_intf.S)() = struct
is_true = false;
aid = -102 }
let dummy_clause =
{ name = "";
{ name = -1;
tag = None;
atoms = [| |];
activity = -1.;
@ -129,13 +130,13 @@ module McMake (E : Expr_intf.S)() = struct
visited = false;
cpremise = History [] }
let () =
dummy_atom.watched <- Vec.make_empty dummy_clause
let () = dummy_atom.watched <- Vec.make_empty dummy_clause
(* Constructors *)
module MF = Hashtbl.Make(E.Formula)
module MT = Hashtbl.Make(E.Term)
(* TODO: embed a state `t` with these inside *)
let f_map = MF.create 4096
let t_map = MT.create 4096
@ -146,229 +147,286 @@ module McMake (E : Expr_intf.S)() = struct
let cpt_mk_var = ref 0
let make_semantic_var t =
try MT.find t_map t
with Not_found ->
let res = {
lid = !cpt_mk_var;
term = t;
l_weight = 1.;
l_idx= -1;
l_level = -1;
assigned = None;
} in
incr cpt_mk_var;
MT.add t_map t res;
Vec.push vars (E_lit res);
res
let name_of_clause c = match c.cpremise with
| Hyp -> "H" ^ string_of_int c.name
| Local -> "L" ^ string_of_int c.name
| Lemma _ -> "T" ^ string_of_int c.name
| History _ -> "C" ^ string_of_int c.name
let make_boolean_var : formula -> var * Expr_intf.negated =
fun t ->
let lit, negated = E.Formula.norm t in
try
MF.find f_map lit, negated
module Lit = struct
type t = lit
let[@inline] term l = l.term
let[@inline] level l = l.l_level
let[@inline] set_level l lvl = l.l_level <- lvl
let[@inline] assigned l = l.assigned
let[@inline] set_assigned l t = l.assigned <- t
let[@inline] weight l = l.l_weight
let[@inline] set_weight l w = l.l_weight <- w
let make t =
try MT.find t_map t
with Not_found ->
let cpt_fois_2 = !cpt_mk_var lsl 1 in
let rec var =
{ vid = !cpt_mk_var;
pa = pa;
na = na;
v_fields = Var_fields.empty;
v_level = -1;
v_idx= -1;
v_weight = 0.;
v_assignable = None;
reason = None;
}
and pa =
{ var = var;
lit = lit;
watched = Vec.make 10 dummy_clause;
neg = na;
is_true = false;
aid = cpt_fois_2 (* aid = vid*2 *) }
and na =
{ var = var;
lit = E.Formula.neg lit;
watched = Vec.make 10 dummy_clause;
neg = pa;
is_true = false;
aid = cpt_fois_2 + 1 (* aid = vid*2+1 *) } in
MF.add f_map lit var;
let res = {
lid = !cpt_mk_var;
term = t;
l_weight = 1.;
l_idx= -1;
l_level = -1;
assigned = None;
} in
incr cpt_mk_var;
Vec.push vars (E_var var);
var, negated
MT.add t_map t res;
Vec.push vars (E_lit res);
res
let add_term t = make_semantic_var t
let debug_assign fmt v =
match v.assigned with
| None ->
Format.fprintf fmt ""
| Some t ->
Format.fprintf fmt "@[<hov>@@%d->@ %a@]" v.l_level E.Term.print t
let add_atom lit =
let var, negated = make_boolean_var lit in
match negated with
| Formula_intf.Negated -> var.na
| Formula_intf.Same_sign -> var.pa
let pp out v = E.Term.print out v.term
let debug out v =
Format.fprintf out "%d[%a][lit:@[<hov>%a@]]"
(v.lid+1) debug_assign v E.Term.print v.term
end
let make_clause ?tag name ali premise =
let atoms = Array.of_list ali in
{ name = name;
tag = tag;
atoms = atoms;
attached = false;
visited = false;
activity = 0.;
cpremise = premise}
module Var = struct
type t = var
let dummy = dummy_var
let[@inline] level v = v.v_level
let[@inline] set_level v lvl = v.v_level <- lvl
let[@inline] pos v = v.pa
let[@inline] neg v = v.na
let[@inline] reason v = v.reason
let[@inline] set_reason v r = v.reason <- r
let[@inline] assignable v = v.v_assignable
let[@inline] set_assignable v x = v.v_assignable <- x
let[@inline] weight v = v.v_weight
let[@inline] set_weight v w = v.v_weight <- w
let empty_clause = make_clause "Empty" [] (History [])
let make : formula -> var * Expr_intf.negated =
fun t ->
let lit, negated = E.Formula.norm t in
try
MF.find f_map lit, negated
with Not_found ->
let cpt_fois_2 = !cpt_mk_var lsl 1 in
let rec var =
{ vid = !cpt_mk_var;
pa = pa;
na = na;
v_fields = Var_fields.empty;
v_level = -1;
v_idx= -1;
v_weight = 0.;
v_assignable = None;
reason = None;
}
and pa =
{ var = var;
lit = lit;
watched = Vec.make 10 dummy_clause;
neg = na;
is_true = false;
aid = cpt_fois_2 (* aid = vid*2 *) }
and na =
{ var = var;
lit = E.Formula.neg lit;
watched = Vec.make 10 dummy_clause;
neg = pa;
is_true = false;
aid = cpt_fois_2 + 1 (* aid = vid*2+1 *) } in
MF.add f_map lit var;
incr cpt_mk_var;
Vec.push vars (E_var var);
var, negated
(* Marking helpers *)
let clear v = v.v_fields <- Var_fields.empty
(* Marking helpers *)
let[@inline] clear v =
v.v_fields <- Var_fields.empty
let seen a =
let pos = (a == a.var.pa) in
let field = if pos then v_field_seen_pos else v_field_seen_neg in
Var_fields.get field a.var.v_fields
let[@inline] seen_both v =
Var_fields.get v_field_seen_pos v.v_fields &&
Var_fields.get v_field_seen_neg v.v_fields
end
let seen_both v =
Var_fields.get v_field_seen_pos v.v_fields &&
Var_fields.get v_field_seen_neg v.v_fields
module Atom = struct
type t = atom
let dummy = dummy_atom
let[@inline] level a = a.var.v_level
let[@inline] var a = a.var
let[@inline] neg a = a.neg
let[@inline] abs a = a.var.pa
let[@inline] lit a = a.lit
let[@inline] equal a b = a == b
let[@inline] compare a b = Pervasives.compare a.aid b.aid
let[@inline] reason a = Var.reason a.var
let[@inline] id a = a.aid
let[@inline] is_true a = a.is_true
let[@inline] is_false a = a.neg.is_true
let mark a =
let pos = (a == a.var.pa) in
let field = if pos then v_field_seen_pos else v_field_seen_neg in
a.var.v_fields <- Var_fields.set field true a.var.v_fields
let[@inline] seen a =
let pos = equal a (abs a) in
if pos
then Var_fields.get v_field_seen_pos a.var.v_fields
else Var_fields.get v_field_seen_neg a.var.v_fields
(* Decisions & propagations *)
type t =
| Lit of lit
| Atom of atom
let[@inline] mark a =
let pos = equal a (abs a) in
if pos
then a.var.v_fields <- Var_fields.set v_field_seen_pos true a.var.v_fields
else a.var.v_fields <- Var_fields.set v_field_seen_neg true a.var.v_fields
let of_lit l = Lit l
let of_atom a = Atom a
let[@inline] make lit =
let var, negated = Var.make lit in
match negated with
| Formula_intf.Negated -> var.na
| Formula_intf.Same_sign -> var.pa
let pp fmt a = E.Formula.print fmt a.lit
let pp_a fmt v =
if Array.length v = 0 then (
Format.fprintf fmt ""
) else (
pp fmt v.(0);
if (Array.length v) > 1 then begin
for i = 1 to (Array.length v) - 1 do
Format.fprintf fmt " %a" pp v.(i)
done
end
)
(* Complete debug printing *)
let sign a = if a == a.var.pa then "+" else "-"
let debug_reason fmt = function
| n, _ when n < 0 ->
Format.fprintf fmt "%%"
| n, None ->
Format.fprintf fmt "%d" n
| n, Some Decision ->
Format.fprintf fmt "@@%d" n
| n, Some Bcp c ->
Format.fprintf fmt "->%d/%s" n (name_of_clause c)
| n, Some Semantic ->
Format.fprintf fmt "::%d" n
let pp_level fmt a =
debug_reason fmt (a.var.v_level, a.var.reason)
let debug_value fmt a =
if a.is_true then
Format.fprintf fmt "T%a" pp_level a
else if a.neg.is_true then
Format.fprintf fmt "F%a" pp_level a
else
Format.fprintf fmt ""
let debug out a =
Format.fprintf out "%s%d[%a][atom:@[<hov>%a@]]"
(sign a) (a.var.vid+1) debug_value a E.Formula.print a.lit
let debug_a out vec =
Array.iter (fun a -> Format.fprintf out "%a@ " debug a) vec
end
(* Elements *)
let[@inline] elt_of_lit l = E_lit l
let[@inline] elt_of_var v = E_var v
module Elt = struct
type t = elt
let[@inline] of_lit l = E_lit l
let[@inline] of_var v = E_var v
let get_elt_id = function
| E_lit l -> l.lid | E_var v -> v.vid
let get_elt_level = function
| E_lit l -> l.l_level | E_var v -> v.v_level
let get_elt_idx = function
| E_lit l -> l.l_idx | E_var v -> v.v_idx
let get_elt_weight = function
| E_lit l -> l.l_weight | E_var v -> v.v_weight
let[@inline] id = function
| E_lit l -> l.lid | E_var v -> v.vid
let[@inline] level = function
| E_lit l -> l.l_level | E_var v -> v.v_level
let[@inline] idx = function
| E_lit l -> l.l_idx | E_var v -> v.v_idx
let[@inline] weight = function
| E_lit l -> l.l_weight | E_var v -> v.v_weight
let set_elt_level e lvl = match e with
| E_lit l -> l.l_level <- lvl | E_var v -> v.v_level <- lvl
let set_elt_idx e i = match e with
| E_lit l -> l.l_idx <- i | E_var v -> v.v_idx <- i
let set_elt_weight e w = match e with
| E_lit l -> l.l_weight <- w | E_var v -> v.v_weight <- w
let[@inline] set_level e lvl = match e with
| E_lit l -> l.l_level <- lvl | E_var v -> v.v_level <- lvl
let[@inline] set_idx e i = match e with
| E_lit l -> l.l_idx <- i | E_var v -> v.v_idx <- i
let[@inline] set_weight e w = match e with
| E_lit l -> l.l_weight <- w | E_var v -> v.v_weight <- w
end
(* Name generation *)
let fresh_lname =
let cpt = ref 0 in
fun () -> incr cpt; "L" ^ (string_of_int !cpt)
module Trail_elt = struct
type t = trail_elt
let[@inline] of_lit l = Lit l
let[@inline] of_atom a = Atom a
let fresh_hname =
let cpt = ref 0 in
fun () -> incr cpt; "H" ^ (string_of_int !cpt)
let debug fmt = function
| Lit l -> Lit.debug fmt l
| Atom a -> Atom.debug fmt a
end
let fresh_tname =
let cpt = ref 0 in
fun () -> incr cpt; "T" ^ (string_of_int !cpt)
module Clause = struct
type t = clause
let dummy = dummy_clause
let fresh_name =
let cpt = ref 0 in
fun () -> incr cpt; "C" ^ (string_of_int !cpt)
let make =
let n = ref 0 in
fun ?tag ali premise ->
let atoms = Array.of_list ali in
let name = !n in
incr n;
{ name;
tag = tag;
atoms = atoms;
visited = false;
attached = false;
activity = 0.;
cpremise = premise}
(* Pretty printing for atoms and clauses *)
let print_lit fmt v = E.Term.print fmt v.term
let empty = make [] (History [])
let name = name_of_clause
let[@inline] atoms c = c.atoms
let[@inline] tag c = c.tag
let print_atom fmt a = E.Formula.print fmt a.lit
let[@inline] premise c = c.cpremise
let[@inline] set_premise c p = c.cpremise <- p
let print_atoms fmt v =
if Array.length v = 0 then
Format.fprintf fmt ""
else begin
print_atom fmt v.(0);
if (Array.length v) > 1 then begin
for i = 1 to (Array.length v) - 1 do
Format.fprintf fmt " %a" print_atom v.(i)
done
end
end
let[@inline] visited c = c.visited
let[@inline] set_visited c b = c.visited <- b
let print_clause fmt c =
Format.fprintf fmt "%s : %a" c.name print_atoms c.atoms
let[@inline] attached c = c.attached
let[@inline] set_attached c b = c.attached <- b
(* Complete debug printing *)
let sign a = if a == a.var.pa then "+" else "-"
let[@inline] activity c = c.activity
let[@inline] set_activity c w = c.activity <- w
let pp_reason fmt = function
| n, _ when n < 0 ->
Format.fprintf fmt "%%"
| n, None ->
Format.fprintf fmt "%d" n
| n, Some Decision ->
Format.fprintf fmt "@@%d" n
| n, Some Bcp c ->
Format.fprintf fmt "->%d/%s" n c.name
| n, Some Semantic ->
Format.fprintf fmt "::%d" n
let pp fmt c =
Format.fprintf fmt "%s : %a" (name c) Atom.pp_a c.atoms
let pp_level fmt a =
pp_reason fmt (a.var.v_level, a.var.reason)
let debug_premise out = function
| Hyp -> Format.fprintf out "hyp"
| Local -> Format.fprintf out "local"
| Lemma _ -> Format.fprintf out "th_lemma"
| History v ->
List.iter (fun c -> Format.fprintf out "%s,@ " (name_of_clause c)) v
let pp_value fmt a =
if a.is_true then
Format.fprintf fmt "T%a" pp_level a
else if a.neg.is_true then
Format.fprintf fmt "F%a" pp_level a
else
Format.fprintf fmt ""
let debug out ({atoms=arr; cpremise=cp;_}as c) =
Format.fprintf out "%s@[<hov>{@[<hov>%a@]}@ cpremise={@[<hov>%a@]}@]"
(name c) Atom.debug_a arr debug_premise cp
let pp_premise out = function
| Hyp -> Format.fprintf out "hyp"
| Local -> Format.fprintf out "local"
| Lemma _ -> Format.fprintf out "th_lemma"
| History v -> List.iter (fun { name; _ } -> Format.fprintf out "%s,@ " name) v
let pp_assign fmt v =
match v.assigned with
| None ->
Format.fprintf fmt ""
| Some t ->
Format.fprintf fmt "@[<hov>@@%d->@ %a@]" v.l_level E.Term.print t
let pp_lit out v =
Format.fprintf out "%d[%a][lit:@[<hov>%a@]]"
(v.lid+1) pp_assign v E.Term.print v.term
let pp_atom out a =
Format.fprintf out "%s%d[%a][atom:@[<hov>%a@]]"
(sign a) (a.var.vid+1) pp_value a E.Formula.print a.lit
let pp_atoms_vec out vec =
Array.iter (fun a -> Format.fprintf out "%a@ " pp_atom a) vec
let pp_clause out {name=name; atoms=arr; cpremise=cp;_} =
Format.fprintf out "%s@[<hov>{@[<hov>%a@]}@ cpremise={@[<hov>%a@]}@]"
name pp_atoms_vec arr pp_premise cp
let pp_dimacs fmt {atoms;_} =
let aux fmt a =
Array.iter (fun p ->
let pp_dimacs fmt {atoms;_} =
let aux fmt a =
Array.iter (fun p ->
Format.fprintf fmt "%s%d "
(if p == p.var.pa then "-" else "")
(p.var.vid+1)
) a
in
Format.fprintf fmt "%a0" aux atoms
let pp fmt = function
| Lit l -> pp_lit fmt l
| Atom a -> pp_atom fmt a
in
Format.fprintf fmt "%a0" aux atoms
end
end

View file

@ -24,6 +24,8 @@ Copyright 2016 Simon Cruanes
module Var_fields = BitField.Make()
type 'a printer = Format.formatter -> 'a -> unit
module type S = sig
(** The signatures of clauses used in the Solver. *)
@ -86,7 +88,7 @@ module type S = sig
[a.neg] wraps the theory negation of [f]. *)
and clause = {
name : string; (** Clause name, mainly for printing, unique. *)
name : int; (** Clause name, mainly for printing, unique. *)
tag : int option; (** User-provided tag for clauses. *)
atoms : atom array; (** The atoms that constitute the clause.*)
mutable cpremise : premise; (** The premise of the clause, i.e. the justification
@ -124,15 +126,11 @@ module type S = sig
satisfied by the solver. *)
(** {2 Decisions and propagations} *)
type t =
type trail_elt =
| Lit of lit
| Atom of atom (**)
(** Either a lit of an atom *)
val of_lit : lit -> t
val of_atom : atom -> t
(** Constructors and destructors *)
(** {2 Elements} *)
type elt =
@ -145,77 +143,136 @@ module type S = sig
val iter_elt : (elt -> unit) -> unit
(** Read access to the vector of variables created *)
val elt_of_lit : lit -> elt
val elt_of_var : var -> elt
(** Constructors & destructor for elements *)
(** {2 Variables, Literals & Clauses } *)
val get_elt_id : elt -> int
val get_elt_level : elt -> int
val get_elt_idx : elt -> int
val get_elt_weight : elt -> float
val set_elt_level : elt -> int -> unit
val set_elt_idx : elt -> int -> unit
val set_elt_weight : elt -> float -> unit
(** Accessors for elements *)
module Lit : sig
type t = lit
val term : t -> term
val make : term -> t
(** Returns the variable associated with the term *)
(** {2 Variables, Litterals & Clauses } *)
val level : t -> int
val set_level : t -> int -> unit
val dummy_var : var
val dummy_atom : atom
val dummy_clause : clause
(** Dummy values for use in vector dummys *)
val assigned : t -> term option
val set_assigned : t -> term option -> unit
val weight : t -> float
val set_weight : t -> float -> unit
val add_term : term -> lit
(** Returns the variable associated with the term *)
val add_atom : formula -> atom
(** Returns the atom associated with the given formula *)
val make_boolean_var : formula -> var * Formula_intf.negated
(** Returns the variable linked with the given formula, and whether the atom associated with the formula
is [var.pa] or [var.na] *)
val pp : t printer
val debug : t printer
end
val empty_clause : clause
(** The empty clause *)
val make_clause : ?tag:int -> string -> atom list -> premise -> clause
(** [make_clause name atoms size premise] creates a clause with the given attributes. *)
module Var : sig
type t = var
val dummy : t
(** {2 Helpers} *)
val pos : t -> atom
val neg : t -> atom
val mark : atom -> unit
(** Mark the atom as seen, using the 'seen' field in the variable. *)
val level : t -> int
val set_level : t -> int -> unit
val reason : t -> reason option
val set_reason : t -> reason option -> unit
val assignable : t -> lit list option
val set_assignable : t -> lit list option -> unit
val weight : t -> float
val set_weight : t -> float -> unit
val seen : atom -> bool
(** Returns wether the atom has been marked as seen. *)
val make : formula -> t * Formula_intf.negated
(** Returns the variable linked with the given formula,
and whether the atom associated with the formula
is [var.pa] or [var.na] *)
val seen_both : var -> bool
(** both atoms have been seen? *)
val seen_both : t -> bool
(** both atoms have been seen? *)
val clear : var -> unit
(** Clear the 'seen' field of the variable. *)
val clear : t -> unit
(** Clear the 'seen' field of the variable. *)
end
module Atom : sig
type t = atom
val dummy : t
val level : t -> int
val reason : t -> reason option
val lit : t -> formula
val equal : t -> t -> bool
val compare : t -> t -> int
val var : t -> Var.t
val abs : t -> t (** positive atom *)
val neg : t -> t
val id : t -> int
val is_true : t -> bool
val is_false : t -> bool
(** {2 Clause names} *)
val make : formula -> t
(** Returns the atom associated with the given formula *)
val fresh_name : unit -> string
val fresh_lname : unit -> string
val fresh_tname : unit -> string
val fresh_hname : unit -> string
(** Fresh names for clauses *)
val mark : t -> unit
(** Mark the atom as seen, using the 'seen' field in the variable. *)
(** {2 Printing} *)
val seen : t -> bool
(** Returns wether the atom has been marked as seen. *)
val print_lit : Format.formatter -> lit -> unit
val print_atom : Format.formatter -> atom -> unit
val print_clause : Format.formatter -> clause -> unit
(** Pretty printing functions for atoms and clauses *)
val pp : t printer
val pp_a : t array printer
val debug : t printer
val debug_a : t array printer
end
val pp : Format.formatter -> t -> unit
val pp_lit : Format.formatter -> lit -> unit
val pp_atom : Format.formatter -> atom -> unit
val pp_clause : Format.formatter -> clause -> unit
val pp_dimacs : Format.formatter -> clause -> unit
val pp_reason : Format.formatter -> (int * reason option) -> unit
(** Debug function for atoms and clauses (very verbose) *)
module Elt : sig
type t = elt
val of_lit : Lit.t -> t
val of_var : Var.t -> t
val id : t -> int
val level : t -> int
val idx : t -> int
val weight : t -> float
val set_level : t -> int -> unit
val set_idx : t -> int -> unit
val set_weight : t -> float -> unit
end
module Clause : sig
type t = clause
val dummy : t
val name : t -> string
val atoms : t -> Atom.t array
val tag : t -> int option
val premise : t -> premise
val set_premise : t -> premise -> unit
val visited : t -> bool
val set_visited : t -> bool -> unit
val attached : t -> bool
val set_attached : t -> bool -> unit
val activity : t -> float
val set_activity : t -> float -> unit
val empty : t
(** The empty clause *)
val make : ?tag:int -> Atom.t list -> premise -> clause
(** [make_clause name atoms size premise] creates a clause with the given attributes. *)
val pp : t printer
val pp_dimacs : t printer
val debug : t printer
end
module Trail_elt : sig
type t = trail_elt
val of_lit : Lit.t -> t
val of_atom : Atom.t -> t
(** Constructors and destructors *)
val debug : t printer
end
end

View file

@ -41,7 +41,7 @@ module Make
let check_clause c =
let l = List.map (function a ->
Log.debugf 99
(fun k -> k "Checking value of %a" S.St.pp_atom (S.St.add_atom a));
(fun k -> k "Checking value of %a" S.St.Atom.debug (S.St.Atom.make a));
state.Msat.eval a) c in
List.exists (fun x -> x) l
in