From 43a3e0760ed672d3ca5c47670ad147549f0a9be4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Bobot?= <francois.bobot@cea.fr>
Date: Wed, 11 Aug 2021 12:33:20 +0200
Subject: [PATCH] Use an external table for polynome/product to node

In order to not keep some and simplify the debug gui
---
 src_colibri2/theories/LRA/dom_polynome.ml  | 38 +++++++++++++++---
 src_colibri2/theories/LRA/dom_polynome.mli |  2 +-
 src_colibri2/theories/LRA/dom_product.ml   | 46 ++++++++++++++++++----
 src_colibri2/theories/LRA/dom_product.mli  |  2 +-
 src_colibri2/theories/LRA/fourier.ml       |  2 +-
 src_colibri2/theories/LRA/pivot.ml         | 26 ++++++------
 src_colibri2/theories/LRA/pivot.mli        |  4 +-
 7 files changed, 88 insertions(+), 32 deletions(-)

diff --git a/src_colibri2/theories/LRA/dom_polynome.ml b/src_colibri2/theories/LRA/dom_polynome.ml
index 4b22129c3..9217b9591 100644
--- a/src_colibri2/theories/LRA/dom_polynome.ml
+++ b/src_colibri2/theories/LRA/dom_polynome.ml
@@ -34,9 +34,35 @@ end
 
 module ThE = ThTerm.Register (T)
 
-let node_of_polynome p =
+module Table = struct
+  module H = Datastructure.Hashtbl (T)
+
+  let h = H.create Node.pp "HARITH_POLY"
+
+  let set ~old_ ~new_ n d =
+    (match old_ with
+    | None -> ()
+    | Some old_ -> if not (Polynome.equal old_ new_) then H.remove h d old_);
+    H.change
+      (function
+        | None -> Some n
+        | Some n' as s ->
+            Egraph.merge d n n';
+            s)
+      h d new_
+
+  let new_ d p =
+    match H.find_opt h d p with
+    | Some n -> n
+    | None ->
+        let n = ThE.node (ThE.index p) in
+        H.set h d p n;
+        n
+end
+
+let node_of_polynome d p =
   match Polynome.is_cst p with
-  | None -> ThE.node (ThE.index p)
+  | None -> Table.new_ d p
   | Some q -> RealValue.node (RealValue.index q)
 
 include Pivot.Total (struct
@@ -56,11 +82,11 @@ include Pivot.Total (struct
     let add acc cl c = Polynome.x_p_cy acc c (f cl) in
     Polynome.fold add (Polynome.cst p.cst) p
 
-  let set d cl p =
-    match is_one_node p with
+  let set d cl ~old_ ~new_ =
+    match is_one_node new_ with
     | None -> (
-        match Polynome.is_cst p with
-        | None -> Egraph.set_thterm d cl (ThE.thterm (ThE.index p))
+        match Polynome.is_cst new_ with
+        | None -> Table.set ~old_ ~new_ cl d
         | Some q ->
             Egraph.set_value d cl (RealValue.nodevalue (RealValue.index q)))
     | Some cl' -> Egraph.merge d cl cl'
diff --git a/src_colibri2/theories/LRA/dom_polynome.mli b/src_colibri2/theories/LRA/dom_polynome.mli
index b88d42211..f9051653d 100644
--- a/src_colibri2/theories/LRA/dom_polynome.mli
+++ b/src_colibri2/theories/LRA/dom_polynome.mli
@@ -30,6 +30,6 @@ val events_repr_change :
 
 val init : Egraph.wt -> unit
 
-val node_of_polynome : Polynome.t -> Node.t
+val node_of_polynome : _ Egraph.t -> Polynome.t -> Node.t
 
 val normalize : _ Egraph.t -> Polynome.t -> Polynome.t
diff --git a/src_colibri2/theories/LRA/dom_product.ml b/src_colibri2/theories/LRA/dom_product.ml
index be0975b67..62d3bbffc 100644
--- a/src_colibri2/theories/LRA/dom_product.ml
+++ b/src_colibri2/theories/LRA/dom_product.ml
@@ -40,16 +40,42 @@ end
 
 module ThE = ThTerm.Register (T)
 
-let node_of_product abs sign =
+module Table = struct
+  module H = Datastructure.Hashtbl (T)
+
+  let h = H.create Node.pp "HARITH_PRODUCT"
+
+  let set ~old_ ~new_ d n =
+    if not (T.equal old_ new_) then H.remove h d old_;
+    H.change
+      (function
+        | None -> Some n
+        | Some n' as s ->
+            Egraph.merge d n n';
+            s)
+      h d new_
+
+  let new_ d p =
+    match H.find_opt h d p with
+    | Some n -> n
+    | None ->
+        let n = ThE.node (ThE.index p) in
+        H.set h d p n;
+        n
+end
+
+let node_of_product d abs sign =
   let t = { T.abs; sign } in
-  ThE.node (ThE.index t)
+  Table.new_ d t
 
-let set d cl abs sign =
+let set d cl ~old_abs ~old_sign abs sign =
   if Sign_product.equal Sign_product.zero sign then
     Egraph.merge d cl RealValue.zero
   else
     let aux () =
-      Egraph.set_thterm d cl (ThE.thterm (ThE.index { abs; sign }))
+      Table.set d cl
+        ~old_:{ T.abs = old_abs; sign = old_sign }
+        ~new_:{ T.abs; sign }
     in
     match Product.is_one_node abs with
     | None -> aux ()
@@ -85,7 +111,9 @@ end = Pivot.WithUnsolved (struct
     let p, c = subst p n q in
     if Q.is_zero c then None else Some p
 
-  let set d cl abs = SolveSign.iter_eqs d cl ~f:(fun sign -> set d cl abs sign)
+  let set d cl ~old_ ~new_ =
+    SolveSign.iter_eqs d cl ~f:(fun sign ->
+        set d cl ~old_abs:old_ ~old_sign:sign new_ sign)
 
   type data = Q.t
 
@@ -176,7 +204,9 @@ end = Pivot.WithUnsolved (struct
 
   let attach_info_change d f = Events.attach_any_dom d Dom_interval.dom f
 
-  let set d cl sign = SolveAbs.iter_eqs d cl ~f:(fun abs -> set d cl abs sign)
+  let set d cl ~old_ ~new_ =
+    SolveAbs.iter_eqs d cl ~f:(fun abs ->
+        set d cl ~old_abs:abs ~old_sign:old_ abs new_)
 
   type info = Sign_product.presolve * Sign_product.t
 
@@ -234,14 +264,14 @@ let factorize res a coef b d _ =
                 | NODE n, NODE n' when Egraph.is_equal d n n' ->
                     (cst, (n, v) :: acc)
                 | _ ->
-                    let n = node_of_product abs sign in
+                    let n = node_of_product d abs sign in
                     Egraph.register d n;
                     (cst, (n, v) :: acc))
               (Q.zero, [])
               [ (pa, sa, Q.one); (pb, sb, coef) ]
           in
           let p = Polynome.of_list cst l in
-          let n = Dom_polynome.node_of_polynome p in
+          let n = Dom_polynome.node_of_polynome d p in
           let pp_coef fmt coef =
             if Q.equal Q.one coef then Fmt.pf fmt "+" else Fmt.pf fmt "-"
           in
diff --git a/src_colibri2/theories/LRA/dom_product.mli b/src_colibri2/theories/LRA/dom_product.mli
index 3b2f1ac3c..df0dd22e7 100644
--- a/src_colibri2/theories/LRA/dom_product.mli
+++ b/src_colibri2/theories/LRA/dom_product.mli
@@ -20,7 +20,7 @@
 
 (* val assume_equality : Egraph.wt -> Node.t -> Product.t -> unit *)
 
-val node_of_product : Product.t -> Sign_product.t -> Node.t
+val node_of_product : _ Egraph.t -> Product.t -> Sign_product.t -> Node.t
 
 module SolveAbs : sig
   val get_repr : _ Egraph.t -> Node.t -> Product.t option
diff --git a/src_colibri2/theories/LRA/fourier.ml b/src_colibri2/theories/LRA/fourier.ml
index 7f4daa6c1..311f557d4 100644
--- a/src_colibri2/theories/LRA/fourier.ml
+++ b/src_colibri2/theories/LRA/fourier.ml
@@ -91,7 +91,7 @@ let divide d (p : Polynome.t) =
               | NODE n, NODE n' when Egraph.is_equal d n n' ->
                   (cst, (n, v) :: acc)
               | _ ->
-                  let n = Dom_product.node_of_product abs sign in
+                  let n = Dom_product.node_of_product d abs sign in
                   (cst, (n, v) :: acc))
             (Q.zero, []) l
         in
diff --git a/src_colibri2/theories/LRA/pivot.ml b/src_colibri2/theories/LRA/pivot.ml
index 5d5be6e49..c5199deb8 100644
--- a/src_colibri2/theories/LRA/pivot.ml
+++ b/src_colibri2/theories/LRA/pivot.ml
@@ -55,7 +55,7 @@ module WithUnsolved (P : sig
 
   val solve : info -> info -> t solve_with_unsolved
 
-  val set : Egraph.wt -> Node.t -> t -> unit
+  val set : Egraph.wt -> Node.t -> old_:t -> new_:t -> unit
 end) : sig
   val assume_equality : Egraph.wt -> Node.t -> P.t -> unit
 
@@ -96,7 +96,7 @@ end = struct
 
   let set_poly d cl p chg =
     Egraph.set_dom d dom cl p;
-    List.iter (fun p -> P.set d cl p) chg
+    List.iter (fun (old_, new_) -> P.set d cl ~old_ ~new_) chg
 
   let add_used_product d cl' new_cls =
     Node.M.iter
@@ -143,7 +143,7 @@ end = struct
               in
               match P.subst q cl p with
               | None -> (new_cl, P.S.add q acc, chg)
-              | Some q -> (new_cl, P.S.add q acc, q :: chg)
+              | Some q' -> (new_cl, P.S.add q' acc, (q, q') :: chg)
             in
             let new_cl, acc, chg = fold (Node.M.empty, P.S.empty, []) q.repr in
             let repr = P.S.choose acc in
@@ -227,7 +227,7 @@ end = struct
       match po with
       | None ->
           add_used_product d cl (P.nodes eq);
-          set_poly d cl { repr = eq; eqs = P.S.empty } [ eq ]
+          set_poly d cl { repr = eq; eqs = P.S.empty } [ (eq, eq) ]
       | Some p -> (
           if (not (P.S.mem eq p.eqs)) && not (P.equal eq p.repr) then
             match
@@ -246,7 +246,7 @@ end = struct
                 let eqs = p.eqs |> P.S.add eq |> P.S.remove repr in
                 let p = { repr; eqs } in
                 add_used_product d cl (P.nodes eq);
-                set_poly d cl p [ eq ])
+                set_poly d cl p [ (eq, eq) ])
 
     and subst d cl eq =
       Debug.dprintf4 debug "[Pivot] subst %a with %a" Node.pp cl P.pp eq;
@@ -255,7 +255,7 @@ end = struct
       | None ->
           let p = { repr = eq; eqs = P.S.empty } in
           add_used_product d cl (P.nodes eq);
-          set_poly d cl p [ eq ]
+          set_poly d cl p [ (eq, eq) ]
       | Some p ->
           assert (Option.equal Node.equal (P.is_one_node p.repr) (Some cl));
           subst_doms d cl eq;
@@ -396,7 +396,7 @@ module Total (P : sig
 
   val solve : t -> t -> t solve_total
 
-  val set : Egraph.wt -> Node.t -> t -> unit
+  val set : Egraph.wt -> Node.t -> old_:t option -> new_:t -> unit
 end) : sig
   val assume_equality : Egraph.wt -> Node.t -> P.t -> unit
 
@@ -428,9 +428,9 @@ end = struct
   let used_in_poly : Node.t Bag.t Node.HC.t =
     Node.HC.create (Bag.pp Pp.semi Node.pp) "used_in_poly"
 
-  let set_poly d cl p =
-    Egraph.set_dom d dom cl p;
-    P.set d cl p
+  let set_poly d cl old_ new_ =
+    Egraph.set_dom d dom cl new_;
+    P.set d cl ~old_ ~new_
 
   let add_used d cl' new_cl =
     Node.M.iter
@@ -463,12 +463,12 @@ end = struct
         | None -> assert false (* absurd: can't be used and absent *)
         | Some q ->
             let new_cl = Node.M.set_diff (P.nodes p) (P.nodes q) in
-            let q = P.subst q cl p in
+            let q_new = P.subst q cl p in
             add_used d cl' new_cl;
-            set_poly d cl' q)
+            set_poly d cl' (Some q) q_new)
       b;
     add_used d cl (P.nodes p);
-    set_poly d cl p
+    set_poly d cl None p
 
   module Th = struct
     include P
diff --git a/src_colibri2/theories/LRA/pivot.mli b/src_colibri2/theories/LRA/pivot.mli
index 54857e51a..ee9fc5306 100644
--- a/src_colibri2/theories/LRA/pivot.mli
+++ b/src_colibri2/theories/LRA/pivot.mli
@@ -69,7 +69,7 @@ module WithUnsolved (P : sig
   (** [solve t1 t2] solve the equation [t1 = t2] by returning a substitution.
         Return Unsolved if the equation can't be yet solved *)
 
-  val set : Egraph.wt -> Node.t -> t -> unit
+  val set : Egraph.wt -> Node.t -> old_:t -> new_:t -> unit
   (** Called a new term equal to this node is found *)
 end) : sig
   val assume_equality : Egraph.wt -> Node.t -> P.t -> unit
@@ -125,7 +125,7 @@ module Total (P : sig
   val solve : t -> t -> t solve_total
   (** [solve t1 t2] solve the equation [t1 = t2] by returning a substitution. *)
 
-  val set : Egraph.wt -> Node.t -> t -> unit
+  val set : Egraph.wt -> Node.t -> old_:t option -> new_:t -> unit
   (** Called a new term equal to this node is found *)
 end) : sig
   val assume_equality : Egraph.wt -> Node.t -> P.t -> unit
-- 
GitLab