34
35:- module(varnumbers,
36 [ numbervars/1, 37 varnumbers/2, 38 max_var_number/3, 39 varnumbers/3, 40 varnumbers_names/3 41 ]). 42:- use_module(library(error)). 43:- use_module(library(assoc)). 44:- use_module(library(apply)).
76numbervars(Term) :-
77 numbervars(Term, 0, _).
84varnumbers(Term, Copy) :-
85 varnumbers(Term, 0, Copy).
97varnumbers(Term, Min, Copy) :-
98 must_be(acyclic, Term),
99 MaxStart is Min-1,
100 max_var_number(Term, MaxStart, Max),
101 NVars is Max-MaxStart,
102 ( NVars == 0
103 -> Copy = Term
104 ; roundup_next_power_two(NVars, Len),
105 functor(Vars, v, Len),
106 varnumbers(Term, MaxStart, Vars, Copy)
107 ).
108
109varnumbers(Var, _, _, Copy) :-
110 var(Var),
111 !,
112 Copy = Var.
113varnumbers(Var, _, _, Copy) :-
114 atomic(Var),
115 !,
116 Copy = Var.
117varnumbers('$VAR'(I), Min, Vars, Copy) :-
118 integer(I),
119 I > Min,
120 !,
121 Index is I-Min,
122 arg(Index, Vars, Copy).
123varnumbers(Term, Min, Vars, Copy) :-
124 functor(Term, Name, Arity),
125 functor(Copy, Name, Arity),
126 varnumbers_args(1, Arity, Term, Min, Vars, Copy).
127
128varnumbers_args(I, Arity, Term, Min, Vars, Copy) :-
129 I =< Arity,
130 !,
131 arg(I, Term, AT),
132 arg(I, Copy, CT),
133 varnumbers(AT, Min, Vars, CT),
134 I2 is I + 1,
135 varnumbers_args(I2, Arity, Term, Min, Vars, Copy).
136varnumbers_args(_, _, _, _, _, _).
142roundup_next_power_two(1, 1) :- !.
143roundup_next_power_two(N, L) :-
144 L is 1<<(msb(N-1)+1).
154max_var_number(V, Max, Max) :-
155 var(V),
156 !.
157max_var_number('$VAR'(I), Max0, Max) :-
158 integer(I),
159 !,
160 Max is max(I,Max0).
161max_var_number(S, Max0, Max) :-
162 functor(S, _, Ar),
163 max_var_numberl(Ar, S, Max0, Max).
164
165max_var_numberl(0, _, Max, Max) :- !.
166max_var_numberl(I, T, Max0, Max) :-
167 arg(I, T, Arg),
168 I2 is I-1,
169 max_var_number(Arg, Max0, Max1),
170 max_var_numberl(I2, T, Max1, Max).
183varnumbers_names(Term, Copy, Bindings) :-
184 must_be(acyclic, Term),
185 empty_assoc(Named),
186 varnumbers_names(Term, Named, BindingAssoc, Copy),
187 assoc_to_list(BindingAssoc, BindingPairs),
188 maplist(pair_equals, BindingPairs, Bindings).
189
190pair_equals(N-V, N=V).
191
192varnumbers_names(Var, Bindings, Bindings, Copy) :-
193 var(Var),
194 !,
195 Copy = Var.
196varnumbers_names(Var, Bindings, Bindings, Copy) :-
197 atomic(Var),
198 !,
199 Copy = Var.
200varnumbers_names('$VAR'(Name), Bindings0, Bindings, Copy) :-
201 !,
202 ( get_assoc(Name, Bindings0, Copy)
203 -> Bindings = Bindings0
204 ; put_assoc(Name, Bindings0, Copy, Bindings)
205 ).
206varnumbers_names(Term, Bindings0, Bindings, Copy) :-
207 functor(Term, Name, Arity),
208 functor(Copy, Name, Arity),
209 varnumbers_names_args(1, Arity, Term, Bindings0, Bindings, Copy).
210
211varnumbers_names_args(I, Arity, Term, Bindings0, Bindings, Copy) :-
212 I =< Arity,
213 !,
214 arg(I, Term, AT),
215 arg(I, Copy, CT),
216 varnumbers_names(AT, Bindings0, Bindings1, CT),
217 I2 is I + 1,
218 varnumbers_names_args(I2, Arity, Term, Bindings1, Bindings, Copy).
219varnumbers_names_args(_, _, _, Bindings, Bindings, _)
Utilities for numbered terms
This library provides the inverse functionality of the built-in numbervars/3. Note that this library suffers from the known issues that '$VAR'(X) is a normal Prolog term and, -unlike the built-in numbervars-, the inverse predicates do not process cyclic terms. The following predicate is true for any acyclic term that contains no '$VAR'(X),
integer(X)
terms and no constraint variables: