: sig
val pure_smt_check : Node.t -> Node.t list -> int list option
val check : Node.t -> Node.t list -> int list option
end = struct
let check_fixpoint ?(pure_smt=false) n visited =
Prover.assume_goal n;
let n_array = n.cube.Cube.array in
let nodes =
List.fold_left
(fun nodes vis_n ->
let vis_cube = vis_n.cube in
let d = Instantiation.relevant ~of_cube:vis_cube ~to_cube:n.cube in
List.fold_left
(fun nodes ss ->
let vis_renamed = ArrayAtom.apply_subst ss vis_cube.Cube.array in
if not pure_smt && ArrayAtom.subset vis_renamed n_array then
raise (Fixpoint [vis_n.tag])
else if not pure_smt &&
Cube.inconsistent_2arrays vis_renamed n_array then nodes
else if ArrayAtom.nb_diff vis_renamed n_array > 1 then
(vis_n, vis_renamed)::nodes
else (Prover.assume_node vis_n vis_renamed; nodes)
) nodes d
) [] visited
in
TimeSort.start ();
let nodes =
List.fast_sort
(fun (n1, a1) (n2, a2) -> ArrayAtom.compare_nb_common n_array a1 a2)
nodes
in
TimeSort.pause ();
List.iter (fun (vn, ar_renamed) -> Prover.assume_node vn ar_renamed) nodes
let easy_fixpoint s nodes =
if delete && (s.deleted || Node.has_deleted_ancestor s)
then Some []
else
let db = ref None in
let ars = Node.array s in
ignore (List.exists
(fun sp ->
if ArrayAtom.subset (Node.array sp) ars then
begin db := Some [sp.tag]; true end
else false
) nodes);
!db
let hard_fixpoint s nodes =
try
check_fixpoint s nodes;
None
with
| Fixpoint db -> Some db
| Exit -> None
| Smt.Unsat db -> Some db
let pure_smt_check s nodes =
try
check_fixpoint ~pure_smt:true s nodes;
None
with
| Fixpoint db -> Some db
| Exit -> None
| Smt.Unsat db -> Some db
let check s visited =
Debug.unsafe s;
TimeFix.start ();
let r =
match easy_fixpoint s visited with
| None -> hard_fixpoint s visited
| r -> r
in
TimeFix.pause ();
r
end