Jekyll20210823T05:16:10+00:00https://ftclausen.github.io/feed.xmlFriedrich’s “Fred” NotesJust some random notes of random things I am working on/studyingFriedrich "Fred" Clausenftclausen@gmail.comConcrete Mathematics Notes: Summation by Parts20210817T20:34:00+00:0020210817T20:34:00+00:00https://ftclausen.github.io/mathematics/concretemathematicsnotessummationbyparts<p>Just a quick note to more verbosely explain some things that took a while to sink in. This post primarily concerns page
55 of Concrete Mathematics (Knuth, Graham, Patashnick) where they derive <em>Summation by Parts</em>.</p>
<h2 id="applyingdifferenceoperatortoproductoftwofunctions">Applying Difference Operator to Product of Two Functions</h2>
<p>This is equation 2.54 and, at first, I did not understand the second step especially the section highlighted in blue</p>
\[\begin{align}
\Delta(u(x)v(x)) &= u(x+1)v(x+1)  u(x)v(x) \\
&= u(x+1)v(x+1) \boldsymbol{\color{blue}{ u(x)v(x+1) + u(x)v(x+1)}}\color{#3d4144}  u(x)v(x) \\
&= u(x)\Delta v(x) + v(x+1)\Delta u(x)
\end{align}\]
<p>My initial reaction was: wtf is the new terms above? Had me stumped for a while I must confess.. Then I realised they
were just cancelling out extras conjured into existence like a
quickly annihilating virtual particle/antiparticle in the quantum vacuum. These “nothing terms” are used for factoring to arrive at our
differenceofaproduct form at 2.54 in the book. So, more verbosely, the factoring step is in blue this time:</p>
\[\begin{align}
\Delta(u(x)v(x)) &= u(x+1)v(x+1)  u(x)v(x) \\
&= u(x+1)v(x+1)  u(x)v(x+1) + u(x)v(x+1)  u(x)v(x) \\
&= \boldsymbol{\color{blue}v(x+1)(u(x+1)  u(x)) + u(x)(v(x+1)  v(x))\color{#3d4144}} \\
&= v(x+1)\Delta u(x) + u(x)\Delta v(x) \\
&= u(x)\Delta v(x) + v(x+1)\Delta u(x)
\end{align}\]
<p>Last two lines just swapped to end up where the book does. This seemed kind of magical to me but, I suppose, it works
due to the commutative and associative laws of addition/multiplication. I even tried it out with actual numbers and it works :D</p>
<h2 id="derivingactualsummationbyparts">Deriving Actual Summation by Parts</h2>
<p>My next moment of confusion came when deriving the actual summation by parts. We start with the compact rule for
difference of a product using the $E$ “nuisance” (quoting the book here :) ):</p>
\[\Delta(uv) = u\Delta v + Ev\Delta u\]
<p>Then they say:</p>
<blockquote>
<p>Taking the indefinite sum on both sites of this equation, and rearranging its terms, yields the advertised rule for
summation by parts:</p>
</blockquote>
\[\sum u\Delta v = uv  \sum Ev\Delta u\]
<p>I get the rearrangement of terms but how $\Delta(uv)$ becomes $uv$ was a bit of a mystery. After the requisite amount of
time overthinking it, it is just literally following through the steps of turning $\Delta(uv)$ into $\Delta(uv)$ when
rearranging; then shaking things out. I find it useful to expand everything and go from there:</p>
\[\begin{align}
\Delta(uv) &= \Delta(u(x)v(x)) \\
&= (u(x+1)v(x+1)  u(x)v(x)) \\
&= u(x+1)v(x+1) + u(x)v(x) \\
&= u(x)v(x) \\
&= uv \\
\end{align}\]
<p>Then, in 2.56 in the book, the rearrangment part makes it positive:</p>
\[\begin{align}
\Delta(uv) &= u\Delta v + Ev\Delta u \\
u\Delta v &= \Delta(uv) + Ev\Delta u \\
u\Delta v &= \Delta(uv)  Ev\Delta u
\end{align}\]
<p>Finally they take the indefinite sum on both sides giving us the summation by parts rule</p>
\[\sum u\Delta v = \Delta(uv)  \sum Ev\Delta u\]Friedrich "Fred" Clausenftclausen@gmail.comJust a quick note to more verbosely explain some things that took a while to sink in. This post primarily concerns page 55 of Concrete Mathematics (Knuth, Graham, Patashnick) where they derive Summation by Parts.Using JobDSL and Jenkinsfiles to fully automate Jenkins job management20210809T14:48:00+00:0020210809T14:48:00+00:00https://ftclausen.github.io/jenkins/usingjobdslandjenkinsfilestofullyautomatejenkinsjobmanagement<p>By using JobDSL and Jenkinsfiles we can fully automate all aspects of Jenkins job management. The two components play the following roles</p>
<ul>
<li><em>JobDSL</em>: The skeletal framework of a job that “registers” it in the Jenkins UI but does not contain any core job logic</li>
<li><em>Jenkinsfiles</em>: Contains all the project specific steps to accomplish the project goals such as building or deploying code</li>
</ul>
<p><img src="/images/sandwhich.png" alt="Sandwhich DSL goodness" height="600px" width="600px" /></p>
<p>It does not have to be JobDSL vs. Jenkinsfiles but, rather, JobDSL <strong>and</strong> Jenkinsfiles.</p>
<h1 id="jobdsl">JobDSL</h1>
<p>The code statements in JobDSL map directly to what is in the Jenkins UI as shown below</p>
<p><img src="/images/job_dsl.png" alt="Yummy JobDSL FRED_AI" /></p>
<h1 id="jenkinsfiles">Jenkinsfiles</h1>
<p>The “meat” of the job, that is, the core logic and all logic specific to the project in question is contained in the
Jenkinsfile. Quite often this is just called “Jenkinsfile” or “Jenkinsfile.groovy” (if you want to clue in your
editor/IDE) but it can be called anything.</p>
<p>Below are some Jenkinsfile snippets showing, roughly, how the correspond to what you might see in the Jenkins UI.</p>
<p><img src="/images/jenkinsfile.png" alt="Yummy Jenkinsfiles" /></p>Friedrich "Fred" Clausenftclausen@gmail.comBy using JobDSL and Jenkinsfiles we can fully automate all aspects of Jenkins job management. The two components play the following rolesBatch cancelling stuck Jenkins queued jobs20210708T09:43:00+00:0020210708T09:43:00+00:00https://ftclausen.github.io/jenkins/batchcancellingstuckjenkinsjobs<p>We use Kubernetes to run Jenkins jobs on disposable pods and, if Jenkins is restarted while jobs are running, the pods
go away and Jenkins attempts to restart the jobs on the now missing pods. This results in stuck jobs in the build queue with
the following status</p>
<blockquote>
<p>There are no nodes with the label <some label></p>
<p>Waiting for <some long period></p>
</blockquote>
<p>There is a handy
<a href="https://javadoc.jenkinsci.org/hudson/model/Queue.Item.html#isStuck">hudson.model.Queue.Item#isStuck()</a> method for
this however, in our Kubernetes environment, we find that it returns very newly created tasks are also marked as “stuck”
even when they have only been in the queue for milliseconds. So I’m using <code class="languageplaintext highlighterrouge">isStuck()</code> as a prefilter and then further
checking by our own criteria.</p>
<p>Without further ado, here is a <a href="https://www.jenkins.io/doc/book/managing/scriptconsole/">Groovy script console</a> snippet
to clean up jobs queued for more than 6 hours. Tweak for your environment and use at your own risk:</p>
<div class="languagegroovy highlighterrouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">hudson.model.*</span>
<span class="kn">import</span> <span class="nn">groovy.time.TimeCategory</span>
<span class="kt">def</span> <span class="n">q</span> <span class="o">=</span> <span class="n">Jenkins</span><span class="o">.</span><span class="na">instance</span><span class="o">.</span><span class="na">queue</span>
<span class="kt">def</span> <span class="n">now</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Date</span><span class="o">();</span>
<span class="kt">def</span> <span class="n">maxAgeHours</span> <span class="o">=</span> <span class="mi">6</span>
<span class="n">q</span><span class="o">.</span><span class="na">items</span><span class="o">.</span><span class="na">findAll</span> <span class="o">{</span> <span class="n">it</span><span class="o">.</span><span class="na">stuck</span> <span class="o">}.</span><span class="na">each</span> <span class="o">{</span>
<span class="kt">def</span> <span class="n">taskStart</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Date</span><span class="o">(</span><span class="n">it</span><span class="o">.</span><span class="na">inQueueSince</span><span class="o">)</span>
<span class="kt">def</span> <span class="n">age</span> <span class="o">=</span> <span class="n">TimeCategory</span><span class="o">.</span><span class="na">minus</span><span class="o">(</span><span class="n">now</span><span class="o">,</span> <span class="n">taskStart</span><span class="o">)</span>
<span class="k">if</span> <span class="o">(</span><span class="n">age</span><span class="o">.</span><span class="na">hours</span> <span class="o">></span> <span class="n">maxAgeHours</span><span class="o">)</span> <span class="o">{</span>
<span class="n">println</span> <span class="s2">"${it.task.name} is stuck for more than $maxAgeHours hours (${age.hours} hours), cancelling."</span>
<span class="n">q</span><span class="o">.</span><span class="na">cancel</span><span class="o">(</span><span class="n">it</span><span class="o">.</span><span class="na">task</span><span class="o">)</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="k">return</span> <span class="s2">"DONE"</span>
</code></pre></div></div>Friedrich "Fred" Clausenftclausen@gmail.comWe use Kubernetes to run Jenkins jobs on disposable pods and, if Jenkins is restarted while jobs are running, the pods go away and Jenkins attempts to restart the jobs on the now missing pods. This results in stuck jobs in the build queue with the following statusUsing integrals to find sum of squares closed form20210310T20:08:00+00:0020210310T20:08:00+00:00https://ftclausen.github.io/mathematics/usingintegralstofindsumofsquaresclosedform<p>As with all my posts here I’ll try to give a more verbose version of what the book covers; specifically how to get the
sum of squares closed form using “Method 4: Replace sums by integrals”. All the book explains is finding the error in
the approximation and the approximation itself.</p>
<p>This post assumes you have the book to hand although hopefully it’s readable on it’s own. Any mistakes in this text are
my own.</p>
<p>In Concrete Mathematics (Knuth, Graham, Patashnik) they use integrals to as a stepping stone to find the closed form for
the sum of squares. I am not as eloquent as they are so I’ll just quote them here</p>
<blockquote>
<p>In calculus, an integral can be regarded as the area under a curve, and we can approximate this area by adding up the
areas of long, skinny rectangles that touch the curve. We can also go the other way if a collection of long, skinny
rectangles is given: Since $\unicode{9744}_n$ is the sum of the areas of rectangles whose sizes are $1 × 1$, $1 × 4$, . . . , $1 × n^2$, it is
approximately equal to the area under the curve $f(x) = x^2$ between $0$ and $n$.</p>
</blockquote>
<p>I am not even going to try and replicate the graph in the book so here is one made with
<a href="https://www.mathsisfun.com/calculus/integralapproximationcalculator.html">mathisfun.com</a> integral approximation
calculator. The area under this graph is approximately $\unicode{9744}_n$</p>
<p><img src="/images/approximation_x_squared.png" alt="approximation x^2" /></p>
<p>This post covers the first “submethod” in <em>Method 4: Replace sums by integrals</em></p>
<h1 id="method1examineerrorinapproximationn33">Method 1  Examine Error in Approximation $n^3/3$</h1>
<p>What confused me is this is not exactly the same as counting the error wedges on the beautiful graph in the book (that
comes in the next method). This is literally the error in our first pass closed form approximation using the integration
rules where the area under $x^2$ is $\int x^2dx = n^3/3$. Thus we know the sum of squares is approximately
$\frac{1}{3}n^3$.</p>
<p>Thus the error in approximation is $E_n = \unicode{9744}_n  \frac{1}{3}n^3$ and therefore $E_{n1} = \unicode{9744}_{n1}  \frac{(n1)^3}{3}$. Rearranging we get $\color{green}{\unicode{9744}_{n1} = E_{n1} + \frac{(n1)^3}{3} }$</p>
<p>We also know what $\color{red}{\unicode{9744}_n = \unicode{9744}_{n1} + n^2}$. The book then very elegantly puts this all together to find a simple recurrence for $E_n$ as follows</p>
\[\begin{align}
E_n &= \unicode{9744}_n  \frac13 n^3 = \color{red}\unicode{9744}_{n1} + n^2 \color{#3d4144}  \frac13 n^3 \\
&= \color{green}E_{n1} + \frac{(n1)^3}{3} \color{#3d4144}+ n^2  \frac13 n^3 \\
&= E_{n1} + n  \frac13
\end{align}\]
<h1 id="method2summingwedgeshapederrorterms">Method 2  Summing Wedge Shaped Error Terms</h1>
<p>This means summing the <span style="color:rgb(226,155,150)">error shaped wedges</span> above the curve</p>
<p><img src="/images/approximation_x_squared_part2.png" alt="error wedges" /></p>
<p>What I needed some pondering to understand is that a given <em>rectangle</em> is $x^2$ and the area under the curve for that
section is is $\int_{k1}^kx^2dx$. What we are doing is subtracting the latter from the former to find the error wedges.
Thus in total the full error would be</p>
\[E_n = \unicode{9744}_n  \int_0^n x^2dx\]
<p>Now let’s stepwise sum of each $x^2$ rectangle and that sections portion under the curve using the same colours as in the
graph</p>
\[\definecolor{squared}{RGB}{143,232,128}
\definecolor{under_curve}{RGB}{118,187,237}
\begin{align}
\sum^n_{k=1}(\color{squared}k^2\color{#3d4144}  \color{under_curve}\int_{k1}^k x^2dx \color{#3d4144})
\end{align}\]
<p>Then, by using the rules of integration to find the antiderivative of something squared, we will find the area under
graph of just that section $\int_{k1}^k$</p>
\[\definecolor{squared}{RGB}{143,232,128}
\definecolor{under_curve}{RGB}{118,187,237}
\begin{align}
\sum^n_{k=1}(\color{squared}k^2\color{#3d4144}  \color{under_curve}\frac{k^3}{3}  \frac{(k  1)^3}{3} \color{#3d4144})
\end{align}\]
<p>And finally we land at our error in the approximation recurrence again</p>
\[\sum_{k=1}^n k\frac13\]
<h1 id="steppingstonefindinge_nrecurrenceclosedform">Stepping Stone: Finding $E_n$ Recurrence Closed Form</h1>
<p>Therefore if we could just find the closed form of $E_n$ we can find the closed form of $\unicode{9744}_n$ because we can do $\unicode{9744}_n = E_n + \frac13 n^3$. Let’s break the recurrence $E_n$ down to it’s component bits</p>
<ul>
<li>$E_{n1} + n$  Here we are just summing in which we can do with Gauss’ formula: $n(n1)/2$</li>
<li>$\frac13$  This is just a constant so to find the sum we simply multiply by how many times we’re summing so $n \cdot \frac13$</li>
</ul>
<p>THUS our $E_n$ closed form is</p>
\[E_n = \frac{n(n+1)}{2}  \frac{n}{3}\]
<h1 id="tyingittogetherusinge_ntofindunicode9744_nclosedform">Tying it Together: Using $E_n$ to Find $\unicode{9744}_n$ Closed Form</h1>
<p>We can prove $E_n$ closed form works via some induction I’ll add at the end to avoid distracting from the main topic.
So, finally, our $\unicode{9744}_n$ ends up being</p>
\[\unicode{9744}_n = \frac{n(n+1)}{2}  \frac{n}{3} + \frac13 n^3\ \ \ \ \ \text{for }n \geq 0\]
<p>Which is equivalent to what the book provides in equation 2.39</p>
\[\unicode{9744}_n = \frac{n(n+\frac12)(n+1)}{3}\ \ \ \ \ \text{for }n \geq 0\]
<p>TODO: Convert from the form I have above to the book’s closed form 2.39.</p>
<h1 id="appendixinductionproofofe_n">Appendix: Induction Proof of $E_n$</h1>
<p>For the recurrence $E_n = E_{n1} + n  \frac13$ we find that the closed form is $E_n = \frac{n(n+1)}{2}  \frac{n}{3}$.
This checks out via the following induction proof (following the same process as in <a href="http://ftclausen.github.io/mathematics/induction/">my super simple induction post</a>)</p>
\[\begin{align}
\frac{n(n + 1)}{2}  \frac n3 &= \frac{(n1)n}{2}  \frac{n1}{3} + n  \frac13 \\
\frac{3n(n+1)  2n}{6} &= \frac{3n(n1) 2(n1) +6n 2}{6} \\
\frac{3n^2 + 3n  2n}{6} &= \frac{3n^2  3n  2n + 2 + 6n  2}{6} \\
\frac{3n^2 + n}{6} &= \frac{3n^2 + n}{6} \\
\end{align}\]
<p>And RHS is the same as LHS so closed form is OK.</p>Friedrich "Fred" Clausenftclausen@gmail.comAs with all my posts here I’ll try to give a more verbose version of what the book covers; specifically how to get the sum of squares closed form using “Method 4: Replace sums by integrals”. All the book explains is finding the error in the approximation and the approximation itself.Another repertoire method example from Concrete Mathematics20210107T20:16:00+00:0020210107T20:16:00+00:00https://ftclausen.github.io/mathematics/repertoiremethodpart3<p>This is my third post on the repertoire method. This method seems quite magical (or perhaps that means I don’t fully
understand it 😅). In this case I am referring, as is often the case, to the book Concrete Mathematics by Graham,
Patishnick, and Knuth  in particular the example 3, equation 2.40 under “General Methods” for solving a summation.
There they present many ways to find the sum of squares $\unicode{9744}_n$ and what I am attempting to cement my knowledge in is the
repertoire method approach in the aforementioned example. It’s frightfully clever.</p>
<p>To reproduce it here:</p>
\[\begin{align}
R_0 &= \alpha \\
R_n &= R_{n1} + \beta + \gamma n + \delta n^2 \ \ \ \text{for} \ n > 0 \\
\end{align}\]
<p>This will have a solution of the general form</p>
\[R_n = A(n)\alpha + B(n)\beta + C(n)\gamma + D(n)\delta\]
<p>Conveniently we have already determined $A(n)$, $B(n)$, and $C(n)$ which I wrote about in <a href="http://ftclausen.github.io/mathematics/concretemathematics/concretemathematicsrepertoiremethodsection2.2thesequel/">this blog
post</a>. More rigorously we can say that because if we set $\delta$ to $0$ then we end up with what we determined before.</p>
<p>The book then says, rather tersely for me anyway,</p>
<blockquote>
<p>If we now plug in $R_n = n^3$, we find that $n^3$ is the solution when $\alpha = 0$, $\beta = 1$, $\gamma = –3$, $\delta = 3$. Hence</p>
\[3D(n)  3C(n) + B(n) = n^3\]
</blockquote>
<p>The process to arrive at that is pretty much the same as the $n^2$ <a href="http://ftclausen.github.io/mathematics/concretemathematics/concretemathematicsrepertoiremethodsection2.2thesequel/">as discussed
here</a>.
Which goes something like this:</p>
<p>1  We start with our recurrence form for which we want to find a closed form
\(R_n = R_{n1} + \beta + \gamma n + \delta n^2 \ \ \ \text{for} \ n > 0\)</p>
<p>As above the closed form will have the below general structure; we need to find $D(n)$  we already know the rest <a href="http://ftclausen.github.io/mathematics/concretemathematics/concretemathematicsrepertoiremethodsection2.2thesequel/">from
before</a>:
\(R_n = A(n)\alpha + B(n)\beta + C(n)\gamma + D(n)\delta\)</p>
<p>2a  This is the magic bit: we set the recurrence to $n^3$ and see what $\alpha$, $\beta$, $\gamma$, and $\delta$ need to
be in order to make the RHS of the recurrence equal to $n^3$</p>
\[\begin{align}
n^3 &= (n1)^3 + \alpha + \beta + \gamma n + \delta n^2 \\
&= n^3 + 3n^2 1 + \alpha + \beta + \gamma n + \delta n^2 \\
\end{align}\]
<p>2b  Rearrange things to make the process clearer</p>
\[\begin{align}
n^3 &= n^3 + \delta n^2  3n^2 + \gamma n + 3n + \beta 1 + \alpha \\
&= n^3 + n^2(\delta  3) + n(\gamma + 3) + \beta 1 + \alpha
\end{align}\]
<p>2c  Now we can see what we need to set $\alpha$, $\beta$, $\gamma$, and $\delta$ to in order to make that equation true
i.e. $n^3 = n^3$. Specifically $\alpha = 0$, $\beta = 1$, $\gamma = 3$, and $\delta = 3$</p>
<p>3  Then we substitute (linearly apply?) the found values for $\alpha$, $\beta$, $\gamma$, and $\delta$ into
the general form set to n^3.</p>
\[\begin{align}
n^3 = A(n)\cdot0 + B(n)\cdot1 + C(n)\cdot3 + D(n)\cdot3 \\
n^3 = B(n)  3C(n) + 3D(n) \\
3D(n)  3C(n) + B(n) = n^3 \\
\end{align}\]
<p>Last reordering to match what is in the book at the top of page 45. This will tell us what $D(n)$ needs to be linearly
combined with  namely $3$  for that general form to be $n^3$.</p>
<p>3  Express in terms of our target  sum of squares $\unicode{9744}_n$. Now that we have built a repertoire let’s see what things have to be set to in order to find $\unicode{9744}_n$. So $\unicode{9744}_n$ equals $\unicode{9744} _{n1} + n^2$ thus we’ll get $\unicode{9744}_n = R_n$ by setting $\alpha
= \beta = \gamma = 0$ and $\delta = 1$. In other words $R_n = A(n)\cdot0 + B(n)\cdot0 + C(n)\cdot0 + D(n)\cdot1$.</p>
<p>So this shows us that $D(n)$ is what we are after  namely  $\unicode{9744}_n$.</p>
<p>4  Finally substitute in the already known values for $A(n)$, $B(n)$, $C(n)$ and <em>finally</em> solving for $D(n)$.</p>
<p>As mentioned above, surprisingly, solving for $D(n)$ gives us our closed form! Let’s take a look:</p>
\[\begin{align}
3D(n) &= n^3 + 3C(n)  B(n) \\
3D(n) &= n^3  \frac{3(n+1)n}{2}  n \\
3D(n) &= n(n + 1/2)(n + 1) \\
D(n) &= \frac{n(n + 1/2)(n + 1)}{3} \\
\end{align}\]
<p>So sometimes, in the process of building a repertoire, one of the items actually ends up being The Solution!</p>Friedrich "Fred" Clausenftclausen@gmail.comThis is my third post on the repertoire method. This method seems quite magical (or perhaps that means I don’t fully understand it 😅). In this case I am referring, as is often the case, to the book Concrete Mathematics by Graham, Patishnick, and Knuth  in particular the example 3, equation 2.40 under “General Methods” for solving a summation. There they present many ways to find the sum of squares $\unicode{9744}_n$ and what I am attempting to cement my knowledge in is the repertoire method approach in the aforementioned example. It’s frightfully clever.Sums of sums visually and as nested “for” loops20201114T20:05:00+00:0020201114T20:05:00+00:00https://ftclausen.github.io/mathematics/dev/sumsofsumsinpicturesandasnestedforloops<p>In Concrete Mathematics (Graham, Patashnik, Knuth) I am working my way through page 36 about sums of sums. Specifically
the “rocky road” (yum) method for swapping the order of summation when the range of the inner sum depends on the index
variable on the outer sum.</p>
<p>I find the Iversonian notation confusing to start with and now I see it’s “just symbols” and that, for example, $K’$
does not mean the complement of some set $K$ <em>in that context</em>. The ever helpful Brian M. Scott helper <a href="https://math.stackexchange.com/questions/3897525/concretemathmaticsnotationforsumsofsumswhereinnersumdependsonouter">clear that up
for
me</a>:</p>
<blockquote>
<p>The sets $K’$ and $J’(k)$ for $k \in K’$ are not defined in (2.30): (2.30) simply describes in very general terms a kind
of rearrangement of a double summation — reversing the order of summation — that is often very helpful, just as
reversing the order of integration in a double iterated integral is often very helpful.</p>
</blockquote>
<p>To help cement my knowledge I’ve decided to explicitly visualise and also bring sums of sums to something I do know:
nested loops. Standard disclaimer of “maybe I have this wrong” applies.</p>
<p>I’ll get into the Iversonian in the last section but, for now, here is a reversed summation I’ll use as a reference for
below</p>
\[\sum_{j=1}^n\sum_{k=j}^na_{j,k}=\sum_{1\le j\le k\le n}a_{j,k}=\sum_{k=1}^n\sum_{j=1}^ka_{j,k}\,,\]
<p>Specially the RHS and LHS.</p>
<h1 id="visualoverview">Visual Overview</h1>
<p>Basically by reversing the order of summation we are going from counting by rows first to counting by columns first:</p>
<p><img src="/images/cm_2.32.png" alt="images/cm_2.32.png" /></p>
<p>Pretty simple really</p>
<h1 id="asnestedloops">As Nested Loops</h1>
<p>NOTE: This illustration is focused on the <em>index variables</em> not the actual summation operation. We’re iterating over an
existing table to show how the results end up the same when swapping the indexes. In a “real” summation we’d be summing
over the previous value not some preexisting data set.</p>
<p>For loops, especially classic ones, are basically summations in code. This Python snippet adds up an array of arrays
“table” where the inner loop depends on the index of the outer loop</p>
<div class="languagepython highlighterrouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="c1"># Random table of things to add up  we are adding the upper right triangle. So
# [ 19555, 2038, 3413 ],
# [ 35620, 3734 ],
# [ 34234 ]
</span><span class="n">table</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">[</span> <span class="mi">19555</span><span class="p">,</span> <span class="mi">2038</span><span class="p">,</span> <span class="mi">3413</span> <span class="p">],</span>
<span class="p">[</span> <span class="mi">3432</span><span class="p">,</span> <span class="mi">35620</span><span class="p">,</span> <span class="mi">3734</span> <span class="p">],</span>
<span class="p">[</span> <span class="mi">4543</span><span class="p">,</span> <span class="mi">43543</span><span class="p">,</span> <span class="mi">34234</span> <span class="p">]</span>
<span class="p">]</span>
<span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">table</span><span class="p">)</span>
<span class="c1"># loop1
</span><span class="n">total1</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">j</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
<span class="n">total1</span> <span class="o">+=</span> <span class="n">table</span><span class="p">[</span><span class="n">j</span><span class="p">][</span><span class="n">k</span><span class="p">]</span>
<span class="c1"># loop2
</span><span class="n">total2</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
<span class="c1"># We need k+1 because range is not inclusive of last number
</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">k</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="n">total2</span> <span class="o">+=</span> <span class="n">table</span><span class="p">[</span><span class="n">j</span><span class="p">][</span><span class="n">k</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Total1 = </span><span class="si">{</span><span class="n">total1</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Total2 = </span><span class="si">{</span><span class="n">total2</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
</code></pre></div></div>
<p>Where <code class="languageplaintext highlighterrouge">loop1</code> is</p>
\[\sum_{j=1}^n\sum_{k=j}^na_{j,k}\]
<p>And <code class="languageplaintext highlighterrouge">loop2</code> is</p>
\[\sum_{k=1}^n\sum_{j=1}^ka_{j,k}\]
<p>When it runs it prints</p>
<div class="languageplaintext highlighterrouge"><div class="highlight"><pre class="highlight"><code>$ ./nested_loops.py
Total1 = 98594
Total2 = 98594
</code></pre></div></div>
<p>Showing the two summation approaches are adding up the same section because it is not a symmetric table.</p>
<h1 id="moregenerally">More Generally</h1>
<p>The book uses a general notation that, as mentioned in the intro above, confused me. This section is more a brain dump
of me attempting to understand this and I’ll tweak it as I gain more understanding. They present this equation</p>
\[\sum_{j \in J} \sum_{k \in K(j)} a_{j,k} = \sum_{k \in K'} \sum_{j \in J'(k)}a_{j,k}\]
<p>And say</p>
<blockquote>
<p>Here the sets $J$, $K(j)$, $K’$, and $J’(k)$ must be related in such a way that</p>
</blockquote>
\[[j \in J][k \in K(j)] = [k \in K'][j \in J'(k)]\]
<p>These are just symbols and, for example, $K’$ is not meaning the complement of some set. It’s just showing to “return 1”
when the inner sum’s condition is met. Dissecting even more the conditions are</p>
<ol>
<li>$[j \in J]$ and $[k \in K’]$ where the book says “let $J = K’$ be the set of all integers. So this will return 1 all
the time.</li>
<li>$[k \in K(j)]$ and $[j \in J’(k)]$ is the outer sum dependent property. So, for example, “loop from current value k” or
“loop to current value of k”. The book calls this “the basic property $P(j,k)$ that governs a double sum”. This will
return 0 <em>except</em> when we are in the “upper right triangle”.</li>
</ol>
<p>Furthermore #1 above is the main loop and #2 is the nested loop in the code example.</p>Friedrich "Fred" Clausenftclausen@gmail.comIn Concrete Mathematics (Graham, Patashnik, Knuth) I am working my way through page 36 about sums of sums. Specifically the “rocky road” (yum) method for swapping the order of summation when the range of the inner sum depends on the index variable on the outer sum.Terraform: Solving the double slash mystery with Terragrunt20201020T11:36:00+00:0020201020T11:36:00+00:00https://ftclausen.github.io/dev/infra/terraformsolvingthedoubleslashmystery<p>The solution I found to my particular case of “Error: Unreadable module directory” when using Terragrunt.</p>
<h1 id="terms">Terms</h1>
<p>A quick note on wording</p>
<ul>
<li><em>Concrete service</em>: A service in TF <em>using</em> a shared module. Example: a specific web site site.example.com</li>
<li><em>Shared module</em> or <em>module</em>: Encapsulated TF provisioning logic to be reused as required. Example: the “webserver” module
used by the above web site concrete service</li>
</ul>
<h1 id="details">Details</h1>
<p>Where: Concrete service definition.</p>
<p>I was baffled by the following error message from Terraform when standing up a concrete service (using contrived module
names):</p>
<div class="languageplaintext highlighterrouge"><div class="highlight"><pre class="highlight"><code>Initializing modules...
 sibling1_mod in
 sibling2_mod in

Error: Unreadable module directory
Unable to evaluate directory symlink: lstat ../sibling1: no such file or directory
</code></pre></div></div>
<p>This is triggered when including a module as follows when trying to instantiate the concrete service</p>
<div class="languageplaintext highlighterrouge"><div class="highlight"><pre class="highlight"><code>terraform {
source = "../../../../../modules/example1"
}
</code></pre></div></div>
<p>The fix was <strong>simply to add a missing slash (<code class="languageplaintext highlighterrouge">/</code>)</strong> to the base of the repository relative path above. So if
<code class="languageplaintext highlighterrouge">../../../../../</code> takes you to the Git repo root then you need a double slash at the end <code class="languageplaintext highlighterrouge">../../../../..//</code> followed by
the module path. Full example:</p>
<div class="languageplaintext highlighterrouge"><div class="highlight"><pre class="highlight"><code>terraform {
source = "../../../../..//modules/example1"
# ^^ Double slash here!
}
</code></pre></div></div>
<p>I should say Terragrunt also offers a useful hint; the implications of which I did not fully understand initially:</p>
<blockquote>
<p>WARNING: no doubleslash (//) found in source URL /Users/fclausen/freddiegit/tf12modsourceissue/modules/example1. Relative paths in downloaded Terraform code may not work.</p>
</blockquote>
<h1 id="circumstancesinwhichthishappen">Circumstances in which this happen</h1>
<p>This will happen under the following conditions</p>
<ul>
<li>Using inrepo Terraform modules; either part of the repo or placed there some other way</li>
<li>Forgetting the double slash as described above (obviously)</li>
<li>The module you are <code class="languageplaintext highlighterrouge">source</code>ing includes transitive dependencies at the same level in the directory tree. E.g.
<div class="languageplaintext highlighterrouge"><div class="highlight"><pre class="highlight"><code>.
├── accounts
│ └── account1
│ └── earth
│ └── dev
│ └── service1 # < source = "../../../../..//modules/example1"
├── common
└── modules
├── example1 # Depends on sibling1 and sibling2 via `source ../sibling1`, `source ../sibling2`
├── sibling1
└── sibling2
</code></pre></div> </div>
</li>
</ul>
<h1 id="examplerepo">Example Repo</h1>
<p>I have put an example repo to demonstrate this issue here:</p>
<p>https://github.com/ftclausen/tf12modsourceissue</p>
<p>Specifically you can check out the <code class="languageplaintext highlighterrouge">demonstrate_incorrect_slash_usage</code> tag to replicate</p>Friedrich "Fred" Clausenftclausen@gmail.comThe solution I found to my particular case of “Error: Unreadable module directory” when using Terragrunt.Concrete Mathematics: Quick geometric series with Towers of Hanoi Clarification20200905T21:25:00+00:0020200905T21:25:00+00:00https://ftclausen.github.io/mathematics/concretemathematics/concretemathematicsquickgeometricserieswithtowersofhanoiclarification<p>This concerns the paragraph just before equation 2.9. I will quote it here</p>
<blockquote>
<p>The sum of the geometric series $2^{1} + 2^{2}+ \cdot\cdot\cdot + 2^{n} = (\frac{1}{2})^1 + (\frac{1}{2})^2 +
\cdot\cdot\cdot + (\frac{1}{2})^n$ will be derived later in this chapter; it turns out to be $1  (\frac{1}{2})^n$.
Hence $T_n = 2^nS_n = 2^n  1$</p>
</blockquote>
<p>That last bit</p>
\[T_n = 2^nS_n = 2^n  1\]
<p>Had me confused for a while but, after stopping overthinking it, I came to release they mean things quite literally
using the previous definitions in the book with some algebraic manipulations</p>
\[\begin{align}
\frac{T_n}{2^n} &= S_n \\
T_n &= 2^nS_n \\
\end{align}\]
<p>Now at this point we can substitute in the definition for $S_n$ which is the sum of the geometric series given to us in
the quote above as $1  (\frac{1}{2})^n$. First we slightly rearrange it as $1  \frac{1}{2^n}$ then plug that in</p>
\[\begin{align}
T_n &= 2^n(1  \frac{1}{2^n}) \\
T_n &= 2^n  \frac{2^n}{2^n} \\
T_n &= 2^n  1
\end{align}\]
<p>Tada! We get the closed form for the Towers of Hanoi recurrence.</p>Friedrich "Fred" Clausenftclausen@gmail.comThis concerns the paragraph just before equation 2.9. I will quote it hereConcrete Mathematics: Repertoire Method Section 2.2  The Sequel20200829T21:00:00+00:0020200829T21:00:00+00:00https://ftclausen.github.io/mathematics/concretemathematics/concretemathematicsrepertoiremethodsection2.2thesequel<p>As with most of my posts on Concrete Mathematics this is a more verbose outline of the repertoire method in section
2.2. It explains how to find the closed form to the sum recurrence 2.7 which I reproduce here</p>
\[\begin{align}
R_0 &= \alpha \\
R_n &= R_{n1} + \beta + \gamma n
\end{align}\]
<p>Then, as in chapter one, we work through a few small cases like $R_1 = \alpha + \beta + \gamma$, $R_2 = \alpha + 2\beta + 3\gamma$ and so on.
We can see that there is $\alpha$, $\beta$, $\gamma$ (the “general parameters”) which have “something done” to them to give us the final closed
form. This “something we do” is represented by, at this point, unknown functions $A(n)$, $B(n)$, and $C(n)$ (a.k.a.
coefficients of dependence on the before mentioned general parameters). Putting them together we have a framework for starting
to find our closed form</p>
\[R_n = A(n)\alpha + B(n)\beta + C(n)\gamma\]
<p>What the book does is cleverly plug in “simple functions of n for $R_n$” and letting the righthandside shake itself out. With some
luck we’ll just have one of $\alpha$, $\beta$, or $\gamma$ left equalling the “simple function of n”. Let’s put it to
action</p>
<h1 id="findingan">Finding $A(n)$</h1>
<p>Here they set $R_n = 1$ and, lo and behold, the general parameters end up as $\alpha = 1$, $\beta = 0$, $\gamma = 0$.
Now, why this is confused me (I could still be confused but not know it), until I pondered the logical implications of
setting $R_n = 1$. <strong>NOTE</strong> it is not the same as setting $n = 1$; for this repertoire item <em>the whole sum</em> is 1</p>
<p>So if the whole sum is $1$ what does that mean? Using the recurrence it must mean that $S_{n1}$ is $1$, $\beta$ is $0$,
and $\gamma$ is $0$. If $\beta$ and $\gamma$ were anything other than zero then the sum would not be $1$. Hence $\alpha
= 1$</p>
<p>Now, using that info, we can subin $\alpha = 1$, $\beta = 0$, $\gamma = 0$ to the closed form</p>
\[\begin{align}
1 &= A(n)\cdot 1 + B(n)0 + C(n)0 \\
1 &= A(n)
\end{align}\]
<h1 id="findingbn">Finding $B(n)$</h1>
<p>With similar logic to above, setting $R_n = n$, it means <em>the whole sum</em> is the same as $n$. The only way that could be is
if we’re simply adding $1$ with each recurrence iteration. So it would be like a recurrence of $R_n = S_{n1} + 1 +
0(n)$ meaning $\alpha = 0$ (the first iteration would be 0) and $\gamma = 0$ otherwise we’d have a result of $R_n > n$.
Hence $\alpha = 0$, $\beta = 1$, $\gamma = 0$. Plugging in those values to our proposed closed form we get</p>
\[\begin{align}
n &= A(n)\cdot0 + B(n)\cdot1 + C(n)\cdot0 \\
n &= B(n)
\end{align}\]
<h1 id="findingcn">Finding $C(n)$</h1>
<p>This one I didn’t figure out without some help from Professor Internet in the form of Hans Lundmark in <a href="https://math.stackexchange.com/questions/67939/repertoiremethodclarificationrequiredconcretemathematics#comment161060_67946">a
comment</a>.
For this particular repertoire item the authors are setting $R_n$ to $n^2$. With that done it implies $\alpha = 0$ because $0^2 = \alpha$. To then see what $\beta$ and $\gamma$ need to be in order to eliminate them we simply plug in
$n^2$ to the recurrence RHS so</p>
\[\begin{align}
n^2 &= (n  1)^2 + \beta + \gamma n \\
n^2 &= n^2 2n +1 + \beta + \gamma n
\end{align}\]
<p>At this point we do some selective factoring in order to see what $\beta$ and $\gamma$ need to be set to
in order to get our simple repertoire item for $C(n)$. First rearrange to make it more obvious (swap $\beta$ and
$\gamma$)</p>
\[\begin{align}
n^2 &= n^2  2n + \gamma n + 1 + \beta \\
n^2 &= n^2 + n(\gamma 2) + 1(1 + \beta)
\end{align}\]
<p>And, tada, we can see we need to set $\gamma = 2$ and $\beta$ to $1$. Using this info we can plug it back into our
proposed closed form:</p>
\[\begin{align}
n^2 &= A(n)\cdot0 + B(n)\cdot1 + C(n)\cdot2 \\
n^2 &= 0 B(n) + 2C(n) \\
n^2 &= 2C(n) B(n)
\end{align}\]
<p>At this point we know $B(n) = n$ (from previous repertoire step for $B(n)$) so sub that in and rearrange to get the result</p>
\[\begin{align}
n^2 &= 2C(n)  n \\
n^2 + n &= 2C(n) \\
\frac{n^2 + n}{2} &= C(n)
\end{align}\]
<h1 id="tieitalltogether">Tie it all together</h1>
<p>So the final closed form ends up being</p>
\[R_n = \alpha + n\beta + (\frac{n^2 + n}{2})\gamma\]
<p>But, wait, there’s more! The sum recurrence of the form (2.6 in book)</p>
\[\begin{align}
S_0 &= a_0 \\
S_n &= S_{n1} + a_n
\end{align}\]
<p>Looks like this in the general sumrecurrence form</p>
\[\begin{align}
R_0 &= \alpha \\
R_n &= R_{n1} + \beta + \gamma n
\end{align}\]
<p>Which, in turn, looks like this in summation form</p>
\[\sum^n_{k=0} (a + bk)\]
<p>Now, in the case of 2.7, we see that $\alpha = \beta = a$ and $\gamma = b$. So our closed form
can be simplified in the following way</p>
\[aA(n) + aB(n) + bC(n) \\
= a\cdot 1 + a\cdot n + b(\frac{n^2 + n}{2}) \\
= a(n + 1) + b(n + 1)n/2\]
<p>Because we can <em>plug in</em> the known values for $A(n)$, $B(n)$, and $C(n)$</p>Friedrich "Fred" Clausenftclausen@gmail.comAs with most of my posts on Concrete Mathematics this is a more verbose outline of the repertoire method in section 2.2. It explains how to find the closed form to the sum recurrence 2.7 which I reproduce hereConcrete Mathematics: Solving Towers of Hanoi recurrence without clairvoyance20200810T12:25:00+00:0020200810T12:25:00+00:00https://ftclausen.github.io/mathematics/concretemathematics/concretemathematicssolvingtowersofhanoiwithoutclairvoyance<p>This post expands, in terms of verbosity, what is presented in equation 1.3 where they say</p>
<blockquote>
<p>It doesn’t take genius to discover that the solution to <em>this</em> recurrence is just $U_n = 2^n$; hence $T_n = 2^n  1$.
Even a computer could discover this.</p>
</blockquote>
<p>This was not immediately obvious to me because a) I’m early in my maths adventures and b) I don’t have the mathematical
fluency that comes with either working in the field or being in fulltime study. What I needed to do was unroll that
recurrence both in symbolic and concrete forms to “get it”. For reference, the recurrences are labelled as 1.1 in the
book, I’ll put them here</p>
\[\begin{align}
T_0 &= 0; \\
Tn &= 2T_{n1} + 1 \\
\end{align}\]
<h1 id="settingthescene">Setting the Scene</h1>
<p>We are trying to find a solution to the recurrence $Tn = 2T_{n1} + 1$. It helped me to expand this to bear a more direct
relevance to actually solving the Towers of Hanoi puzzle</p>
\[T_n = T_{n1} + 1 + T_{n1}\]
<p>To turn the above recurrence into a sentence: We first move all disks above the bottom most one to the middle peg
($T_{n1}$), then move the bottom disk to the destination peg ($+1$), and finally the disks on the middle peg are moved
to the destination ($T_{n1}$).</p>
<p>Now the authors suggest adjusting the recurrence by adding $1$ to both sides turning it into</p>
\[\begin{align}
T_0 + 1 &= 1; \\
T_n + 1 &= 2T_{n1} + 2 \\
&= T_{n1} + 1 + T_{n1} + 1 \\
\end{align}\]
<p>Notice we now have a common form we can reference easily: $T_n + 1$ where $n$ is just a placeholder. It can be $n1$ as
well. As said on Math SE by Jaap Scherphuis <a href="https://math.stackexchange.com/questions/2899754/concretemathematicsbookidontunderstandconversionin11to13#comment5989495_2899754">over
here</a>.</p>
<h1 id="simplifying">Simplifying</h1>
<p>Now, with the “common form”, $T_n + 1$, above we can assign that a simple label. The book uses $U_n$, as in $U_n = T_n +
1$. Now we can make our recurrence super simple to reason about</p>
\[\begin{align}
U_0 &= 1 \\
U_n &= 2U_{n1} \\
\end{align}\]
<p>Reminder: $U_{n1} = T_{n1} + 1$. To see how we end up with the recurrence just being $U_n = 2^n$ we can unroll this
both symbolically and concretely</p>
\[\begin{align}
U_n &= 2U_{n1} \\
&= 2(2(U_{n2})) \\
&= 2(2(..(2U_{nn}))) \\
\end{align}\]
<p>The $2^n$ nature of it is becoming more clear. As for a concrete example where $n=3$</p>
\[\begin{align}
U_3 &= 2(U_2) \\
&= 2(2(U_1)) \\
&= 2(2(2(U_0))) \\
&= 2(2(2(1))) \\
&= 8 \\
&= 2^3 \\
\end{align}\]
<p>To get from that to our final closed form of $T_n = 2^n  1$ we have, as discussed above</p>
\[U_n = 2^n \\\]
<p>But also</p>
\[\begin{align}
U_n &= T_n + 1 \\
\therefore \\
T_n + 1 &= 2^n \\
T_n &= 2^n  1 \\
\end{align}\]
<blockquote>
<p>Even a computer could discover this.</p>
</blockquote>
<p>This human was glad to work it out eventually.</p>Friedrich "Fred" Clausenftclausen@gmail.comThis post expands, in terms of verbosity, what is presented in equation 1.3 where they say