mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-10 05:03:59 -05:00
feat: add ite theory
This commit is contained in:
parent
431988d5e4
commit
314bd7f8b2
4 changed files with 123 additions and 1 deletions
|
|
@ -5,7 +5,7 @@
|
||||||
(public_name sidekick)
|
(public_name sidekick)
|
||||||
(package sidekick)
|
(package sidekick)
|
||||||
(libraries containers sequence result msat sidekick.smt sidekick.smtlib
|
(libraries containers sequence result msat sidekick.smt sidekick.smtlib
|
||||||
sidekick.dimacs)
|
sidekick.smt.th-ite sidekick.dimacs)
|
||||||
(flags :standard -w +a-4-42-44-48-50-58-32-60@8
|
(flags :standard -w +a-4-42-44-48-50-58-32-60@8
|
||||||
-safe-string -color always -open Sidekick_util)
|
-safe-string -color always -open Sidekick_util)
|
||||||
(ocamlopt_flags :standard -O3 -color always
|
(ocamlopt_flags :standard -O3 -color always
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,7 @@ let main () =
|
||||||
| Smtlib ->
|
| Smtlib ->
|
||||||
[ Sidekick_th_bool.th_dynamic_tseitin;
|
[ Sidekick_th_bool.th_dynamic_tseitin;
|
||||||
Sidekick_th_distinct.th;
|
Sidekick_th_distinct.th;
|
||||||
|
Sidekick_th_ite.th;
|
||||||
] (* TODO: more theories *)
|
] (* TODO: more theories *)
|
||||||
in
|
in
|
||||||
Sidekick_smt.Solver.create ~store_proof:!check ~theories ()
|
Sidekick_smt.Solver.create ~store_proof:!check ~theories ()
|
||||||
|
|
|
||||||
113
src/th-ite/Sidekick_th_ite.ml
Normal file
113
src/th-ite/Sidekick_th_ite.ml
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
|
||||||
|
(** {1 Theory for if-then-else} *)
|
||||||
|
|
||||||
|
type 't ite_view =
|
||||||
|
| T_ite of 't * 't * 't
|
||||||
|
| T_bool of bool
|
||||||
|
| T_other of 't
|
||||||
|
|
||||||
|
|
||||||
|
module type S = sig
|
||||||
|
type lit
|
||||||
|
type term
|
||||||
|
|
||||||
|
val th : Sidekick_smt.Theory.t
|
||||||
|
end
|
||||||
|
|
||||||
|
module type ARG = sig
|
||||||
|
module T : sig
|
||||||
|
type t
|
||||||
|
type state
|
||||||
|
val pp : t Fmt.printer
|
||||||
|
val equal : t -> t -> bool
|
||||||
|
val view_as_ite : t -> t ite_view
|
||||||
|
|
||||||
|
module Set : CCSet.S with type elt = t
|
||||||
|
end
|
||||||
|
module Lit : sig
|
||||||
|
type t
|
||||||
|
val term : t -> T.t
|
||||||
|
val atom : T.state -> ?sign:bool -> T.t -> t
|
||||||
|
val pp : t Fmt.printer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module Make(Arg : ARG with type T.state = Sidekick_smt.Term.state and type T.t = Sidekick_smt.Term.t)
|
||||||
|
: S with type lit = Arg.Lit.t and type term = Arg.T.t
|
||||||
|
= struct
|
||||||
|
module Th = Sidekick_smt.Theory
|
||||||
|
module N = Th.CC_eq_class
|
||||||
|
module Expl = Th.CC_expl
|
||||||
|
module CC = Sidekick_smt.CC
|
||||||
|
|
||||||
|
open Arg
|
||||||
|
type lit = Lit.t
|
||||||
|
type term = T.t
|
||||||
|
|
||||||
|
type data = T.Set.t
|
||||||
|
(* associate to each class [t] the set of [ite a b c] where [a=t] *)
|
||||||
|
|
||||||
|
let pp_data = Fmt.(map T.Set.to_seq @@ seq ~sep:(return ",@ ") T.pp)
|
||||||
|
|
||||||
|
let key : (_,_,data) Sidekick_cc.Key.t = Sidekick_cc.Key.create
|
||||||
|
~pp:pp_data ~name:"ite" ~eq:T.Set.equal ~merge:T.Set.union ()
|
||||||
|
|
||||||
|
type t = T.state
|
||||||
|
|
||||||
|
let on_merge (_st:t) (acts:Sidekick_smt.Theory.actions) n1 n2 e_n1_n2 : unit =
|
||||||
|
let (module A) = acts in
|
||||||
|
Log.debugf 5
|
||||||
|
(fun k->k "(@[th-ite.on_merge@ :c1 %a@ :c2 %a@])" N.pp n1 N.pp n2);
|
||||||
|
(* check if [n1] has some [ite] parents, and if [n2] is true/false *)
|
||||||
|
let check_ n1 n2 =
|
||||||
|
match CC.Theory.get_data A.cc n1 key, T.view_as_ite (N.term n2) with
|
||||||
|
| Some set, T_bool n2_true ->
|
||||||
|
assert (not @@ T.Set.is_empty set);
|
||||||
|
T.Set.iter
|
||||||
|
(fun parent_1 -> match T.view_as_ite parent_1 with
|
||||||
|
| T_ite (a1,b1,c1) ->
|
||||||
|
let n_parent1 = CC.add_term A.cc parent_1 in
|
||||||
|
let expl = Expl.mk_list [e_n1_n2; Expl.mk_merge n1 (CC.add_term A.cc a1)] in
|
||||||
|
if n2_true then (
|
||||||
|
(* [a1 = n1 = n2 = true] so [if a1 b1 c1 = b1] *)
|
||||||
|
CC.Theory.merge A.cc n_parent1 (CC.add_term A.cc b1) expl
|
||||||
|
) else (
|
||||||
|
(* [a1 = n1 = n2 = false] so [if a1 b1 c1 = c1] *)
|
||||||
|
CC.Theory.merge A.cc n_parent1 (CC.add_term A.cc c1) expl
|
||||||
|
)
|
||||||
|
| _ -> assert false)
|
||||||
|
set
|
||||||
|
| _ -> ()
|
||||||
|
in
|
||||||
|
check_ n1 n2;
|
||||||
|
check_ n2 n1;
|
||||||
|
()
|
||||||
|
|
||||||
|
let on_new_term _ (acts:Sidekick_smt.Theory.actions) (t:T.t) =
|
||||||
|
let (module A) = acts in
|
||||||
|
match T.view_as_ite t with
|
||||||
|
| T_ite (a,_,_) ->
|
||||||
|
(* add [t] to parents of [a] *)
|
||||||
|
let n_a = CC.find A.cc @@ CC.add_term A.cc a in
|
||||||
|
CC.Theory.add_data A.cc n_a key (T.Set.singleton t)
|
||||||
|
| _ -> ()
|
||||||
|
|
||||||
|
let th =
|
||||||
|
Sidekick_smt.Theory.make ~name:"ite" ~create:(fun st->st)
|
||||||
|
~on_merge ~final_check:(fun _ _ _ -> ())
|
||||||
|
~on_new_term
|
||||||
|
()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
include Make(struct
|
||||||
|
module T = struct
|
||||||
|
include Sidekick_smt.Term
|
||||||
|
let[@inline] view_as_ite t = match view t with
|
||||||
|
| If (a,b,c) -> T_ite (a,b,c)
|
||||||
|
| Bool b -> T_bool b
|
||||||
|
| _ -> T_other t
|
||||||
|
end
|
||||||
|
module Lit = Sidekick_smt.Lit
|
||||||
|
end)
|
||||||
8
src/th-ite/dune
Normal file
8
src/th-ite/dune
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
(library
|
||||||
|
(name Sidekick_th_ite)
|
||||||
|
(public_name sidekick.smt.th-ite)
|
||||||
|
(libraries containers sidekick.smt)
|
||||||
|
(flags :standard -open Sidekick_util))
|
||||||
|
|
||||||
Loading…
Add table
Reference in a new issue