diff options
Diffstat (limited to 'macros/luatex/latex/luacas/doc/tutorial/tut2/tut2.tex')
-rw-r--r-- | macros/luatex/latex/luacas/doc/tutorial/tut2/tut2.tex | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/macros/luatex/latex/luacas/doc/tutorial/tut2/tut2.tex b/macros/luatex/latex/luacas/doc/tutorial/tut2/tut2.tex new file mode 100644 index 0000000000..a80e285782 --- /dev/null +++ b/macros/luatex/latex/luacas/doc/tutorial/tut2/tut2.tex @@ -0,0 +1,476 @@ +\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 2: Finding Maxima/Minima} + +Bob is teaching calculus too, and he wants to give his students many examples of the process of \emph{finding the local max/min of a given function}. But, like Alice, Bob doesn't want to work out a bunch of examples by-hand. Bob decides to try his hand with \texttt{luacas} after having been taught the basics by Alice. + +Bob decides to stick with polynomials for these examples; if anything because those functions are in the wheel-house of \texttt{luacas}. In particular, Bob decides that the \emph{derivative} of the function he wants to use should be a composition of quadratics. This ought to ensure that the roots of that derivative are expressible in a nice way. + +Accordingly, Bob declares variables and chooses two quadratic polynomials to compose, say $f$ and $g$, and sets $dh = g \circ f$: + +\begin{minted}{latex} +\begin{CAS} + vars('x') + f = x^2+2*x-2 + g = x^2-1 + subs = {[x] = f} + dh = substitute(subs,g) +\end{CAS} +\end{minted} +\begin{CAS} + vars('x') + f = x^2+2*x-2 + g = x^2-1 + subs = {[x] = f} + dh = substitute(subs,g) +\end{CAS} + +Bob wants to compute $h$, the integral of $dh$. Bob could certainly compute this quantity by-hand, but why hardcode that information into the document when \texttt{luacas} can do this for you? So Bob uses the \texttt{int} command and shifts the result (with some malice aforethought): + +\begin{minted}{latex} +\begin{CAS} + h = int(dh,x) + 10 +\end{CAS} +\end{minted} +\begin{CAS} + h = int(dh,x) + 10 +\end{CAS} + +Bob is curious to know the value of $h$. So he uses \mintinline{latex}{\print{h}} to produce: +\begin{codebox} +\begin{minted}[fontsize=\small]{latex} +\[ \print{h} \] +\end{minted} + \tcblower +\[\print{h} \] +\end{codebox} +This isn't exactly what Bob had in mind. It occurs to Bob that he may need to simplify the expression $h$, so he tries: + +\begin{codebox} +\begin{minted}[fontsize=\small]{latex} +\begin{CAS} + h = simplify(int(dh,x)+10) +\end{CAS} +\[ \print{h} \] +\end{minted} + \tcblower +\begin{CAS} + h = simplify(h) +\end{CAS} +\[\print{h} \] +\end{codebox} + +That's more like it! Now, Bob wants to find the roots to $dh$. Bob uses the \texttt{roots} command to do this: + +\begin{minted}{latex} +\begin{CAS} + r = roots(dh) +\end{CAS} +\end{minted} +\begin{CAS} + r = roots(dh) +\end{CAS} + +But then Bob wonders to himself, ``How do I actually retrieve the roots of $dh$ from \texttt{luacas}?'' The assignment \mintinline{lua}{r = roots(dh)} stores the roots of the polynomial $dh$ in a table named \texttt{r}: + +\begin{codebox}[] +\begin{minted}[fontsize=\small]{latex} +\[ \print{r[1]}, \quad \print{r[2]}, \quad \print{r[3]}, \quad\print{r[4]} \] +\end{minted} + \tcblower + \begin{CAS} + r = roots(dh) + \end{CAS} + \[ \print{r[1]}, \quad \print{r[2]}, \quad \print{r[3]}, \quad \print{r[4]} \] +\end{codebox} +If Bob truly wants to print the entire list \texttt{r}, Bob can use the \mintinline{latex}{\lprint} (\textbf{l}ist \textbf{print}) command: +\begin{codebox}[] + \begin{minted}[fontsize=\small]{latex} +\[ \left\{ \lprint{r} \right\} \] + \end{minted} + \tcblower + \[ \left\{ \lprint{r} \right\} \] +\end{codebox} +Splendid! Bob would now like to evaluate the function $h$ at these roots (for these are the local max/min values of $h$). Here's Bob's first thought: + +\begin{codebox} +\begin{minted}[fontsize=\small]{latex} +\begin{CAS} + v = simplify(substitute({[x]=r[1]},h)) +\end{CAS} +\[ \print{v} \] +\end{minted} + \tcblower + \begin{CAS} + v = simplify(substitute({[x]=r[1]},h)) + \end{CAS} + \[ \print{v} \] +\end{codebox} + +What the heck?! Bob is (understandably) confused. But here's where Bob learns a valuable lesson\dots + +\subsubsection{A brief interlude: Lua numbers vs \texttt{luacas Integers}} + +The \LaTeX{} environment \mintinline{latex}{\begin{CAS}..\end{CAS}} is really a glorified Lua environment. The ``glory'' comes in how the contents of the environment are parsed in a special manner to make interacting with the CAS (mostly) easy. Bob has encountered a situation where that interaction is not as easy as we'd like. + +For comparison, consider the following: +\begin{multicols}{2} +Here's some code using the \mintinline{latex}{\begin{CAS}..\end{CAS}}: +\begin{codebox}\small + \begin{minted}[fontsize=\small]{latex} +\begin{CAS} + vars('y') + a = 1 + b = y+a +\end{CAS} +\[ \print{b} \] +\end{minted} + \tcblower + \begin{CAS} + vars('y') + a = 1 + b = y+a + \end{CAS} + \[ \print{b} \] +\end{codebox} +Here's that same code but using \mintinline{latex}{\directlua} instead: +\begin{codebox}\small +\begin{minted}[fontsize=\small]{latex} +\directlua{ + vars('y') + a = Integer(1) + b = y+a +} +\[ \print{b} \] +\end{minted} + \tcblower + \directlua{ + vars('y') + a = Integer(1) + b = y+a +} +\[ \print{b} \] +\end{codebox} +\end{multicols} +The essential difference being: +\begin{itemize} + \item Using \mintinline{latex}{\begin{CAS}..\end{CAS}}, a parser automatically interprets any digit strings as an \texttt{Integer}; this is a special class defined within the bowels of \texttt{luacas}. Ultimately, it allows for us to define things like the addition of an \texttt{Integer} and an \texttt{Expression} (in this case, the result is a new \texttt{Expression}) as well as arbitrary precision arithmetic. + \item Using \mintinline{latex}{\directlua}, there is no parsing, so the user (aka Bob) is responsible for telling \texttt{luacas} what to interpret as an \texttt{Integer} versus what to interpret as a normal Lua \texttt{number}. +\end{itemize} +Generally speaking, we like what the parser in \mintinline{latex}{\begin{CAS}..\end{CAS}} does: it keeps us from having to wrap all integers in \texttt{Integer(..)} (among other things). But the price we pay is that the parser indiscriminately wraps \emph{all} (or rather, most) digit strings in \texttt{Integer(..)}. This causes a problem in the following line in Bob's code: +\begin{minted}{lua} +v = simplify(substitute({[x]=r[1]},h)) +\end{minted} +The parser sees \mintinline{lua}{r[1]} and interprets \texttt{1} as \texttt{Integer(1)} -- but \mintinline{lua}{r[Integer(1)]} is \texttt{nil}, so no substitution is performed. + +The good news is that, excluding the annoyance between \texttt{Integer} and Lua number, interacting with the CAS via \mintinline{latex}{\directlua} is not much different than interacting with it via \mintinline{latex}{\begin{CAS}..\end{CAS}}. + +\subsubsection*{Back to the tutorial...} + +After that enlightening interlude, Bob realizes that some care needs to be taken when constructing tables. Here's a solution from within \mintinline{latex}{\begin{CAS}..\end{CAS}}: + +\begin{codebox}[] + \begin{minted}[fontsize=\small]{latex} +\begin{CAS} + r = ZTable(r) + v = ZTable() + for i in range(1, 4) do + v[i] = simplify(substitute({[x]=r[i]},h)) + end +\end{CAS} +\[ \left\{ \lprint{v} \right\} \] +\end{minted} +\tcblower +\begin{CAS} + r = ZTable(r) + v = ZTable() + for i in range(1, 4) do + v[i] = simplify(substitute({[x]=r[i]},h)) + end + \end{CAS} + \[ \left\{ \lprint{v} \right\} \] +\end{codebox} + +The function \mintinline{lua}{ZTable()} sets indices appropriately for use within \mintinline{latex}{\begin{CAS}..\end{CAS}} while the function \mintinline{lua}{range()} protects the bounds of the for-loop. Alternatively, Bob can make tables directly within \mintinline{latex}{\directlua} (or \mintinline{latex}{\luaexec} from the \texttt{luacode} package) using whatever Lua syntax pleases him: + +\begin{codebox}[] +\begin{minted}[fontsize=\small]{latex} +\directlua{ + v = {} + for i=1,4 do + table.insert(v,simplify(substitute({[x]=r[i]},h))) + end} +\[ \left\{ \lprint{v} \right\} \] +\end{minted} + \tcblower + \directlua{ + v = {} + for i=1,4 do + table.insert(v,simplify(substitute({[x]=r[i]},h))) + end +} +\[ \left\{ \lprint{v} \right\} \] +\end{codebox} +Great! But still; Bob doesn't want to just pretty-print the roots of $dh$ (or the values that $h$ takes at those roots). Bob is determined to plot the results -- he wants to hammer home the point that the roots of $dh$ point to the local extrema of $h$. + +Luckily, Bob is familiar with some of the fantastic graphics tools in the \LaTeX{} ecosystem, like \texttt{pgfplots} and \texttt{asymptote}. But then Bob begins to wonder, ``How can I yoink results out of \texttt{luacas} so that I may yeet them into something like \texttt{pgfplots}?'' +Bob is delighted to find the following commands: \mintinline{latex}{\fetch} and \mintinline{latex}{\store}. + +Whereas the \mintinline{latex}{\print} command relies on the \texttt{luacas} method \mintinline{lua}{tolatex()}, the commands \mintinline{latex}{\fetch} and \mintinline{latex}{\store} rely on the \texttt{luacas} function \mintinline{lua}{tostring()}. Bob can view the output of \mintinline{lua}{tostring()} using the \mintinline{latex}{\vprint} command ({\bf v}erbatim {\bf print}). For example, \mintinline{latex}{\vprint{h}} produces: +\vprint{h} +This is more-or-less what Bob wants -- but he doesn't want the verbatim output printed to his document, Bob just wants the contents of \mintinline{lua}{tostring(h)}. Here's where \mintinline{latex}{\fetch} comes in. The command \mintinline{latex}{\fetch{h}} is equivalent to: +\begin{minted}{latex} + \directlua{ + tex.print(tostring(h)) + } +\end{minted} +For comparison, the command \mintinline{latex}{\print{h}} is equivalent to: +\begin{minted}{latex} + \directlua{ + tex.print(h:tolatex()) + } +\end{minted} +For Bob's purposes, \mintinline{latex}{\fetch{h}} is exactly what he needs: + +\begin{codebox}\small +\begin{minted}[breaklines,fontsize=\small]{latex} +\begin{tikzpicture}[scale=0.9] + \begin{axis}[legend pos = north west] + \addplot [domain=-3.5:1.5,samples=100] + {\fetch{h}}; + \addlegendentry{$f$}; + \addplot[densely dashed] + [domain=-3.25:1.25,samples=100] + {\fetch{dh}}; + \addlegendentry{$df/dx$}; + \addplot[gray,dashed,thick] + [domain=-3.5:1.5] {0}; + \end{axis} +\end{tikzpicture} +\end{minted} +\tcblower +\begin{tikzpicture}[scale=0.9] + \begin{axis}[legend pos = north west] + \addplot [domain=-3.5:1.5,samples=100] {\fetch{h}}; + \addlegendentry{$f$}; + \addplot[densely dashed] + [domain=-3.25:1.25,samples=100] {\fetch{dh}}; + \addlegendentry{$df/dx$}; + \addplot[gray,dashed,thick] + [domain=-3.5:1.5] {0}; + \end{axis} +\end{tikzpicture} +\end{codebox} +Alternatively, Bob could use \mintinline{latex}{\store}. The \mintinline{latex}{\store} command will \emph{fetch} the contents of its mandatory argument and store it in a macro of the same name. +\begin{minted}{latex} +\store{h} +\store{dh} +\end{minted} +Now the macros \mintinline{latex}{\h} and \mintinline{latex}{\dh} can be used in place of \mintinline{latex}{\fetch{h}} and \mintinline{latex}{\fetch{dh}}, respectively. An optional argument can be used to store contents in a macro under a different name. This is useful for situations like the following: +\begin{minted}{latex} +\store{r[1]}[rootone] +\end{minted} +Now \mintinline{latex}{\rootone} can be used in place of \mintinline{latex}{\fetch{r[1]}}. But Bob wants to fetch all the values stored in \texttt{r} (and \texttt{v}, for that matter). In this case, Bob can use: +\begin{minted}{latex} +\store{r} +\store{v} +\end{minted} +The command \mintinline{latex}{\store{r}} is equivalent to: +\begin{minted}{latex} +\def\r{{ \fetch{r[1]}, \fetch{r[2]}, \fetch{r[3]}, \fetch{r[4]} }} +\end{minted} +The contents of the \LaTeX{} macro \mintinline{latex}{\r} can be accessed with \mintinline{latex}{\pgfmathsetmacro}. For example: + +\begin{codebox} +\begin{minted}[fontsize=\small,numbersep=6pt,linenos]{latex} +\begin{tikzpicture}[scale=0.6] + \draw [dashed,latex-latex] + (-7,0) -- (4,0); + \foreach \k in {0,1,2,3}{ + \pgfmathsetmacro\a{\r[\k]} + \draw (\a,0) circle (\a); + } + \foreach \x in {-6,...,3}{ + \draw[fill,orange] + (\x,0) circle (2pt) + node[below] {\footnotesize$\x$}; + } +\end{tikzpicture} +\end{minted} + \tcblower + \store{r} + \begin{center} + \begin{tikzpicture}[scale=0.65] + \draw [dashed,latex-latex] (-7,0) -- (4,0); + \foreach \k in {0,1,2,3}{ + \pgfmathsetmacro\a{\r[\k]} + \draw (\a,0) circle (\a); + } + \foreach \x in {-6,...,3}{ + \draw[fill,orange] (\x,0) circle (2pt) + node[below] {\footnotesize$\x$}; + } + \end{tikzpicture} +\end{center} +\end{codebox} + +Alternatively, Bob could avoid the call to \mintinline{latex}{\pgfmathsetmacro} by replacing lines 5-6 in the above code with the slightly more verbose: + +\begin{minted}{latex} + \draw ({\fetch{r[\k]}},0) circle (\fetch{r[\k]}); +\end{minted} + +Alternatively still, Bob could appeal directly to the \mintinline{lua}{tostring()} function in \texttt{luacas} and iterate over tables like \texttt{r} using Lua itself. This can often be a simpler solution (particularly when working within \mintinline{latex}{\begin{axis}..\end{axis}}), and it is exactly what Bob does in his complete project shared below: +\begin{codebox}[frame hidden,breakable] +\begin{minted}[breaklines,fontsize=\small]{latex} +Consider the function $f(x)$ defined by: +\begin{CAS} + vars('x') + f = x^2+2*x-2 + g = x^2-1 + subs = {[x] = f} + dh = expand(substitute(subs,g)) + h = simplify(int(dh,x)+10) +\end{CAS} +$\displaystyle f(x) = \print{h}$. +\begin{multicols}{2} + Note that: + \[ f'(x) = \print{dh}.\] + The roots to $f'(x)=0$ equation are: + \begin{CAS} + r = roots(dh) + \end{CAS} + \[ \left\{ \lprint{r} \right\} \] + Recall: $f'(x_0)$ measures the slope of the tangent line to $y= (x)$ at $x=x_0$. The values $r$ where $f'(r)=0$ correspond to places where the slope of the tangent line to $y=f(x)$ is horizontal (see the illustration). This gives us a method for identifying locations where the graph $y=f(x)$ attains a peak (local maximum) or a valley (local minimum). + \begin{CAS} + r = ZTable(r) + v = ZTable() + for i in range(1, 4) do + v[i] = simplify(substitute({[x]=r[i]},h)) + end + \end{CAS} + \columnbreak + \store{h}\store{dh} + \begin{tikzpicture}[scale=0.95] + \begin{axis}[legend pos = north west] + \addplot [domain=-3.5:1.5,samples=100] {\h}; + \addlegendentry{$f$}; + \addplot[densely dashed] [domain=-3.25:1.25,samples=100] {\dh}; + \addlegendentry{$df/dx$}; + \addplot[gray,dashed,thick] [domain=-3.5:1.5] {0}; + \luaexec{for i=1,4 do + tex.print("\\draw[fill=purple,purple]", + "(axis cs:{",tostring(r[i]),"},0) circle (1.5pt)", + "(axis cs:{",tostring(r[i]),"},{",tostring(v[i]),"}) circle (1.5pt)", + "(axis cs:{",tostring(r[i]),"},{",tostring(v[i]),"}) edge[dashed] (axis cs:{",tostring(r[i]),"},0);") + end} + \end{axis} + \end{tikzpicture} +\end{multicols} +\end{minted} +\end{codebox} +And here is Bob's completed project: +\begin{tcolorbox}[colback=rosenavy!10, + colframe=rosenavy, + arc=1pt, + frame hidden] + {\bf Tutorial 2:} {\itshape A local max/min diagram for Bob}. + \vskip 0.2cm + Consider the function $f(x)$ defined by: + \begin{CAS} + vars('x') + f = x^2+2*x-2 + g = x^2-1 + subs = {[x] = f} + dh = expand(substitute(subs,g)) + h = simplify(int(dh,x)+10) + \end{CAS} + $\displaystyle f(x) = \print{h}$. +\begin{multicols}{2} + Note that: + \[ f'(x) = \print{dh}.\] + The roots to $f'(x)=0$ equation are: + \begin{CAS} + r = roots(dh) + \end{CAS} + \[ \left\{ \lprint{r} \right\} \] + Recall: $f'(x_0)$ measures the slope of the tangent line to $y=f(x)$ at $x=x_0$. The values $r$ where $f'(r)=0$ correspond to places where the slope of the tangent line to $y=f(x)$ is horizontal (see the illustration). This gives us a method for identifying locations where the graph $y=f(x)$ attains a peak (local maximum) or a valley (local minimum). + \begin{CAS} + r = ZTable(r) + v = ZTable() + for i in range(1, 4) do + v[i] = simplify(substitute({[x]=r[i]},h)) + end + \end{CAS} + \columnbreak + \store{h}\store{dh} + \begin{tikzpicture}[scale=0.95] + \begin{axis}[legend pos = north west] + \addplot + [domain=-3.5:1.5,samples=100] {\h}; + \addlegendentry{$f$}; + \addplot[densely dashed] + [domain=-3.25:1.25,samples=100] {\dh}; + \addlegendentry{$df/dx$}; + \addplot[gray,dashed,thick] + [domain=-3.5:1.5] {0}; + \luaexec{for i=1,4 do + tex.print("\\draw[fill=purple,purple]", + "(axis cs:{", tostring(r[i]) ,"},0) circle (1.5pt)", + "(axis cs:{", tostring(r[i]) ,"},{", tostring(v[i]), "}) circle (1.5pt)", + "(axis cs:{", tostring(r[i]) ,"},{", tostring(v[i]), "}) edge[dashed] (axis cs:{", tostring(r[i]) ,"},0);") + end} + \end{axis} + \end{tikzpicture} +\end{multicols} +\end{tcolorbox} + +\end{document}
\ No newline at end of file |