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):-
!.
d(C,X,0):-
atomic(C).
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),
!.
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