The rules of symbolic differentiation, such as,

d d d
- (A+B) = - A + - B
dx dx dx

can be easily expressed in Prolog:

diff(plus(A,B), X, plus(DA, DB))
<= diff(A, X, DA) and diff(B, X, DB).
diff(times(A,B), X, plus(times(A, DB), times(DA, B)))
<= diff(A, X, DA) and diff(B, X, DB).
equal(X, X).
diff(X, X, 1).
diff(Y, X, 0) <= not equal(Y, X).
? diff( plus(times(x, x), times(3,x)), x, Dx).
{\fB Symbolic Differentiator. \fP}

The symbolic differentiator gives the correct answer
as the first solution
(it is not in simplified form but that could be achieved easily).
However other incorrect "solutions" are also output.
These are caused by the rule `diff(Y,X,0`

being too general.
It only holds if not(X=Y).

Negative Information.
The problem
with the first symbolic differentiator
can be fixed by insisting that `not(X=Y)`

for `diff(Y,X,0)`

:

diff(plus(A,B), X, plus(DA, DB))
<= diff(A, X, DA) and diff(B, X, DB).
diff(times(A,B), X, plus(times(A, DB), times(DA, B)))
<= diff(A, X, DA) and diff(B, X, DB).
atomic(x). atomic(y). atomic(3).
equal(X, X).
diff(X, X, 1).
diff(Y, X, 0) <= atomic(Y) and not equal(Y, X).
? diff( plus(times(x, x), times(3,x)), x, Dx).
{\fB Symbolic Differentiator. \fP}

Production Prolog systems
have the full set of comparison operators built in
but unification (`eq(X,X)`

) is used here.

diff(plus(A,B), X, plus(DA, DB))
<= diff(A, X, DA) and diff(B, X, DB).
diff(times(A,B), X, plus(times(A, DB), times(DA, B)))
<= diff(A, X, DA) and diff(B, X, DB).
atomic(x). atomic(y). atomic(3).
equal(X, X).
diff(X, X, 1).
diff(Y, X, 0) <= atomic(Y) and not equal(Y, X).
? diff( plus(times(x, x), times(3,x)), x, Dx).
{\fB Symbolic Differentiator. \fP}

Just in case you were wondering,
the differentiator cannot be run backwards
to get an integrator.