% exemple de différentiation d'une expression symbolique % adapté de http://www.cs.ubc.ca/spider/poole/cs502/sols/diff.pl % diff(X,V,Y)is true if Y is the derivative of X with respect to V. diff(X,X,1). diff(Y,X,0) :- atomic(Y),Y\==X. diff(X+Y,V,DX+DY) :- diff(X,V,DX), diff(Y,V,DY). diff(X-Y,V,DX-DY) :- diff(X,V,DX), diff(Y,V,DY). diff(X*Y,V,X*DY+Y*DX) :- diff(X,V,DX), diff(Y,V,DY). diff(X/Y,V,(DX*Y-DY*X)/(Y*Y)) :- diff(X,V,DX), diff(Y,V,DY). diff(-X,V,-DX) :- diff(X,V,DX). diff(sin(X),V,cos(X)*DX) :- diff(X,V,DX). diff(cos(X),V,(0-sin(X)*DX)) :- diff(X,V,DX). diff(log(X),V,DX/X) :- diff(X,V,DX). /* simplify(X,E,Y) is true if Y is a simplified expression equivalent to X, where E is an environment (a list of terms of the form val(X,N) which means that algebaric variable X has value N), in which to evaluate some of the algebraic variables. */ simplify(A,E,V) :- atomic(A), lookup(A,E,V). simplify(A+B,E,V) :- simplify(A,E,AS), simplify(B,E,BS), simp(AS+BS,V). simplify(A-B,E,V) :- simplify(A,E,AS), simplify(B,E,BS), simp(AS-BS,V). simplify(A*B,E,V) :- simplify(A,E,AS), simplify(B,E,BS), simp(AS*BS,V). simplify(A/B,E,V) :- simplify(A,E,AS), simplify(B,E,BS), simp(AS/BS,V). simplify(cos(X),E,V) :- simplify(X,E,XS), simp(cos(XS),V). simplify(sin(X),E,V) :- simplify(X,E,XS), simp(sin(XS),V). simplify(log(X),E,V) :- simplify(X,E,XS), simp(log(XS),V). simplify(-X,E,SS) :- simplify(X,E,XS), simp(-XS,SS). % "simplified" call simplify(E,S):-simplify(E,[],S). % lookup(Var,Env,Val) is true if variable Var has value Val in environment Env. lookup(X,[],X). lookup(X,[val(X,V)|_],V). lookup(X,[val(X1,_)|R],V) :- X\==X1, lookup(X,R,V). % simp(E1,E2) is true if E2 is the simplified version of E1, where E1 % has all of its subexpressions simplified simp(0+X,X). simp(X+0,X). simp(N+M,S) :- integer(N), integer(M), S is N+M. simp(X+X,2*X). simp(X+Y,X+Y). simp(X-0,X). simp(N-M,S) :- integer(N), integer(M), S is N-M. simp(X-Y,X-Y). simp(0*_,0). simp(_*0,0). simp(X*1,X). simp(1*X,X). simp(N*M,S) :- integer(N), integer(M), S is N*M. simp(X*Y,X*Y). simp(0/_,0). simp(_/0,overflow). simp(N/M,S) :- integer(N), integer(M), S is N/M. simp(X/Y,X/Y). simp(sin(0),0). simp(sin(X),sin(X)). simp(cos(0),1). simp(cos(X),cos(X)). simp(log(1),0). simp(log(X),log(X)). simp(-M,MM) :- integer(M), MM is -M. simp(-X,-X). % TEST QUERY % | ?- diff((x+y)*x,x,A), simplify(A,[],B), simplify(A,[val(x,4),val(y,5)],C). % A = (x+y)*1+x*(1+0), % B = x+y+x, % C = 13 % | ?- diff((4*x*x+8*x+4)/cos(x),x,D),simplify(D,D1). % D = ((4*x*1+x*(4*1+x*0)+(8*1+x*0)+0)*cos(x)-(0-sin(x)*1)*(4*x*x+8*x+4))/(cos(x)*cos(x)), % D1 = ((4*x+x*4+8)*cos(x)-(0-sin(x))*(4*x*x+8*x+4))/(cos(x)*cos(x)) ? % | ?- diff((4*x*x+8*x+4)/cos(x),x,D),simplify(D,[val(x,1)],D1). % D = ((4*x*1+x*(4*1+x*0)+(8*1+x*0)+0)*cos(x)-(0-sin(x)*1)*(4*x*x+8*x+4))/(cos(x)*cos(x)), % D1 = (16*cos(1)-(0-sin(1))*16)/(cos(1)*cos(1)) ?