Skip to content

Commit 78dac20

Browse files
committed
fix(AC, Arith): Use a separate namespace for AC abstractions
We are using the same name space for all the constants introduced by any abstraction procedure. However, we also have code in the arithmetic module that cares specifically about abstractions introduced by AC(X) in order to determine whether distributivity should be applied or not. This patch uses different namespaces for symbols introduced for AC(X) purposes and symbols introduced by other abstraction procedures (such as Shostak's record abstraction). After reviewing the different places where we use `Expr.fresh_name`, I believe only the two locations changed to `Expr.fresh_ac_name` in this commit are related to AC(X), and other uses of `Expr.fresh_name` are for separate, independent abstraction procedures. Fixes OCamlPro#1172
1 parent 15e4a50 commit 78dac20

File tree

10 files changed

+298
-20
lines changed

10 files changed

+298
-20
lines changed

src/lib/reasoners/ac.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ module Make (X : Sig.X) = struct
214214
let eq = Expr.mk_eq ~iff:false aro_t t in
215215
X.term_embed aro_t, eq::acc
216216
| _, { ty; _ } ->
217-
let k = Expr.fresh_name ty in
217+
let k = Expr.fresh_ac_name ty in
218218
let eq = Expr.mk_eq ~iff:false k t in
219219
X.term_embed k, eq::acc
220220

src/lib/reasoners/arith.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ module Shostak
455455
List.exists
456456
(fun x ->
457457
match X.term_extract x with
458-
| Some t, _ -> E.is_internal_name t
458+
| Some t, _ -> E.is_fresh_ac_name t
459459
| _ -> false
460460
) (X.leaves xp)
461461

@@ -540,7 +540,7 @@ module Shostak
540540
List.fold_left
541541
(fun (l, sb) (b, y) ->
542542
if X.ac_extract y != None && X.str_cmp y x > 0 then
543-
let k = X.term_embed (E.fresh_name Ty.Tint) in
543+
let k = X.term_embed (E.fresh_ac_name Ty.Tint) in
544544
(b, k) :: l, (y, embed k)::sb
545545
else (b, y) :: l, sb)
546546
([], []) l

src/lib/reasoners/uf.ml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,8 +1188,7 @@ let compute_concrete_model_of_val cache =
11881188
We should check if these symbols can be defined as solvable to
11891189
remove this particular case here. *)
11901190
if X.is_solvable_theory_symbol f || is_destructor f
1191-
|| Sy.is_internal f || E.is_internal_name t || E.is_internal_skolem t
1192-
|| E.equal t E.vrai || E.equal t E.faux
1191+
|| Sy.is_internal f || E.equal t E.vrai || E.equal t E.faux
11931192
then
11941193
(* These terms are built-in interpreted ones and we don't have
11951194
to produce a definition for them. *)

src/lib/structures/expr.ml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -987,13 +987,14 @@ let fresh_name ty =
987987
let mk_abstract ty =
988988
mk_term (Sy.name ~ns:Abstract @@ Id.Namespace.Abstract.fresh ()) [] ty
989989

990-
let is_internal_name t =
990+
let fresh_ac_name ty =
991+
mk_term (Sy.name ~ns:Fresh_ac @@ Id.Namespace.Internal.fresh ()) [] ty
992+
993+
let is_fresh_ac_name t =
991994
match t with
992-
| { f = Name { ns = Fresh; _ }; xs = []; _ } -> true
995+
| { f = Name { ns = Fresh_ac; _ }; xs = []; _ } -> true
993996
| _ -> false
994997

995-
let is_internal_skolem t = Sy.is_fresh_skolem t.f
996-
997998
let positive_int i = mk_term (Sy.int i) [] Ty.Tint
998999

9991000
let int i =

src/lib/structures/expr.mli

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,6 @@ val size : t -> int
228228
val depth : t -> int
229229
val is_positive : t -> bool
230230
val neg : t -> t
231-
val is_internal_name : t -> bool
232-
val is_internal_skolem : t -> bool
233231
val is_int : t -> bool
234232
val is_real : t -> bool
235233
val type_info : t -> Ty.t
@@ -256,6 +254,11 @@ val real : string -> t
256254
val bitv : string -> Ty.t -> t
257255
val fresh_name : Ty.t -> t
258256

257+
(* Special names used for AC(X) abstraction.
258+
These corresponds to the K sort in the AC(X) paper. *)
259+
val fresh_ac_name : Ty.t -> t
260+
val is_fresh_ac_name : t -> bool
261+
259262
val mk_abstract : Ty.t -> t
260263
(** [mk_abstract ty] creates an abstract model term of type [ty].
261264
This function is intended to be used only in models. *)

src/lib/structures/symbols.ml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ type form =
7575

7676
type name_kind = Ac | Other
7777

78-
type name_space = User | Internal | Fresh | Skolem | Abstract
78+
type name_space = User | Internal | Fresh | Fresh_ac | Skolem | Abstract
7979

8080
let compare_name_space ns1 ns2 =
8181
match ns1, ns2 with
@@ -91,6 +91,10 @@ let compare_name_space ns1 ns2 =
9191
| Fresh, _ -> -1
9292
| _, Fresh -> 1
9393

94+
| Fresh_ac, Fresh_ac -> 0
95+
| Fresh_ac, _ -> -1
96+
| _, Fresh_ac -> 1
97+
9498
| Skolem, Skolem -> 0
9599
| Skolem, _ -> -1
96100
| _, Skolem -> 1
@@ -128,6 +132,7 @@ let mangle ns s =
128132
| User -> s
129133
| Internal -> ".!" ^ s
130134
| Fresh -> ".k" ^ s
135+
| Fresh_ac -> ".K" ^ s
131136
| Skolem -> ".?__" ^ s
132137
| Abstract -> "@a" ^ s
133138

@@ -514,10 +519,6 @@ let fresh_skolem_string base = Id.Namespace.Skolem.fresh ~base ()
514519
let fresh_skolem_name base = name ~ns:Skolem (fresh_skolem_string base)
515520
let fresh_skolem_var base = Var.of_string (fresh_skolem_string base)
516521

517-
let is_fresh_skolem = function
518-
| Name { ns = Skolem; _ } -> true
519-
| _ -> false
520-
521522
let is_get f = equal f (Op Get)
522523
let is_set f = equal f (Op Set)
523524

src/lib/structures/symbols.mli

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,30 @@ type name_space =
102102
(** This symbol is a "fresh" internal name. Fresh internal names play a
103103
similar role as internal names, but they always represent a constant
104104
that was introduced during solving as part of some kind of purification
105-
or abstraction procedure. This is notably used by some parts of AC(X)
106-
that check if terms contains fresh symbols (see [contains_a_fresh_alien]
107-
in the [Arith] module for an example).
105+
or abstraction procedure.
106+
107+
In order to correctly implement AC(X) in the presence of distributive
108+
symbols, symbols generated for AC(X) abstraction use a special
109+
namespace, [Fresh_ac] below.
108110
109111
To ensure uniqueness, fresh names must always be generated using
110112
[Id.Namespace.Internal.fresh ()].
111113
112114
In particular, fresh names are only used to denote constants, not
113115
arbitrary functions. *)
116+
| Fresh_ac
117+
(** This symbol has been introduced as part of the AC(X) abstraction process.
118+
This is notably used by some parts of AC(X) that check if terms contains
119+
fresh symbols (see [contains_a_fresh_alien] in the [Arith] module for an
120+
example).
121+
122+
These correspond to the K sort in the AC(X) paper. They use a different
123+
name space from other fresh symbols because we need to be able to know
124+
whether a fresh symbol comes from the AC(X) abstraction procedure in order
125+
to prevent loops.
126+
127+
To ensure uniqueness, AC abstraction names must always be generated using
128+
[Id.Namespace.Internal.fresh ()]. *)
114129
| Skolem
115130
(** This symbol has been introduced as part of skolemization, and represents
116131
the (dependent) variable of an existential quantifier. Skolem names can
@@ -202,7 +217,6 @@ val pp_smtlib_operator : operator Fmt.t
202217

203218
val fresh_skolem_var : string -> Var.t
204219
val fresh_skolem_name : string -> t
205-
val is_fresh_skolem : t -> bool
206220

207221
(** Resets to 0 the fresh symbol counter *)
208222

0 commit comments

Comments
 (0)