summaryrefslogtreecommitdiff
path: root/macros/luatex/latex/luacas/doc/tutorial/tut3/tut3.tex
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/latex/luacas/doc/tutorial/tut3/tut3.tex')
-rw-r--r--macros/luatex/latex/luacas/doc/tutorial/tut3/tut3.tex575
1 files changed, 575 insertions, 0 deletions
diff --git a/macros/luatex/latex/luacas/doc/tutorial/tut3/tut3.tex b/macros/luatex/latex/luacas/doc/tutorial/tut3/tut3.tex
new file mode 100644
index 0000000000..1fda71a5a0
--- /dev/null
+++ b/macros/luatex/latex/luacas/doc/tutorial/tut3/tut3.tex
@@ -0,0 +1,575 @@
+\documentclass{article}
+
+\usepackage{luacas}
+\usepackage{amsmath}
+\usepackage{amssymb}
+
+\usepackage[margin=1in]{geometry}
+\usepackage[shortlabels]{enumitem}
+
+\usepackage{pgfplots}
+\pgfplotsset{compat=1.18}
+\usetikzlibrary{positioning,calc}
+\usepackage{forest}
+\usepackage{minted}
+\usemintedstyle{pastie}
+\usepackage[hidelinks]{hyperref}
+\usepackage{parskip}
+\usepackage{multicol}
+\usepackage[most]{tcolorbox}
+ \tcbuselibrary{xparse}
+\usepackage{microtype}
+
+\definecolor{rose}{RGB}{128,0,0}
+\definecolor{roseyellow}{RGB}{222,205,99}
+\definecolor{roseblue}{RGB}{167,188,214}
+\definecolor{rosenavy}{RGB}{79,117,139}
+\definecolor{roseorange}{RGB}{232,119,34}
+\definecolor{rosegreen}{RGB}{61,68,30}
+\definecolor{rosewhite}{RGB}{223,209,167}
+\definecolor{rosebrown}{RGB}{108,87,27}
+\definecolor{rosegray}{RGB}{84,88,90}
+
+\usepackage[
+backend=biber,
+style=numeric,
+]{biblatex}
+\addbibresource{sources.bib}
+
+\newtcolorbox{codebox}[1][sidebyside]{
+ enhanced,skin=bicolor,
+ #1,
+ arc=1pt,
+ colframe=brown,
+ colback=brown!15,colbacklower=white,
+ boxrule=1pt,
+ notitle
+}
+
+\begin{document}
+
+\subsection{Tutorial 3: Adding Functionality}
+
+Charlie, like Alice and Bob, is also teaching calculus. Charlie likes Alice's examples and wants to try something similar. But Charlie would like to do more involved examples using rational functions. Accordingly, Charlie copy-and-pastes Alice's code:
+\begin{CAS}
+ vars('x','h')
+ f = 1/(x^2+1)
+ subs = {[x]=x+h}
+ q = (substitute(subs,f)-f)/h
+ q = expand(q)
+\end{CAS}
+\begin{minted}{latex}
+\begin{CAS}
+ vars('x','h')
+ f = 1/(x^2+1)
+ subs = {[x]=x+h}
+ q = (substitute(subs,f)-f)/h
+ q = expand(q)
+\end{CAS}
+\end{minted}
+Unfortunately, \mintinline{latex}{\[ q=\print{q} \]} produces:
+\[ q = \print{q} \]
+The \mintinline{lua}{simplify()} command doesn't seem to help either! What Charlie truly needs is to combine terms, i.e., Charlie needs to find a \emph{common denominator}. They're horrified to learn that no such functionality exists in this burgeoning package.
+
+So what's Charlie to do? They could put a feature request in, but they're concerned that the schlubs in charge of managing the package won't get around to it until who-knows-when. So Charlie decides to take matters into their own hands. Besides, looking for that silver lining, they'll learn a little bit about how \texttt{luacas} is structured.
+
+At the heart of any CAS is the idea of an \texttt{Expression}. Mathematically speaking, an \texttt{Expression} is a rooted tree. Luckily, this tree can be drawn using the (wonderful) \texttt{forest} package. In particular, the command \mintinline{latex}{\parseforest{q}} will scan the contents of the expression \texttt{q} and parse the results into a form compatible with the \texttt{forest} package; those results are saved in a macro named \mintinline{latex}{\forestresult}.
+
+\tcbsidebyside[
+ sidebyside adapt=right,
+ enhanced,skin=bicolor,
+ arc=1pt,
+ colframe=brown,
+ colback=brown!15,colbacklower=white,
+ boxrule=1pt,
+ notitle,
+ frame hidden
+ ]{
+ \inputminted[
+ firstline = 1,
+ lastline = 13,
+ breaklines,
+ fontsize=\small
+ ]
+ {latex}
+ {demotut3.dat}}
+ {\parseforest{q}
+ \bracketset{action character = @}
+ \begin{forest}
+ for tree = {
+ font=\ttfamily,
+ rectangle,
+ rounded corners=1pt
+ },
+ where level=0{%
+ fill=orange!25
+ }{},
+ @\forestresult
+ \end{forest}}
+
+The root of the tree above is \texttt{ADD} since $q$ is, at its heart, the addition of two other expressions. Charlie wonders how they might check to see if a mystery \texttt{Expression} is an \texttt{ADD}? But this is putting the cart before the horse; Charlie should truly wonder how to check for the \emph{type} of \texttt{Expression} -- then they can worry about other attributes.
+
+Charlie can print the \texttt{Expression} type directly into their document using the \mintinline{latex}{\whatis} command:
+
+\begin{codebox}
+ \inputminted[
+ firstline = 15,
+ lastline = 18,
+ breaklines,
+ fontsize=\small
+ ]
+ {latex}
+ {demotut3.dat}
+ \tcblower
+ \begin{CAS}
+ r = diff(q,x,h)
+ \end{CAS}
+ \whatis{q} vs \whatis{r}
+\end{codebox}
+
+So \texttt{q} is a \texttt{BinaryOperation}? This strikes Charlie as a little strange. On the other hand, \texttt{q} is the result of a binary operation applied to two other expressions; so perhaps this makes a modicum of sense.
+
+At any rate, Charlie now knows, according to \texttt{luacas}, that \texttt{q} is of the \texttt{Expression}-type \whatis{q}. The actual operator that's used to form \texttt{q} is stored in the attribute \mintinline{lua}{q.operation}:
+
+\tcbsidebyside[
+ sidebyside adapt=right,
+ enhanced,skin=bicolor,
+ arc=1pt,
+ colframe=brown,
+ colback=brown!15,colbacklower=white,
+ boxrule=1pt,
+ notitle,
+ frame hidden
+ ]{
+ \inputminted[
+ firstline = 20,
+ lastline = 22,
+ breaklines,
+ fontsize=\small
+ ]
+ {latex}
+ {demotut3.dat}}
+ {
+ \luaexec{
+ if q.operation == BinaryOperation.ADD then
+ tex.sprint("I'm an \\texttt{ADD}")
+ end
+ }}
+
+Of course, different \texttt{Expression} types have different attributes. For example, being a \texttt{DiffExpression}, \texttt{r} has the attribute \texttt{r.degree}:
+
+\tcbsidebyside[
+ sidebyside adapt=right,
+ enhanced,skin=bicolor,
+ arc=1pt,
+ colframe=brown,
+ colback=brown!15,colbacklower=white,
+ boxrule=1pt,
+ notitle,
+ frame hidden
+ ]{
+ \inputminted[
+ firstline = 24,
+ lastline = 24,
+ breaklines,
+ fontsize=\small
+ ]
+ {latex}
+ {demotut3.dat}}
+ {
+ \luaexec{
+ tex.print("I'm an order", r.degree, "derivative.")
+ }}
+
+\texttt{BinaryOperation}s have several attributes, but the most important attribute for Charlie's purposes is \texttt{q.expressions}. In this case, \texttt{q.expressions} is a table with two entries; those two entries are precisely the \texttt{Expressions} whose sum forms \texttt{q}. In particular,
+
+\mintinline{latex}{\[ \print{q.expressions[1]} \qquad \text{and} \qquad \print{q.expressions[2]} \]}
+
+produces:
+\[ \print{q.expressions[1]} \qquad\text{and} \qquad \print{q.expressions[2]} \]
+
+The expression \texttt{q.expressions[1]} is another \texttt{BinaryOperation}. Instead of printing the entire expression tree (as we've done above), Charlie might be interested in the commands \mintinline{latex}{\parseshrub} and \mintinline{latex}{\shrubresult}:
+
+\tcbsidebyside[
+ sidebyside adapt=right,
+ enhanced,skin=bicolor,
+ arc=1pt,
+ colframe=brown,
+ colback=brown!15,colbacklower=white,
+ boxrule=1pt,
+ notitle,
+ frame hidden
+ ]{\small
+ \inputminted[
+ firstline = 26,
+ lastline = 30,
+ breaklines
+ ]
+ {latex}
+ {demotut3.dat}}
+ {\parseshrub{q.expressions[1]}
+ \bracketset{action character = @}
+ \begin{forest}
+ for tree = {draw,rectangle,rounded corners=1pt,fill=lightgray!20,font=\ttfamily, s sep=1.5cm}
+ @\shrubresult
+ \end{forest}
+}
+
+The ``shrub'' is essentially the first level of the ``forest'', but with some extra information concerning attributes. For contrast, here's the result of \mintinline{latex}{\parseshrub} and \mintinline{latex}{\shrubresult} applied to \texttt{r}, the \texttt{DiffExpression} defined above.
+
+\tcbsidebyside[
+ sidebyside adapt=right,
+ enhanced,skin=bicolor,
+ arc=1pt,
+ colframe=brown,
+ colback=brown!15,colbacklower=white,
+ boxrule=1pt,
+ notitle,
+ frame hidden
+ ]{\small
+ \inputminted[
+ firstline = 40,
+ lastline = 46,
+ breaklines
+ ]
+ {latex}
+ {demotut3.dat}}
+ {\parseshrub{r}
+ \bracketset{action character = @}
+ \begin{forest}
+ for tree = {draw,rectangle,rounded corners=1pt,
+ fill=lightgray!20,font=\ttfamily, s sep=1.5cm}
+ @\shrubresult
+ \end{forest}
+}
+The attribute \mintinline{lua}{r.degree} returns the size of the table stored in \mintinline{lua}{r.symbols} which, in turn, records the variables (and order from left-to-right) with which to differentiate the expression stored in \mintinline{lua}{r.expression}.
+
+Now that Charlie knows the basics of how \texttt{luacas} is structured, they're ready to try their hand at adding some functionality.
+
+
+\begin{multicols}{2}
+First, Charlie decides to up the complexity of their expression {\ttfamily f} so that they have something more general to work with:
+\begin{CAS}
+ vars('x','h')
+ f = x/(x^2+1)
+ subs = {[x]=x+h}
+ q = (substitute(subs,f)-f)/h
+\end{CAS}
+\begin{minted}{latex}
+\begin{CAS}
+ vars('x','h')
+ f = x/(x^2+1)
+ subs = {[x]=x+h}
+ q = (substitute(subs,f)-f)/h
+\end{CAS}
+\end{minted}
+Next, Charlie decides to print the un\texttt{expand}ed expression tree for $q$ to help give them a clear view (see right).
+
+\begin{center}
+\parseforest{q}
+\bracketset{action character = @}
+\begin{forest}
+ for tree = {
+ font=\ttfamily}
+ @\forestresult
+\end{forest}
+\end{center}
+\end{multicols}
+
+Charlie now wants to write their own function for combining expressions like this into a single denominator. It's probably best that Charlie writes this function in a separate file, say \texttt{myfile.lua}. Like most functions in \texttt{luacas}, Charlie defines this function as a \emph{method} applied to an \texttt{Expression}:
+
+\begin{minted}[linenos]{lua}
+function Expression:mycombine()
+\end{minted}
+
+Next, Charlie declares some local variables to identify appropriate numerators and denominators:
+\begin{minted}[linenos,firstnumber=2]{lua}
+ local a = self.expressions[1].expressions[1].expressions[1]
+ local b = self.expressions[1].expressions[1].expressions[2]
+ local c = self.expressions[1].expressions[2].expressions[1]
+ local d = self.expressions[1].expressions[2].expressions[2]
+\end{minted}
+
+So, for example, $a = x+h$, $b = (x+h)^2+1$, and so on. Charlie now forms the numerator and denominator, and returns the function:
+
+\begin{minted}[linenos,firstnumber=6]{lua}
+ local numerator = a*d-b*c
+ local denominator = self.expressions[2]*b*d
+ return numerator/denominator
+end
+\end{minted}
+
+\luaexec{
+ function Expression:mycombine()
+ local a = self.expressions[1].expressions[1].expressions[1]
+ local b = self.expressions[1].expressions[1].expressions[2]
+ local c = self.expressions[1].expressions[2].expressions[1]
+ local d = self.expressions[1].expressions[2].expressions[2]
+ local numerator = a*d-b*c
+ local denominator = self.expressions[2]*b*d
+ return numerator/denominator
+ end
+}
+Now Charlie only needs to ensure that \texttt{myfile.lua} is in a location visible to their TeX installation (e.g. in the current working folder). Charlie can then produce the following:
+
+\begin{codebox}
+ \begin{minted}[fontsize=\small]{latex}
+\directlua{dofile('myfile.lua')}
+\begin{CAS}
+ q = q:mycombine()
+\end{CAS}
+\[ \print{q} \]
+ \end{minted}
+ \tcblower
+ \begin{CAS}
+ q = q:mycombine()
+ \end{CAS}
+ \[ \print{q}\]
+\end{codebox}
+
+Charlie wants to simplify the numerator (but not the denominator). So they decide to write another function in \texttt{myfile.lua} that does precisely this:
+
+\begin{minted}[linenos,firstnumber = 11]{lua}
+function Expression:mysimplify()
+ local a = self.expressions[1]
+ local b = self.expressions[2]
+ a = simplify(a)
+ return a/b
+end
+\end{minted}
+\luaexec{
+function Expression:simplifynum()
+ local a = self.expressions[1]
+ local b = self.expressions[2]
+ a = simplify(a)
+ return a/b
+end
+}
+Now Charlie has:
+\begin{codebox}
+ \begin{minted}[fontsize=\small]{latex}
+\begin{CAS}
+ q = q:mysimplify()
+\end{CAS}
+\[ \print{q} \]
+\end{minted}
+\tcblower
+\begin{CAS}
+ q = q:simplifynum()
+\end{CAS}
+\[ \print{q} \]
+\end{codebox}
+Finally, Charlie wants to factor the numerator. So Charlie writes the following final function to \texttt{myfile.lua}:
+\begin{minted}[linenos,firstnumber = 18]{lua}
+function Expression:myfactor()
+ local a = self.expressions[1]
+ local b = self.expressions[2]
+ a = factor(a)
+ return a/b
+end
+\end{minted}
+
+\luaexec{
+function Expression:factornum()
+ local a = self.expressions[1]
+ local b = self.expressions[2]
+ a = factor(a)
+ return a/b
+end
+}
+\begin{codebox}
+ \begin{minted}[fontsize=\small]{latex}
+After factoring the numerator:
+\begin{CAS}
+ q = q:myfactor()
+\end{CAS}
+\[ \print{q} \]
+And then simplifying:
+\begin{CAS}
+ q = simplify(q)
+\end{CAS}
+\[ \print{q} \]
+\end{minted}
+\tcblower
+After factoring the numerator:
+\begin{CAS}
+ q = q:factornum()
+\end{CAS}
+\[ \print{q} \]
+And then simplifying:
+\begin{CAS}
+ q = simplify(q)
+\end{CAS}
+\[ \print{q} \]
+\end{codebox}
+Armed with their custom functions \texttt{mycombine}, \texttt{mysimplify}, and \texttt{myfactor}, Charlie can write examples just like Alice's examples, but using rational functions instead.
+
+Of course, the schlubs that manage this package feel for Charlie, and recognize that there are other situations in which folks may want to combine a sum of rational expressions into a single rational expression. Accordingly, there is indeed a \texttt{combine} command included in \texttt{luacas} that performs this task:
+\begin{codebox}
+ \begin{minted}[fontsize=\small]{latex}
+\begin{CAS}
+ vars('x','y','z')
+ a = y/z
+ b = z/x
+ c = x/y
+ d = combine(a+b+c)
+\end{CAS}
+\[ \print{a+b+c} = \print{d} \]
+\end{minted}
+\tcblower
+\begin{CAS}
+ vars('x','y','z')
+ a = y/z
+ b = z/x
+ c = x/y
+ d = combine(a+b+c)
+\end{CAS}
+\[ \print{a+b+c} = \print{d} \]
+\end{codebox}
+
+Here's Charlie's complete code (but using \mintinline{latex}{\directlua}) instead:
+
+\begin{codebox}[frame hidden,breakable]
+\begin{minted}[breaklines,fontsize=\small]{latex}
+\begin{CAS}
+ vars('x','h')
+ f = x/(x^2+1)
+\end{CAS}
+Let $f(x) = \print{f}$. We wish to compute the derivative of $f(x)$ at $x$ using the limit definition of the derivative. Toward that end, we start with the appropriate difference quotient:
+\begin{CAS}
+ subs = {[x] = x+h}
+ q = (f:substitute(subs) - f)/h
+\end{CAS}
+\directlua{
+\end{minted}
+\end{codebox}
+And now the Lua code:
+\begin{codebox}[frame hidden, breakable]
+\begin{minted}[breaklines,fontsize=\small]{lua}
+ function Expression:mycombine()
+ local a = self.expressions[1].expressions[1].expressions[1]
+ local b = self.expressions[1].expressions[1].expressions[2]
+ local c = self.expressions[1].expressions[2].expressions[1]
+ local d = self.expressions[1].expressions[2].expressions[2]
+ local numerator = a*d-b*c
+ local denominator = self.expressions[2]*b*d
+ return numerator/denominator
+ end
+ function Expression:mysimplify()
+ local a = self.expressions[1]
+ local b = self.expressions[2]
+ a = simplify(a)
+ return a/b
+ end
+ function Expression:myfactor()
+ local a = self.expressions[1]
+ local b = self.expressions[2]
+ a = factor(a)
+ return a/b
+ end
+\end{minted}
+\end{codebox}
+And now back to the \LaTeX{} code:
+\begin{codebox}[frame hidden,breakable]
+\begin{minted}[breaklines,fontsize=\small]{latex}
+}
+\[ \begin{aligned}
+ \print{q} &=
+ \begin{CAS}
+ q = q:mycombine()
+ \end{CAS}
+ \print{q}& &\text{get a common denominator} \\
+ &=
+ \begin{CAS}
+ q = q:mysimplify()
+ \end{CAS}
+ \print{q}& &\text{simplify the numerator} \\
+ &=
+ \begin{CAS}
+ q = q:myfactor()
+ \end{CAS}
+ \print{q} & &\text{factor numerator} \\
+ &=
+ \begin{CAS}
+ q = simplify(q)
+ \end{CAS}
+ \print{q}& &\text{cancel the $h$s} \\
+ &\xrightarrow{h\to 0}
+ \begin{CAS}
+ subs = {[h] = 0}
+ q = substitute(subs,q):autosimplify()
+ \end{CAS}
+ \print{q}& &\text{take limit.}
+\end{aligned} \]
+\end{minted}
+\end{codebox}
+And here is Charlie's completed project:
+\begin{tcolorbox}[colback=roseorange!10,
+ colframe=roseorange,
+ arc=1pt,
+ frame hidden]
+{\bf Tutorial 3:} {\itshape A limit definition of the derivative for Charlie.}\vskip 0.2cm
+
+\begin{CAS}
+ vars('x','h')
+ f = x/(x^2+1)
+\end{CAS}
+Let $f(x) = \print{f}$. We wish to compute the derivative of $f(x)$ at $x$ using the limit definition of the derivative. Toward that end, we start with the appropriate difference quotient:
+\begin{CAS}
+ subs = {[x] = x+h}
+ q = (f:substitute(subs) - f)/h
+\end{CAS}
+\directlua{
+ function Expression:mycombine()
+ local a = self.expressions[1].expressions[1].expressions[1]
+ local b = self.expressions[1].expressions[1].expressions[2]
+ local c = self.expressions[1].expressions[2].expressions[1]
+ local d = self.expressions[1].expressions[2].expressions[2]
+ local numerator = a*d-b*c
+ local denominator = self.expressions[2]*b*d
+ return numerator/denominator
+ end
+ function Expression:mysimplify()
+ local a = self.expressions[1]
+ local b = self.expressions[2]
+ a = simplify(a)
+ return a/b
+ end
+ function Expression:myfactor()
+ local a = self.expressions[1]
+ local b = self.expressions[2]
+ a = factor(a)
+ return a/b
+ end
+}
+\[ \begin{aligned}
+ \print{q} &=
+ \begin{CAS}
+ q = q:mycombine()
+ \end{CAS}
+ \print{q}& &\text{get a common denominator} \\
+ &=
+ \begin{CAS}
+ q = q:mysimplify()
+ \end{CAS}
+ \print{q}& &\text{simplify the numerator} \\
+ &=
+ \begin{CAS}
+ q = q:myfactor()
+ \end{CAS}
+ \print{q} & &\text{factor numerator} \\
+ &=
+ \begin{CAS}
+ q = simplify(q)
+ \end{CAS}
+ \print{q}& &\text{cancel the $h$s} \\
+ &\xrightarrow{h\to 0}
+ \begin{CAS}
+ subs = {[h] = 0}
+ q = substitute(subs,q):autosimplify()
+ \end{CAS}
+ \print{q}& &\text{take limit.}
+\end{aligned} \]
+\end{tcolorbox}
+
+\end{document} \ No newline at end of file