diff --git a/src_colibri2/core/dune b/src_colibri2/core/dune index 2709e1eb32e3118144f1a3b502c865a9be1b09fa..b258dddedc50d2f414b7bc6226c13296f5ea3605 100644 --- a/src_colibri2/core/dune +++ b/src_colibri2/core/dune @@ -2,7 +2,7 @@ (name colibri2_core) (public_name colibri2.core) (synopsis "core for colibri2, e.g. trail, egraph") - (libraries containers ocamlgraph str colibri2.stdlib colibri2.popop_lib dolmen.std) + (libraries containers ocamlgraph str colibri2.stdlib colibri2.popop_lib dolmen.std dolmen_loop) (preprocess (pps ppx_deriving.std ppx_hash)) (flags :standard -w +a-4-42-44-48-50-58-60-40-9@8 -color always -open diff --git a/src_colibri2/core/structures/expr.ml b/src_colibri2/core/structures/expr.ml index b5c34015fcfd3e4398682819d3321f4ff41b4a41..f4674eb6cd6412727eb8f3677b72f6dc3d8d1c09 100644 --- a/src_colibri2/core/structures/expr.ml +++ b/src_colibri2/core/structures/expr.ml @@ -26,28 +26,38 @@ module Ty = struct let pp = print - include Colibri2_popop_lib.Popop_stdlib.MkDatatype(struct + include Colibri2_popop_lib.Popop_stdlib.MkDatatype (struct + type nonrec t = t + + let equal = equal + + let compare = compare + + let hash = hash + + let pp = pp + + let hash_fold_t s t = Base.Hash.fold_int s (hash t) + end) + + module Var = struct + include Dolmen_std.Expr.Ty.Var + + let pp = Dolmen_std.Expr.Print.ty_var + + include Colibri2_popop_lib.Popop_stdlib.MkDatatype (struct type nonrec t = t + let equal = equal + let compare = compare + let hash = hash + let pp = pp + let hash_fold_t s t = Base.Hash.fold_int s (hash t) end) - - module Var = struct - include Dolmen_std.Expr.Ty.Var - - let pp = Dolmen_std.Expr.Print.ty_var - - include Colibri2_popop_lib.Popop_stdlib.MkDatatype(struct - type nonrec t = t - let equal = equal - let compare = compare - let hash = hash - let pp = pp - let hash_fold_t s t = Base.Hash.fold_int s (hash t) - end) end let rec free_vars acc (t : t) = @@ -56,117 +66,160 @@ module Ty = struct | TyApp (_, l) -> List.fold_left free_vars acc l | Arrow (args, ret) -> List.fold_left free_vars (free_vars acc ret) args | Pi (vars, body) -> - let fv = free_vars Var.S.empty body in - let fv = List.fold_left (fun acc v -> Var.S.remove v acc) fv vars in - Var.S.union fv acc + let fv = free_vars Var.S.empty body in + let fv = List.fold_left (fun acc v -> Var.S.remove v acc) fv vars in + Var.S.union fv acc module Const = struct include Dolmen_std.Expr.Ty.Const - let pp fmt (t:t) = Dolmen_std.Expr.Id.print fmt t - - include Colibri2_popop_lib.Popop_stdlib.MkDatatype(struct - type nonrec t = t - let equal = equal - let compare = compare - let hash = hash - let pp = pp - let hash_fold_t s t = Base.Hash.fold_int s (hash t) - end) - end -end + let pp fmt (t : t) = Dolmen_std.Expr.Id.print fmt t -module Term = struct - include Dolmen_std.Expr.Term - let pp = print - - include Colibri2_popop_lib.Popop_stdlib.MkDatatype(struct + include Colibri2_popop_lib.Popop_stdlib.MkDatatype (struct type nonrec t = t + let equal = equal + let compare = compare + let hash = hash + let pp = pp + let hash_fold_t s t = Base.Hash.fold_int s (hash t) end) + end +end - module Const = struct +module Term = struct + include Dolmen_std.Expr.Term + + let pp = print + + include Colibri2_popop_lib.Popop_stdlib.MkDatatype (struct + type nonrec t = t + + let equal = equal + let compare = compare + + let hash = hash + + let pp = pp + + let hash_fold_t s t = Base.Hash.fold_int s (hash t) + end) + + module Const = struct module D = struct - include Dolmen_std.Expr.Term.Const - let pp fmt (t:t) = Dolmen_std.Expr.Id.print fmt t - include Colibri2_popop_lib.Popop_stdlib.MkDatatype(struct + include Dolmen_std.Expr.Term.Const + + let pp fmt (t : t) = Dolmen_std.Expr.Id.print fmt t + + include Colibri2_popop_lib.Popop_stdlib.MkDatatype (struct type nonrec t = t + let equal = equal + let compare = compare + let hash = hash + let pp = pp + let hash_fold_t s t = Base.Hash.fold_int s (hash t) end) end include D - - module HC = Datastructure.Hashtbl(D) - + module HC = Datastructure.Hashtbl (D) end module Var = struct include Dolmen_std.Expr.Term.Var - let pp fmt (t:t) = Dolmen_std.Expr.Id.print fmt t - include Colibri2_popop_lib.Popop_stdlib.MkDatatype(struct - type nonrec t = t - let equal = equal - let compare = compare - let hash = hash - let pp = pp - let hash_fold_t s t = Base.Hash.fold_int s (hash t) + let pp fmt (t : t) = Dolmen_std.Expr.Id.print fmt t + + include Colibri2_popop_lib.Popop_stdlib.MkDatatype (struct + type nonrec t = t + + let equal = equal + + let compare = compare + + let hash = hash + + let pp = pp + + let hash_fold_t s t = Base.Hash.fold_int s (hash t) end) end - let rec free_vars ((acc_ty,acc_term) as acc) (t : t) = match t.term_descr with - | Var v -> (Ty.free_vars acc_ty v.id_ty,Var.S.add v acc_term) + let rec free_vars ((acc_ty, acc_term) as acc) (t : t) = + match t.term_descr with + | Var v -> (Ty.free_vars acc_ty v.id_ty, Var.S.add v acc_term) | Cst _ -> acc | App (f, tys, ts) -> - let acc_ty, acc_term = free_vars acc f in - List.fold_left free_vars ( - List.fold_left Ty.free_vars acc_ty tys, acc_term - ) ts + let acc_ty, acc_term = free_vars acc f in + List.fold_left free_vars + (List.fold_left Ty.free_vars acc_ty tys, acc_term) + ts | Binder ((Lambda (tys, ts) | Exists (tys, ts) | Forall (tys, ts)), body) -> - let (fty,fv) = free_vars (Ty.Var.S.empty,Var.S.empty) body in - let fty = List.fold_left (fun acc ty -> Ty.Var.S.remove ty acc) fty tys in - let fv = List.fold_left (fun acc t -> Var.S.remove t acc) fv ts in - (Ty.Var.S.union acc_ty fty, Var.S.union acc_term fv) + let fty, fv = free_vars (Ty.Var.S.empty, Var.S.empty) body in + let fty = + List.fold_left (fun acc ty -> Ty.Var.S.remove ty acc) fty tys + in + let fv = List.fold_left (fun acc t -> Var.S.remove t acc) fv ts in + (Ty.Var.S.union acc_ty fty, Var.S.union acc_term fv) | Binder (Let_seq l, body) -> - let (acc_ty,fv) = free_vars (acc_ty,Var.S.empty) body in - let (acc_ty,fv) = List.fold_right (fun (v, t) (acc_ty,fv) -> - let fv = Var.S.remove v fv in - let (acc_ty,fv) = free_vars (acc_ty,fv) t in - let acc_ty = Ty.free_vars acc_ty v.id_ty in - (acc_ty,fv) - ) l (acc_ty,fv) in - (acc_ty, Var.S.union acc_term fv) + let acc_ty, fv = free_vars (acc_ty, Var.S.empty) body in + let acc_ty, fv = + List.fold_right + (fun (v, t) (acc_ty, fv) -> + let fv = Var.S.remove v fv in + let acc_ty, fv = free_vars (acc_ty, fv) t in + let acc_ty = Ty.free_vars acc_ty v.id_ty in + (acc_ty, fv)) + l (acc_ty, fv) + in + (acc_ty, Var.S.union acc_term fv) | Binder (Let_par l, body) -> - let (acc_ty,fv) = free_vars (acc_ty,Var.S.empty) body in - let fv = List.fold_right (fun (v, _) fv -> - let fv = Var.S.remove v fv in - fv - ) l fv in - let (acc_ty,fv) = List.fold_right (fun (v, t) (acc_ty,fv) -> - let (acc_ty,fv) = free_vars (acc_ty,fv) t in - let acc_ty = Ty.free_vars acc_ty v.id_ty in - (acc_ty,fv) - ) l (acc_ty,fv) in - (acc_ty, Var.S.union acc_term fv) + let acc_ty, fv = free_vars (acc_ty, Var.S.empty) body in + let fv = + List.fold_right + (fun (v, _) fv -> + let fv = Var.S.remove v fv in + fv) + l fv + in + let acc_ty, fv = + List.fold_right + (fun (v, t) (acc_ty, fv) -> + let acc_ty, fv = free_vars (acc_ty, fv) t in + let acc_ty = Ty.free_vars acc_ty v.id_ty in + (acc_ty, fv)) + l (acc_ty, fv) + in + (acc_ty, Var.S.union acc_term fv) | Match (scrutinee, branches) -> - let acc = free_vars (acc_ty,acc_term) scrutinee in - List.fold_left (fun (acc_ty,acc_term) (pat, body) -> - let (acc_ty,freet) = free_vars (acc_ty,Var.S.empty) body in - let (acc_ty,boundt) = free_vars (acc_ty,Var.S.empty) pat in - let bound = Var.S.diff freet boundt in - (acc_ty, Var.S.union acc_term bound) - ) acc branches - + let acc = free_vars (acc_ty, acc_term) scrutinee in + List.fold_left + (fun (acc_ty, acc_term) (pat, body) -> + let acc_ty, freet = free_vars (acc_ty, Var.S.empty) body in + let acc_ty, boundt = free_vars (acc_ty, Var.S.empty) pat in + let bound = Var.S.diff freet boundt in + (acc_ty, Var.S.union acc_term bound)) + acc branches end -let foo = 1 +let add_builtins, additional_builtins = + let q : Dolmen_loop.Typer.T.builtin_symbols Base.Queue.t = + Base.Queue.create () + in + ( Base.Queue.enqueue q, + fun e t -> + let o = + Base.Queue.find_map q ~f:(fun f -> + match f e t with `Not_found -> None | x -> Some x) + in + Option.value ~default:`Not_found o ) diff --git a/src_colibri2/solver/input.ml b/src_colibri2/solver/input.ml index 07ed927216150b2a36ac409fb7e13fbed9ef6827..a5cab114417c344e821fdfb4256b0eaf420e9892 100644 --- a/src_colibri2/solver/input.ml +++ b/src_colibri2/solver/input.ml @@ -63,6 +63,8 @@ module Typer = struct Dolmen_loop.Typer.Pipe (Dolmen.Std.Expr) (Dolmen.Std.Expr.Print) (State) (T) end +let () = Typer.additional_builtins := Colibri2_core.Expr.additional_builtins + let split_input = function | `Stdin -> (Sys.getcwd (), `Stdin) | `File f -> (Filename.dirname f, `File (Filename.basename f)) diff --git a/src_colibri2/tests/solve/models/abs_real.smt2 b/src_colibri2/tests/solve/models/abs_real.smt2 new file mode 100644 index 0000000000000000000000000000000000000000..509d830f5ba39243715e097c66dd9bba0efe3cf2 --- /dev/null +++ b/src_colibri2/tests/solve/models/abs_real.smt2 @@ -0,0 +1,13 @@ +(set-logic ALL) +(set-info :status-colibri2 sat) + +(declare-fun a () Int) +(declare-fun b () Real) + +(assert (< a 0)) +(assert (< b 0)) + +(check-sat) +(get-model) +(get-value ((abs a))) +(get-value ((colibri_abs_real b))) diff --git a/src_colibri2/tests/solve/models/abs_real.smt2.oracle b/src_colibri2/tests/solve/models/abs_real.smt2.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7b5c3b712725c9a9c61f70e38539c108d694ce1f --- /dev/null +++ b/src_colibri2/tests/solve/models/abs_real.smt2.oracle @@ -0,0 +1,4 @@ +sat +((a -1)(b -1)) +((abs a 1)) +((colibri_abs_real b 1)) diff --git a/src_colibri2/tests/solve/models/dune.inc b/src_colibri2/tests/solve/models/dune.inc index 0ffbe69bc24028ef9b0cf0b7c4e79d4a40ddf5d4..c9eaba0f3712b7401bd9cbf990aa709bdf7bc93d 100644 --- a/src_colibri2/tests/solve/models/dune.inc +++ b/src_colibri2/tests/solve/models/dune.inc @@ -1,2 +1,4 @@ +(rule (action (with-stdout-to abs_real.smt2.res (run %{bin:colibri2} --size=15M --time=30s --max-steps 3500 --check-status colibri2 %{dep:abs_real.smt2})))) +(rule (alias runtest) (action (diff abs_real.smt2.oracle abs_real.smt2.res))) (rule (action (with-stdout-to get_value.smt2.res (run %{bin:colibri2} --size=15M --time=30s --max-steps 3500 --check-status colibri2 %{dep:get_value.smt2})))) (rule (alias runtest) (action (diff get_value.smt2.oracle get_value.smt2.res))) diff --git a/src_colibri2/theories/LRA/realValue.ml b/src_colibri2/theories/LRA/realValue.ml index 1656d81f4ea5a9c13e81390053db86fb32490167..ff7d8c648b2490e41edecd3177642249a2e764e1 100644 --- a/src_colibri2/theories/LRA/realValue.ml +++ b/src_colibri2/theories/LRA/realValue.ml @@ -22,6 +22,25 @@ open Colibri2_core open Colibri2_popop_lib open Colibri2_stdlib.Std +module Builtin = struct + type _ Expr.t += Abs_real + + let abs_real = + Expr.Id.mk ~name:"colibri_abs_real" ~builtin:Abs_real "Abs" + (Expr.Ty.arrow [ Expr.Ty.real ] Expr.Ty.real) + + let () = + Expr.add_builtins (fun env s -> + match s with + | Dolmen_loop.Typer.T.Id { ns = Term; name = "colibri_abs_real" } -> + `Term + (Dolmen_type.Base.term_app1 + (module Dolmen_loop.Typer.T) + env "colibri_abs_real" + (fun a -> Expr.Term.apply_cst abs_real [] [ a ])) + | _ -> `Not_found) +end + module RealValue = Value.Register (struct include Q @@ -141,6 +160,10 @@ module Check = struct | { app = { builtin = Expr.Floor }; tyargs = []; args; _ } -> let a = IArray.extract1_exn args in !<(Q.floor !>a) + | { app = { builtin = Expr.Abs | Builtin.Abs_real }; tyargs = []; args; _ } + -> + let a = IArray.extract1_exn args in + !<(Q.abs !>a) | _ -> `None let init d = @@ -312,6 +335,10 @@ let converter d (f : Ground.t) = let a = IArray.extract1_exn args in reg a; Check.attach d f + | { app = { builtin = Expr.Abs | Builtin.Abs_real }; tyargs = []; args; _ } -> + let a = IArray.extract1_exn args in + reg a; + Check.attach d f | _ -> () let init env = diff --git a/src_colibri2/theories/LRA/realValue.mli b/src_colibri2/theories/LRA/realValue.mli index 0584e07e7fdd511918420706958925140b16bf92..c2862ae8aecb795c3673802d740f334f4c547623 100644 --- a/src_colibri2/theories/LRA/realValue.mli +++ b/src_colibri2/theories/LRA/realValue.mli @@ -18,6 +18,12 @@ (* for more details (enclosed in the file licenses/LGPLv2.1). *) (*************************************************************************) +module Builtin : sig + type _ Expr.t += Abs_real + + val abs_real : Colibri2_core.Expr.Term.Const.t +end + include Value.S with type s = Q.t val cst' : Q.t -> t