mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-06 11:15:43 -05:00
210 lines
5.9 KiB
OCaml
210 lines
5.9 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 Hashcons
|
|
|
|
type 'a view =
|
|
| Eq of 'a * 'a
|
|
| Distinct of bool * 'a list
|
|
| Builtin of bool * Hstring.t * 'a list
|
|
|
|
module type OrderedType = sig
|
|
type t
|
|
val compare : t -> t -> int
|
|
val hash : t -> int
|
|
val print : Format.formatter -> t -> unit
|
|
end
|
|
|
|
module type S = sig
|
|
type elt
|
|
type t
|
|
|
|
val make : elt view -> t
|
|
val view : t -> elt view
|
|
|
|
val neg : t -> t
|
|
|
|
val add_label : Hstring.t -> t -> unit
|
|
val label : t -> Hstring.t
|
|
|
|
val print : Format.formatter -> t -> unit
|
|
|
|
val compare : t -> t -> int
|
|
val equal : t -> t -> bool
|
|
val hash : t -> int
|
|
|
|
module Map : Map.S with type key = t
|
|
module Set : Set.S with type elt = t
|
|
|
|
end
|
|
|
|
module Make (X : OrderedType) : S with type elt = X.t = struct
|
|
|
|
type elt = X.t
|
|
type t = (X.t view) hash_consed
|
|
|
|
module V = struct
|
|
type t = X.t view
|
|
|
|
let equal a1 a2 =
|
|
match a1, a2 with
|
|
| Eq(t1, t2), Eq(u1, u2) ->
|
|
(X.compare t1 u1 = 0 && X.compare t2 u2 = 0) ||
|
|
(X.compare t1 u2 = 0 && X.compare t2 u1 = 0)
|
|
| Distinct (b1,lt1), Distinct (b2,lt2) ->
|
|
(try
|
|
b1 = b2 &&
|
|
List.for_all2 (fun x y -> X.compare x y = 0) lt1 lt2
|
|
with Invalid_argument _ -> false)
|
|
| Builtin(b1, n1, l1), Builtin(b2, n2, l2) ->
|
|
(try
|
|
b1 = b2 && Hstring.equal n1 n2
|
|
&&
|
|
List.for_all2 (fun x y -> X.compare x y = 0) l1 l2
|
|
with Invalid_argument _ -> false)
|
|
| _ -> false
|
|
|
|
let hash a = match a with
|
|
| Eq(t1, t2) -> abs (19 * (X.hash t1 + X.hash t2))
|
|
| Distinct (b,lt) ->
|
|
let x = if b then 7 else 23 in
|
|
abs (17 * List.fold_left (fun acc t -> (X.hash t) + acc ) x lt)
|
|
| Builtin(b, n, l) ->
|
|
let x = if b then 7 else 23 in
|
|
abs
|
|
(List.fold_left
|
|
(fun acc t-> acc*13 + X.hash t) (Hstring.hash n+x) l)
|
|
end
|
|
|
|
module H = Make_consed(V)
|
|
|
|
let compare a1 a2 = Pervasives.compare a1.tag a2.tag
|
|
let equal a1 a2 = a1 == a2
|
|
let hash a1 = a1.tag
|
|
|
|
module T = struct
|
|
type t' = t
|
|
type t = t'
|
|
let compare=compare
|
|
let equal = equal
|
|
let hash = hash
|
|
end
|
|
|
|
let make t = H.hashcons t
|
|
let view a = a.node
|
|
|
|
let neg a = match view a with
|
|
| Eq(x, y) -> make (Distinct (false,[x; y]))
|
|
| Distinct (false, [x; y]) -> make (Eq (x, y))
|
|
| Distinct (true, [x; y]) -> make (Distinct (false,[x; y]))
|
|
| Distinct (false, l) -> make (Distinct (true,l))
|
|
| Distinct _ -> assert false
|
|
| Builtin(b, n, l) -> make (Builtin (not b, n, l))
|
|
|
|
module Labels = Hashtbl.Make(T)
|
|
|
|
let labels = Labels.create 100007
|
|
|
|
let add_label lbl t = Labels.replace labels t lbl
|
|
|
|
let label t = try Labels.find labels t with Not_found -> Hstring.empty
|
|
|
|
let print_list fmt = function
|
|
| [] -> ()
|
|
| z :: l ->
|
|
Format.fprintf fmt "%a" X.print z;
|
|
List.iter (Format.fprintf fmt ", %a" X.print) l
|
|
|
|
let ale = Hstring.make "<="
|
|
let alt = Hstring.make "<"
|
|
|
|
let print fmt a =
|
|
let lbl = Hstring.view (label a) in
|
|
let lbl = if lbl = "" then lbl else lbl^":" in
|
|
match view a with
|
|
| Eq (z1, z2) ->
|
|
if equal z1 z2 then Format.fprintf fmt "True"
|
|
else Format.fprintf fmt "%s%a=%a" lbl X.print z1 X.print z2
|
|
| Distinct (b,(z::l)) ->
|
|
let b = if b then "~" else "" in
|
|
Format.fprintf fmt "%s%s%a" lbl b X.print z;
|
|
List.iter (fun x -> Format.fprintf fmt "<>%a" X.print x) l
|
|
|
|
| Builtin (true, n, [v1;v2]) when Hstring.equal n ale ->
|
|
Format.fprintf fmt "%s %a <= %a" lbl X.print v1 X.print v2
|
|
|
|
| Builtin (true, n, [v1;v2]) when Hstring.equal n alt ->
|
|
Format.fprintf fmt "%s %a < %a" lbl X.print v1 X.print v2
|
|
|
|
| Builtin (false, n, [v1;v2]) when Hstring.equal n ale ->
|
|
Format.fprintf fmt "%s %a > %a" lbl X.print v1 X.print v2
|
|
|
|
| Builtin (false, n, [v1;v2]) when Hstring.equal n alt ->
|
|
Format.fprintf fmt "%s %a >= %a" lbl X.print v1 X.print v2
|
|
|
|
| Builtin (b, n, l) ->
|
|
let b = if b then "" else "~" in
|
|
Format.fprintf fmt "%s%s%s(%a)" lbl b (Hstring.view n) print_list l
|
|
| _ -> assert false
|
|
|
|
module Set = Set.Make(T)
|
|
module Map = Map.Make(T)
|
|
|
|
end
|
|
|
|
module type S_Term = sig
|
|
|
|
include S with type elt = Term.t
|
|
|
|
val mk_pred : Term.t -> t
|
|
|
|
val true_ : t
|
|
val false_ : t
|
|
|
|
(* val terms_of : t -> Term.Set.t
|
|
val vars_of : t -> Symbols.Set.t
|
|
*)
|
|
(* module SetEq : Set.S with type elt = t * Term.t * Term.t*)
|
|
end
|
|
|
|
module LT : S_Term = struct
|
|
|
|
module L = Make(Term)
|
|
include L
|
|
|
|
let mk_pred t = make (Eq (t, Term.true_) )
|
|
|
|
let true_ = mk_pred Term.true_
|
|
let false_ = mk_pred Term.false_
|
|
|
|
let neg a = match view a with
|
|
| Eq(t1, t2) when Term.equal t2 Term.false_ ->
|
|
make (Eq (t1, Term.true_))
|
|
| Eq(t1, t2) when Term.equal t2 Term.true_ ->
|
|
make (Eq (t1, Term.false_))
|
|
| _ -> L.neg a
|
|
|
|
(* let terms_of a =
|
|
let l = match view a with
|
|
| Eq (t1, t2) -> [t1; t2]
|
|
| Distinct (_, l) | Builtin (_, _, l) -> l
|
|
in
|
|
List.fold_left Term.subterms Term.Set.empty l
|
|
*)
|
|
|
|
module SS = Symbols.Set
|
|
(* let vars_of a =
|
|
Term.Set.fold (fun t -> SS.union (Term.vars_of t)) (terms_of a) SS.empty
|
|
*)
|
|
end
|
|
|