Skip to content

Commit a938a58

Browse files
committed
Add a cache for extensionality witnesses
In `extensionality` propagator of `Arrays_rel`, there is no cache to prevent from duplicating these witnesses. This PR adds such a cache.
1 parent 4d1e17e commit a938a58

File tree

1 file changed

+38
-10
lines changed

1 file changed

+38
-10
lines changed

src/lib/reasoners/arrays_rel.ml

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,24 @@ end
8787

8888
let 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+
90108
module H = Ephemeron.K1.Make (Expr)
91109

92110
type 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

Comments
 (0)