From 6af6d2113afeb383b4b1b1c088413e97896c43d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Bobot?= <francois.bobot@cea.fr>
Date: Thu, 2 Jan 2014 11:28:45 +0100
Subject: [PATCH] clsem in place remains to remove invtable

---
 Makefile                                   |   2 +-
 src/arith.ml                               |  47 ++--
 src/arith.mli                              |   1 -
 src/bool.ml                                |  65 ++---
 src/bool.mli                               |   6 -
 src/conflict.ml                            |  51 +---
 src/conflict.mli                           |   9 +-
 src/demon.ml                               |   1 +
 src/equality.ml                            | 146 ++---------
 src/equality.mli                           |  13 -
 src/explanation.ml                         |  10 -
 src/explanation.mli                        |  11 -
 src/inputlang/altergo/popop_of_altergo.mli |   2 -
 src/solver.ml                              | 279 ++++++++-------------
 src/solver.mli                             |  16 +-
 src/types.ml                               | 200 +++++++++++++--
 src/types.mli                              |  74 ++++--
 src/uninterp.ml                            |  50 ++--
 src/util/hashcons.ml                       |  85 ++++++-
 src/util/hashcons.mli                      |  29 ++-
 src/util/strings.ml                        |  38 +--
 src/util/strings.mli                       |   2 +
 src/util/util.ml                           |   3 +
 src/util/util.mli                          |   3 +
 src/variable.ml                            |   4 +-
 src/variable.mli                           |   1 -
 26 files changed, 588 insertions(+), 560 deletions(-)

diff --git a/Makefile b/Makefile
index 45201d9d0..e23354964 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 
 PACKAGES=oUnit zarith ocamlgraph cryptokit #-package lablgtk2
 # I don't understand warning 18
-OPTIONS=-tag annot -no-sanitize -tag debug -use-ocamlfind -cflags -w,+a-4-9-18-41-44-40 -cflags -warn-error,+5+10+8+12+20+11 -cflag -bin-annot -j 8
+OPTIONS=-tag annot -no-sanitize -tag debug -use-ocamlfind -cflags -w,+a-4-9-18-41-44-40-45-42 -cflags -warn-error,+5+10+8+12+20+11 -cflag -bin-annot -j 8
 #OPTIONS += -cflags -warn-error,+a
 DIRECTORIES=src src/util src/inputlang/altergo src/inputlang/dimacs_cnf src/inputlang/smtlib2 tests src/cmd fuzz
 OCAMLBUILD=ocamlbuild \
diff --git a/src/arith.ml b/src/arith.ml
index 0bf1ca2dd..8e765e439 100644
--- a/src/arith.ml
+++ b/src/arith.ml
@@ -596,7 +596,7 @@ module P = struct
   let x_p_cy = x_p_cy
 end
 
-module E = RegisterSem(Th)
+module ThE = RegisterSem(Th)
 module D = RegisterDom(struct include Th let key = dom end)
 
 let embed t cl =
@@ -615,7 +615,7 @@ module DaemonPropa = struct
 
   let immediate = true
   let wakeup d v ev =
-    match Delayed.get_cl_sem d sem v with
+    match Delayed.get_cl_sem d sem v real with
     | None -> assert false
     | Some own ->
       match Delayed.get_dom d dom own with
@@ -789,7 +789,7 @@ module DaemonMultPropa = struct
 
   let immediate = false
   let wakeup d v _ev =
-    match Delayed.get_cl_sem d mul_sem v with
+    match Delayed.get_cl_sem d mul_sem v real with
     | None -> assert false
     | Some own ->
       Debug.dprintf4 debug "[Uninterp] @[wakeup own %a v:%a@]@\n"
@@ -852,7 +852,7 @@ end
 
 module RDaemonMultInit = Demon.Key.Register(DaemonMultInit)
 
-let zero = Cl.create "0" real
+let zero = ThE.cl (ThE.index poly_zero real)
 
 let propagate env =
   RDaemonPropa.init env;
@@ -864,8 +864,6 @@ let propagate env =
   Demon.Key.attach env
     DaemonMultInit.key () [Demon.Create.EventPropaSem(mul_sem,())];
   Delayed.propagate env zero;
-  Delayed.set_sem env Explanation.pexpfact
-    sem zero poly_zero;
   Delayed.set_dom env (Solver.Delayed.mk_pexp env Explanation.expfact ())
     dom zero poly_zero
 
@@ -995,7 +993,6 @@ module GenEquality = struct
           (* let p,deps = get_rlist_conpoly_deps t cl r1 deps in *)
           (* assert (is_zero p.exp); *)
           (* Explanation.Deps.add_unknown_con deps conpoly p); *)
-      sem = get_sem;
       dodec = true (** TODO *);
     }
 
@@ -1034,7 +1031,8 @@ module ConPoly = struct
             let _,vn = Th.normalize d v in
             if not (Cl.M.is_empty vn.poly)
             then
-              let c = (Equality.Sem(sem,v,zero,false)) in
+              let cl = ThE.cl (ThE.index v real) in
+              let c = Equality.Eq(cl,zero,false) in
               f.fold_decisions acc Equality.choequal c ()
             else acc) acc v
     method conflict_add d =
@@ -1076,10 +1074,16 @@ module ConPoly = struct
     else Some (new finalized s)
 
 
-  let same_sem t age _sem (_,pexp2) pexp1 cl1 cl2 =
+  let same_sem (type a) t age (sem':a sem) (v:a) pexp1 cl1 cl2 =
+    let r2 =
+      match Sem.Eq.eq_type sem sem' with
+      | None -> raise Impossible (* understand why that happend *)
+      | Some Eqtype.Eq ->
+        let p2 = x_p_cy (monome Q.one cl2) Q.minus_one v in
+        Some {imp = p2; exp = p2}
+    in
     let r1 = get_pexp_conpoly t pexp1 in
-    let r2 = get_pexp_conpoly t pexp2 in
-    let p = match r1, r2 with
+    let p = match r1,r2 with
       | Some p1, Some p2 ->
         x_p_cy_conpoly p2 Q.minus_one p1
       | _ -> dist_conpoly cl1 cl2 in
@@ -1094,17 +1098,6 @@ module ConPoly = struct
     then GRequested (dist_conpoly cl rcl)
     else GRequested {imp = poly_zero; exp = dist cl rcl}
 
-  let propasem :
-    type a. ComputeConflict.t -> age -> a sem -> a -> Cl.t -> t rescon =
-    fun t age sem' v cl ->
-      match Sem.Eq.eq_type sem sem' with
-      | None -> raise Impossible
-      | Some Eqtype.Eq ->
-        let p = x_p_cy (monome Q.one cl) Q.minus_one v in
-        if ComputeConflict.before_first_dec t age
-        then GRequested {imp = p; exp = p}
-        else GRequested {imp = poly_zero; exp = p}
-
 end
 
 module EConPoly = Conflict.RegisterCon(ConPoly)
@@ -1214,13 +1207,8 @@ module ExpEquality = struct
       x_p_cy_conpoly p q (get_rlist_conpoly t age modcl cl)
     | CombiS(q,v,n) ->
       let n = analyse_combi t age n in
-      let cl,pexp = get_sem t sem v in
-      let pexp = match get_pexp_conpoly t pexp with
-        | None -> mk_conpoly (x_p_cy (monome Q.one cl) Q.minus_one v)
-        | Some p ->
-          assert (Th.equal (x_p_cy (monome Q.one cl) Q.minus_one v) p.exp);
-          p
-      in
+      let cl = ThE.cl (ThE.index v real) in
+      let pexp = mk_conpoly (x_p_cy (monome Q.one cl) Q.minus_one v) in
       x_p_cy_conpoly n q pexp
     | CombiRepr(q,cl,n) ->
       let n = analyse_combi t age n in
@@ -1299,7 +1287,6 @@ module ExpMulSubst = struct
         | Some Eqtype.Eq -> GRequested () in
       begin match exp with
       | Mul(f,g) as v ->
-        get_con () t (get_pexp t (snd (get_sem t mul_sem v)) confact);
         get_cons ()
           (ComputeConflict.get_equal t age f (get_repr_at t age f));
         get_cons ()
diff --git a/src/arith.mli b/src/arith.mli
index 189bc7f36..600c31ffc 100644
--- a/src/arith.mli
+++ b/src/arith.mli
@@ -20,7 +20,6 @@
 (*                                                                        *)
 (**************************************************************************)
 open Types
-open Solver
 
 val real: Ty.t
 val real_ctr: Ty.Constr.t
diff --git a/src/bool.ml b/src/bool.ml
index 918e1f395..453a7efe9 100644
--- a/src/bool.ml
+++ b/src/bool.ml
@@ -32,8 +32,8 @@ let debug = Debug.register_info_flag
 let ty_ctr = Ty.Constr.create "Bool"
 let ty = Ty.ctr ty_ctr
 let dom : bool dom = Conflict.dom_bool
-let cl_true = Cl.create "⊤" ty
-let cl_false = Cl.create "⊥" ty
+let cl_true = Cl.fresh "⊤" ty
+let cl_false = Cl.fresh "⊥" ty
 
 let union_disjoint m1 m2 =
   Cl.M.union (fun _ b1 b2 -> assert (b1 == b2); Some b1) m1 m2
@@ -352,7 +352,7 @@ module DaemonPropa = struct
     | Events.Fired.EventDom(_ownr,dom',All v) ->
       assert( Dom.equal dom dom' );
       (** use this own because the other is the representant *)
-      let own = Opt.get (Delayed.get_cl_sem d sem v) in
+      let own = ThE.cl (ThE.index v ty) in
       ignore (wakeup_own ~first:false d v own)
     | _ -> raise UnwaitedEvent
 
@@ -533,13 +533,6 @@ let mk_conequal:
   (ComputeConflict.t -> Cl.t -> Cl.t -> clause_conflict rescon) ref =
   ref (fun _ _ -> assert false)
 
-type mk_conequal_sem =
-  {mutable mk_conequal_sem:
-     'a. ComputeConflict.t -> 'a sem -> 'a -> Cl.t -> clause_conflict rescon}
-let mk_conequal_sem: mk_conequal_sem =
-  { mk_conequal_sem = (fun _ _ _ -> assert false) }
-
-
 let concat s1 s2 =
   Cl.M.union (fun _ b1 b2 -> assert (DBool.equal b1 b2); Some b1) s1 s2
 
@@ -570,9 +563,9 @@ let get_pexp t s pexp =
   get_con s t (ComputeConflict.get_pexp t pexp conclause)
 
 
-let get_sem t v s =
-  let _, pexp = ComputeConflict.get_sem t sem v in
-  get_pexp t s pexp
+let check_sem v cl =
+  let own = ThE.cl (ThE.index v ty) in
+  Cl.equal cl own
 
 (** **)
 module ExpMerge = struct
@@ -689,24 +682,24 @@ module ExpProp = struct
         raise Impossible
       | ExpBCP  (v,own,propa,kind,_) ->
         let s = Cl.M.empty in
-        let s = get_sem t v s in
+        assert (check_sem v own);
         let s = if kind == BCPOwnKnown then get_dom t age own s else s in
         fold (fun s (cl,_) ->
           if kind != BCPLeavesKnown && (Cl.equal cl propa) then s
           else get_dom t age cl s) s v
-      | ExpUp (v,_,leaf)    ->
+      | ExpUp (v,own,leaf)    ->
         let s = Cl.M.empty in
-        let s = get_sem t v s in
+        assert (check_sem v own);
         let s = get_dom  t age leaf s in
         s
       | ExpDown  (v,own,_,_)    ->
         let s = Cl.M.empty in
-        let s = get_sem t v s in
+        assert (check_sem v own);
         let s = get_dom  t age own s in
         s
       | ExpNot  ((v,clfrom,clto),_)->
         let s = Cl.M.empty in
-        let s = get_sem t v s in
+        assert (check_sem v clto || check_sem v clfrom);
         let s = get_dom t age clfrom s in
         fold (fun s (cl,_) ->
           if (Cl.equal cl clfrom) ||
@@ -802,9 +795,8 @@ module ConClause = struct
       Some (new finalized s)
 
 
-  let same_sem t _age _sem (_,pexp1) pexp2 _cl1 _cl2 =
+  let same_sem t _age _sem _v pexp2 _cl1 _cl2 =
     let s = Cl.M.empty in
-    let s = get_con s t (ComputeConflict.get_pexp t pexp1 conclause) in
     let s = get_con s t (ComputeConflict.get_pexp t pexp2 conclause) in
     GRequested s
 
@@ -828,26 +820,19 @@ module ConClause = struct
       | _ ->
         !mk_conequal t clo rcl
 
-  let propasem t age sem v cl =
-    if ComputeConflict.before_first_dec t age
-    then GRequested Cl.M.empty
-    else
-      (** TODO ty bool if sem is bool? *)
-      mk_conequal_sem.mk_conequal_sem t sem v cl
-
-  let propadom:
-    type a. ComputeConflict.t ->
-      Explanation.Age.t -> a dom -> Cl.t -> a option -> t rescon =
-      fun t age dom' cl bval ->
-        if ComputeConflict.before_first_dec t age
-        then GRequested Cl.M.empty
-        else
-          match Dom.Eq.coerce_type dom dom' with
-          | Eqtype.Eq ->
-            if Cl.equal cl cl_true || Cl.equal cl cl_false then
-              GRequested Cl.M.empty
-            else
-              GRequested (Cl.M.singleton cl (Opt.get bval))
+  (* let propadom: *)
+  (*   type a. ComputeConflict.t -> *)
+  (*     Explanation.Age.t -> a dom -> Cl.t -> a option -> t rescon = *)
+  (*     fun t age dom' cl bval -> *)
+  (*       if ComputeConflict.before_first_dec t age *)
+  (*       then GRequested Cl.M.empty *)
+  (*       else *)
+  (*         match Dom.Eq.coerce_type dom dom' with *)
+  (*         | Eqtype.Eq -> *)
+  (*           if Cl.equal cl cl_true || Cl.equal cl cl_false then *)
+  (*             GRequested Cl.M.empty *)
+  (*           else *)
+  (*             GRequested (Cl.M.singleton cl (Opt.get bval)) *)
 end
 
 module EC = Conflict.RegisterCon(ConClause)
diff --git a/src/bool.mli b/src/bool.mli
index bef16b84c..163c363c5 100644
--- a/src/bool.mli
+++ b/src/bool.mli
@@ -78,9 +78,3 @@ val mk_clause: Solver.Delayed.t -> clause_conflict -> Cl.t
 val mk_conequal:
   (Conflict.ComputeConflict.t ->
    Cl.t -> Cl.t -> clause_conflict Conflict.rescon) ref
-
-type mk_conequal_sem =
-  {mutable mk_conequal_sem:
-     'a. Conflict.ComputeConflict.t -> 'a sem -> 'a -> Cl.t ->
-     clause_conflict Conflict.rescon}
-val mk_conequal_sem: mk_conequal_sem
diff --git a/src/conflict.ml b/src/conflict.ml
index d4486c603..34ac4a06e 100644
--- a/src/conflict.ml
+++ b/src/conflict.ml
@@ -29,7 +29,6 @@ exception DontKnowThisDec of Dom.K.t * Cl.t
 
 exception DomNeverSet
 exception ClNotEqual
-exception SemNeverSet
 
 let debug = Debug.register_info_flag
   ~desc:"for@ the@ main@ part@ of@ conflicts."
@@ -44,29 +43,26 @@ let return : type a b. a con -> b con -> b -> a rescon = fun con con' v ->
   | Some Eqtype.Eq -> GRequested v
   | None -> GOther(con',v)
 
-exception NotMarkedAge
-
 type explearnt =
 | ExpLearnt: Tags.t -> explearnt
 
 let explearnt : explearnt exp = Exp.create_key "Explanation.learnt_exp"
 let dom_bool : bool dom = Dom.create_key "bool"
 
-type tofind =
-| FDom : Cl.t * 'a dom      -> tofind
-
 exception NotMarkedExp
 
+(*
 module type SemH = sig
   type k
   type v
-  module S : Solver.Sem with type t = k
+  module S : Types.Sem with type t = k
   val h : v S.H.t
 end
 
 module SemH = Sem.MkVector(struct
     type ('a,'b) t = (module SemH with type k = 'a and type v = 'b)
   end)
+*)
 
 (** *)
 let hash_chogen = ref (fun _ -> assert false)
@@ -243,11 +239,9 @@ module type Con' = sig
   val key: t con
 
   val same_sem:
-    con_iter -> age -> 'a sem -> Cl.t * pexp ->
+    con_iter -> age -> 'a sem -> 'a ->
     pexp -> Cl.t -> Cl.t -> t rescon
 
-  val propasem: con_iter -> Age.t -> 'a sem -> 'a -> Cl.t -> t rescon
-
   val propacl : con_iter -> Age.t -> Cl.t -> Cl.t -> t rescon
 
   val finalize: con_iter -> t Bag.t -> finalized option
@@ -355,9 +349,6 @@ let print_modif fmt = function
   | Cl (cl1,cl2) -> Format.fprintf fmt "Cl %a  -> %a" Cl.print cl1 Cl.print cl2
   | Dom (cl,dom,_,cl0) -> Format.fprintf fmt "Dom %a for %a(%a)"
       Dom.print dom Cl.print cl0 Cl.print cl;
-  | Sem (cl0,sem,s) ->
-    Format.fprintf fmt "Sem %a for %a with value %a"
-      Sem.print sem Cl.print cl0 (Solver.print_sem sem) s;
   | Dec _ -> Format.fprintf fmt "Dec"
   | DomL (cl,dom,v,_,_,cl0) ->
     Format.fprintf fmt "DomL %a for %a(%a) with value %a"
@@ -380,14 +371,9 @@ type explimit =
   (** At the limit the first cl is represented by this cl *)
   | LDom: 'a dom * Explanation.mod_dom -> explimit
   (** At the limit this class have this value for this dom *)
-  | LSem: 'a sem * 'a * Cl.t -> explimit
-  (** Similar to LCl. At the limit this cl is the representant and
-      before the limit this sem have been associated to it *)
 
 let print_explimit fmt = function
   | LCl (cl,rcl) -> Format.fprintf fmt "LCl(%a,%a)" Cl.print cl Cl.print rcl
-  | LSem (sem,v,cl) -> Format.fprintf fmt "LSem(%a,%a,%a)"
-                         Sem.print sem (Solver.print_sem sem) v Cl.print cl
   | LDom (dom,moddom) ->
     Format.fprintf fmt "LDom(%a,%a)" Dom.print dom
       Explanation.print_mod_dom moddom
@@ -461,15 +447,6 @@ module ComputeConflict = struct
         {eto=cln;epexp=pexp;einv=false}::l
       | GEAAfterDec l -> l
 
-  let get_sem (type a) t (sem : a sem) v =
-    match Solver.get_sem_first t.csolver_unsat sem v with
-    | None -> raise SemNeverSet
-    | Some (cl,age,pexp) when
-        Age.compare t.ctrail.last_dec age <= 0 -> (cl,pexp)
-    | Some (cl,age,pexp) ->
-      let pexp = Explanation.mk_pexp_direct ~age explimit (LSem (sem,v,cl)) in
-      (cl,pexp)
-
   let rec get_repr_at t age cl =
     try
       let (agemerge,cl') = Cl.M.find cl t.ctrail.clhist in
@@ -1176,11 +1153,9 @@ module type Con = sig
   val key: t con
 
   val same_sem:
-    ComputeConflict.t -> age -> 'a sem -> Cl.t * pexp ->
+    ComputeConflict.t -> age -> 'a sem -> 'a ->
     pexp -> Cl.t -> Cl.t -> t rescon
 
-  val propasem: con_iter -> Age.t -> 'a sem -> 'a -> Cl.t -> t rescon
-
   val propacl : con_iter -> Age.t -> Cl.t -> Cl.t -> t rescon
 
   val finalize: ComputeConflict.iter -> t Bag.t -> finalized option
@@ -1345,17 +1320,15 @@ module ConFact = struct
 
   let finalize _ = assert false (** catched before *)
 
-  let same_sem t age _ (_,pexp1) pexp2 _ _  =
+  let same_sem t age _ _ pexp2 _ _  =
     let get_con () t = function
       | GRequested ()      -> ()
       | GOther (con,c) -> ComputeConflict.unknown_con t con c
     in
-    get_con () t (ComputeConflict.get_pexp t pexp1 confact);
     get_con () t (ComputeConflict.get_pexp t pexp2 confact);
     GRequested ()
 
   let propacl _  _ _ _ = raise Impossible
-  let propasem _ _ _ _ _ = raise Impossible
   let propadom _ _ dom cl v =
     Debug.dprintf6 debug
       "[Conflict] @[Error: Ask ConFact for the limit for %a with %a of %a @]@\n"
@@ -1399,9 +1372,6 @@ module ExpLimit = struct
       | LCl (cl,rcl) ->
         let module C = (val (get_con con)) in
         C.propacl t age cl rcl
-      | LSem (sem,v,cl) ->
-        let module C = (val (get_con con)) in
-        C.propasem t age sem v cl
       | LDom (dom,{modcl;modage;modpexp}) ->
         let f (type b) (k : b exp) (exp: b) =
           let module S = (val (get_exp k) : Exp' with type t = b) in
@@ -1439,11 +1409,10 @@ module ExpSameSem = struct
 *)
   let analyse (type b) t age (con : b con) = function
     | Solver.ExpSameSem(pexp,cl1,cl2,sem,v) ->
-      let c = get_con con in
-      let module C = (val c : Con' with type t = b) in
-      let (cl0,_) as c1 = ComputeConflict.get_sem t sem v in
-      assert (Cl.equal cl0 cl2);
-      C.same_sem t age sem c1 pexp cl1 cl2
+      assert (Ty.equal (Cl.ty cl1) (Cl.ty cl2));
+      assert (Cl.equal (Cl.index sem v (Cl.ty cl2)) cl2);
+      let module C = (val get_con con) in
+      C.same_sem t age sem v pexp cl1 cl2
 
   (** not used for dom *)
   let expdom _ _ _ _ _ _ = raise Impossible
diff --git a/src/conflict.mli b/src/conflict.mli
index d3706dade..c44432a9b 100644
--- a/src/conflict.mli
+++ b/src/conflict.mli
@@ -74,8 +74,6 @@ module ComputeConflict: sig
   (** get the list of merge that make the too classes equal. *)
   val get_repr_at: t -> age -> Cl.t -> Cl.t
   (** get the repr of the class at this age . *)
-  val get_sem    : t -> 'b sem -> 'b -> Cl.t * pexp
-  (** get the explication why the sem have been linked for the first time *)
 
   val get_dom    : t -> age -> Cl.t -> 'b dom -> mod_dom list
   (** get the explications for the domain of this class at the given age *)
@@ -188,11 +186,9 @@ module type Con = sig
 
   (** Particular conflict computation *)
   val same_sem:
-    ComputeConflict.t -> age -> 'a sem -> Cl.t * pexp ->
+    ComputeConflict.t -> age -> 'a sem -> 'a ->
     pexp -> Cl.t -> Cl.t -> t rescon
 
-  val propasem: ComputeConflict.t -> Age.t -> 'a sem -> 'a -> Cl.t -> t rescon
-
   val propacl : ComputeConflict.t -> Age.t -> Cl.t -> Cl.t -> t rescon
     (* cl1 -> cl2 repr *)
 
@@ -264,9 +260,6 @@ type explimit =
   (** At the limit the first cl is represented by this cl *)
   | LDom: 'a dom * Explanation.mod_dom -> explimit
   (** At the limit this class have this value for this dom *)
-  | LSem: 'a sem * 'a * Cl.t -> explimit
-  (** Similar to LCl. At the limit this cl is the representant and
-      before the limit this sem have been associated to it *)
 
 val is_explimit : pexp -> explimit option
 
diff --git a/src/demon.ml b/src/demon.ml
index 27616b7ba..4372e3001 100644
--- a/src/demon.ml
+++ b/src/demon.ml
@@ -381,6 +381,7 @@ module Fast = struct
             Dem.print D.key.dk_id Solver.Events.Fired.print event
             D.Data.print (Solver.Events.Fired.get_data event);
           D.wakeup d event;
+          Debug.dprintf0 debug "[Demon] @[Done@]@\n";
           if not D.immediate then Solver.Delayed.flush d;
           run_one () in
       try
diff --git a/src/equality.ml b/src/equality.ml
index 1430f76ef..52bd53f93 100644
--- a/src/equality.ml
+++ b/src/equality.ml
@@ -123,8 +123,11 @@ module Th = struct
 
 end
 
-module Registered = RegisterSem(Th)
+module ThE = RegisterSem(Th)
 
+let check_sem v cl =
+  let own = ThE.cl (ThE.index v Bool.ty) in
+  Cl.equal cl own
 
 (** API *)
 
@@ -219,7 +222,6 @@ let norm_set d own v =
 (** Conflict *)
 type eqconflict =
   | Eq : Cl.t * Cl.t * bool -> eqconflict
-  | Sem: 'a sem * 'a * Cl.t * bool -> eqconflict
 
 module EqConflict = struct
 
@@ -236,23 +238,11 @@ module EqConflict = struct
       let print fmt = function
         | Eq(cl1,cl2,b) ->
           Format.fprintf fmt "%a%a%a" Cl.print cl1 print_equal b Cl.print cl2
-        | Sem(sem,v,cl,b) ->
-          Format.fprintf fmt "%a:%a%a%a"
-            Sem.print sem (Solver.print_sem sem) v print_equal b Cl.print cl
 
       let equal e1 e2 =
         match e1, e2 with
         | Eq(cla1,clb1,b1), Eq(cla2,clb2,b2) ->
           Cl.equal cla1 cla2 && Cl.equal clb1 clb2 && DBool.equal b1 b2
-        | Sem(sem1,v1,c1,b1), Sem(sem2,v2,c2,b2) ->
-          Cl.equal c1 c2 && DBool.equal b1 b2 &&
-          begin match Sem.Eq.eq_type sem1 sem2 with
-            | None -> false
-            | Some Eqtype.Eq ->
-              let module Sem = (val Solver.get_sem sem1) in
-              Sem.equal v1 v2
-          end
-        | _ -> false
 
       let compare e1 e2 =
         match e1, e2 with
@@ -262,31 +252,11 @@ module EqConflict = struct
             let c = Cl.compare clb1 clb2 in
             if c != 0 then c else
               DBool.compare b1 b2
-        | Sem(sem1,v1,c1,b1), Sem(sem2,v2,c2,b2) ->
-          let c = Cl.compare c1 c2 in
-          if c != 0 then c
-          else
-          let c = DBool.compare b1 b2 in
-          if c != 0 then c
-          else
-            begin match Sem.Eq.eq_type sem1 sem2 with
-              | None -> Sem.compare sem1 sem2
-              | Some Eqtype.Eq ->
-                let module Sem = (val Solver.get_sem sem1) in
-                Sem.compare v1 v2
-            end
-        | Eq _, _  -> 1
-        | _, Eq _  -> -1
 
       let hash e1 =
         match e1 with
         | Eq(cla1,clb1,b) ->
           Hashcons.combine2 (Cl.hash cla1) (Cl.hash clb1) (DBool.hash b)
-        | Sem(sem1,v1,c1,b) ->
-          Hashcons.combine3
-            (Cl.hash c1) (DBool.hash b) (Sem.hash sem1)
-            (let module Sem = (val Solver.get_sem sem1) in
-             Sem.hash v1)
     end)
 
   include K
@@ -296,9 +266,6 @@ module EqConflict = struct
     then Eq(cl1,cl2,b)
     else Eq(cl2,cl1,b)
 
-  let mk_sem sem v cl = Sem(sem,v,cl,true)
-
-
 end
 
 let choequal : (EqConflict.t,unit) Explanation.cho =
@@ -335,10 +302,6 @@ module ConDefaultEq = struct
         match v with
         | Eq(cl1,cl2,b) ->
           f cl1 cl2 b
-        | Sem(sem,v,cl,b) ->
-          match Delayed.get_cl_sem d sem v with
-          | Some own -> f own cl b
-          | _ -> ToDecide
       in
       try
         EqConflict.S.fold_left fold False eqs
@@ -353,11 +316,7 @@ module ConDefaultEq = struct
         match v with
         | Eq(cl1,cl2,b) ->
           return cl1 cl2 (Eq(cl1,cl2,not b))
-        | Sem(sem,v,cl,b) ->
-          let c = (Sem(sem,v,cl,not b)) in
-          match Delayed.get_cl_sem d sem v with
-          | Some own -> return own cl c
-          | _ -> f.fold_decisions acc choequal c () in
+      in
       EqConflict.S.fold_left fold acc eqs
     method conflict_add d =
       let fold acc v =
@@ -368,9 +327,6 @@ module ConDefaultEq = struct
         match v with
         | Eq(cl1,cl2,b) ->
           f cl1 cl2 b
-        | Sem(sem,v,cl,b) ->
-          let cl' = Delayed.index d sem v (Cl.ty cl) in
-          f cl' cl b
       in
       EqConflict.S.fold_left fold Cl.M.empty eqs
   end
@@ -389,9 +345,8 @@ module ConDefaultEq = struct
 
   let get_cons t _age s rlist = fold_rescon_list t get_con key s rlist
 
-  let same_sem t age _sem (_,pexp1) pexp2 _cl1 _cl2 =
+  let same_sem t age _sem _v pexp2 _cl1 _cl2 =
     let s = Bag.empty in
-    let s = get_con s t (ComputeConflict.get_pexp t pexp1 key) in
     let s = get_con s t (ComputeConflict.get_pexp t pexp2 key) in
     GRequested s
 
@@ -403,15 +358,6 @@ module ConDefaultEq = struct
       ComputeConflict.set_dec_cho t choequal v;
       GRequested(Bag.elt v)
 
-  (** For the extension *)
-  let propasem t age sem v cl =
-    if ComputeConflict.before_first_dec t age
-    then GRequested Bag.empty
-    else
-      let v = mk_sem sem v cl in
-      ComputeConflict.set_dec_cho t choequal v;
-      GRequested(Bag.elt v)
-
 end
 
 module EConDefaultEq = Conflict.RegisterCon(ConDefaultEq)
@@ -420,12 +366,7 @@ let () =
   Bool.mk_conequal := (fun t cl1 cl2 ->
       let v = EqConflict.mk_eq cl1 cl2 true in
       Conflict.ComputeConflict.set_dec_cho t choequal v;
-      Conflict.GOther(ConDefaultEq.key,Bag.elt v));
-  Bool.mk_conequal_sem.Bool.mk_conequal_sem <-
-    (fun t sem v cl ->
-       let v = EqConflict.mk_sem sem v cl in
-       Conflict.ComputeConflict.set_dec_cho t choequal v;
-       Conflict.GOther(ConDefaultEq.key,Bag.elt v))
+      Conflict.GOther(ConDefaultEq.key,Bag.elt v))
 
 module ChoEquals = struct
   open Conflict
@@ -441,8 +382,8 @@ module ChoEquals = struct
   let key = Explanation.Cho.create_key "Equals.cho"
 
   let choose_decision d v =
-    match Delayed.get_cl_sem d sem v with
-    | None -> DecNo
+    match Delayed.get_cl_sem d sem v Bool.ty with
+    | None -> assert false
     | Some own ->
       Debug.dprintf4 debug "[Equality] @[dec on %a for %a@]@\n"
         Cl.print own Th.print v;
@@ -491,11 +432,6 @@ module ChoEqual = struct
     match v with
     | Eq(cl1,cl2,_) ->
       f cl1 cl2
-    | Sem(sem,v,cl,_) ->
-      match Delayed.get_cl_sem d sem v with
-      | Some own -> f cl own
-      | _ -> DecTodo ()
-
 
   let make_decision d dec v () =
     Debug.dprintf2 Conflict.print_decision
@@ -505,9 +441,7 @@ module ChoEqual = struct
     match v with
     | Eq(cl1,cl2,b) ->
       cl1,cl2, b
-    | Sem(sem,v,cl,b) ->
-      let cl' = Delayed.index d sem v (Cl.ty cl) in
-      cl',cl, b in
+    in
     if b then begin
       Delayed.propagate d cl1;
       Delayed.propagate d cl2;
@@ -586,10 +520,6 @@ type special_equality = {
     Conflict.ComputeConflict.t -> Explanation.Deps.t -> Explanation.Age.t ->
     Cl.t -> Conflict.rlist ->
     Explanation.Deps.t;
-  sem: 'a.
-    Conflict.ComputeConflict.t -> Explanation.Deps.t -> Explanation.Age.t ->
-    'a sem -> 'a -> Explanation.pexp ->
-    Explanation.Deps.t;
   dodec: bool;
 }
 
@@ -640,7 +570,6 @@ module GenEquality = struct
       repr = (fun t deps age _ r1 ->
           let b,deps = get_cons t (Bag.empty,deps) r1 in
           Explanation.Deps.add_unknown_con deps ConDefaultEq.key b);
-      sem = get_sem;
       dodec;
     }
 
@@ -671,28 +600,8 @@ module GenEquality = struct
     assert (deps0 == ComputeConflict.get_current_deps t);
     deps
 *)
-  let sem t deps age sem v rl1 ty =
-    let deps0 = ComputeConflict.get_current_deps t in
-    let deps = (find_expspecial ty).sem t deps age sem v rl1 in
-    assert (deps0 == ComputeConflict.get_current_deps t);
-    deps
 
   let dodec ty = (find_expspecial ty).dodec
-
-  let get_con = Conflict.fold_requested_deps
-      (fun (b1,deps) _ b2 -> Bag.concat b1 b2, deps)
-  let get_cons t age = fold_rescon_list_deps t get_con ConDefaultEq.key
-  let get_sem t deps age _ _ r =
-    let accdeps = Bag.empty,deps in
-    let b,deps = get_cons t age accdeps r in
-    Explanation.Deps.add_unknown_con deps ConDefaultEq.key b
-
-  let sem_def t deps age rl1 =
-    let deps0 = ComputeConflict.get_current_deps t in
-    let deps = get_sem t deps age () () rl1 in
-    assert (deps0 == ComputeConflict.get_current_deps t);
-    deps
-
 end
 
 let register_sort_con ty ~dodec con = register_sort ty
@@ -714,7 +623,7 @@ module DaemonPropa = struct
 
   let immediate = false
   let wakeup d v _ev =
-    norm_dom d (Opt.get (Delayed.get_cl_sem d sem v)) v
+    norm_dom d (Opt.get (Delayed.get_cl_sem d sem v Bool.ty)) v
 
 end
 
@@ -986,13 +895,11 @@ module ExpSubst = struct
     | SubstUpTrue    (v,e1,e2,_)   -> (** two are equals *)
       let ty = Th.get_ty v in
       let s = Cl.M.empty in
-      let s = Bool.get_pexp t s (snd (get_sem t sem v)) in
       GenEquality.equality t age e1 e2 ty;
       return con conclause s
     | SubstUpFalse   (v,_)   ->
       let ty = Th.get_ty v in
       let s = Cl.M.empty in
-      let s = Bool.get_pexp t s (snd (get_sem t sem v)) in
       let l = Cl.S.fold_left
           (fun acc cl -> (cl,ComputeConflict.get_dom t age cl dom)::acc) [] v in
       begin match l with
@@ -1015,13 +922,13 @@ module ExpSubst = struct
       end
     | SubstDownTrue  (v,own)   ->
       let ty = Th.get_ty v in
-      let s = Bool.get_pexp t Cl.M.empty (snd (get_sem t sem v)) in
-      let s = Bool.get_dom t age own s in
+      assert (check_sem v own);
+      let s = Bool.get_dom t age own Cl.M.empty in
       return con conclause s
     | SubstDownFalse (v,own,i)   ->
       let ty = Th.get_ty v in
-      let s = Bool.get_pexp t Cl.M.empty (snd (get_sem t sem v)) in
-      let s = Bool.get_dom t age own s in
+      assert (check_sem v own);
+      let s = Bool.get_dom t age own Cl.M.empty in
       unknown_con t conclause s;
       return_dis con i
     | SubstDownDec (pexp,i)   ->
@@ -1103,7 +1010,7 @@ module ITE = struct
 end
 open ITE
 
-module EITE = Solver.RegisterSem(ITE)
+module EITE = Types.RegisterSem(ITE)
 
 let ite env cond then_ else_ =
   let ty1 = Cl.ty then_ in
@@ -1115,11 +1022,10 @@ let expite : (ITE.t * bool) Explanation.exp =
   Explanation.Exp.create_key "Ite.exp"
 
 module DaemonPropaITE = struct
-  type d = ITE.t
+  type d = EITE.t
   let key = Demon.Fast.create "ITE.propa"
 
-  module Key = DUnit
-  module Data = ITE
+  module Data = EITE
 
   let simplify d own b v =
     let branch = if b then v.then_ else v.else_ in
@@ -1130,15 +1036,14 @@ module DaemonPropaITE = struct
   let immediate = false
   let throttle = 100
   let wakeup d = function
-    | Events.Fired.EventDom(cond,dom,v) ->
+    | Events.Fired.EventDom(cond,dom,clsem) ->
       assert (Dom.equal dom Bool.dom);
+      let v = EITE.sem clsem in
       assert (Delayed.is_equal d cond v.cond);
-      begin match Delayed.get_cl_sem d ITE.key v with
+      let own = EITE.cl clsem in
+      begin match Bool.is d v.cond with
         | None -> assert false
-        | Some own ->
-          match Bool.is d v.cond with
-          | None -> assert false
-          | Some b -> simplify d own b v
+        | Some b -> simplify d own b v
       end
     | _ -> raise UnwaitedEvent
 
@@ -1163,9 +1068,11 @@ module DaemonInitITE = struct
         | Some b ->
           DaemonPropaITE.simplify d own b v
         | None ->
+          let clsem = EITE.index v (Cl.ty own) in
+          assert (Cl.equal (EITE.cl clsem) own);
           Delayed.propagate d v.cond;
           Delayed.ask_decision d (Explanation.GCho(Bool.chobool,v.cond));
-          let events = [Demon.Create.EventDom(v.cond,Bool.dom,v)] in
+          let events = [Demon.Create.EventDom(v.cond,Bool.dom,clsem)] in
           Demon.Fast.attach d DaemonPropaITE.key events
     end
     | _ -> raise UnwaitedEvent
@@ -1192,7 +1099,6 @@ module ExpITE = struct
     Explanation.age -> a Explanation.con -> t -> a Conflict.rescon =
     fun t age con (ite,_) ->
     let s = Cl.M.empty in
-    let s = Bool.get_pexp t s (snd (ComputeConflict.get_sem t ITE.key ite)) in
     let s = Bool.get_dom t age ite.cond s in
     return con conclause s
 
diff --git a/src/equality.mli b/src/equality.mli
index 68a2b8e0b..cb3ca3d57 100644
--- a/src/equality.mli
+++ b/src/equality.mli
@@ -19,9 +19,7 @@
 (*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
 (*                                                                        *)
 (**************************************************************************)
-open Stdlib
 open Types
-open Solver
 
 val equality    : Solver.d -> Cl.t list -> Cl.t
 val disequality : Solver.d -> Cl.t list -> Cl.t
@@ -34,7 +32,6 @@ val ite : Solver.d -> Cl.t -> Cl.t -> Cl.t -> Cl.t
 val propagate : Solver.d -> unit
 
 open Explanation
-open Conflict
 
 type special_equality = {
   equality:
@@ -53,10 +50,6 @@ type special_equality = {
     Conflict.ComputeConflict.t -> Explanation.Deps.t -> Explanation.Age.t ->
     Cl.t -> Conflict.rlist ->
     Explanation.Deps.t;
-  sem: 'a.
-    Conflict.ComputeConflict.t -> Explanation.Deps.t -> Explanation.Age.t ->
-    'a sem -> 'a -> Explanation.pexp ->
-    Explanation.Deps.t;
   dodec: bool;
 }
 
@@ -67,15 +60,9 @@ module GenEquality: sig
   val equality: Conflict.ComputeConflict.t ->
     Explanation.Age.t -> Types.Cl.t -> Types.Cl.t -> Ty.t -> unit
 
-  val sem:
-    Conflict.ComputeConflict.t -> Explanation.Deps.t -> Explanation.Age.t ->
-    'a sem -> 'a -> Explanation.pexp -> Ty.t ->
-    Explanation.Deps.t
-
 end
 
 type eqconflict =
   | Eq : Cl.t * Cl.t * bool -> eqconflict
-  | Sem: 'a sem * 'a * Cl.t * bool -> eqconflict
 
 val choequal : (eqconflict, unit) Explanation.cho
diff --git a/src/explanation.ml b/src/explanation.ml
index 5b9c4efb7..c3fda5dfa 100644
--- a/src/explanation.ml
+++ b/src/explanation.ml
@@ -218,7 +218,6 @@ type modif =
 | Cl : Cl.t * Cl.t             -> modif (** Just for taking an age *)
 | Dom: Cl.t * 'a dom      * pexp * Cl.t -> modif
 | DomL: Cl.t * 'a dom * 'a option * Age.t * pexp * Cl.t -> modif
-| Sem: Cl.t * 'a sem * 'a -> modif (** Just for taking an age *)
 | Dec: dec                       -> modif
 
 let print_modif_ref = ref (fun _ _ -> assert false)
@@ -400,15 +399,6 @@ let add_pexp_dom t pexp dom ~cl ~cl0 _ =
 let expfact : unit exp = Exp.create_key "Explanation.fact"
 let pexpfact = Pexp(Age.bef,expfact,(),Tags.empty,Concache.mk ())
 
-let add_pexp_sem t pexp _sem _v _cl =
-  (* let modif = Sem(cl,sem,v) in *)
-  push (* modif *) t;
-  Debug.dprintf2 debug "[Trail] @[change sem %a@]@\n"
-    (* print_modif modif *) Age.print t.age;
-  if pexp == pexpfact (** because it depend of nothing *)
-  then Age.min
-  else t.age
-
 type invclhist = Cl.t Age.M.t Cl.H.t
 
 let print_invclhist fmt h =
diff --git a/src/explanation.mli b/src/explanation.mli
index c288ea063..12fbba992 100644
--- a/src/explanation.mli
+++ b/src/explanation.mli
@@ -83,11 +83,6 @@ type modif =
 | DomL: Cl.t * 'a dom * 'a option * Age.t * pexp * Cl.t -> modif
 (** same as before but the first time in this level *)
 
-| Sem: Cl.t * 'a sem * 'a         -> modif
-  (** Cl(cl,sem,v,pexp) explication why (sem,v) is binded to this cl
-      perhaps not the representative of its eq class
-  *)
-
 | Dec: dec                       -> modif
 (** new level decision *)
 
@@ -161,12 +156,6 @@ val add_pexp_dom:
   t -> pexp -> 'b dom -> cl:Cl.t -> cl0:Cl.t -> 'b option -> unit
 (** The value must be the old value *)
 
-val add_pexp_sem:
-  t -> pexp -> 'b sem -> 'b -> Cl.t -> Age.t
-(** cl the representative cl0 the class *)
-
-
-
 val trail: t -> modif list
 val last_dec: t -> Age.t
 val nbdec: t -> int
diff --git a/src/inputlang/altergo/popop_of_altergo.mli b/src/inputlang/altergo/popop_of_altergo.mli
index 45d8b8d69..9005ccdcf 100644
--- a/src/inputlang/altergo/popop_of_altergo.mli
+++ b/src/inputlang/altergo/popop_of_altergo.mli
@@ -20,8 +20,6 @@
 (*                                                                        *)
 (**************************************************************************)
 
-open Why_ptree
-
 exception Not_supported of Loc.position
 
 val read_file: string -> Why_ptree.file
diff --git a/src/solver.ml b/src/solver.ml
index 512d51e0e..2d5319a69 100644
--- a/src/solver.ml
+++ b/src/solver.ml
@@ -148,12 +148,6 @@ module type Dom' = sig
   val key: t dom
 end
 
-module type Sem' = sig
-  type delayed
-  include Stdlib.Datatype
-  val key: t sem
-end
-
 
 type _ enqueue =
 | EnqRun: 'r -> 'r enqueue
@@ -188,8 +182,7 @@ end
 
 module type SemTable' = sig
   type delayed
-  module S : Sem' with type delayed := delayed
-  val invtable  : (Cl.t * age * pexp) S.M.t
+  module S : Sem
   (** class where propa of this sem must be done *)
   val events : Events.Wait.t list Cl.M.t
   (** propa of new semantic value *)
@@ -221,7 +214,6 @@ type t = {
   mutable event : Events.Wait.t Bag.t Cl.M.t;
   mutable event_propa : Events.Wait.t list Cl.M.t;
   mutable event_any_propa : Events.Wait.t list;
-  mutable when_propa : (delayed_t -> Cl.t -> unit) list Cl.M.t;
           (** extensible "number of fields" *)
           dom   : delayed_t VDomTable.t;
           sem   : delayed_t VSemTable.t;
@@ -286,7 +278,6 @@ let new_t () = {
   event = Cl.M.empty;
   event_propa = Cl.M.empty;
   event_any_propa = [];
-  when_propa = Cl.M.empty;
   dom = VDomTable.create 5;
   sem = VSemTable.create 5;
   envs = Env.VectorH.create 5;
@@ -301,7 +292,6 @@ let new_handler t =
   event = t.event;
   event_propa = t.event_propa;
   event_any_propa = t.event_any_propa;
-  when_propa = t.when_propa;
   dom = VDomTable.copy t.dom;
   sem = VSemTable.copy t.sem;
   envs = Env.VectorH.copy t.envs;
@@ -311,24 +301,18 @@ let new_handler t =
 
 (** {2 Dom and Sem} *)
 module type Dom = Dom' with type delayed := delayed_t
-module type Sem = Sem' with type delayed := delayed_t
 module type Dem = Dem' with type delayed := delayed_t
 
 module VDom = Dom.MkVector
   (struct type ('a,'unedeed) t =
             (module Dom with type t = 'a)
    end)
-module VSem = Sem.MkVector
-  (struct type ('a,'unedeed) t =
-            (module Sem with type t = 'a)
-   end)
 
 module VDem = Dem.MkVector
   (struct type ('k,'d,'unedeed) t =
     (module Dem with type event = 'k and type runable = 'd) end)
 
 let defined_dom : unit VDom.t = VDom.create 8
-let defined_sem : unit VSem.t = VSem.create 8
 let defined_dem : unit VDem.t = VDem.create 8
 
 module RegisterDom (D:Dom) = struct
@@ -342,16 +326,6 @@ module RegisterDom (D:Dom) = struct
 
 end
 
-module RegisterSem (D:Sem) = struct
-
-  let () =
-    VSem.inc_size D.key defined_sem;
-    assert (if not (VSem.is_uninitialized defined_sem D.key)
-      then raise AlreadyRegisteredKey else true);
-    let sem = (module D: Sem with type t = D.t) in
-    VSem.set defined_sem D.key sem
-
-end
 
 module RegisterDem (D:Dem) = struct
 
@@ -370,11 +344,6 @@ let get_dom k =
     then raise UnregisteredKey else true);
   VDom.get defined_dom k
 
-let get_sem k =
-  assert (if VSem.is_uninitialized defined_sem k
-    then raise UnregisteredKey else true);
-  VSem.get defined_sem k
-
 let get_dem k =
   assert (if VDem.is_uninitialized defined_dem k
     then raise UnregisteredKey else true);
@@ -521,15 +490,13 @@ let get_table_dom : t -> 'a dom -> (module DomTable with type D.t = 'a)
 
 let get_table_sem : t -> 'a sem -> (module SemTable with type S.t = 'a)
   = fun (type a) t k ->
-  assert (if VSem.is_uninitialized defined_sem k
-    then raise UnregisteredKey else true);
+  assert (if sem_uninitialized k then raise UnregisteredKey else true);
   VSemTable.inc_size k t.sem;
   if VSemTable.is_uninitialized t.sem k then
     let sem = get_sem k in
     let module SemTable = struct
       type delayed = delayed_t
       module S = (val sem : Sem with type t = a)
-      let invtable = S.M.empty
       let events = Cl.M.empty
       let propa_events = []
     end in
@@ -543,35 +510,36 @@ exception UninitializedEnv of Env.K.t
 
 exception NotNormalized
 
-let rec find t cl =
-  let cl' = Cl.M.find_exn NotNormalized cl t.repr in
-  if Cl.equal cl cl' then cl else
-    let r = find t cl' in
-    t.repr <- Cl.M.add cl r t.repr;
-    r
+(** Just used for being able to qualify these function on t *)
+module T = struct
+  let rec find t cl =
+    let cl' = Cl.M.find_exn NotNormalized cl t.repr in
+    if Cl.equal cl cl' then cl else
+      let r = find t cl' in
+      t.repr <- Cl.M.add cl r t.repr;
+      r
 
-let find_def t cl =
-  let cl' = Cl.M.find_def cl cl t.repr in
-  if Cl.equal cl cl' then cl else
-    let r = find t cl' in
-    t.repr <- Cl.M.add cl r t.repr;
-    r
-
-let is_repr t cl =
-  try Cl.equal (Cl.M.find cl t.repr) cl
-  with Not_found -> true
+  let find_def t cl =
+    let cl' = Cl.M.find_def cl cl t.repr in
+    if Cl.equal cl cl' then cl else
+      let r = find t cl' in
+      t.repr <- Cl.M.add cl r t.repr;
+      r
 
-let is_equal t cl1 cl2 =
-  let cl1 = find_def t cl1 in
-  let cl2 = find_def t cl2 in
-  Cl.equal cl1 cl2
+  let is_repr t cl =
+    try Cl.equal (Cl.M.find cl t.repr) cl
+    with Not_found -> true
 
+  let is_equal t cl1 cl2 =
+    let cl1 = find_def t cl1 in
+    let cl2 = find_def t cl2 in
+    Cl.equal cl1 cl2
+end
+open T
 
-let get_cl_sem  (type a) t (sem : a sem) s =
-  let module SemTable =
-    (val (get_table_sem t sem) : SemTable with type S.t = a) in
-  Opt.map (fun (cl,_,_) -> cl)
-    (SemTable.S.M.find_opt s SemTable.invtable)
+let get_cl_sem  (type a) t (sem : a sem) s ty =
+  let cl = Cl.index sem s ty in
+  Some cl
 
 let get_direct_dom (type a) t (dom : a dom) cl =
   let module DomTable =
@@ -582,12 +550,6 @@ let get_dom t dom cl =
   let cl = find_def t cl in
   get_direct_dom t dom cl
 
-
-let add_when_propa t cl todo =
-  t.when_propa <-
-    Cl.M.add_change Lists.singleton Lists.add cl todo t.when_propa
-
-
 (** {2 For debugging and display} *)
 let _print_env fmt t =
   let printd (type a) _ fmt domtable =
@@ -612,24 +574,6 @@ let output_graph filename t =
     let default_vertex_attributes _ = [`Shape `Record]
     let vertex_name cl = string_of_int (Cl.hash cl)
 
-    let table = Cl.H.create 10
-
-    let iter_sem =
-                     fun (type a) sem ->
-      let module Sem =
-            (val sem : SemTable' with type delayed = delayed_t
-                                  and type S.t = a) in
-      let iter s (cl,_,_) =
-        let mssg = Pp.sprintf_wnl "| {%a | %a} "
-          Types.Sem.print Sem.S.key Sem.S.print s in
-        let mssg' = (Cl.H.find_def table "" cl) in
-        let mssg = mssg' ^ mssg in
-        Cl.H.replace table cl mssg
-      in
-      Sem.S.M.iter iter Sem.invtable
-
-    let () = VSemTable.iter_initialized {VSemTable.iter = iter_sem} t.sem
-
     let print fmt cl =
       let iter_dom (type a) _ fmt dom =
         let module Dom =
@@ -645,10 +589,18 @@ let output_graph filename t =
         if is_repr t cl
         then Format.fprintf fmt ": %a" Ty.print (Cl.ty cl)
       in
-      Format.fprintf fmt "{%a %a %s %a}" (* "{%a | %a | %a}" *)
+      let print_sem fmt cl =
+        match Only_for_solver.sem_of_cl cl with
+        | Only_for_solver.Fresh -> ()
+        | Only_for_solver.Sem(sem,v) ->
+          let module S = (val get_sem sem) in
+          Format.fprintf fmt "| {%a | %a}"
+            Sem.print sem S.print v
+      in
+      Format.fprintf fmt "{%a %a %a %a}" (* "{%a | %a | %a}" *)
         Cl.print cl
         print_ty cl
-        (Cl.H.find_def table "" cl)
+        print_sem cl
         (if is_repr t cl
          then VDomTable.print Pp.nothing Pp.nothing
              {VDomTable.printk=Pp.nothing}
@@ -690,6 +642,7 @@ let draw_graph =
 (** {2 Delayed} *)
 
 module Delayed = struct
+  open T
   type t = delayed_t
 
   let find t cl =
@@ -704,9 +657,9 @@ module Delayed = struct
     assert (t.env.current_delayed == t);
     is_repr t.env cl
 
-  let is_repr_of t cl1 cl2 =
-    try Cl.equal (find t cl2) cl1
-    with NotNormalized -> Cl.equal cl2 cl1
+  (* let is_repr_of t cl1 cl2 = *)
+  (*   try Cl.equal (find t cl2) cl1 *)
+  (*   with NotNormalized -> Cl.equal cl2 cl1 *)
 
   let is_equal t cl1 cl2 =
     assert (t.env.current_delayed == t);
@@ -715,7 +668,7 @@ module Delayed = struct
 
   let is_propagated t cl = Cl.M.mem cl t.env.repr
 
-  let get_cl_sem t sem s = get_cl_sem t.env sem s
+  let get_cl_sem t sem s ty = get_cl_sem t.env sem s ty
 
   let add_pending_merge (t : t) pexp cl cl' =
     Debug.dprintf4 debug "[Solver] @[add_pending_merge for %a and %a@]@\n"
@@ -806,44 +759,16 @@ module Delayed = struct
       include SemTable
       let propa_events = event::propa_events
     end in
-    (** propagate the sematic value that are already propagated *)
-    VSemTable.set t.env.sem sem (module SemTable');
-    SemTable'.S.M.iter (fun s (cl,_,_) ->
-        let wakeup t cl =
-          wakeup_event Events.Fired.translate_propasem t (cl,sem,s) event
-        in
-        if is_propagated t cl
-        then wakeup t cl
-        else add_when_propa t.env cl wakeup
-      )
-      SemTable'.invtable
+    VSemTable.set t.env.sem sem (module SemTable')
 
   let index_t  (type a) t (sem : a sem) s ty =
-    let module SemTable = (val (get_table_sem t sem)) in
-    try
-      let cl,_,_ = SemTable.S.M.find s SemTable.invtable in
-      assert (Ty.equal (Cl.ty cl) ty);
-      cl
-    with Not_found ->
-      let cl = Cl.create "" ty in
-      let age = add_pexp_sem t.trail pexpfact sem s cl in
-      let module SemTable = struct
-        include SemTable
-        let invtable = SemTable.S.M.add s (cl,age,pexpfact) SemTable.invtable
-      end in
-      Debug.dprintf4 debug_create "[Solver] @[index %a into %a@]@\n"
-        SemTable.S.print s Cl.print cl;
-      VSemTable.set t.sem sem
-        (module SemTable);
-      (** propasem *)
-      begin if SemTable.propa_events != [] then
-          let wakeup t cl =
-            wakeup_events_list Events.Fired.translate_propasem
-              t (Some SemTable.propa_events) (cl,sem,s);
-          in
-          add_when_propa t cl wakeup
-      end;
-      cl
+    let cl = Cl.index sem s ty in
+    begin if Debug.test_flag debug_create && not (Cl.M.mem cl t.repr) then
+        let module Sem = (val get_sem sem) in
+        Debug.dprintf4 debug_create "[Solver] @[index %a into %a@]@\n"
+          Sem.print s Cl.print cl
+    end;
+    cl
 
   let index t sem s =
     assert (t.env.current_delayed == t);
@@ -853,7 +778,7 @@ module Delayed = struct
       (type k) (type d) d cl (dem:(k,d) dem) : k Enum.t =
     Enum.from_list
       ~filter:(function
-          | Events.Wait.Event(dem',event) ->
+          | Events.Wait.Event(dem',_) ->
             Dem.equal dem dem'
         )
       ~map:(function
@@ -867,7 +792,7 @@ module Delayed = struct
     (type k) (type d) d cl (dem:(k,d) dem) : k Enum.t =
     Enum.from_bag
       ~filter:(function
-          | Events.Wait.Event(dem',event) ->
+          | Events.Wait.Event(dem',_) ->
             Dem.equal dem dem'
         )
       ~map:(function
@@ -881,57 +806,66 @@ module Delayed = struct
 (** *)
 
 
+  let check_no_dom t cl =
+    let foldi (type a) acc _dom domtable =
+      acc &&
+      let module DomTable =
+        (val domtable : DomTable' with type D.t = a
+                                   and type delayed = delayed_t) in
+      not (Cl.M.mem cl DomTable.table)
+    in
+    VDomTable.fold_initializedi {VDomTable.foldi} true t.env.dom
+
   let propagate t cl =
     assert (t.env.current_delayed == t);
     if not (is_propagated t cl) then begin
       Debug.dprintf2 debug "[Solver] propagate %a@\n" Cl.print cl;
+      assert ( check_no_dom t cl );
       t.env.repr <- Cl.M.add cl cl t.env.repr;
+      (** propa_cl *)
       let new_events, cl_events = Cl.M.find_remove cl t.env.event_propa in
       t.env.event_propa <- new_events;
       wakeup_events_list Events.Fired.translate_propacl t cl_events cl;
+      (** propa *)
       wakeup_events_list Events.Fired.translate_propa
         t (Some t.env.event_any_propa) cl;
-      let when_propa, todos = Cl.M.find_remove cl t.env.when_propa in
-      begin match todos with
-      | None -> ()
-      | Some todos ->
-        t.env.when_propa <- when_propa;
-        List.iter (fun f -> f t cl) todos
-      end;
+      (** propa_sem *)
+      match Only_for_solver.sem_of_cl cl with
+      | Only_for_solver.Fresh -> ()
+      | Only_for_solver.Sem(sem,s) ->
+        let module SemTable = (val get_table_sem t.env sem) in
+        wakeup_events_list Events.Fired.translate_propasem
+          t (Some SemTable.propa_events) (cl,sem,s)
     end
 
   let set_sem_pending (type a) t pexp (sem : a sem) cl0 v =
     let cl = find t cl0 in
-    let module SemTable = (val (get_table_sem t.env sem)) in
-    let clo' = SemTable.S.M.find_opt v SemTable.invtable in
-    match clo' with
-    | Some (cl',_,_) when is_repr_of t cl cl' ->
-      (** if cl is the representant of cl' then we have nothing to do *)
-      ()
-    | _ ->
-      begin match clo' with
-      | None ->
-        let age = add_pexp_sem t.env.trail pexp sem v cl0 in
-        let module SemTable' = struct
-          include SemTable
-          let invtable =
-            SemTable.S.M.add v (cl0,age,pexp) invtable
-        end in
-        VSemTable.set t.env.sem sem (module SemTable');
-        wakeup_events_list Events.Fired.translate_propasem
-          t (Some SemTable.propa_events) (cl,sem,v)
-      | Some (cl',_,_) ->
-        assert (is_repr t cl);
-        (** come from invtable, can be just indexed *)
+    let cl0' = Cl.index sem v (Cl.ty cl0) in
+    begin
+      if not (is_propagated t cl0') then begin
+        propagate t cl0';
+        t.env.repr <- Cl.M.add cl0' cl t.env.repr;
+        add_pexp_cl t.env.trail pexp ~inv:false
+          ~other_cl:cl0' ~other_cl0:cl0'
+          ~repr_cl:cl ~repr_cl0:cl0;
+        (** wakeup the daemons propagate_cl *)
+        let event, other_event = Cl.M.find_remove cl0' t.env.event in
+        wakeup_events_bag Events.Fired.translate_change t other_event cl0';
+        t.env.event <- event
+      end
+      (** cl' is already propagated *)
+      else if Cl.equal cl (find t cl0') then
+        (** if cl is the representant of cl' then we have nothing to do *)
+        ()
+      else
+        (** merge cl and cl0' *)
         let pexp' = mk_pexp t.env.trail exp_same_sem
-          (ExpSameSem(pexp,cl0,cl',sem,v)) in
-        propagate t cl';
-        if not (Cl.equal cl (find t cl'))
-        then
-          add_pending_merge t pexp' cl0 cl'
-      end;
-      let cl_events = Cl.M.find_opt cl SemTable.events in
-      wakeup_events_list Events.Fired.translate_sem t cl_events (cl,sem,v)
+            (ExpSameSem(pexp,cl0,cl0',sem,v)) in
+        add_pending_merge t pexp' cl0 cl0'
+    end;
+    let module SemTable = (val get_table_sem t.env sem) in
+    let cl_events = Cl.M.find_opt cl SemTable.events in
+    wakeup_events_list Events.Fired.translate_sem t cl_events (cl,sem,v)
 
   let set_dom_pending (type a) t pexp (dom : a dom) cl0 new_v =
     Debug.incr stats_set_dom;
@@ -1150,7 +1084,9 @@ module Delayed = struct
 
   let merge t pexp cl1_0 cl2_0 =
     assert (t.env.current_delayed == t);
-    if not (Cl.equal (find t cl1_0) (find t cl2_0)) then
+    if not (Cl.equal
+              (find t cl1_0)
+              (find t cl2_0)) then
       add_pending_merge t pexp cl1_0 cl2_0
 
   let set_sem  d pexp sem cl v =
@@ -1353,10 +1289,6 @@ let get_trail t =
 let current_age t = Explanation.current_age t.trail
 let current_nbdec t = Explanation.nbdec t.trail
 
-let get_sem_first  (type a) t (sem : a sem) s =
-  let module SemTable = (val (get_table_sem t sem)) in
-  SemTable.S.M.find_opt s SemTable.invtable
-
 let get_direct_dom t dom cl =
   assert (t.current_delayed == dumb_delayed ||
           t.current_delayed == unsat_delayed);
@@ -1379,7 +1311,7 @@ module type Ro = sig
   val is_repr      : t -> Cl.t -> bool
 
 
-  val get_cl_sem : t -> 'a sem -> 'a -> Cl.t option
+  val get_cl_sem : t -> 'a sem -> 'a -> Ty.t -> Cl.t option
   (** return the first class associated to this sem
       in the current context. Return None if it has never been binded
   *)
@@ -1419,13 +1351,6 @@ let check_initialization () =
         Dom.print dom;
     end};
 
-  Sem.iter {Sem.iter = fun sem ->
-    if VSem.is_uninitialized defined_sem sem then begin
-      Format.eprintf
-        "[Warning] The set of values %a is not registered@." Sem.print sem;
-      well_initialized := false;
-    end};
-
   Dem.iter {Dem.iter = fun dem ->
     if VDem.is_uninitialized defined_dem dem then begin
       Format.eprintf
diff --git a/src/solver.mli b/src/solver.mli
index 34d443290..237674b18 100644
--- a/src/solver.mli
+++ b/src/solver.mli
@@ -83,16 +83,16 @@ module type Ro = sig
 
   val is_equal      : t -> Cl.t -> Cl.t -> bool
   val find_def  : t -> Cl.t -> Cl.t
-
-  (** {4 The classes must have been marked has propagated} *)
   val get_dom   : t -> 'a dom -> Cl.t -> 'a option
     (** dom of the representative class *)
 
+  (** {4 The classes must have been marked has propagated} *)
+
   val find      : t -> Cl.t -> Cl.t
   val is_repr      : t -> Cl.t -> bool
 
 
-  val get_cl_sem : t -> 'a sem -> 'a -> Cl.t option
+  val get_cl_sem : t -> 'a sem -> 'a -> Ty.t -> Cl.t option
   (** return the first class associated to this sem
       in the current context. Return None if it has never been binded
   *)
@@ -186,15 +186,6 @@ end
 
 module RegisterDom (D:Dom) : sig end
 
-module type Sem = sig
-  include Datatype
-
-  val key: t sem
-end
-
-module RegisterSem (D:Sem) : sig end
-
-val get_sem: 'a sem -> (module Sem with type t = 'a)
 
 val register_env: 'a Pp.printer -> 'a env -> unit
 val print_env: 'a env -> 'a Pp.printer
@@ -271,7 +262,6 @@ val current_age : t -> Explanation.Age.t
 val current_nbdec : t -> int
 
 (** for conflict *)
-val get_sem_first : t -> 'a sem -> 'a -> (Cl.t * age * pexp) option
 val get_direct_dom   : t -> 'a dom -> Cl.t -> 'a option
     (** dom of the class directly (the last time modified) *)
 
diff --git a/src/types.ml b/src/types.ml
index 9e76addad..b2ab265a9 100644
--- a/src/types.ml
+++ b/src/types.ml
@@ -65,21 +65,6 @@ module Ty = struct
 
 end
 
-module Cl = struct
-  include Strings.Fresh(struct end)
-
-  let ty_of_cl = Simple_vector.create 100
-  let create debug ty =
-    let cl = create debug in
-    Simple_vector.inc_size ((cl :> int) + 1) ty_of_cl;
-    Simple_vector.set ty_of_cl (cl :> int) ty;
-    cl
-
-  let ty (cl : t) = Simple_vector.get ty_of_cl (cl :> int)
-
-end
-
-
 module type Key = sig
 
   module K: Datatype
@@ -88,6 +73,7 @@ module type Key = sig
   val compare: 'a k -> 'b k -> int
   val equal: 'a k -> 'b k -> bool
   val hash : 'a k -> int
+  val tag: 'a k -> int
 
   type iter = {iter : 'a. 'a k -> unit}
   val iter : iter -> unit
@@ -109,7 +95,7 @@ module type Key = sig
   module M : Intmap_hetero.R1 with type 'a key = 'a k
 end
 
-module Make_key(X:sig end) : Key = struct
+module Make_key(X:sig end): Key = struct
   module K = Strings.Fresh(struct end)
 
   type 'a k = K.t (* >= 0 *)
@@ -117,6 +103,7 @@ module Make_key(X:sig end) : Key = struct
   let compare x y   = K.compare x y
   let equal x y   = K.equal x y
   let hash  x     = K.hash x
+  let tag (x:K.t) = (x:>int)
 
   type iter = {iter : 'a. 'a k -> unit}
   let iter f = K.iter f.iter
@@ -143,6 +130,161 @@ module Sem = Make_key(struct end)
 type 'a dom = 'a Dom.k
 type 'a sem = 'a Sem.k
 
+module type Sem = sig
+  include Stdlib.Datatype
+  val key: t sem
+end
+
+
+module VSem = Sem.MkVector
+  (struct type ('a,'unedeed) t =
+            (module Sem with type t = 'a)
+   end)
+
+let defined_sem : unit VSem.t = VSem.create 8
+let sem_uninitialized sem = VSem.is_uninitialized defined_sem sem
+let get_sem k =
+  assert (if sem_uninitialized k then raise UnregisteredKey else true);
+  VSem.get defined_sem k
+
+module Cl = struct
+  type 'a r =
+    | Fresh: int * Ty.t -> [>`Fresh] r
+    | Sem  : int * Ty.t * 'a sem * 'a -> [>`Sem] r
+
+  type t' = [ `Fresh | `Sem] r
+
+  let tag: t' -> int = function
+    | Fresh(tag,_) -> tag
+    | Sem(tag,_,_,_) -> tag
+
+  let names = Simple_vector.create 100
+  let used_names : (* next id to use *) int DStr.H.t = DStr.H.create 100
+
+  (** remove the empty string *)
+  let () = DStr.H.add used_names "" 0
+
+  let print fmt x =
+    Format.pp_print_char fmt '@';
+    Format.pp_print_string fmt (Simple_vector.get names (tag x))
+
+  module T = Stdlib.MakeMSH(struct
+      type t = t' let tag = tag
+      let print = print
+    end)
+
+  include T
+
+  let next_tag, incr_tag = Util.get_counter ()
+
+  let fresh s ty : t =
+    let i = next_tag () in
+    incr_tag ();
+    let s = Strings.find_new_name used_names s in
+    Simple_vector.inc_size (i+1) names;
+    Simple_vector.set names i s;
+    Fresh(i,ty)
+
+  let rename cl s =
+    let s = Strings.find_new_name used_names s in
+    Simple_vector.set names (tag cl) s
+
+  let ty = function | Fresh (_,ty) | Sem(_,ty,_,_) -> ty
+
+  module SemIndex = Sem.MkVector
+      (struct type ('a,'unedeed) t = 'a -> Ty.t -> t' end)
+
+  let semindex : unit SemIndex.t = SemIndex.create 8
+
+  let index sem v ty =
+    assert (if sem_uninitialized sem then raise UnregisteredKey else true);
+    (SemIndex.get semindex sem) v ty
+
+end
+
+module RegisterSem (D:Sem) = struct
+
+  module HC = Hashcons.MakeTag(struct
+      open Cl
+      type t = [`Sem] Cl.r
+
+      let next_tag = Cl.next_tag
+      let incr_tag = Cl.incr_tag
+
+      let equal: t -> t -> bool = fun a b ->
+        match a, b with
+        | Sem(_,tya,sema,va), Sem(_,tyb,semb,vb) ->
+          match Sem.Eq.coerce_type sema D.key,
+                Sem.Eq.coerce_type semb D.key with
+          | Eqtype.Eq, Eqtype.Eq  ->
+             Ty.equal tya tyb && D.equal va vb
+
+      let hash: t -> int = fun a ->
+        match a with
+        | Sem(_,tya,sema,va) ->
+          match Sem.Eq.coerce_type sema D.key with
+          | Eqtype.Eq ->
+            Hashcons.combine (Ty.hash tya) (D.hash va)
+
+      let set_tag: int -> t -> t = fun tag x ->
+        match x with
+        | Sem(_,ty,sem,v) -> Sem(tag,ty,sem,v)
+
+      let tag: t -> int = function
+        | Sem(tag,_,_,_) -> tag
+
+      let print fmt x =
+        Format.pp_print_char fmt '@';
+        Format.pp_print_string fmt (Simple_vector.get names (tag x))
+    end)
+
+  include HC
+
+  let tag: t -> int = function
+    | Cl.Sem(tag,_,_,_) -> tag
+
+  let index v ty =
+    let cl =
+      HC.hashcons3
+        (fun tag sem v ty -> Cl.Sem(tag,ty,sem,v))
+        D.key v ty in
+    let i = tag cl in
+    Simple_vector.inc_size (i+1) Cl.names;
+    begin
+      if Simple_vector.is_uninitialized Cl.names i then
+        let s = Strings.find_new_name Cl.used_names ""
+        (** TODO use Sem.print or Sem.print_debug *) in
+        Simple_vector.set Cl.names i s
+    end;
+    cl
+
+  (** Just used for checking the typability *)
+  let _cl : t -> Cl.t = function
+    | Cl.Sem(tag,ty,sem,v) -> Cl.Sem(tag,ty,sem,v)
+
+  (** IF the previous function is typable this one is correct:
+      I'm not able to defined is without obj.magic
+  *)
+  let cl : t -> Cl.t = Obj.magic
+
+  let sem : t -> D.t = function
+    | Cl.Sem(_,_,sem,v) ->
+      match Sem.Eq.coerce_type sem D.key with
+      | Eqtype.Eq -> v
+
+  let ty : t -> Ty.t = function
+    | Cl.Sem(_,ty,_,_) -> ty
+
+  let () =
+    VSem.inc_size D.key defined_sem;
+    assert (if not (VSem.is_uninitialized defined_sem D.key)
+      then raise AlreadyRegisteredKey else true);
+    let sem = (module D: Sem with type t = D.t) in
+    VSem.set defined_sem D.key sem;
+    Cl.SemIndex.set Cl.semindex D.key (fun v ty -> cl (index v ty))
+
+end
+
 module Env = Make_key(struct end)
 type 'a env = 'a Env.k
 
@@ -185,8 +327,6 @@ module Dem = Make_key2(struct end)
 
 type ('k,'d) dem = ('k,'d) Dem.k
 
-
-
 module Print = struct (** Cutting the knot for printer *)
   type psem = { mutable psem : 'a. ('a sem -> 'a Pp.printer)}
 
@@ -210,3 +350,27 @@ module Print = struct (** Cutting the knot for printer *)
 
 
 end
+
+module Only_for_solver = struct
+  type sem_of_cl =
+    | Fresh: sem_of_cl
+    | Sem: 'a sem * 'a -> sem_of_cl
+
+  let sem_of_cl = function
+    | Cl.Fresh _ -> Fresh
+    | Cl.Sem (_,_,sem,v) -> Sem(sem,v)
+end
+
+
+let check_initialization () =
+  let well_initialized = ref true in
+
+  Sem.iter {Sem.iter = fun sem ->
+    if VSem.is_uninitialized defined_sem sem then begin
+      Format.eprintf
+        "[Warning] The set of values %a is not registered@." Sem.print sem;
+      well_initialized := false;
+    end};
+
+  !well_initialized
+
diff --git a/src/types.mli b/src/types.mli
index a9343f9dd..0e2aeef8c 100644
--- a/src/types.mli
+++ b/src/types.mli
@@ -49,20 +49,6 @@ module Ty : sig
 end
 
 
-(** Classes *)
-module Cl : sig
-  type t = private int
-  include Datatype with type t := t
-
-  val create: string -> Ty.t -> t
-  (** the string is used as the prefix for the debug output *)
-
-  val rename: t -> string -> unit
-  (** to use with care *)
-
-  val ty: t -> Ty.t
-end
-
 (** the key shouldn't be used before its registration and shouldn't be
     registered again *)
 exception UnregisteredKey
@@ -77,6 +63,7 @@ module type Key = sig
   val compare: 'a k -> 'b k -> int
   val equal: 'a k -> 'b k -> bool
   val hash : 'a k -> int
+  val tag: 'a k -> int
 
   type iter = {iter : 'a. 'a k -> unit}
   val iter : iter -> unit
@@ -108,9 +95,53 @@ module Dom: Key
 type 'a dom = 'a Dom.k
 type 'a sem = 'a Sem.k
 
+module type Sem = sig
+  include Datatype
+
+  val key: t sem
+end
+
+val get_sem: 'a sem -> (module Sem with type t = 'a)
+val sem_uninitialized: 'a sem -> bool
+
 module Env: Key
 type 'a env = 'a Env.k
 
+(** Classes *)
+module Cl : sig
+  include Datatype
+
+  val fresh: string -> Ty.t -> t
+  (** the string is used as the prefix for the debug output *)
+
+  val rename: t -> string -> unit
+  (** to use with care *)
+
+  val ty: t -> Ty.t
+
+  val index: 'a sem -> 'a -> Ty.t -> t
+  (** Return the corresponding cl from a semantical value *)
+
+end
+
+module RegisterSem (D:Sem) : sig
+  (** clsem *)
+  include Datatype
+
+  val index: D.t -> Ty.t -> t
+  (** Return a clsem from a semantical value *)
+
+  val cl: t -> Cl.t
+  (** Return a class from a clsem *)
+
+  val ty: t -> Ty.t
+  (** Return the type from a clsem *)
+
+  val sem: t -> D.t
+  (** Return the sem from a clsem *)
+
+end
+
 module type Key2 = sig
   module K: Datatype
   type ('k,'d) k = private K.t
@@ -156,3 +187,18 @@ module Print : sig (** Cutting the knot for printer *)
 
 
 end
+
+val check_initialization: unit -> bool
+(** Check if the initialization of all the dom, sem and dem have been done *)
+
+(** Only for Solver *)
+module Only_for_solver: sig
+  type sem_of_cl =
+    | Fresh: sem_of_cl
+    | Sem: 'a sem * 'a -> sem_of_cl
+
+  val sem_of_cl:
+    Cl.t -> sem_of_cl
+    (** give the sem associated with a cl, make sens only for not merged
+        class. So only the module solver can use it *)
+end
diff --git a/src/uninterp.ml b/src/uninterp.ml
index 0675176f2..857a27839 100644
--- a/src/uninterp.ml
+++ b/src/uninterp.ml
@@ -70,7 +70,7 @@ module Th = struct
 
 end
 
-module Registered = RegisterSem(Th)
+module ThE = RegisterSem(Th)
 
 let funty_ctr = Ty.Constr.create "Fun"
 let funty = Ty.ctr funty_ctr
@@ -100,7 +100,7 @@ let result_to_dec = Cl.H.create 20
 
 let fresh_fun _env ~result ~arity name =
   assert (arity > 0);
-  let cl = Cl.create name funty in
+  let cl = Cl.fresh name funty in
   let result_info = Ty.H.find_def result_of_sort None result in
   Cl.H.add result_to_dec cl (result,arity,result_info);
   cl
@@ -133,16 +133,16 @@ let fun5 t ty s =
   (fun t x1 x2 x3 x4 x5 -> app_fun t f [x1;x2;x3;x4;x5])
 
 
-type expsubst = Th.t
+type expsubst = ThE.t
 let expsubst : expsubst Explanation.exp =
   Explanation.Exp.create_key "Uninterp"
 
 module DaemonPropa = struct
-  type k = Th.t
+  type k = ThE.t
   type d = unit
   let key = Demon.Key.create "Uninterp.DaemonPropa"
 
-  module Key = Th
+  module Key = ThE
   module Data = DUnit
 
   let is_unborn d v =
@@ -158,17 +158,17 @@ module DaemonPropa = struct
       [EventChange(f,()); EventChange(g,())]
 
   let immediate = true (** can be false *)
-  let wakeup d (App(f,g) as v) _ev =
-    match Delayed.get_cl_sem d sem v with
-    | None -> assert false
-    | Some own ->
+  let wakeup d (clsem:k) _ev =
+    match ThE.sem clsem with
+    | App(f,g) as v ->
       Debug.dprintf4 debug "[Uninterp] @[wakeup own %a v:%a@]@\n"
-        Cl.print own Th.print v;
+        Cl.print (ThE.cl clsem) Th.print v;
       let v' = App(Delayed.find d f, Delayed.find d g) in
       assert (not (Th.equal v v'));
-      let pexp = Delayed.mk_pexp d expsubst v in
-      Delayed.set_sem d pexp sem own v';
-      Demon.AliveRedirected v'
+      let pexp = Delayed.mk_pexp d expsubst clsem in
+      Delayed.set_sem d pexp sem (ThE.cl clsem) v';
+      let clsem' = ThE.index v' (ThE.ty clsem) in
+      Demon.AliveRedirected clsem'
 end
 
 module RDaemonPropa = Demon.Key.Register(DaemonPropa)
@@ -189,17 +189,19 @@ module DaemonInit = struct
         begin match Sem.Eq.coerce_type sem sem' with
         | Eqtype.Eq ->
           Debug.dprintf2 debug "[Uninterp] @[init %a@]@\n" Th.print v;
-          if DaemonPropa.is_unborn d v then
+          let clsem = ThE.index v (Cl.ty own) in
+          assert (Cl.equal own (ThE.cl clsem));
+          if DaemonPropa.is_unborn d clsem then
           match v with
           | App(f,g) ->
             Delayed.propagate d f; Delayed.propagate d g;
             let f' = Delayed.find d f in
             let g' = Delayed.find d g in
             if Cl.equal f' f && Cl.equal g' g then
-              DaemonPropa.attach d f g (v : t)
+              DaemonPropa.attach d f g clsem
             else
               let v' = App(f',g') in
-              let pexp = Delayed.mk_pexp d expsubst v in
+              let pexp = Delayed.mk_pexp d expsubst clsem in
               Delayed.set_sem d pexp sem own v'
         end
       | _ -> raise UnwaitedEvent
@@ -225,8 +227,10 @@ module ExpSubst = struct
 
   type t = expsubst
 
-  let print fmt (App(f,g)) =
-    Format.fprintf fmt "Subst(%a,%a)" Cl.print f Cl.print g
+  let print fmt clsem =
+    match ThE.sem clsem with
+    | App(f,g) ->
+      Format.fprintf fmt "Subst(%a,%a)" Cl.print f Cl.print g
 
 (*
   let iterexp t age = function
@@ -238,18 +242,12 @@ module ExpSubst = struct
   let analyse :
     type a. Conflict.ComputeConflict.t ->
     Explanation.age -> a Explanation.con -> t -> a Conflict.rescon =
-    fun t age con exp ->
-      begin match exp with
+    fun t age con clsem ->
+      begin match ThE.sem clsem with
       | App(f,g) as v ->
         let fty = Cl.ty f in
         let gty = Cl.ty g in
         let deps = Deps.empty in
-        let own,pexp = get_sem t sem v in
-        let ty = Cl.ty own in
-        let deps =
-          (** TODO separate the first Merge(UF) from the others(GenEquality)? *)
-          Equality.GenEquality.sem t deps age sem v pexp ty in
-        add_deps t deps;
         Equality.GenEquality.equality t age f (get_repr_at t age f) fty;
         Equality.GenEquality.equality t age g (get_repr_at t age g) gty
       end;
diff --git a/src/util/hashcons.ml b/src/util/hashcons.ml
index f8fe6565f..7175b6596 100644
--- a/src/util/hashcons.ml
+++ b/src/util/hashcons.ml
@@ -27,24 +27,40 @@ module type S =
   sig
     include Datatype
     val hashcons : t -> t
+    val hashcons0: (int -> t) -> t
+    val hashcons1: (int -> 'a -> t) -> 'a -> t
+    val hashcons2: (int -> 'a -> 'b -> t) -> 'a -> 'b -> t
+    val hashcons3: (int -> 'a -> 'b -> 'c -> t) -> 'a -> 'b -> 'c -> t
     val iter : (t -> unit) -> unit
-    val stats : unit -> int * int * int * int * int * int
+    type cat
+    val stats : cat -> int * int * int * int * int * int
+    val fresh_tag: unit -> int
   end
 
-module Make(H : HashedType) : (S with type t = H.t) =
+
+module MakeTag(H : sig include HashedType
+                 val next_tag: unit -> int
+                 val incr_tag: unit -> unit
+               end) :
+  (S with type t = H.t and type cat := unit) =
 struct
   module WH = Weak.Make (H)
 
-  let next_tag = ref 0
+  let fresh_tag () = let tag = H.next_tag () in H.incr_tag (); tag
 
   let htable = WH.create 5003
 
-  let hashcons d =
-    let d = H.set_tag !next_tag d in
+  let hashcons' d =
     let o = WH.merge htable d in
-    if o == d then incr next_tag;
+    if o == d then H.incr_tag ();
     o
 
+  let hashcons d = hashcons' (H.set_tag (H.next_tag ()) d)
+  let hashcons0 f = hashcons' (f (H.next_tag ()))
+  let hashcons1 f a = hashcons' (f (H.next_tag ()) a)
+  let hashcons2 f a b = hashcons' (f (H.next_tag ()) a b)
+  let hashcons3 f a b c = hashcons' (f (H.next_tag ()) a b c)
+
   let iter f = WH.iter f htable
 
   let stats () = WH.stats htable
@@ -61,6 +77,63 @@ struct
 
 end
 
+module Make(H : HashedType) :
+  (S with type t = H.t and type cat := unit) =
+  MakeTag(struct
+    include H
+    let next_tag, incr_tag = Util.get_counter ()
+  end)
+
+module MakeCat(H : sig include HashedType val category: t -> int end) :
+  (sig include S with type t = H.t and type cat := int
+    val new_category: int -> unit
+    val iter_cat: (t -> unit) -> int -> unit
+  end) =
+struct
+  module WH = Weak.Make (H)
+
+  let next_tag = ref 0
+  let fresh_tag () = let tag = !next_tag in incr next_tag; tag
+
+  let htable: WH.t Simple_vector.t = Simple_vector.create 10
+
+  let new_category cat =
+    Simple_vector.inc_size cat htable;
+    assert (Simple_vector.is_uninitialized htable cat);
+    Simple_vector.set htable cat (WH.create 64)
+
+  let hashcons' d =
+    let o = WH.merge (Simple_vector.get htable (H.category d)) d in
+    if o == d then incr next_tag;
+    o
+
+  let hashcons d = hashcons' (H.set_tag !next_tag d)
+  let hashcons0 f = hashcons' (f !next_tag)
+  let hashcons1 f a = hashcons' (f !next_tag a)
+  let hashcons2 f a b = hashcons' (f !next_tag a b)
+  let hashcons3 f a b c = hashcons' (f !next_tag a b c)
+
+  let iter f =
+    Simple_vector.iter_initialized (fun h -> WH.iter f h) htable
+
+  let iter_cat f cat =
+    WH.iter f (Simple_vector.get htable cat)
+
+  let stats cat = WH.stats (Simple_vector.get htable cat)
+
+  module T = struct
+    type t = H.t
+    let hash = H.tag
+    let equal ts1 ts2 = ts1 == ts2
+    let compare ts1 ts2 = Pervasives.compare (H.tag ts1) (H.tag ts2)
+    let print = H.print
+  end
+
+  include MkDatatype(T)
+
+end
+
+
 let combine acc n = n * 65599 + acc
 let combine2 acc n1 n2 = combine acc (combine n1 n2)
 let combine3 acc n1 n2 n3 = combine acc (combine n1 (combine n2 n3))
diff --git a/src/util/hashcons.mli b/src/util/hashcons.mli
index 321b8b42c..5034ee5bb 100644
--- a/src/util/hashcons.mli
+++ b/src/util/hashcons.mli
@@ -43,17 +43,42 @@ module type S =
           in the table and returns it.
       *)
 
+    (** Versions where you don't create a value before modifying it *)
+    val hashcons0: (int -> t) -> t
+    val hashcons1: (int -> 'a -> t) -> 'a -> t
+    val hashcons2: (int -> 'a -> 'b -> t) -> 'a -> 'b -> t
+    val hashcons3: (int -> 'a -> 'b -> 'c -> t) -> 'a -> 'b -> 'c -> t
+
     val iter : (t -> unit) -> unit
       (** [iter f] iterates [f] over all elements of the table . *)
-    val stats : unit -> int * int * int * int * int * int
+
+    type cat
+    val stats : cat -> int * int * int * int * int * int
       (** Return statistics on the table.  The numbers are, in order:
           table length, number of entries, sum of bucket lengths,
           smallest bucket length, median bucket length, biggest
           bucket length. *)
+
+    val fresh_tag: unit -> int
+      (** get a fresh tag *)
   end
 
-module Make(H : HashedType) : (S with type t = H.t)
+module Make(H : HashedType) : (S with type t = H.t
+                                  and type cat := unit)
+
+module MakeCat(H : sig include HashedType val category: t -> int end) :
+  (sig
+    include S with type t = H.t and type cat := int
+    val new_category: int -> unit
+    val iter_cat: (t -> unit) -> int -> unit
+  end)
+
 
+module MakeTag(H : sig include HashedType
+                 val next_tag: unit -> int
+                 val incr_tag: unit -> unit
+               end) :
+  (S with type t = H.t and type cat := unit)
 
 (* helpers *)
 
diff --git a/src/util/strings.ml b/src/util/strings.ml
index bb0d41aac..9be4e27f4 100644
--- a/src/util/strings.ml
+++ b/src/util/strings.ml
@@ -85,6 +85,24 @@ module type Fresh = sig
   val rename: t -> string -> unit
 end
 
+
+let find_new_name used_names s =
+  let rec aux used_names  s n =
+    let sid = s^(string_of_int n) in
+    if DStr.H.mem used_names sid then
+      aux used_names s (n+1)
+    else sid,(n+1) in
+  try
+    let n = DStr.H.find used_names s in
+    let s',n = aux used_names s n in
+    DStr.H.replace used_names s n;
+    DStr.H.add     used_names s' 2;
+    s'
+  with Not_found ->
+    DStr.H.add     used_names s 2;
+    s
+
+
 module Fresh (X : sig end) = struct
   include DInt
   let names = Simple_vector.create 100
@@ -94,28 +112,12 @@ module Fresh (X : sig end) = struct
     Format.pp_print_char fmt '@';
     Format.pp_print_string fmt (Simple_vector.get names (x:>int))
 
-  let find_new_name s =
-    let rec aux s n =
-      let sid = s^(string_of_int n) in
-      if DStr.H.mem used_names sid then
-        aux s (n+1)
-      else sid,(n+1) in
-    try
-      let n = DStr.H.find used_names s in
-      let s',n = aux s n in
-      DStr.H.replace used_names s n;
-      DStr.H.add     used_names s' 2;
-      s'
-    with Not_found ->
-      DStr.H.add     used_names s 2;
-      s
-
   let c = ref (-1)
 
   let create s =
     incr c;
     let i = !c in
-    let s = find_new_name s in
+    let s = find_new_name used_names s in
     Simple_vector.inc_size (i+1) names;
     Simple_vector.set names i s;
     i
@@ -129,6 +131,6 @@ module Fresh (X : sig end) = struct
   let hint_size () = !c + 1
 
   let rename i s =
-    let s = find_new_name s in
+    let s = find_new_name used_names s in
     Simple_vector.set names i s
 end
diff --git a/src/util/strings.mli b/src/util/strings.mli
index cf686a071..c111433ef 100644
--- a/src/util/strings.mli
+++ b/src/util/strings.mli
@@ -45,3 +45,5 @@ module type Fresh = sig
 end
 
 module Fresh (X : sig end) : Fresh
+
+val find_new_name: int Stdlib.DStr.H.t -> string -> string
diff --git a/src/util/util.ml b/src/util/util.ml
index 50aa37ec7..513f3b6c5 100644
--- a/src/util/util.ml
+++ b/src/util/util.ml
@@ -40,3 +40,6 @@ let any_fn pr _ t = pr t && raise FoldSkip
 let ttrue _ = true
 let ffalse _ = false
 
+let get_counter () =
+  let r = ref 0 in
+  (fun () -> !r), (fun () -> incr r)
diff --git a/src/util/util.mli b/src/util/util.mli
index 192406563..141b4581c 100644
--- a/src/util/util.mli
+++ b/src/util/util.mli
@@ -41,3 +41,6 @@ val ffalse : 'a -> bool
 
 val ttrue : 'a -> bool
 (** [ttrue] constant function [true] *)
+
+val get_counter: unit -> (unit -> int) * (unit -> unit)
+(** a strictly increasing counter (next_tag,incr_tag) *)
diff --git a/src/variable.ml b/src/variable.ml
index c87d4bb13..7e338f61b 100644
--- a/src/variable.ml
+++ b/src/variable.ml
@@ -56,7 +56,7 @@ let cst =
       assert (Ty.equal (Cl.ty cl) ty);
       cl
     with Not_found ->
-      let cl = Cl.create s ty in
+      let cl = Cl.fresh s ty in
       DStr.H.add h s cl;
       cl
 
@@ -68,7 +68,7 @@ let register_sort ~dec ty =
 
 
 let fresh t ty s =
-  let cl = Cl.create s ty in
+  let cl = Cl.fresh s ty in
   (try add_dec ~dec:(Ty.H.find dec_of_sort ty) t cl;
    with Not_found -> ());
   cl
diff --git a/src/variable.mli b/src/variable.mli
index 977b49483..ac794884f 100644
--- a/src/variable.mli
+++ b/src/variable.mli
@@ -20,7 +20,6 @@
 (*                                                                        *)
 (**************************************************************************)
 open Types
-open Solver
 
 type make_dec = Cl.t -> Explanation.chogen
 
-- 
GitLab