Analüütiline differentseerimine ja avaldise lihtsustamine

Prologi sisseehitatud mustri järgi alamstringi otsimine (pattern-matching) võimaldab Prologi abil lahendada mitte ainult numbrilisi matemaatikaülesandeid, vaid ka paljusid matemaatiliste valemite töötlusega seotud ülesandeid.

Lihtne on kirjeldada nelja esimest tehet (+, -, *, / ) sisaldavate matemaatiliste avaldiste differentseerimist. Predikaadi d esimene attribuut on differentseeritav avaldis (väiketähtedes!), teine - muutuja, mille järgi differentseeritakse (ka väiketäht!), kolmas - differentseerimise tulemusena saadud avaldis:

d(X,X,1):-
!. % x-i tuletis x-i järgi on 1
d(C,X,0):-
atomic(C). % konstandi tuletis on 0

d(U+V,X,A+B):-
d(U,X,A),d(V,X,B).
d(U-V,X,A-B):-
d(U,X,A),d(V,X,B).
d(C*U,X,C*A):-
atomic(C),C\=X,d(U,X,A),
!. % süsteemiprediaat atomic on tõene, kui selle argument on kas number või (teksti)aatom.
d(U*V,X,B*U+A*V):-
d(U,X,A),d(V,X,B).

d(U/V,X,(B*U-A*V)/(V*V)):-
d(U,X,A),d(V,X,B).

Saadud avaldist võib veidi lihtsustada - liita (lahutada, korrutada, jagada) kõrvuti tekkivad arvud. Et süsteemipredikaadi is kasutamisel veateadet ei tuleks, kontrollitakse enne arvutusi, kas mõlemad argumendid on arvud; seda teeb süsteemipredikaat number. Kuna lihtsustamisel võib-olla saadakse alamavaldiste lihtsustamisel taas arv, korratakse alamavaldiste lihtsustamist seni, kuni need enam ei muutu; kompaktsema esituse huvides on kasutatud süsteemipredikaati ; (OR, või).

Kõigepealt kaotame ära tegurid "1" ja liidetavad "0":

taanda(1*X,Y):-
!,taanda(X,Y).
taanda(X*1,Y):-
!,taanda(X,Y).
taanda(0+X,Y):-
!,taanda(X,Y).
taanda(X+0,Y):-
!,taanda(X,Y).

Ühesugused liidetavad tuleb kokku võtta:

taanda(N1*X+N2*X,Y):-
number(N1),
number(N2),
N is N1+N2,
taanda(N*X,Y).

Ja lõpuks lihtsustame summad, vahed ja korrutised (kui neid saab lihtsustada).

taanda(X,X):-
atomic(X),!.
taanda(X+Y,Z):- number(X),
number(Y),!,
Z is X+Y.
taanda(X+Y,Z):-
taanda(X,X1),taanda(Y,Y1),
((X=X1,Y=Y1,!,Z=X1+Y1);taanda(X1+Y1,Z)).
taanda(X-Y,Z):-
number(X),
number(Y), !,
Z is X-Y.
taanda(X-Y,Z):-
taanda(X,X1),taanda(Y,Y1),
((X=X1,Y=Y1,!,Z=X1-Y1);taanda(X1-Y1,Z)).
taanda(X*Y,Z):-
number(X),
number(Y),
!,
Z is X*Y.
taanda(X*Y,Z):-
taanda(X,X1),
taanda(Y,Y1),
((X=X1,Y=Y1,!,Z=X1*Y1);
taanda(X1*Y1,Z)).
taanda(X/Y,Z):-
number(X),
number(Y),
Y \=0, !,
Z is X/Y.
taanda(X/Y,Z):-
taanda(X,X1),
taanda(Y,Y1),
((X=X1,Y=Y1,!,Z=X1/Y1);
taanda(X1/Y1,Z)).

Tavaliselt tahetakse tulemus kohe saada lihtsustatult:

differentseeri(Avaldis,Muutuja,Tulemus):-
d(Avaldis,Muutuja,Lihtsustamata),
taanda(Lihtsustamata,Tulemus).

Testime:

? - differentseeri(2*x*x+3*x,x,T).
T = 4*x+3
- õieti!
Ülesandeid:
1. Täienda differentseerimispredikaati nii, et sellega saaks leida ka astmeid, eksponentfunktsioone, logaritme ja trigonomeetrilisi funktsioone sisaldavate avaldiste tuletisi.
2. Täienda lihtsustamispredikaati nii, et see teisendaks iga avaldise hulkliikme kujule, s.t. üksliikmete summaks/vaheks; üksliikmetes on arvuline kordaja kõige esimene, selle järel tuleb muutujate ja funktsioonide (astmed, eksponendid jne) korrutis/jagatis.


Küsimused, probleemid: ©2004 Jaak Henno