1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/** This class provides a method to compute symbolic derivatives of the
* given function with respect to x.
*
* @author Adam Blank
*/
public class SymbolicDifferentiation {
private static final String x = "x";
/** Checks if exp is a constant with respect to x */
public static boolean isConstant(String exp) {
return EvaluatorUtilities.isNumber(exp) || exp.equals("n") || exp.equals("e");
}
/** Computes the symbolic derivative of exp with respect to x */
public static String ddx(String exp) throws NotImplementedException {
exp = exp.replaceAll(" ", "");
/* Remove the outermost parentheses */
if (exp.charAt(0) == '(') {
exp = exp.substring(1, exp.length() - 1);
}
/* dx/dx = 1 */
if (exp.equals(x)) {
return "1";
}
/* dc/dx = 0 */
else if (EvaluatorUtilities.nextOperatorIndex(exp) == -1) {
return "0";
}
/* Split the string up by the op */
int opIndex = EvaluatorUtilities.nextOperatorIndex(exp);
String left = exp.substring(0, opIndex);
String right = exp.substring(opIndex + 1, exp.length());
char op = EvaluatorUtilities.nextOperator(exp);
/* (d/dx)(f(x) + g(x)) = df/dx + dg/dx */
if (op == '+' || op == '-') {
return String.format("(%s %s %s)", ddx(left), op, ddx(right));
}
/* (d/dx)(f(x) * g(x)) = ((f(x) * dg/dx) + (df/dx * g(x))) */
else if (op == '*') {
return String.format("((%s * %s) + (%s * %s))", left, ddx(right), right, ddx(left));
}
else if (op == '^') {
/* dc/dx = 0 */
if ((isConstant(left) && isConstant(right))) {
return "0";
}
/* (d/dx)(e^x) = e^x */
else if (left.equals("e") && right.equals(x)) {
return "(e^x)";
}
/* (d/dx)(x^n) = (n * (x ^ (n - 1))) */
else if (left.equals(x) && isConstant(right)) {
return String.format("(%s * ((%s^(%s - 1))))", right, left, right);
}
/* Chain Rule: Let f(x) = x^C -> f(g(x)).
* (d/dx)(f(g(x))) = ((df/dx)(g(x)) * (dg/dx)) */
else if (left.contains(x) && !right.contains(x)) {
System.out.println(left + " | " + right);
String df = ddx("(x^" + right + ")");
String dfOfg = df.replaceAll("x", left);
return String.format("(%s * %s)", dfOfg, ddx(left));
}
else {
/* Note that most of the other cases are a single case that we could
* write by implementing the chain rule. */
throw new NotImplementedException();
}
}
else {
/* This would just involve implementing more rules... */
throw new NotImplementedException();
}
}
public static void main(String[] args) throws NotImplementedException {
String[] exps = {"(2 * (x^n))", "(((2 * (x^n))*(e^x)) + (x*(2^n)))"};
for (int i = 0; i < exps.length; i++) {
System.out.println("(d/dx)(" + exps[i] + ") = " + ddx(exps[i].replaceAll(" ", "")));
}
}
}