mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-09 04:35:35 -05:00
feat(simplify): add sidekick_simplify library
This commit is contained in:
parent
83e456ef8a
commit
1e1b0f352d
3 changed files with 125 additions and 0 deletions
6
src/simplify/dune
Normal file
6
src/simplify/dune
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
(library
|
||||
(name Sidekick_simplify)
|
||||
(public_name sidekick.simplify)
|
||||
(synopsis "Simplifier")
|
||||
(libraries containers iter sidekick.core sidekick.util)
|
||||
(flags :standard -w +32 -open Sidekick_util))
|
||||
80
src/simplify/sidekick_simplify.ml
Normal file
80
src/simplify/sidekick_simplify.ml
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
open Sidekick_core
|
||||
|
||||
open struct
|
||||
module P = Proof_trace
|
||||
module Rule_ = Proof_core
|
||||
end
|
||||
|
||||
type t = {
|
||||
tst: Term.store;
|
||||
proof: Proof_trace.t;
|
||||
mutable hooks: hook list;
|
||||
(* store [t --> u by step_ids] in the cache.
|
||||
We use a bag for the proof steps because it gives us structural
|
||||
sharing of subproofs. *)
|
||||
cache: (Term.t * Proof_step.id Bag.t) Term.Tbl.t;
|
||||
}
|
||||
|
||||
and hook = t -> Term.t -> (Term.t * Proof_step.id Iter.t) option
|
||||
|
||||
let create tst ~proof : t =
|
||||
{ tst; proof; hooks = []; cache = Term.Tbl.create 32 }
|
||||
|
||||
let[@inline] tst self = self.tst
|
||||
let[@inline] proof self = self.proof
|
||||
let add_hook self f = self.hooks <- f :: self.hooks
|
||||
let clear self = Term.Tbl.clear self.cache
|
||||
|
||||
let normalize (self : t) (t : Term.t) : (Term.t * Proof_step.id) option =
|
||||
(* compute and cache normal form of [t] *)
|
||||
let rec loop t : Term.t * _ Bag.t =
|
||||
match Term.Tbl.find self.cache t with
|
||||
| res -> res
|
||||
| exception Not_found ->
|
||||
let steps_u = ref Bag.empty in
|
||||
let u = aux_rec ~steps:steps_u t self.hooks in
|
||||
Term.Tbl.add self.cache t (u, !steps_u);
|
||||
u, !steps_u
|
||||
and loop_add ~steps t =
|
||||
let u, pr_u = loop t in
|
||||
steps := Bag.append !steps pr_u;
|
||||
u
|
||||
(* try each function in [hooks] successively, and rewrite subterms *)
|
||||
and aux_rec ~steps t hooks : Term.t =
|
||||
match hooks with
|
||||
| [] ->
|
||||
let u =
|
||||
Term.map_shallow self.tst ~f:(fun _inb u -> loop_add ~steps u) t
|
||||
in
|
||||
if Term.equal t u then
|
||||
t
|
||||
else
|
||||
loop_add ~steps u
|
||||
| h :: hooks_tl ->
|
||||
(match h self t with
|
||||
| None -> aux_rec ~steps t hooks_tl
|
||||
| Some (u, _) when Term.equal t u -> aux_rec ~steps t hooks_tl
|
||||
| Some (u, pr_u) ->
|
||||
let bag_u = Bag.of_iter pr_u in
|
||||
steps := Bag.append !steps bag_u;
|
||||
let v, pr_v = loop u in
|
||||
(* fixpoint *)
|
||||
steps := Bag.append !steps pr_v;
|
||||
v)
|
||||
in
|
||||
let u, pr_u = loop t in
|
||||
if Term.equal t u then
|
||||
None
|
||||
else (
|
||||
(* proof: [sub_proofs |- t=u] by CC + subproof *)
|
||||
let step =
|
||||
P.add_step self.proof
|
||||
@@ Rule_.lemma_preprocess t u ~using:(Bag.to_iter pr_u)
|
||||
in
|
||||
Some (u, step)
|
||||
)
|
||||
|
||||
let normalize_t self t =
|
||||
match normalize self t with
|
||||
| Some (u, pr_u) -> u, Some pr_u
|
||||
| None -> t, None
|
||||
39
src/simplify/sidekick_simplify.mli
Normal file
39
src/simplify/sidekick_simplify.mli
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
(** Term simplifier *)
|
||||
|
||||
open Sidekick_core
|
||||
|
||||
type t
|
||||
|
||||
val tst : t -> Term.store
|
||||
|
||||
val create : Term.store -> proof:Proof_trace.t -> t
|
||||
(** Create a simplifier *)
|
||||
|
||||
val clear : t -> unit
|
||||
(** Reset internal cache, etc. *)
|
||||
|
||||
val proof : t -> Proof_trace.t
|
||||
(** Access proof *)
|
||||
|
||||
type hook = t -> Term.t -> (Term.t * Proof_step.id Iter.t) option
|
||||
(** Given a Term.t, try to simplify it. Return [None] if it didn't change.
|
||||
|
||||
A simple example could be a hook that takes a Term.t [t],
|
||||
and if [t] is [app "+" (const x) (const y)] where [x] and [y] are number,
|
||||
returns [Some (const (x+y))], and [None] otherwise.
|
||||
|
||||
The simplifier will take care of simplifying the resulting Term.t further,
|
||||
caching (so that work is not duplicated in subterms), etc.
|
||||
*)
|
||||
|
||||
val add_hook : t -> hook -> unit
|
||||
|
||||
val normalize : t -> Term.t -> (Term.t * Proof_step.id) option
|
||||
(** Normalize a Term.t using all the hooks. This performs
|
||||
a fixpoint, i.e. it only stops when no hook applies anywhere inside
|
||||
the Term.t. *)
|
||||
|
||||
val normalize_t : t -> Term.t -> Term.t * Proof_step.id option
|
||||
(** Normalize a Term.t using all the hooks, along with a proof that the
|
||||
simplification is correct.
|
||||
returns [t, ø] if no simplification occurred. *)
|
||||
Loading…
Add table
Reference in a new issue