mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-06 03:05:31 -05:00
253 lines
6.8 KiB
OCaml
253 lines
6.8 KiB
OCaml
(**************************************************************************)
|
|
(* *)
|
|
(* Cubicle *)
|
|
(* Combining model checking algorithms and SMT solvers *)
|
|
(* *)
|
|
(* Sylvain Conchon and Alain Mebsout *)
|
|
(* Universite Paris-Sud 11 *)
|
|
(* *)
|
|
(* Copyright 2011. This file is distributed under the terms of the *)
|
|
(* Apache Software License version 2.0 *)
|
|
(* *)
|
|
(**************************************************************************)
|
|
|
|
open Format
|
|
open Sig
|
|
|
|
module rec CX : sig
|
|
include Sig.X
|
|
|
|
val extract1 : r -> X1.t option
|
|
val embed1 : X1.t -> r
|
|
|
|
val extract5 : r -> X5.t option
|
|
val embed5 : X5.t -> r
|
|
|
|
end =
|
|
struct
|
|
|
|
type r =
|
|
| Term of Term.t
|
|
| X1 of X1.t
|
|
| X5 of X5.t
|
|
|
|
let extract1 = function X1 r -> Some r | _ -> None
|
|
let extract5 = function X5 r -> Some r | _ -> None
|
|
|
|
let embed1 x = X1 x
|
|
let embed5 x = X5 x
|
|
|
|
let is_int v =
|
|
let ty = match v with
|
|
| X1 x -> X1.type_info x
|
|
| X5 x -> X5.type_info x
|
|
| Term t -> (Term.view t).Term.ty
|
|
in
|
|
ty = Ty.Tint
|
|
|
|
let rec compare a b =
|
|
let c = compare_tag a b in
|
|
if c = 0 then comparei a b else c
|
|
|
|
and compare_tag a b =
|
|
Pervasives.compare (theory_num a) (theory_num b)
|
|
|
|
and comparei a b =
|
|
match a, b with
|
|
| X1 x, X1 y -> X1.compare x y
|
|
| X5 x, X5 y -> X5.compare x y
|
|
| Term x , Term y -> Term.compare x y
|
|
| _ -> assert false
|
|
|
|
and theory_num x = Obj.tag (Obj.repr x)
|
|
|
|
let equal a b = compare a b = 0
|
|
|
|
let hash = function
|
|
| Term t -> Term.hash t
|
|
| X1 x -> X1.hash x
|
|
| X5 x -> X5.hash x
|
|
|
|
module MR = Map.Make(struct type t = r let compare = compare end)
|
|
|
|
let print fmt r =
|
|
match r with
|
|
| X1 t -> fprintf fmt "%a" X1.print t
|
|
| X5 t -> fprintf fmt "%a" X5.print t
|
|
| Term t -> fprintf fmt "%a" Term.print t
|
|
|
|
let leaves r =
|
|
match r with
|
|
| X1 t -> X1.leaves t
|
|
| X5 t -> X5.leaves t
|
|
| Term _ -> [r]
|
|
|
|
let term_embed t = Term t
|
|
|
|
let term_extract r =
|
|
match r with
|
|
| X1 _ -> X1.term_extract r
|
|
| X5 _ -> X5.term_extract r
|
|
| Term t -> Some t
|
|
|
|
let subst p v r =
|
|
if equal p v then r
|
|
else match r with
|
|
| X1 t -> X1.subst p v t
|
|
| X5 t -> X5.subst p v t
|
|
| Term _ -> if equal p r then v else r
|
|
|
|
let make t =
|
|
let {Term.f=sb} = Term.view t in
|
|
match X1.is_mine_symb sb, X5.is_mine_symb sb with
|
|
| true, false -> X1.make t
|
|
| false, true -> X5.make t
|
|
| false, false -> Term t, []
|
|
| _ -> assert false
|
|
|
|
let fully_interpreted sb =
|
|
match X1.is_mine_symb sb, X5.is_mine_symb sb with
|
|
| true, false -> X1.fully_interpreted sb
|
|
| false, true -> X5.fully_interpreted sb
|
|
| false, false -> false
|
|
| _ -> assert false
|
|
|
|
let add_mr =
|
|
List.fold_left
|
|
(fun solved (p,v) ->
|
|
MR.add p (v::(try MR.find p solved with Not_found -> [])) solved)
|
|
|
|
let unsolvable = function
|
|
| X1 x -> X1.unsolvable x
|
|
| X5 x -> X5.unsolvable x
|
|
| Term _ -> true
|
|
|
|
let partition tag =
|
|
List.partition
|
|
(fun (u,t) ->
|
|
(theory_num u = tag || unsolvable u) &&
|
|
(theory_num t = tag || unsolvable t))
|
|
|
|
let rec solve_list solved l =
|
|
List.fold_left
|
|
(fun solved (a,b) ->
|
|
let cmp = compare a b in
|
|
if cmp = 0 then solved else
|
|
match a , b with
|
|
(* both sides are empty *)
|
|
| Term _ , Term _ ->
|
|
add_mr solved (unsolvable_values cmp a b)
|
|
|
|
(* only one side is empty *)
|
|
| (a, b)
|
|
when unsolvable a || unsolvable b || compare_tag a b = 0 ->
|
|
let a,b = if unsolvable a then b,a else a,b in
|
|
let cp , sol = partition (theory_num a) (solvei b a) in
|
|
solve_list (add_mr solved cp) sol
|
|
|
|
(* both sides are not empty *)
|
|
| a , b -> solve_theoryj solved a b
|
|
) solved l
|
|
|
|
and unsolvable_values cmp a b =
|
|
match a, b with
|
|
(* Clash entre theories: On peut avoir ces pbs ? *)
|
|
| X1 _, X5 _
|
|
| X5 _, X1 _
|
|
-> assert false
|
|
|
|
(* theorie d'un cote, vide de l'autre *)
|
|
| X1 _, _ | _, X1 _ -> X1.solve a b
|
|
| X5 _, _ | _, X5 _ -> X5.solve a b
|
|
| Term _, Term _ -> [if cmp > 0 then a,b else b,a]
|
|
|
|
and solve_theoryj solved xi xj =
|
|
let cp , sol = partition (theory_num xj) (solvei xi xj) in
|
|
solve_list (add_mr solved cp) (List.rev_map (fun (x,y) -> y,x) sol)
|
|
|
|
and solvei a b =
|
|
match b with
|
|
| X1 _ -> X1.solve a b
|
|
| X5 _ -> X5.solve a b
|
|
| Term _ -> assert false
|
|
|
|
let rec solve_rec mt ab =
|
|
let mr = solve_list mt ab in
|
|
let mr , ab =
|
|
MR.fold
|
|
(fun p lr ((mt,ab) as acc) -> match lr with
|
|
[] -> assert false
|
|
| [_] -> acc
|
|
| x::lx ->
|
|
MR.add p [x] mr , List.rev_map (fun y-> (x,y)) lx)
|
|
mr (mr,[])
|
|
in
|
|
if ab = [] then mr else solve_rec mr ab
|
|
|
|
let solve a b =
|
|
MR.fold
|
|
(fun p lr ret ->
|
|
match lr with [r] -> (p ,r)::ret | _ -> assert false)
|
|
(solve_rec MR.empty [a,b]) []
|
|
|
|
let rec type_info = function
|
|
| X1 t -> X1.type_info t
|
|
| X5 t -> X5.type_info t
|
|
| Term t -> let {Term.ty = ty} = Term.view t in ty
|
|
|
|
module Rel = struct
|
|
type elt = r
|
|
type r = elt
|
|
|
|
type t = {
|
|
r1: X1.Rel.t;
|
|
r5: X5.Rel.t;
|
|
}
|
|
|
|
let empty _ = {
|
|
r1=X1.Rel.empty ();
|
|
r5=X5.Rel.empty ();
|
|
}
|
|
|
|
let assume env sa =
|
|
let env1, { assume = a1; remove = rm1} = X1.Rel.assume env.r1 sa in
|
|
let env5, { assume = a5; remove = rm5} = X5.Rel.assume env.r5 sa in
|
|
{r1=env1; r5=env5},
|
|
{ assume = a1@a5; remove = rm1@rm5;}
|
|
|
|
let query env a =
|
|
match X1.Rel.query env.r1 a with
|
|
| Yes _ as ans -> ans
|
|
| No -> X5.Rel.query env.r5 a
|
|
|
|
let case_split env =
|
|
let seq1 = X1.Rel.case_split env.r1 in
|
|
let seq5 = X5.Rel.case_split env.r5 in
|
|
seq1 @ seq5
|
|
|
|
let add env r =
|
|
{r1=X1.Rel.add env.r1 r;
|
|
r5=X5.Rel.add env.r5 r }
|
|
end
|
|
|
|
end
|
|
|
|
and TX1 : Polynome.T with type r = CX.r = Arith.Type(CX)
|
|
|
|
and X1 : Sig.THEORY with type t = TX1.t and type r = CX.r =
|
|
Arith.Make(CX)(TX1)
|
|
(struct
|
|
type t = TX1.t
|
|
type r = CX.r
|
|
let extract = CX.extract1
|
|
let embed = CX.embed1
|
|
let assume env _ _ = env, {Sig.assume = []; remove = []}
|
|
end)
|
|
|
|
and X5 : Sig.THEORY with type r = CX.r and type t = CX.r Sum.abstract =
|
|
Sum.Make
|
|
(struct
|
|
include CX
|
|
let extract = extract5
|
|
let embed = embed5
|
|
end)
|