8787
8888let timer = Timers. M_Arrays
8989
90+ module Witness = struct
91+ include Map. Make (struct
92+ type t = E .t * E .t
93+
94+ let compare (a1 , b1 ) (a2 , b2 ) =
95+ let c = E. compare a1 a2 in
96+ if c <> 0 then c
97+ else E. compare b1 b2
98+ end )
99+
100+ let normalize a b =
101+ if E. compare a b > 0 then (b, a)
102+ else (a, b)
103+
104+ let add a b = add (normalize a b)
105+ let find a b = find (normalize a b)
106+ end
107+
90108module H = Ephemeron.K1. Make (Expr )
91109
92110type t = {
@@ -118,6 +136,12 @@ type t = {
118136 (* Cache used to prevent from generating several times the same instantiation
119137 in [get_of_set]. *)
120138
139+ witnesses : E .t Witness .t ;
140+ (* Cache for extensionality witnesses. For each disequality `a != b` of
141+ arrays, the [extensionality] propagator generates a fresh index [wit]
142+ and propagates the literal `(select a wit) != (select b wit)`.
143+ This cache ensures that these are not duplicated. *)
144+
121145 new_terms : E.Set .t ;
122146 (* Set of get and set terms produced by the theory. These terms
123147 are supposed to be sent to the instantiation engine. *)
@@ -135,6 +159,7 @@ let empty uf = {
135159 conseq = LRmap. empty;
136160 seen = Tmap. empty;
137161 new_terms = E.Set. empty;
162+ witnesses = Witness. empty;
138163 (* size_splits = Numbers.Q.one; *)
139164 cached_relevant_terms = H. create 1024 ;
140165}, Uf. domains uf
@@ -398,16 +423,19 @@ let extensionality accu la =
398423 | A. Distinct (false , [r ;s ]) ->
399424 begin
400425 match X. type_info r, X. term_extract r, X. term_extract s with
401- | Ty. Tfarray (ty , _ ), (Some t1 , _ ), (Some t2 , _ ) ->
402- let i = E. fresh_name ty in
403- let g1 = E.ArraysEx. select t1 i in
404- let g2 = E.ArraysEx. select t2 i in
405- let d = E. mk_distinct ~iff: false [g1;g2] in
406- let acc = Conseq. add (d, dep) acc in
407- let env =
408- {env with new_terms =
409- E.Set. add g2 (E.Set. add g1 env.new_terms) } in
410- env, acc
426+ | Ty. Tfarray (ty , _ ), (Some t1 , _ ), (Some t2 , _ ) -> (
427+ match Witness. find t1 t2 env.witnesses with
428+ | exception Not_found ->
429+ let wit = E. fresh_name ty in
430+ let g1 = E.ArraysEx. select t1 wit in
431+ let g2 = E.ArraysEx. select t2 wit in
432+ let d = E. mk_distinct ~iff: false [g1;g2] in
433+ let acc = Conseq. add (d, dep) acc in
434+ let new_terms = E.Set. add g2 (E.Set. add g1 env.new_terms) in
435+ let witnesses = Witness. add t1 t2 wit env.witnesses in
436+ let env = { env with new_terms; witnesses } in
437+ env, acc
438+ | _ -> accu)
411439 | _ -> accu
412440 end
413441 | _ -> accu
0 commit comments