1:- module(reduce,
2 [attach_prefix/3, complete_args/3,
3 optimize_call_N/2,
4 slim_goal/2,
5 subtree/4, subtree/5, subterm/4, subterm/5,
6 reduce/3, reduce/4, reduce_one/4, copy_args_with_hole/4
7 ]). 8
14
15 30
31:- meta_predicate reduce_one(2, 4, ?, ?). 32reduce_one(R, P, X, Y):- call(P, X, Y, S, S0),
33 nonvar(S), 34 call(R, S, S0).
35
36:- meta_predicate reduce(2, ?, ?), reduce(2, 4, ?, ?). 37:- meta_predicate term_rewrite(2, ?, ?), term_rewrite(2, ?, ?, ?). 38
39reduce(R, A, B):- reduce(R, subterm([]), A, B).
41reduce(R, P, X, Y):- reduce_one(R, P, X, X0), !,
42 reduce(R, P, X0, Y).
43reduce(_, _, X, X).
44
61subtree(T, S):- subterm(T, S).
63subtree(Sgn, T, S):- subterm(Sgn, T, S).
64
66subtree(T, T0, S, S0):- subterm(T, T0, S, S0).
68subtree(Sgn, T, T0, S, S0):- subterm(Sgn, T, T0, S, S0).
77subterm(X, Y) :- nonvar(X),
78 functor(X, F, N),
79 ( Y = X
80 ; functor(X, F, N),
81 between(1, N, I),
82 arg(I, X, A),
83 subterm(A, Y)
84 ).
96subterm(S, X, Y) :- nonvar(X),
97 functor(X, F, N),
98 ( sgn_boole_chk(S, F, N, *) -> 99 ( Y = X
100 ; functor(X, F, N),
101 between(1, N, I),
102 arg(I, X, A),
103 subterm(S, A, Y)
104 )
105 ).
112subterm(X, Y, X, Y) :- nonvar(X).
113subterm(X, X0, Y, Y0):- compound(X),
114 functor(X, F, N),
115 functor(X0, F, N),
116 between(1, N, I),
117 arg(I, X, A),
118 copy_args_with_hole(1, I, V, X, X0),
119 subterm(A, V, Y, Y0).
127subterm(S, X, Y, X, Y) :- nonvar(X),
128 functor(X, F, N),
129 sgn_boole_chk(S, F, N, *). 130subterm(S, X, X0, Y, Y0):- compound(X),
131 functor(X, F, N),
132 functor(X0, F, N),
133 between(1, N, I),
134 sgn_boole_chk(S, F, N, I),
135 arg(I, X, A),
136 copy_args_with_hole(1, I, V, X, X0),
137 subterm(S, A, V, Y, Y0).
158sgn_boole_chk(X, Y, Z, U):-
159 once(eval_sgn_boole(X, Y, Z, U)).
160
166eval_sgn_boole([], _, _, _). 167eval_sgn_boole([J|Js], _, _, I):- 168 ( I = 0 -> true
169 ; memberchk(I, [J|Js])
170 ).
171eval_sgn_boole(S/N, F, N, I):- eval_sgn_boole(S, F, N, I).
172eval_sgn_boole((A,B), F, N, I):- 173 eval_sgn_boole(A, F, N, I),
174 eval_sgn_boole(B, F, N, I).
175eval_sgn_boole((A;B), F, N, I):- 176 ( eval_sgn_boole(A, F, N, I)
177 ; eval_sgn_boole(B, F, N, I)
178 ).
179eval_sgn_boole(\+(A), F, N, I):- 180 \+ eval_sgn_boole(A, F, N, I).
181eval_sgn_boole(G, F, _, _):-
182 ( atomic(G) -> G == F
183 ; G = [_|_] -> memberchk(F, G)
184 ).
192copy_args_with_hole(I, A, T, T0):- copy_args_with_hole(1, I, A, T, T0).
194copy_args_with_hole(J, I, A, T, T0):- arg(J, T, X), !,
195 ( J == I -> arg(I, T0, A)
196 ; arg(J, T0, X)
197 ),
198 J1 is J + 1,
199 copy_args_with_hole(J1, I, A, T, T0).
200copy_args_with_hole(_, _, _, _, _).
202term_complete([], G, G):-!.
203term_complete(A, G, G0):- G =.. H,
204 append(H, A, H0),
205 G0 =.. H0.
206
211complete_args(X, As, Y):- var(X), !,
212 Y=..[call, X|As].
213complete_args(M:X, As, Y):- !,
214 ( M == []
215 -> complete_args(X, As, Y)
216 ; complete_args(X, As, Y0),
217 Y = M:Y0
218 ).
219complete_args(X, As, Y):- var(As), !,
220 Y =.. [call, X|As].
221complete_args(X, [], X):- !.
222complete_args(G, As, G0):- atom(G), !,
223 G0 =.. [G|As].
224complete_args(G, As, G0):-
225 G =.. H,
226 append(H, As, H0),
227 G0 =.. H0.
228
229 232
235canonical_prefix_form(M:C, M, C).
236canonical_prefix_form(C, [], C).
237
239prefix_var(X):- var(X),!.
240prefix_var(_:X):- prefix_var(X).
241
243prefix_nonvar(X):- nonvar(X), !,
244 ( X = _:Y -> prefix_nonvar(Y)
245 ; true
246 ).
247
254
255slim_goal(X, Y):- boole_rule(X, X0), !, slim_goal(X0, Y).
256slim_goal(X, X).
257
259boole_rule(A, call(A)) :- var(A).
260boole_rule((A, B), (A0, B)) :- boole_rule(A, A0).
261boole_rule((A, B), (A, B0)) :- boole_rule(B, B0).
262boole_rule((A; B), (A0; B)) :- boole_rule(A, A0).
263boole_rule((A; B), (A; B0)) :- boole_rule(B, B0).
264boole_rule((A -> B), (A0->B)) :- boole_rule(A, A0).
265boole_rule((A -> B), (A->B0)) :- boole_rule(B, B0).
266boole_rule(\+(A), \+(A0)) :- boole_rule(A, A0).
267boole_rule(M:A, M:B) :- boole_rule(A, B).
268boole_rule(once(A), once(B)) :- boole_rule(A, B).
269boole_rule(once(A), A) :- ( A == true; A == false ).
270boole_rule((true, A), A).
271boole_rule((A, true), A).
272boole_rule((false, _), false).
274boole_rule((true; true), true).
275boole_rule((A; false), A).
276boole_rule((false; A), A).
277boole_rule((false -> _), false).
278boole_rule((true -> A), A).
279boole_rule(\+(false), true).
280boole_rule(\+(true), false).
281boole_rule(X=Y, true) :- X == Y.
282boole_rule(X=Y, false) :- X \== Y, ground((X,Y)).
283boole_rule(X==Y, true) :- X == Y.
284boole_rule(X==Y, false) :- X \== Y, ground((X,Y)).
285boole_rule(nonvar(X), true) :- nonvar(X).
286boole_rule(var(X), false) :- nonvar(X).
287boole_rule(fail, false).
288boole_rule(_:(M:A), M:A).
289boole_rule(_:E, E) :- prefix_cancellable(E).
290boole_rule(M:A, A) :- M == [].
291boole_rule(M:E, ME) :- propagate_prefix(M, E, ME).
292boole_rule(X, Y) :- slim_call(X, Y).
293
295propagate_prefix(M, X, X):- M==[], !.
296propagate_prefix(M, once(X), once(M:X)).
297propagate_prefix(M, (X, Y), (M:X, M:Y)).
298propagate_prefix(M, (X; Y), (M:X; M:Y)).
299propagate_prefix(M, (X -> Y), (M:X -> M:Y)).
300propagate_prefix(M, \+(X), \+(M:X)).
301
304prefix_cancellable(!).
305prefix_cancellable(true).
306prefix_cancellable(false).
307
309optimize_call_N(X, Y):- slim_call(X, Y).
310optimize_call_N(X, X).
311
313slim_call(X, Y) :- canonical_prefix_form(X, M, X0),
314 reducible_call(X0),
315 slim_call(X0, M, Y).
316
318reducible_call(X) :- X=..[F, A|_],
319 (F == call; F == apply),
320 prefix_nonvar(A).
321
330
331slim_call(X, M, call(Y)):- var(X), !,
332 attach_prefix(M, X, Y).
333slim_call(M:X, _, Y):-!, slim_call(X, M, Y).
334slim_call(X, M, Y):- X =..[call, F|As], !,
335 slim_call(F, M, F0),
336 complete_args(F0, As, Y).
337slim_call(apply(F, As), M, Y):-
338 slim_call(F, M, F0),
339 complete_args(F0, As, Y).
340slim_call(apply(F), M, Y):-
341 slim_call(F, M, Y).
342slim_call(X, M, Y):- attach_prefix(M, X, Y).
343
347
348attach_prefix(M, X, Y):- var(X), !,
349 ( var(M), Y = M:X
350 ; M == [], Y = X
351 ; Y = M:X
352 ),
353 !.
354attach_prefix(_, X, X) :- integer(X), !.
355attach_prefix(_, X, X) :- string(X), !.
356attach_prefix(_, X, X) :- X = (_:_), !.
357attach_prefix(M, X, X) :- M == [], !.
358attach_prefix(M, X, M:X).
359
369
376
377reduce_subsumes(X, Y, G):- collect_subsumes(X, Y, G),
378 check_subsumes_throw(G).
379
380reduce_subsumes(N, X, Y, G):- collect_subsumes(N, X, Y,true,G),
381 check_subsumes_throw(G).
382
383check_subsumes_throw(G):- unzip_equality(G, L, R),
384 ( subsumes_term(L, R)
385 -> true
386 ; throw(error('reduce_subsumes rule'))
387 ).
388
390collect_subsumes(X, Y, X = Y):- var(X), !.
391collect_subsumes(X, Y, X == Y):- atomic(X), !.
392collect_subsumes(X, Y, (nonvar(Y), Y=Y0, G)):- var(Y), !,
393 functor(X, F, N),
394 functor(Y0, F, N),
395 collect_subsumes(N, X, Y0, true, G).
396collect_subsumes(X, Y, G):- functor(X, F, N),
397 functor(Y, F, N),
398 !,
399 collect_subsumes(N, X, Y, true, G).
400
401collect_subsumes(0, _, _, G, G):-!.
402collect_subsumes(J, X, T, G0, G):- arg(J, X, A),
403 arg(J, T, B),
404 collect_subsumes(A, B, H),
405 K is J - 1,
406 collect_subsumes(K, X, T, (H, G0), G).
407
409unzip_equality(E, P, Q):- unzip_equal_dlist(E, []-P, []-Q), !.
411unzip_equal_dlist((E,F), P-Q, R-S):- unzip_equal_dlist(E, P-T, R-U),
412 unzip_equal_dlist(F, T-Q, U-S).
413unzip_equal_dlist(X=Y, A-[X|A], B-[Y|B]).
414unzip_equal_dlist(_, P-P, Q-Q)