home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.yorku.ca 2015
/
ftp.cs.yorku.ca.tar
/
ftp.cs.yorku.ca
/
pub
/
peter
/
SVT
/
GNU
/
simp.prolog
< prev
next >
Wrap
Text File
|
2003-05-15
|
12KB
|
372 lines
/*
SIMPLIFY module
copyright P. H. Roosen-Runge, 1992, 1994, 1998.
% Ver. 1.0: January 1991.
% 1.2: April 16: trace option added.
% 1.3.1 March 18, 1992: puts A = -B into a canonical order
% so that i=-j is recognized as the same as -j=i.
% 1.3.2 July 8, 1992: assigned predicate defined.
% 1.4 November 11, 1993: makes associative expressions left-associative.
% 1.6.1 March 10: theory(Module) now loads rules in lexical order.
% 1.6.2 March 19: handles shift-operators, integer, and float; uses
% memberchk.
% 1.6.3 September 4: 'or' and 'and' added to associative operators.
% 1.7 December 12, 1997: cancellation repaired. '.pl' changed to
% '.prolog'. prove(S) added.
% 1.7.1 December 28, 1998: left-associative cancellation added;
% trace indents
% 1.8 February 7, 1999: commutative expressions are fully sorted;
% x+1+y ->> y + x + 1.
% 2.0 Jan 1, 2000: generate associative and commutative rules
% 2.1 March 21: exclude '=' and '<>' from rearrange
% 2.1.1 August 4: but put X=Y and X<>Y into canonical order
% 3.0 August 20: translate conditions in conditional rules
% 3.1 September 5: circular/1 repaired - handles (X-Y) ->> -(Y-X),
% pretty printing for circular rules.
% 3.1.1 Nov. 10: circular/1 repaired to handle recursive rules.
% 3.2 Feb. 5, 2001: allow theory references in theory files.
% 3.3 August 6: canonical maps -X to 0-X to allow cancellation
% 3.4 Jan. 28, 2002: recompiled with getTheories 1.3
% 3.5 Feb. 12: replace bound variables with 'Vn'.
% 3.6 Feb. 17: collect commutative terms and their inverses
% a-b+c+ e-d ->> a+c+e-b-d
========================================================================
Load this into any program which needs simplify/2.
The calling program or data should load simplification rules
by invoking or including terms of the form theory('<file specification>')>
appropriate for the expressions being simplified.
*/
:- ensure_loaded([library(basics), library(arg), library(change_arg),
library(occurs), library(unify), library(samsort)]).
% path defined in prolog.ini
:- ensure_loaded([lib('operators.prolog'), lib('output.prolog'),
lib('condtrans.prolog')]).
:- multifile '->>'/2.
:- dynamic '->>'/2.
:- no_style_check(single_var). % to avoid warnings in rules.
:- dynamic trace/1. trace(off). % to avoid a warning message
% uses path in prolog.ini
:- ensure_loaded(lib('getTheories.prolog')).
% expects error(X) to be defined in calling module
circular(L ->> R) :-
copy_term(L, Lnew),
copy_term(R, Rnew),
sub_term(T, Rnew), subsumes_chk(Lnew, T) ->
nl,
write('!! '), prettyRule(L->> R, PR),
write(PR), write(' is circular.'), nl.
prettyRule(T, PT ->> PR) :-
copy_term(T, Pretty),
numbervars(Pretty, 0, _), Pretty = (PT ->> PR).
addRuleLast((Rule if Condition)) :-
transcond(Condition, Translation),!,
assertz((Rule :- Translation)),
(makeARules(Rule, ARules),assertRule((ARules :- Translation), z); true),
(makeCRule(Rule, CRule), assertz((CRule :- Translation)); true).
addRuleLast(Rule) :-
functor(Rule, '->>', 2),
(
circular(Rule)
;
assertz(Rule),
(makeARules(Rule, ARules), assertRule(ARules, z) ; true),
(makeCRule(Rule, CRule), assertz(CRule) ; true)
).
addRuleLast(theory(X)) :- theory(X). % if a theory, load it.
addRuleLast(Rule) :- assertz(Rule). % if not a rule or theory, assert it.
addRule((Rule if Condition)) :-
transcond(Condition, Translation),!,
asserta((Rule :- Translation)),
(makeARules(Rule, ARules), assertRule((ARules :- Translation), a)
; true),
(makeCRule(Rule, CRule), asserta((CRule :- Translation)) ; true).
addRule(Rule) :-
functor(Rule, '->>', 2),
(
circular(Rule)
;
asserta(Rule),
(makeARules(Rule, ARules), assertRule(ARules, a) ; true),
(makeCRule(Rule, CRule), asserta(CRule) ; true)
).
addRule(Rule) :- asserta(Rule). % if not a rule, assert it.
makeCRule(Rule, CRule) :-
functor(Rule, '->>', 2),
arg(1, Rule, LHS), arg(2, Rule, RHS),
functor(LHS, Op, 2), commutative(Op), !,
arg(1, LHS, Left), arg(2, LHS, Right),
CLHS =.. [Op, Right, Left],
CRule = (CLHS ->> RHS).
makeARules(Rule, ARules) :-
functor(Rule, '->>', 2),
arg(1, Rule, LHS), arg(2, Rule, RHS),
functor(LHS, Op, 2), associativeF(Op), !,
arg(1, LHS, Left), arg(2, LHS, Right),
A1 =.. [Op, _0, Left],
ALHS =.. [Op, A1, Right],
ARHS =.. [Op, _0, RHS],
ARule = (ALHS ->> ARHS),
(
commutative(Op) ->
AC1 =.. [Op, _0, Right],
ACLHS =.. [Op, AC1, Left],
ACRule = (ACLHS ->> ARHS),
ARules = [ARule, ACRule]
;
ARules = [ARule]
).
assertRule(([Rule1, Rule2] :- Condition), End) :-
End = z, assertz((Rule1 :- Condition)), assertz((Rule2 :- Condition))
;
End = a, asserta((Rule1 :- Condition)), asserta((Rule2 :- Condition)).
assertRule([Rule1, Rule2], End) :-
End = z, assertz(Rule1), assertz(Rule2)
;
End = a, asserta(Rule1), asserta(Rule2).
assertRule(([Rule] :- Condition), End) :-
End = z, assertz((Rule :- Condition))
;
End = a, asserta((Rule :- Condition)).
assertRule([Rule], End) :-
End = z, assertz(Rule)
;
End = a, asserta(Rule).
/*
assertCanonical((LHS ->> RHS :- Condition)) :-
canonical(LHS, CanLHS), asserta((CanLHS ->> RHS :- Condition)).
assertCanonical((LHS ->> RHS)) :- canonical(LHS, CanLHS),
asserta((CanLHS ->> RHS)).
*/
associativeF(F) :- memberchk(F, ['+', '*', or, and]).
traceOn ->> true :- turnTraceOn.
traceOff ->> true :- turnTraceOff.
turnTraceOn :- (retract(trace(off)); true), assert(trace(on)).
turnTraceOff :- (retract(trace(on)); true), assert(trace(off)).
quantifier(Q) :- functor(Q, all, 1).
uncanonical(V) :-
\+ (name(V, VS), append("V",NS, VS), name(N, NS), integer(N)).
boundVars(Term, N, Result) :-
path_arg(Path, Term, Q),
quantifier(Q), arg(1, Q, V::C::P), uncanonical(V),
N1 is N + 1, N2 is N + 2,
boundVars(C, N1, RC), boundVars(P, N2, RQ),
functor(Q, F, 1),
New =.. [F, V::RC::RQ],
change_path_arg(Path, Term, NewTerm, New),
name(N,NS), append("V",NS, VN), name(BN, VN),
substitute(BN, NewTerm, V, Modified),
!,
boundVars(Modified, N, Result).
boundVars(Term, _, Term).
substitute(V, G, R, W) :- % V for R in G
setof(Path,path_arg(Path, G, R), Paths),
changeAll(Paths, V, G, W), !.
substitute(_, G, _, G).
changeAll([Path | Rest], V, G, W) :-
change_path_arg(Path, G, Modified, V),
changeAll( Rest, V, Modified, W).
changeAll(_, _, G, G).
canonical('-'(Term), 0-Term).
canonical(Term, Result) :- nonvar(Term) ->
(functor(Term, F, 2),
arg(1, Term, A1), arg(2, Term, A2),
leftAssociative(F, A1, A2, LA1, LA2),
canonical(LA1, C1), canonical(LA2, C2),
(
reverseOp(F, ReverseF) -> Result =.. [ReverseF, C2, C1]
;
Res =.. [F, C1, C2 ]
),
checkEq(Res, Res1),
(
commutative(F), rearrange(Res1, F, Result)
;
Result = Res1
)
).
canonical(Term, Result) :-
nonvar(Term) ->
Term =.. [F | Args],
canonicals(Args, CanArgs),
Result =.. [F | CanArgs].
canonical(X,X).
canonicals([], []).
canonicals([Arg | Rest], [CanArg | CanRest]) :-
canonical(Arg, CanArg),
canonicals(Rest, CanRest).
commutative(F) :- memberchk(F, ['+', '*', and, or, xor, iff, '=', '<>']),!.
reverseOp('>', '<'). reverseOp('>=', '<='). reverseOp('=>', '<=').
checkEq(Term, (-TH = TL)) :-
(Term = (X = -Y) ; Term = (-Y = X)),
(Y @< X -> TH=X, TL=Y ; TL=X, TH=Y).
checkEq((X = Y), (L = R)) :-
(Y@< X -> L=X, R=Y ; R=X, L=Y).
checkEq((X <> Y), (L <> R)) :-
(Y@< X -> L=X, R=Y ; R=X, L=Y).
checkEq(X,X).
leftAssociative(F, A1, A2, LA1, A22) :-
associativeF(F),
functor(A2, F, 2), arg(1, A2, A21), arg(2, A2, A22),
LA1 =.. [F, A1, A21].
leftAssociative(_, A1, A2, A1, A2).
simplify(Term, Result) :-
boundVars(Term, 0, NewTerm),
simplify0(NewTerm, Simplified),
canonical(Simplified, Canonical),
simplify1(Canonical,Result).
% based on Quintus Prolog Library Manual, p. 40
simplify1(Expr, Final) :-
path_arg(Path, Expr, Lhs),
( Lhs ->> Rhs ; cancellator(Lhs, Rhs), Lhs \== Rhs),
change_path_arg(Path, Expr, Modified, Rhs),
!,
(trace(on) -> indent(1), write(Modified); true),
canonical(Modified, Canonical),
simplify1(Canonical, Final).
simplify1(Expr, Expr).
% N. B. simplify is not intended to fail, so prove(P)
% cannot be just simplify(P, true).
simplify0(Expr, Final) :-
path_arg(Path, Expr, Lhs),
Lhs ->> Rhs ,
change_path_arg(Path, Expr, Modified, Rhs),
!,
(trace(on) -> indent(1), write(Modified); true),
simplify0(Modified, Final).
simplify0(Expr, Expr).
assocInv('-', '+'). assocInv('/', '*').
cancellator(Expr, Result) :-
functor(Expr, F, 2), assocInv(F, Inv),
arg(1, Expr, Left), arg(2, Expr, A),
canonical(Left, CL), canonical(A, CA),
cancel(Inv, CL, CA, Expr, Result),!.
cancellator(Expr, Result) :- laCancel(Expr, Result).
laCancel(Expr, Result) :-
Expr =.. [F, Left, Right],
assocInv(Inv, F),
laCancel( Left, Right, Inv, Result).
laCancel(Expr, Expr).
laCancel(Left, Right, Inv, Result) :-
Left =.. [Inv, Next, Right], Result = Next
;
Left =.. [Op, NextLeft, NextRight],
(Op = Inv ; assocInv(Inv, Op)),
laCancel(NextLeft, Right, Inv, NextResult),
(
NextLeft \== NextResult -> Result =.. [Op, NextResult, NextRight]
;
assocInv(Inv, F),
Result =.. [F, Left, Right]
).
listify(Term, F, Result) :-
commutative(F),
listify(Term, F, [], Result).
listify(Term, _, Term).
listify(Term, Op, SoFar, Result) :-
(
Term =.. [Op, A1, A2],
listify(A1, Op, SoFar, New),
listify(A2, Op, New, Result)
;
append(SoFar, [Term], Result)
).
listify(Term, F, Inv, Commutatives, Inverses) :-
commutative(F), assocInv(Inv, F),
listify(Term, F, Inv, [], [], Commutatives, Inverses).
listify(Term, _, _, Term, []).
listify(Term, F, Inv, SoFarComm, SoFarInv, Commutatives, Inverses) :-
(
Term =.. [F, A1, A2],
listify(A1, F, Inv, SoFarCom, SoFarInv, NewComm, SoFarInv),
listify(A2, F, Inv, NewComm, SoFarInv, Commutatives, Inverses)
;
Term =.. [Inv, A1, A2],
listify(A1, F, Inv, SoFarComm, SoFarInv, SoFarComm, NewInv),
listify(A2, F, Inv, SoFarCom, NewInv, Commutatives, Inverses)
;
append(SoFarCom, [Term], Commutatives), Inverses = SoFarInv
).
rearrange(Term, F, Result) :-
listify(Term, F, List),
(
List = [_| _],
samsort(List, Sorted),
treeify(Sorted, F, Result)
;
Result = List
).
treeify([T], _, T) .
treeify([T | Rest], F, Result) :-
treeify(Rest, F, Sofar),
Result =.. [F, Sofar, T].
cancel('+', Expr, Expr, _, 0). cancel('*', Expr, Expr, _, 1).
cancel(F, Left, A, _, Result) :-
functor(Left, F, 2),
(
arg(1, Left, A) -> arg(2, Left, Result)
;
arg(2, Left, A) -> arg(1, Left, Result)
;
arg(1, Left, Left1), arg(2, Left, Left2),
cancel(F, Left1, A, Left, Result1),
(
Result1 \== Left -> Result =..[F, Result1, Left2]
;
cancel(F, Left2, A, Left, Result2),
Result2 \== Left -> Result =.. [F, Left1, Result2]
)
).
cancel(_, _, _, Expr, Expr).
prove(X=Y) :- number(X), number(Y), X == Y.
prove(X<>Y) :- number(X), number(Y), X =\= Y.
prove(Term) :- simplify(Term, STerm), !, STerm = true.