summaryrefslogtreecommitdiff
path: root/site/content/gsoc/differentiating_code_addendum.typ
diff options
context:
space:
mode:
Diffstat (limited to 'site/content/gsoc/differentiating_code_addendum.typ')
-rw-r--r--site/content/gsoc/differentiating_code_addendum.typ52
1 files changed, 52 insertions, 0 deletions
diff --git a/site/content/gsoc/differentiating_code_addendum.typ b/site/content/gsoc/differentiating_code_addendum.typ
new file mode 100644
index 0000000..b6dcfa5
--- /dev/null
+++ b/site/content/gsoc/differentiating_code_addendum.typ
@@ -0,0 +1,52 @@
+#import "/common.typ": post, link-self
+
+#show: post.with(
+ title: "Differentiating code – addendum",
+ date: datetime(year: 2020, month: 7, day: 14),
+)
+
+This post describes how to the compute derivatives mentioned in an #link-self("gsoc/differentiating_code")[earlier post] using Maxima, a computer algebra system. Code is listed in a monospaced font and answers are written directly below, in LaTeX. *Ending lines with dollar signs in Maxima (instead of semicolons) surpresses the output,* which is very useful for definitions.
+
+Start by defining the reflectance model.
+```
+U: c_0 * lambda^2 + c_1 * lambda + c_2$
+R: 1 / 2 + U / (2 * sqrt(1 + U^2))$
+```
+Differentiate `R` with respect to `c_0`. The expansion of `U` appears a few times in the result. Substitute `U_` for `U` to simplify it. (The underscore is there so it doesn't expand back to the full expression.)
+```
+diff(R, c_0)$
+subst(U_, U, %);
+```
+$
+ (dif R) / (dif c_0) = lambda^2 / (2 sqrt(U^2 + 1)) - (U^2 lambda^2) / (2 (U^2 + 1)^(3 / 2))
+$
+
+This can be further simplified by substituting $t_1 = sqrt(U^2 + 1)$. Unfortunately `subst` won't recognize $(U^2 + 1)^(3 / 2)$ as $t_1^3$ so I recommend doing this manually.
+$
+ (dif R) / (dif c_0) = lambda^2 / (2 t_1) - (U^2 lambda^2) / (2 t_1^3)
+$
+
+Repeating the process for the other coefficients reveals a pattern. Let $t_2 = 1 / (2 t_1) - U^2 / (2 t_1^3)$.
+$
+ (dif R) / (dif c_0) &= lambda^2 t_2 \
+ (dif R) / (dif c_1) &= lambda t_2 \
+ (dif R) / (dif c_2) &= t_2
+$
+
+After skipping trivial derivatives, which can be easily done by hand, one will find themselves having to differentiate the final expression for $Delta E$. Normally an expression like $(dif L) / (dif c_0)$ (`diff(L, c_0)`) would be treated as a derivative of a constant in Maxima and reduced to zero. One can use `depends` to tell the program that the L\*a\*b\* coordinates are functions of the model parameters. The result will then contain derivatives of the coordinates themselves.
+
+An alternative approach is typing out the coordinates as functions explicitly. Instead of using `depends`, replace `L` with `L(c_0, c_1, c_2)` (and so on for `a` and `b`) in the code below. The downside is that the function arguments will appear in the end result, cluttering it and making a mess.
+
+```
+depends([L, a, b], [c_0, c_1, c_2])$
+delta_E: sqrt((L - L_target)^2 + (a - a_target)^2 + (b - b_target)^2)$
+```
+Use the same `subst` trick as before to simplify.
+```
+diff(delta_E, c_0)$
+subst(delta_E_, delta_E, %);
+```
+$
+ ((b - b_"target") (dif b) / (dif c_0) + (a - a_"target") (dif a) / (dif c_0) + (L - L_"target") (dif L) / (dif c_0)) / (Delta E)
+$
+The other derivatives look the same. Simply substitute $c_1$ or $c_2$ for $c_0$ in the expression above to get obtain them.