Toggle navigation
?
users online
Logout
Open hangout
Open chat for current file
:- set_prolog_flag(double_quotes,chars). :- use_module(library(dcg/basics)). differentiate(Variable, String, SimplifiedDerivative) :- phrase(expression(Term), String), derivative(Variable, Term, Derivative), simplify(Derivative, SimplifiedDerivative). % The first applicable simplification that is found % is applied, and no alternatives are explored. The % resulting expression is further simplified if % possible. simplify(E1, E3) :- simplification(E1, E2), !, % This prevents searching for alternatives simplify(E2, E3). % If there is no applicable simplification rule, % then the expression E can not be simplified % further. simplify(E, E) :- \+ simplification(E, _). % Rules in order of most to least preferred simplification % 1. Additive and multiplicative identities simplification(A+number(0), A). simplification(number(0)+A, A). simplification(A-number(0), A). simplification(number(0)-A, -A). simplification(number(0)*_, number(0)). simplification(_*number(0), number(0)). simplification(A*number(1), A). simplification(number(1)*A, A). simplification(A/number(1), A). simplification(_^number(0), number(1)). simplification(A^number(1), A). % 2. Generic simplifications simplification(A+A, number(2)*A). simplification(A-A, number(0)). simplification(A*A, A^number(2)). simplification(A*(A^B), A^(B+number(1))). simplification((A^B)*A, A^(B+number(1))). simplification((A^B)*(A^C), A^(B+C)). simplification(log(A)*log(B), log(A+B)). simplification(log(A)/log(B), log(A-B)). % 3. Unary minuses simplification(A*number(Negative), -(A*number(Positive))) :- Negative < 0, Positive is -Negative. simplification(number(Negative)*A, -(number(Positive)*A)) :- Negative < 0, Positive is -Negative. simplification(A/number(Negative), -(A/number(Positive))) :- Negative < 0, Positive is -Negative. simplification(number(Negative)/A, -(number(Positive)/A)) :- Negative < 0, Positive is -Negative. simplification((-A)*B, -(A*B)). simplification(A*(-B), -(A*B)). simplification((-A)/B, -(A/B)). simplification(A/(-B), -(A/B)). simplification(-(-A), A). simplification(-(A-B), B-A). simplification((-A)-B, -(A+B)). simplification(A+ -B, A-B). simplification(-A + B, B-A). % 4. Constant folding simplification(number(N1)+number(N2), number(N3)) :- N3 is N1 + N2. simplification(number(N1)-number(N2), number(N3)) :- N3 is N1 - N2. simplification(number(N1)*number(N2), number(N3)) :- N3 is N1 * N2. simplification(number(N1)/number(N2), number(N3)) :- N3 is N1 / N2. simplification(number(N1)^number(N2), number(N3)) :- N3 is N1 ^ N2. simplification(-number(N1), number(N2)) :- N2 is -N1. simplification(log(number(N1)), number(N2)) :- N2 is log(N1). simplification(exp(number(N1)), number(N2)) :- N2 is exp(N1). simplification(sin(number(N1)), number(N2)) :- N2 is sin(N1). simplification(cos(number(N1)), number(N2)) :- N2 is cos(N1). simplification(tan(number(N1)), number(N2)) :- N2 is tan(N1). % 5. Distributive laws simplification(A*(B+C), A*B+A*C). simplification(A*(B-C), A*B-A*C). simplification((A+B)*C, A*C+B*C). simplification((A-B)*C, A*C-B*C). % 6. Recursive cases simplification(A+B, SA+B) :- simplification(A, SA). simplification(A-B, SA-B) :- simplification(A, SA). simplification(A*B, SA*B) :- simplification(A, SA). simplification(A/B, SA/B) :- simplification(A, SA). simplification(A^B, SA^B) :- simplification(A, SA). simplification(A+B, A+SB) :- simplification(B, SB). simplification(A-B, A-SB) :- simplification(B, SB). simplification(A*B, A*SB) :- simplification(B, SB). simplification(A/B, A/SB) :- simplification(B, SB). simplification(A^B, A^SB) :- simplification(B, SB). simplification(-A, -SA) :- simplification(A, SA). simplification(log(A), log(SA)) :- simplification(A, SA). simplification(exp(A), exp(SA)) :- simplification(A, SA). simplification(sin(A), sin(SA)) :- simplification(A, SA). simplification(cos(A), cos(SA)) :- simplification(A, SA). simplification(tan(A), tan(SA)) :- simplification(A, SA). %%% %%% Differentiation rules %%% % Sum rule for derivatives derivative(X, A+B, DA+DB) :- derivative(X, A, DA), derivative(X, B, DB). % Difference rule for derivatives derivative(X, A-B, DA-DB) :- derivative(X, A, DA), derivative(X, B, DB). % Product rule for derivatives derivative(X, A*B, (DA*B)+(A*DB)) :- derivative(X, A, DA), derivative(X, B, DB). % Quotient rule for derivatives derivative(X, A/B, (DA*B-A*DB)/(B^number(2))) :- derivative(X, A, DA), derivative(X, B, DB). % Power rule for derivatives derivative(X, A^B, A^(B-number(1))*(B*DA + A*log(A)*DB)) :- derivative(X, A, DA), derivative(X, B, DB). % Special case of constant factor rule for derivatives derivative(X, -E, -DE) :- derivative(X, E, DE). % Logarithmic derivative (+ chain rule) derivative(X, log(E), DE/E) :- derivative(X, E, DE). % Exponential derivative (+ chain rule) derivative(X, exp(E), DE*exp(E)) :- derivative(X, E, DE). % Sine derivative (+ chain rule) derivative(X, sin(E), DE*cos(E)) :- derivative(X, E, DE). % Cosine derivative (+ chain rule) derivative(X, cos(E), -DE*sin(E)) :- derivative(X, E, DE). % Tangent derivative (+ chain rule) derivative(X, tan(E), DE/(cos(E)^number(2))) :- derivative(X, E, DE). % Constant derivative derivative(_, number(_), number(0)). % Variable derivative derivative(X, variable(X), number(1)). derivative(X, variable(OtherX), number(0)) :- X \= OtherX. %%% %%% PARSER %%% % Enable tabled execution to eliminate left recursion :- table expression//1, term//1. % Describes expressions expression(A+B) --> expression(A), "+", term(B). expression(A-B) --> expression(A), "-", term(B). expression(E) --> term(E). % Describes expressions that have multiplication, % division, or a higher precedence operator at their % root. term(A*B) --> term(A), "*", factor(B). term(A/B) --> term(A), "/", factor(B). term(E) --> factor(E). % Describes expressions that have exponentiation, or % a higher precedence operator at their root. factor(A^B) --> unary(A), "^", factor(B). factor(E) --> unary(E). % Describes the remaining cases: unary operators, % function calls, use of parenthesis, numbers, and % variables. unary(-E) --> "-", expression(E). unary(E) --> "(", expression(E), ")". unary(log(E)) --> "log(", expression(E), ")". unary(exp(E)) --> "exp(", expression(E), ")". unary(sin(E)) --> "sin(", expression(E), ")". unary(cos(E)) --> "cos(", expression(E), ")". unary(tan(E)) --> "tan(", expression(E), ")". unary(number(N)) --> number(N). unary(variable(V)) --> letters(V). % Helper DCG rules letters([L]) --> letter(L). letters([L|Ls]) --> letter(L), letters(Ls). letter(L) --> [L], { char_type(L, alpha) }.