JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
JavaScript
class Graph {
constructor(definitions) {
this.definitions = definitions;
}
computeValue(expression) {
switch (expression.type) {
case "value":
return expression.value;
case "add":
return this.computeValue(expression.a) + this.computeValue(expression.b);
case "multiply":
return this.computeValue(expression.a) * this.computeValue(expression.b);
case "negate":
return -this.computeValue(expression.a);
case "inverse":
return 1 / this.computeValue(expression.a);
case "ref":
return this.computeValue(this.definitions[expression.ref]);
default:
throw new Error(`Expression type ${expression.type} not recognized.`);
}
}
derivative(expression, respectingRef) {
const d = (exp) => {
switch (exp.type) {
case "value":
return { type: "value", value: 0 };
case "add":
return {
type: "add",
a: d(exp.a),
b: d(exp.b)
};
case "multiply":
return {
type: "add",
a: { type: "multiply", a: d(exp.a), b: exp.b },
b: { type: "multiply", a: exp.a, b: d(exp.b) }
};
case "negate":
return {
type: "negate",
a: d(exp.a)
};
case "inverse":
return {
type: "multiply",
a: {
type: "negate",
a: {
type: "inverse",
a: {
type: "multiply",
a: exp.a,
b: exp.a
}
}
},
b: d(exp.a)
};
case "ref":
if (exp.ref === respectingRef) {
return { type: "value", value: 1 };
}
if (this.definitions[exp.ref]) {
return d(this.definitions[exp.ref]);
}
return { type: "value", value: 1 };
default:
throw new...