From b1d09eeb9f80be204dec94cfb380b231ed4ee350 Mon Sep 17 00:00:00 2001 From: queue-miscreant Date: Fri, 14 Feb 2025 14:08:28 -0600 Subject: [PATCH] revisions to polycount.5 --- polycount/4/index.qmd | 1 + polycount/5/fibonacci_deficiency_mod_2.png | Bin 0 -> 408 bytes polycount/5/fibonacci_old_bad.png | Bin 0 -> 2807 bytes polycount/5/gif_mp4_size_comparison.png | Bin 0 -> 32046 bytes polycount/5/index.qmd | 629 ++++++++++++++------- 5 files changed, 419 insertions(+), 211 deletions(-) create mode 100644 polycount/5/fibonacci_deficiency_mod_2.png create mode 100644 polycount/5/fibonacci_old_bad.png create mode 100644 polycount/5/gif_mp4_size_comparison.png diff --git a/polycount/4/index.qmd b/polycount/4/index.qmd index e4389cf..017e8f9 100644 --- a/polycount/4/index.qmd +++ b/polycount/4/index.qmd @@ -24,6 +24,7 @@ categories: } + This post assumes you have read [the first](../1), which introduces generalized polynomial counting, and [the second](../2), which restricts the focus and specifies the general aim. diff --git a/polycount/5/fibonacci_deficiency_mod_2.png b/polycount/5/fibonacci_deficiency_mod_2.png new file mode 100644 index 0000000000000000000000000000000000000000..dc33707ab5d1fc0c2a24bf21dce2b5c4d72c738d GIT binary patch literal 408 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 JPDHLkV1iP0TXg^c literal 0 HcmV?d00001 diff --git a/polycount/5/gif_mp4_size_comparison.png b/polycount/5/gif_mp4_size_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..5ec1a1380e86a590efa4e158b2feaa098d534b6b GIT binary patch literal 32046 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

-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 literal 0 HcmV?d00001 diff --git a/polycount/5/index.qmd b/polycount/5/index.qmd index 2cba64c..1249daf 100644 --- a/polycount/5/index.qmd +++ b/polycount/5/index.qmd @@ -1,317 +1,524 @@ --- +title: "Polynomial Counting 5: Pentamerous multiplication" format: html: html-math-method: katex +date: "2021-02-09" +date-modified: "2025-2-12" +jupyter: python3 +categories: + - algebra + - haskell --- + -Arithmetic on Integral Systems ------------------------------- +This post assumes you have read [the first](../1), which introduces generalized polynomial counting. -Addition is a fairly simple process for positional systems: align the place values, add each term together, then apply the carry as many times as possible. Without a carry rule, this can be approached formally by treating the place values as a sequence $b_n$ and gathering terms: +One layer up from counting is arithmetic. +We've done a little arithmetic using irrational expansions in pursuit of counting, but maybe we should investigate it a bit. + + +Arithmetical Algorithms +----------------------- + +Addition is a fairly simple process for positional systems: align the place values, add each term together, + then apply the carry as many times as possible. +Without a carry rule, this can be approached formally by treating the place values as a sequence + $b_n$ and gathering terms: $$ \begin{gather*} -\phantom{+~} -\overset{b_2}{1} -\overset{b_1}{2} -\overset{b_0}{3} & -\phantom{+~}1b_2 + 2b_1 + 3b_0 -\\ -\underline{+\ \smash{ -\overset{\phantom{b_0}}4 -\overset{\phantom{b_0}}5 -\overset{\phantom{b_0}}6 -}\vphantom,} & -\underline{+\ -4b_2 + 5b_1 + 6b_0 -\vphantom,} \\ -\phantom{+~}\smash{ -\overset{\phantom{b_0}}5 -\overset{\phantom{b_0}}7 -\overset{\phantom{b_0}}9} & -\phantom{+~}5b_2 + 7b_1 + 9b_0 + \phantom{+~} \overset{b_2}{1} \overset{b_1}{2} \overset{b_0}{3} & + \phantom{+~} 1b_2 + 2b_1 + 3b_0 \\ + \underline{ + +\ + \smash{ + \overset{\phantom{b_0}}4 + \overset{\phantom{b_0}}5 + \overset{\phantom{b_0}}6 + } + \vphantom, + } & + \underline{ + +\ + 4b_2 + 5b_1 + 6b_0 \vphantom, + } \\ + \phantom{+~} + \smash{ + \overset{\phantom{b_0}}5 + \overset{\phantom{b_0}}7 + \overset{\phantom{b_0}}9 + } & + \phantom{+~} 5b_2 + 7b_1 + 9b_0 \end{gather*} $$ -Multiplication is somewhat trickier. Its validity follows from the interpretation of an expansion as a polynomial. Polynomial multiplication itself is equivalent to [*discrete convolution*](https://en.wikipedia.org/wiki/Convolution#Discrete_convolution) +Multiplication is somewhat trickier. +Its validity follows from the interpretation of an expansion as a polynomial. +Polynomial multiplication itself is equivalent to + [*discrete convolution*](https://en.wikipedia.org/wiki/Convolution#Discrete_convolution). $$ -\begin{align*}& -\begin{matrix} -\phantom{\cdot~} -111_x \\ -\underline{\cdot\ -\phantom{1}21_x\vphantom,} \\ -\phantom{\cdot \ 0} -111_{\phantom{x}} \\ -\underline{\phantom{\cdot\ } -2220_{\phantom{x}} \vphantom,} \\ -\phantom{\cdot\ } -2331_{\phantom{x}} -\end{matrix} &\qquad& -\begin{gather*} -(x^2 + x + 1)(2x + 1) \\ \\ -= 2x^3 + 2x^2 + 2x \phantom{+ 1}\\ -\phantom{= 2x^3 } + \phantom{2}x^2 + \phantom{2}x + 1 \\ -= 2x^3 + 3x^2 + 3x + 1 -\end{gather*} -&\qquad& -\begin{gather*} -[1,1,1] * [2,1] \\ -\begin{matrix} -\textcolor{blue}0 &\textcolor{red}1 & \textcolor{red}1 & \textcolor{red}1 & \textcolor{blue}0 &\\ -& & &1 & 2 & =~1\\ -& & 1 & 2 & &=~3\\ -& 1 & 2 & & &=~3\\ -1 & 2 & & & & =~2 -\end{matrix} -\end{gather*} +\begin{align*} + &\begin{matrix} + \phantom{\cdot~} + 111_x \\ + \underline{\cdot\ \phantom{1}21_x\vphantom,} \\ + \phantom{\cdot \ 0} + 111_{\phantom{x}} \\ + \underline{\phantom{\cdot\ } 2220_{\phantom{x}} \vphantom,} \\ + \phantom{\cdot\ } + 2331_{\phantom{x}} + \end{matrix} + &\qquad& + \begin{gather*} + (x^2 + x + 1)(2x + 1) \\ \\ + = \phantom{2x^3 + } \phantom{2}x^2 + \phantom{2}x + 1 \\ + + \phantom{.} 2x^3 + 2x^2 + 2x \phantom{+ 1}\\ + = 2x^3 + 3x^2 + 3x + 1 + \end{gather*} + &\qquad& + \begin{gather*} + [1,1,1] * [2,1] \\ + \begin{matrix} + \textcolor{blue}0 &\textcolor{red}1 & \textcolor{red}1 & \textcolor{red}1 & \textcolor{blue}0 &\\ + & & &1 & 2 & =~1\\ + & & 1 & 2 & &=~3\\ + & 1 & 2 & & &=~3\\ + 1 & 2 & & & & =~2 + \end{matrix} + \end{gather*} \end{align*} $$ -The left equation shows familiar multiplication, the middle equation is the same product when expressed as polynomials, and the right equation shows this product obtained by convolution. Note that the string of the second argument (\[2, 1\]) is reversed when performing the convolution. +The left equation shows familiar multiplication, the middle equation is the same product when expressed as polynomials, + and the right equation shows this product obtained by convolution. +Note that \[2, 1\], the second argument, is reversed when performing the convolution. -Without carrying, multiplication and addition are base-agnostic. When doing arithmetic in a particular base, we should obtain the same result even if we perform the same operations in another base. +Without carrying, multiplication and addition are base-agnostic. +When doing arithmetic in a particular base, we should obtain the same result even if we perform the same operations in another base. $$ -\begin{gather*} -&18 = 10010_2 && -5 = 101_2 \\ \\ -& -\begin{matrix} -\phantom{\cdot~} -18_{10} \\ -\underline{\cdot\ -\phantom{1}5_{10}\vphantom,} \\ -\phantom{\cdot~}90_{10} \\ \\ -=~1011010_2 -\end{matrix} -&& -\begin{matrix} -[1,0,0,1,0] * [1,0,1] \\ \\ -\begin{matrix} -\textcolor{blue}0 & \textcolor{blue}0 &\textcolor{red}1 & \textcolor{red}0 & \textcolor{red}0 & \textcolor{red}1 & \textcolor{red}0 & \textcolor{blue}0 & \textcolor{blue}0 &\\ -& & & & & &1 & 0 & 1 & =~0\\ -& & & & &1 & 0 & 1 & & =~1\\ -& & & &1 & 0 & 1 & & & =~0\\ -& & &1 & 0 & 1 & & & & =~1\\ -& &1 & 0 & 1 & & & & & =~1\\ -& 1 & 0 & 1 & & & & & & =~0\\ -1 & 0 & 1 & & & & & & & =~1\\ -\end{matrix} -\end{matrix} -\end{gather*} +\begin{array}{c} + 18_{10} \cdot 5_{10} = 10010_2 \cdot 101_2 + \\ \hline \\ + \begin{gather*} + & + \begin{matrix} + \phantom{\cdot~} + 18_{10} \\ + \underline{\cdot\ + \phantom{1}5_{10}\vphantom,} \\ + \phantom{\cdot~}90_{10} \\ \\ + =~1011010_2 + \end{matrix} + && + \begin{matrix} + [1,0,0,1,0] * [1,0,1] \\ \\ + \begin{matrix} + \textcolor{blue}0 & \textcolor{blue}0 &\textcolor{red}1 & \textcolor{red}0 & \textcolor{red}0 + & \textcolor{red}1 & \textcolor{red}0 & \textcolor{blue}0 & \textcolor{blue}0 &\\ + & & & & & &1 & 0 & 1 & =~0\\ + & & & & &1 & 0 & 1 & & =~1\\ + & & & &1 & 0 & 1 & & & =~0\\ + & & &1 & 0 & 1 & & & & =~1\\ + & &1 & 0 & 1 & & & & & =~1\\ + & 1 & 0 & 1 & & & & & & =~0\\ + 1 & 0 & 1 & & & & & & & =~1\\ + \end{matrix} + \end{matrix} + \end{gather*} +\end{array} $$ -In the example above, we multiply 18 and 5 together to obtain 90 in base ten, then convert it to binary. This is precisely the same as converting 18 and 5 to binary, then convolving the strings of digits. Fortunately in this instance, we don't have to worry about any carries in the result. +This shows that regardless of whether we multiply eighteen and five together in base ten or two, + we'll get the same string of digits if afterward everything is rendered in the same base. +Fortunately in this instance, we don't have to worry about any carries in the result. Two Times Tables ---------------- -The strings "10010" and "101" do not contain adjacent "1"s, so they can also be interpreted as the Zeckendorf expansions (of 10 and 4, respectively). This destroys their correspondence to polynomials, so their product by convolution, as a Zeckendorf expansion (when returned to canonical form) is not the product of 10 and 4. +The strings "10010" and "101" do not contain adjacent "1"s, so they can also be interpreted as + Zeckendorf expansions (of ten and four, respectively). +This destroys their correspondence to polynomials, so their product by convolution, + as a Zeckendorf expansion (when returned to canonical form) is not the product of ten and four. $$ \begin{gather*} -[1,0,0,1,0]_{\text{Zeck}} * [1,0,1]_{\text{Zeck}} = 1011010_{\text{Zeck}} -= 1100010_{\text{Zeck}} \\ -= 10000010_{\text{Zeck}} = 36 \\ -\text{Zeck}(10) * \text{Zeck}(4) -= 36 \neq 40 = 10 \cdot 4 + [1,0,0,1,0] * [1,0,1] = 1011010 \\ + 10\textcolor{red}{11}010_{\text{Zeck}} + = 1\textcolor{red}{1}00010_{\text{Zeck}} + = \textcolor{blue}{11}00010_{\text{Zeck}} + = \textcolor{blue}{1}0000010_{\text{Zeck}} = 36_{10} \\ + \text{Zeck}(10_{10}) * \text{Zeck}(4_{10}) + = 36_{10} \neq 40_{10} = 10_{10} \cdot 4_{10} \end{gather*} $$ -The process of expanding both terms, convolving, and interpreting can be captured by the operator $\odot_\text{Zeck}$. Its definition requires a unique greedy expansion for every integer (which exists), and is defined via convolution (which is commutative), so it is commutative. We can tabulate the results in a times table as follows - -| $\odot_\text{Zeck}$ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -|----------------|---|---|---|---|---|---|---|---|---| -| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| 1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -| 2 | 0 | 2 | 3 | 5 | 7 | 8 | 10 | 11 | 13 | -| 3 | 0 | 3 | 5 | 8 | 11 | 13 | 16 | 18 | 21 | -| 4 | 0 | 4 | 7 | 11 | 15 | 18 | 22 | 25 | 29 | -| 5 | 0 | 5 | 8 | 13 | 18 | 21 | 26 | 29 | 34 | -| 6 | 0 | 6 | 10 | 16 | 22 | 26 | 32 | 36 | 42 | -| 7 | 0 | 7 | 11 | 18 | 25 | 29 | 36 | 40 | 47 | -| 8 | 0 | 8 | 13 | 21 | 29 | 34 | 42 | 47 | 55 | - -The expansions for 0 and 1 are invariably the strings "0" and "1". When a sequence has length 1, convolution degenerates to term-by-term multiplication. Thus, convolution by "0" produces a sequence of 0's, and convolution with the string "1" produces the same sequence. Accordingly, the only "correct" columns and rows that appear in the table are the first two. Ignoring them, this array exists in the OEIS ([A101330](https://oeis.org/A101330)) and is known as Knuth's Fibonacci product. - - -Correcting for Errors ---------------------- - -The difference between the actual product and the false product can be interpreted as an error endemic to Zeckendorf expansions. If assigned to the symbol $\oplus_\text{Zeck}$, then the normal product can be recovered as $mn = m \odot_\text{Zeck} n + m \oplus_\text{Zeck} n$. We can then collect errors into table of their own: - -| $\odot_{Zeck}$ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -|----------------|---|---|---|---|---|---|---|---|---| -| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| 2 | 0 | 0 | 1 | 1 | 1 | 2 | 2 | 3 | 3 | -| 3 | 0 | 0 | 1 | 1 | 1 | 2 | 2 | 3 | 3 | -| 4 | 0 | 0 | 1 | 1 | 1 | 2 | 2 | 3 | 3 | -| 5 | 0 | 0 | 2 | 2 | 2 | 4 | 4 | 6 | 6 | -| 6 | 0 | 0 | 2 | 2 | 2 | 4 | 4 | 6 | 6 | -| 7 | 0 | 0 | 3 | 3 | 3 | 6 | 6 | 9 | 9 | -| 8 | 0 | 0 | 3 | 3 | 3 | 6 | 6 | 9 | 9 | - -In this table, unsurprisingly, the first two columns are populated entirely by 0's. The rest of the errors are grouped together in rectangular blocks. - - -Fibonacci Runs --------------- - -A pattern can be observed along any column or row (except the first two) or along the main diagonal (where they squares lie). In each, the number of terms the series "hangs" before progressing (i.e., the [*run lengths*](https://en.wikipedia.org/wiki/Run-length_encoding)) is the same: +We can express this operation for general integers *x* and *y* as $$ -\begin{gather*} -RL(0, 0, 1, 1, 1, 2, 2, 3, 3, ...) = \\ -RL(0, 0, 2, 2, 2, 4, 4, 6, 6, ...) = \\ -RL(0, 0, 1, 1, 1, 4, 4, 9, 9, ...) = \\ -2,3,2,3,3,2,3,2,3,3 ... -\end{gather*} +x \odot_\text{Zeck} y = Unzeck(Zeck(x) * Zeck(y)) $$ -The initial 2 can be ignored since it corresponds to the 0 and 1 rows. If the rest is converted such that $3 \mapsto 0,~ 2 \mapsto 1$, then the sequence becomes (truncated to 30 terms): +where "Zeck" expands an integer into its Zeckendorf expansion and "Unzeck" signifies the process of + re-interpreting the string as an integer. +We can do this because for every integer, a canonical expansion exists. +Further, since this operation is defined via convolution (which is commutative), it is also commutative. + +```{python} +#| output: false + +from itertools import count, chain, islice, takewhile +import numpy as np + +def fibs(): + i = 1 + j = 1 + while True: + yield i + t = i + j + j = i + i = t + +def zeck(n: int) -> list[int]: + fibs_ = list(takewhile(lambda x: x <= n, fibs()))[::-1] + ret = [] + + for i in fibs_: + digit, n = divmod(n, i) + ret.append(digit) + + return ret or [0] + +def unzeck(ns: list[int]) -> int: + return sum(map(lambda x, y: x * y, reversed(ns), fibs())) + +def zeck_times(x: int, y: int) -> int: + return unzeck(np.convolve(zeck(x), zeck(y), "full")) +``` + +We can then build a times table by experimentally multiplying. +The expansions for zero and one are invariably the strings "0" (or the empty string!) and "1". +When a sequence has length one, convolution degenerates to term-by-term multiplication. +Thus, convolution by "0" produces a sequence of "0"s, and convolution by "1" produces the same sequence. + +Ignoring those rows, the table is: + +```{python} +#| code-fold: true + +from IPython.display import Markdown +from tabulate import tabulate + +Markdown(tabulate( + [[zeck_times(i, j) for i in range(1, 10)] for j in range(2, 10)], + headers=["$\\odot_\\text{Zeck}$", *range(2, 10)] +)) +``` + +This resembles a sequence in the OEIS ([A101646](https://oeis.org/A101646)), where it mentions the defining operation + is sometimes called the "arroba" product. + +### Correcting for Errors + +The difference between the actual product and the false product can be interpreted as an error endemic to Zeckendorf expansions. +If assigned to the symbol $\oplus_\text{Zeck}$, then the normal product can be recovered as + $mn = m \odot_\text{Zeck} n + m \oplus_\text{Zeck} n$. + +We can then tabulate these errors just like we did our "products": + +```{python} +#| code-fold: true + +zeck_error = lambda x, y: x*y - zeck_times(x, y) + +Markdown(tabulate( + [[j] + [zeck_error(i, j) for i in range(2, 10)] for j in range(2, 10)], + headers=["$\\oplus_\\text{Zeck}$", *range(2, 10)] +)) +``` + +Notice that the errors seem to be grouped together in rectangular blocks. +Because this operation is commutative, the shapes of the rectangles must agree along the main diagonal, where they are squares. + +### Fibonacci Runs + +The shape of the rectangular blocks is somewhat odd. +We can assess the number of terms the series "hangs" before progressing by looking at the + [*run lengths*](https://en.wikipedia.org/wiki/Run-length_encoding)). + +:::: {.row layout-ncol="1"} +::: {.row} +```{python} +#| code-fold: true + +from IPython.display import Math +from typing import Generator + +def run_lengths(xs: Generator) -> Generator: + last = next(xs) + run_length = 1 + for i in xs: + if i != last: + yield run_length + last = i + run_length = 1 + else: + run_length += 1 + +show_trunc_list = lambda xs, n: "[" + ", ".join(chain(islice(map(str, xs), n), ("...",))) + "]" + +Math( + "RL([i \\oplus 2]_{i}) =" + + f"RL({show_trunc_list((zeck_error(i, 2) for i in count(0)), 10)}) =" + + show_trunc_list(run_lengths(zeck_error(i, 2) for i in count(0)), 10) +) +``` +::: + +::: {.row} +```{python} +#| code-fold: true + +Math( + "RL([i \\oplus 5]_{i}) =" + + f"RL({show_trunc_list((zeck_error(i, 5) for i in count(0)), 10)}) =" + + show_trunc_list(run_lengths(zeck_error(i, 2) for i in count(0)), 10) +) +``` +::: + +::: {.row} +```{python} +#| code-fold: true + +Math( + "RL([i \\oplus i]_{i}) =" + + f"RL({show_trunc_list((zeck_error(i, i) for i in count(0)), 10)}) =" + + show_trunc_list(run_lengths(zeck_error(i, i) for i in count(0)), 10) +) +``` +::: +:::: + +The initial two comes from the errors for $0 \oplus i$ and $1 \oplus i$. +These rows never have errors, so they can be ignored. + +Since the run lengths appear to only be occur in twos and threes, we don't lose any information by converting it + into, say, ones and zeroes. +Arbitrarily mapping $3 \mapsto 0,~ 2 \mapsto 1$, the sequence becomes (truncated to 30 terms): $$ -0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0... +0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,0,... $$ -This matches the *Fibonacci word* ([OEIS A3849](http://oeis.org/A003849)), a sequence obtained in a similar manner to the typical Fibonacci numbers. Rather than operating on integers by addition, it operates on strings by concatenation. Perhaps this is unsurprising, since Zeckendorf expansions are literally expansions in Fibonacci numbers. The run-length transform is the key to this infinite string, which in effect discards the *numbers* in the sequence for information about *discrete chunks* of the sequence. +This sequence matches the *Fibonacci word* ([OEIS A3849](http://oeis.org/A003849)). +The typical definition of this sequence follows from the a slight modification to that of + the Fibonacci sequence: rather than starting with two 1s and adding, we start with + "0" and "1" (as distinct strings), and concatenate. + +Perhaps this is unsurprising, since Zeckendorf expansions are literally strings in Fibonacci numbers. +However, this shows that the errors can be interesting, since it is not obvious that this is the case + from just looking at the multiplication table. Visualizing Tables ------------------ -While a table is a wonderful thing, it does not lend itself well to visualization. WolframAlpha has a feature that produces the multiplication table for a finite field ([example](https://www.wolframalpha.com/input?i=finite+field+of+order+25)). +While it's great that we can build a table, just showing the numbers isn't the best we can do when it comes to visualization. -I'd like to reproduce it with color, but there's a slight problem. Since we don't have a finite number of elements, we'll have to take our tables mod an integer. In the HSV color space, colors are cyclic just like the integers mod n. This actually has an additional appealing feature: two colors with similar hues are "near" in a similar way to the underlying numbers. Then, the entry-to-color mapping can just be given as +For inspiration, I remembered what WolframAlpha does when you ask it for operation tables in finite fields. +Rather than showing you the underlying field elements in a table, it renders + [a grayscale image](https://www.wolframalpha.com/input?i=finite+field+of+order+25). + +I'd like produce something similar in color, but there's a slight problem: we don't have a finite number of elements. +To get around this, we'll have to take our tables mod an integer. +In the HSV color space, colors are cyclic just like the integers mod *n*. +This actually has an additional appealing feature: two colors with similar hues are "near" in a similar way to the underlying numbers. +Then, the entry-to-color mapping can just be given as $$ k \mapsto HSV \left({2\pi k \over n}, 100\%, 100\% \right) $$ -In this mapping, for n = 2, red is 0 and cyan is 1. The following is a 100x100 image of the multiplication table of $\oplus_\text{Zeck}$ from 0 to 99. +In this mapping, for $n = 2$, zero goes to red and one goes to cyan. +The following is a 100x100 image of the multiplication table of $\oplus_\text{Zeck}$ from 0 to 99. -![]() - -Anima Moduli ------------- - -This table can by animated by gathering various n into an animation and incrementing n every frame. Before applying this technique to an error table, I find it prudent to apply it to standard addition and multiplication tables first. +![](fibonacci_deficiency_mod_2.png) -:::{.column width="40%"} -![]() -Addition +### Anima Moduli + +This table can by animated by gathering various n into an animation and incrementing n every frame. +Before applying this technique to an error table, it'd be prudent to apply it to standard addition and multiplication tables first. + +::: {.row layout-ncol="2"} +![ + Addition +](canonical_tables/canonical_addition.gif){.image-wide} + +![ + Multiplication +](canonical_tables/canonical_multiplication.gif){.image-wide} ::: -:::{.column width="40%"} -![]() -Multiplication +Both images appear to zoom in as the animation progresses. +Unsurprisingly, addition produces diagonal stripes, along which the sum is the same. +Multiplication produces a squarish pattern (with somewhat appealing moirés). + +Tables for $\odot_\text{Zeck}$ and $\oplus_\text{Zeck}$ should resemble the table to the right, + since their definition relies on it. + +::: {.row layout-ncol="2"} +![ + $\odot_\text{Zeck}$ +](series_tables/fibonacci_odot.gif){.image-wide} + +![ + $\oplus_\text{Zeck}$ +](series_tables/fibonacci_oplus.gif){.image-wide} ::: +Indeed, the zooming is present in both tables. +At later frames, both tables share the same "square rainbow" pattern, but the error table is closer. +Though both tables appear to have a repeating pattern, the blocks in the error table are still + irregularly shaped, as in the mod 2 case. -Both images appear to zoom in as the animation progresses. Unsurprisingly, addition produces diagonal stripes, along which the sum is the same. Multiplication produces a squarish pattern (with somewhat appealing moirés). - -Tables for $\odot_\text{Zeck}$ and $\oplus_\text{Zeck}$ should resemble the table to the right, since their definition relies on it. - -:::{.column width="40%"} -![]() -$\odot_\text{Zeck}$ -::: - -:::{.column width="40%"} -![]() -$\oplus_\text{Zeck}$ -::: - -The zooming is still present. At later frames, both tables share the same "square rainbow" pattern, but the error table is closer. Though both tables appear to have a repeating pattern, the blocks in the error table are still irregularly shaped, as in the mod 2 case. - -The error table also demonstrates (for a given modulus) how much the series differs from a geometric series. We know there will always be an error since, while Fibonacci numbers grow on the order of $O(\phi^n)$, the place values is only $\phi$ *in the limit*. +The error table also demonstrates (for a given modulus) how much the series differs from a geometric series. +We know there will always be an error since, while Fibonacci numbers grow on the order of + $O(\varphi^n)$, the ratio between place values is only *φ* in the limit. Other Error Tables ------------------ -These operations can can also be defined in terms of any other series expansion (i.e., integral system). Rather than showing both of the multiplication and error tables, I will elect to show only the latter. The error table is more fundamental since the table for $\odot$ can be constructed from it and the normal multiplication table. +These operations can can also be defined in terms of any other series expansion (i.e., integral system). +Rather than showing both of the multiplication and error tables, I will elect to show only the latter. +The error table is more fundamental since the table for $\odot$ can be constructed from it and the normal multiplication table. The error tables for some of the previously-discussed generalizations of the Fibonacci numbers are presented below. ### Pell, Jacobsthal -:::{.column width="40%"} -Pell -$\langle 2,1|$ +::: {.row layout-ncol="2"} +![ + Pell ([OEIS A000129](http://oeis.org/A000129)) + $\langle 2,1|$ +](series_tables/pell_oplus.gif){.image-wide} + +![ + Jacobsthal ([OEIS A001045](http://oeis.org/A001045)), + $\langle 1,2|$ +](series_tables/jacobsthal_oplus.gif){.image-wide} ::: -:::{.column width="40%"} -![]() -Jacobsthal -$\langle 1,2|$ -::: - -Of the two tables, the Pell table looks more similar to the Fibonacci one. Meanwhile, the Jacobsthal table has frames which are significantly redder than the either surrounding it. These occur on frames for which *n* is a power of 2, which is a root of the recurrence polynomial. +Of the two tables, the Pell table looks more similar to the Fibonacci one. +Meanwhile, the Jacobsthal table has frames which are significantly redder than the either surrounding it. +These occur on frames for which *n* is a power of 2, which is a root of the recurrence polynomial. ### *n*-nacci -:::{.column width="40%"} -Tribonacci -$\langle 1,1,1|$ +::: {.row layout-ncol="2"} +![ + Tribonacci, + $\langle 1,1,1|$ +](series_tables/tribonacci_oplus.gif){.image-wide} + +![ + Tetranacci, + $\langle 1,1,1,1|$ +](series_tables/tetranacci_oplus.gif){.image-wide} ::: -:::{.column width="40%"} -Tetranacci -$\langle 1,1,1,1|$ -::: - -Compared to the Fibonacci image, the size of the square pattern in the Tribonacci and Tetranacci images is larger. Higher orders of Fibonacci recurrences approach binary, so in the limit, the pattern disappears, as if the slowly-encroaching red corner is all that remains. +Compared to the Fibonacci image, the size of the square pattern in the Tribonacci and Tetranacci images is larger. +Higher orders of Fibonacci recurrences approach binary, so in the limit, + the pattern disappears, as if the tiny red corner in the upper-left is all that remains. ### Other -Of course, integral systems are not limited to linear recurrences, and tables can also be produced that correspond to other integer sequences. For example, the factorials produce distinct patterns at certain frames. The Catalan numbers (which are their own recurrence) mod 2 appear to be constructed from regular blocks of XORs. To prevent the page from getting bloated, these frames are presented in isolation. +Of course, integral systems are not limited to linear recurrences, and tables can also be produced + that correspond to other integer sequences. +For example, the factorials produce distinct patterns at certain frames. +The Catalan numbers (which are their own recurrence) mod two seem to make a fractal carpet. +To prevent the page from getting bloated, these frames are presented in isolation. -:::{.column width="40%"} -Factorial Error (mod 8) -::: +::: {.row layout-ncol="2"} +![ + Factorial Error (mod 8) +](series_tables/factorial_oplus_mod_8.png){.image-wide} -:::{.column width="40%"} -Catalan Numbers Error (mod 2) +![ + Catalan Numbers Error (mod 2) +](series_tables/catalan_oplus_mod_2.png){.image-wide} ::: Additional tables which I find interesting are: -- [Triangular Numbers (recurrence $\langle 3, \bar{3}, 1|$)]() -- [Square Numbers]() -- [Padovan Numbers (recurrence $\langle 0,1,1|$)]() -- [$\langle 1, 1, 2|$, based on the first 3 Catalan numbers]() +- [ + Triangular Numbers (recurrence $\langle 3, \bar{3}, 1|$) +](series_tables/triangular_oplus.gif){target="_blank_"} +- [ + Square Numbers +](series_tables/square_oplus.gif){target="_blank_"} +- [ + Padovan Numbers (recurrence $\langle 0,1,1|$) +](series_tables/padovan_oplus.gif){target="_blank_"} +- [ + $\langle 1, 1, 2|$, based on the first 3 Catalan numbers +](series_tables/recurrence_1_1_2_oplus.gif){target="_blank_"} Closing ------- -Even if not particularly useful, I enjoy the emergent behavior apparent in the tables. Even for typical multiplication, this visualization technique shows regular patterns which appear to "grow". Meanwhile, the sequence products frequently produce a pattern that either repeats, or is composed of many similar elements. +Even if not particularly useful, I enjoy the emergent behavior apparent in the tables. +Even for typical multiplication, this visualization technique shows regular patterns which appear to "grow". +Meanwhile, the sequence products frequently produce a pattern that either repeats, or is composed of many similar elements. -My first attempt to map integers to colors was to consider the prime factorization of each integer. The largest number in the factorization was related to the hue, and the number of terms in the factorization was related to the saturation. Results were not great. +The project that I used to render the images can be found [here](https://github.com/queue-miscreant/SeriesDeficient). +I didn't put much thought into command line arguments, nor did I build in many features. +As an executable, it should be completely serviceable to generate error tables based on recurrence relations; + the GHCi REPL can be used for more sophisticated sequences. -![]() -While I rendered these animations as GIFs, I also attempted to convert some of them to MP4s in hopes of shrinking the filesize. However, this is a use case where the MP4 is larger than the GIF, at least without compromising on resolution. This is a case when space-compression beats ill-suited time-compression. +### Bad Visualization -![]() -Produced with ffmpeg defaults +My first attempt to map integers to colors was to consider its prime factorization. +The largest number in the factorization was related to the hue, and the number of terms in the factorization + was related to the saturation. +Results were not great. -The project that I used to render the images can be found [here](). I didn't put much thought into command line arguments, nor did I build in many features. As an executable, it should be completely serviceable to generate error tables based on recurrence relations; the GHCi REPL can be used for more sophisticated sequences. +![ ](fibonacci_old_bad.png) + + +### Bad Filesizes + +While I rendered these animations as GIFs, I also attempted to convert some of them to MP4s in hopes of shrinking the filesize. +However, this is a use case where the MP4 is larger than the GIF, at least without compromising on resolution. +This is a case when space-compression beats ill-suited time-compression. + +![Produced with ffmpeg defaults](gif_mp4_size_comparison.png)