:- seqex([term/2, s/1, naturalnumber/1, constant/1, example/1]).  

polynomial(X, X).
polynomial(C, X) :- constant(C).
polynomial(sin(X),X).
polynomial(cos(X),X).
polynomial(+(Term1,Term2), X) :- (polynomial(Term1,X) // polynomial(Term2,X)).
polynomial(-(Term1,Term2), X) :- (polynomial(Term1,X) // polynomial(Term2,X)).
polynomial(*(Term1,Term2), X) :- (polynomial(Term1,X) // polynomial(Term2,X)).
polynomial(/(Term1,Term2), X) :- (polynomial(Term1,X) // constant(Term2)).
polynomial(^(Term,N), X) :-      (polynomial(Term,X)  // naturalnumber(N)).

derivative(X,X,1).
derivative(C,X,0) :- constant(C).
derivative(^(X,N), X, *(N, ^(X,M))) :- M is N - 1.
derivative(sin(X), X, cos(X)).
derivative(cos(X), X, -(0,sin(X))).
derivative(^(e,X), X, ^(e,X)).
derivative(log(X), X, /(1,X)).

derivative(+(F,G), X, +(DF, DG))  :- (derivative(F,X,DF) //
				      derivative(G,X,DG)).
derivative(-(F,G), X, -(DF, DG)):-   (derivative(F,X,DF) //
				      derivative(G,X,DG)).
derivative(*(F,G), X, +(*(F, DG), *(G, DF))) :- 
				      term(F,X) ->
				     (derivative(F,X,DF) //
				      derivative(G,X,DG)).
derivative(*(F,G), X, *(F, DG)) :-    constant(F) ->
				      derivative(G,X,DG).
derivative(/(1,F), X, /(-(0, DF), *(F,F))) :-
				      derivative(F,X,DF).
derivative(/(F,G), X, /(-(*(G, DF), *(F,DG)), ^(G,2))) :- 
				      term(F,X) ->
				     (derivative(F,X,DF) //
				      derivative(G,X,DG)).
derivative(/(F,G), X, /(-(0, *(F,DG)), *(G,G))) :- 
				      constant(F) ->
				      derivative(G,X,DG)).
derivative(/(F,G), X, /(DF, G)) :- 
				      constant(G) ->
				      derivative(F,X,DF)).   


term(X,X).
term(+(A,B),X). term(-(A,B),X). term(*(A,B),X). term(/(A,B),X). term(^(A,B),X).


s(0). s(1).  s(2).  s(3).  s(4).  s(5).
naturalnumber(X) :- s(X).
constant(e). 
constant(X) :- s(X).

example(*(+(*(-(+(*(-(+(*(3, ^(a, 2)), *(5,a)), 4),+(*(4,^(a,3)),-(*(3,^(a,2)),
*(2,a)))), *(-(+(*(3, ^(a,2)), *(5,a)), 4), +(*(4,^(a,3)), -(*(3,^(a,2)),
*(2,a))))), +(-(*(*(^(a,2), +(*(2,a), 4)), +(*(4,a), 1)), *(*(^(a,3), 
+(*(5,a), 1)), +(*(3,a), 2))), -(*(*(^(a,2), +(*(2,a), 4)), +(*(4,a), 1)), 
*(*(^(a,3), +(*(5,a), 1)), +(*(3,a), 4))))), 
-(+(*(-(+(*(2, ^(a, 1)), *(2,a)), 4), +(*(4,^(a,2)), -(*(3,^(a,3)),
*(2,a)))), *(-(+(*(3, ^(a,2)), *(2,a)), 4), +(*(4,^(a,4)), -(*(3,^(a,3)),
*(3,a))))), +(-(*(*(^(a,2), +(*(2,a), 4)), +(*(4,a), 1)), *(*(^(a,5), 
+(*(5,a), 1)), +(*(2,a), 2))), -(*(*(^(a,2), +(*(2,a), 2)), +(*(4,a), 2)), 
*(*(^(a,3), +(*(2,a), 1)), +(*(3,a), 2)))))), 
*(-(+(*(-(+(*(3, ^(a, 2)), *(5,a)), 4), +(*(4,^(a,3)), -(*(3,^(a,2)),
*(2,a)))), *(-(+(*(3, ^(a,2)), *(3,a)), 4), +(*(4,^(a,3)), -(*(3,^(a,2)),
*(2,a))))), +(-(*(*(^(a,2), +(*(2,a), 4)), +(*(4,a), 1)), *(*(^(a,5), 
+(*(5,a), 1)), +(*(3,a), 2))), -(*(*(^(a,2), +(*(2,a), 4)), +(*(4,a), 1)), 
*(*(^(a,3), +(*(5,a), 1)), +(*(2,a), 3))))), 
-(+(*(-(+(*(3, ^(a, 1)), *(2,a)), 4), +(*(4,^(a,1)), -(*(3,^(a,3)),
*(1,a)))), *(-(+(*(3, ^(a,2)), *(2,a)), 4), +(*(4,^(a,5)), -(*(3,^(a,3)),
*(3,a))))), +(-(*(*(^(a,3), +(*(2,a), 4)), -(*(4,a), 1)), *(*(^(a,5), 
+(*(5,a), 1)), +(*(2,a), 2))), -(*(*(^(a,2), +(*(3,a), 2)), +(*(4,a), 2)), 
*(*(^(a,3), +(*(2,a), 1)), +(*(3,a), 2))))))), 
+(*(-(+(*(-(+(*(3, ^(a, 2)), *(5,a)), 4),+(*(4,^(a,3)),-(*(3,^(a,2)),
*(2,a)))), *(-(+(*(3, ^(a,2)), *(5,a)), 4), +(*(4,^(a,3)), -(*(3,^(a,2)),
*(2,a))))), +(-(*(*(^(a,2), +(*(2,a), 4)), +(*(4,a), 1)), *(*(^(a,3), 
+(*(5,a), 1)), +(*(3,a), 2))), -(*(*(^(a,2), +(*(2,a), 4)), +(*(4,a), 1)), 
*(*(^(a,3), +(*(5,a), 1)), +(*(3,a), 4))))), 
-(+(*(-(+(*(2, ^(a, 1)), *(2,a)), 4), +(*(4,^(a,2)), -(*(3,^(a,3)),
*(2,a)))), *(-(+(*(3, ^(a,2)), *(2,a)), 4), +(*(4,^(a,4)), -(*(3,^(a,3)),
*(3,a))))), +(-(*(*(^(a,2), +(*(2,a), 4)), +(*(4,a), 1)), *(*(^(a,5), 
+(*(5,a), 1)), +(*(2,a), 2))), -(*(*(^(a,2), +(*(2,a), 2)), +(*(4,a), 2)), 
*(*(^(a,3), +(*(2,a), 1)), +(*(3,a), 2)))))), 
*(*(^(a,3), +(*(2,a), 1)), +(*(3,a), 2))))).   

/* example2(*(^(a,2), *(2,a))). */


run(done) :-   example(X), polynomial(X,a), derivative(X, a, Derivative).

?- run(X).
