: sig
val easy_fixpoint : Node.t -> Node.t Cubetrie.t -> int list option
val peasy_fixpoint : Node.t -> Node.t Cubetrie.t -> int list option
val hard_fixpoint : Node.t -> Node.t Cubetrie.t -> int list option
val check : Node.t -> Node.t Cubetrie.t -> int list option
end = struct
let first_action =
match Prover.SMT.check_strategy with
| Smt.Eager -> Prover.assume_goal
| Smt.Lazy -> Prover.assume_goal_no_check
let assume =
match Prover.SMT.check_strategy with
| Smt.Eager -> Prover.assume_node
| Smt.Lazy -> Prover.assume_node_no_check
let last_action =
match Prover.SMT.check_strategy with
| Smt.Eager -> fun () -> ()
| Smt.Lazy -> Prover.run
let check_and_add n nodes vis_n=
let n_array = Node.array n in
let vis_cube = vis_n.cube in
let vis_array = vis_cube.Cube.array 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_array in
if Cube.inconsistent_2arrays vis_renamed n_array then nodes
else if true || 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
let check_fixpoint s visited =
first_action s;
let s_array = Node.array s in
let unprioritize_cands = false in
let nodes, cands =
Cubetrie.fold
(fun (nodes, cands) vis_p ->
if unprioritize_cands && vis_p.kind = Approx then
nodes, vis_p :: cands
else check_and_add s nodes vis_p, cands
) ([], []) visited in
let nodes = List.fold_left (check_and_add s) nodes cands in
TimeSort.start ();
let nodes = match Prover.SMT.check_strategy with
| Smt.Lazy -> nodes
| Smt.Eager ->
List.fast_sort
(fun (n1, a1) (n2, a2) ->
if unprioritize_cands &&
n1.kind = Approx && n2.kind <> Approx then 1
else
if unprioritize_cands &&
n2.kind = Approx && n1.kind <> Approx then 1
else ArrayAtom.compare_nb_common s_array a1 a2)
nodes
in
TimeSort.pause ();
List.iter (fun (vn, ar_renamed) -> assume vn ar_renamed) nodes;
last_action ()
let easy_fixpoint s nodes =
if delete && (s.deleted || Node.has_deleted_ancestor s)
then Some []
else Cubetrie.mem_array (Node.array s) nodes
let medium_fixpoint s visited =
let vars, s_array = Node.variables s, Node.array s in
let substs = Variable.all_permutations vars vars in
let substs = List.tl substs in
try
List.iter (fun ss ->
let u = ArrayAtom.apply_subst ss s_array in
match Cubetrie.mem_array u visited with
| Some uc -> raise (Fixpoint uc)
| None -> ()
) substs;
None
with Fixpoint uc -> Some uc
let hard_fixpoint s nodes =
try
check_fixpoint s nodes;
None
with
| Fixpoint db -> Some db
| Exit -> None
| Smt.Unsat db -> Some db
let peasy_fixpoint s nodes =
match easy_fixpoint s nodes with
| None -> medium_fixpoint s nodes
| r -> r
let check s nodes =
Debug.unsafe s;
TimeFix.start ();
let r =
match easy_fixpoint s nodes with
| None ->
(match medium_fixpoint s nodes with
| None -> hard_fixpoint s nodes
| r -> r)
| r -> r
in
TimeFix.pause ();
r
end