revisions for 4.appendix

This commit is contained in:
queue-miscreant 2025-03-03 02:19:50 -06:00
parent e5946df6ec
commit fd57fa066e

View File

@ -1,90 +1,169 @@
--- ---
title: "Polynomial Counting 4, Addendum" title: "Polynomial Counting 4, Addendum"
description: | description: |
Complex embeddings of irrational -adic expansions. Additional notes on irrational -adic expansions, including complex embeddings thereof.
format: format:
html: html:
html-math-method: katex html-math-method: katex
date: "2021-02-09" date: "2025-03-03"
date-modified: "2025-02-12"
categories: categories:
- algebra - algebra
- haskell - haskell
- interactive - interactive
execute:
eval: false
--- ---
```{haskell}
-- | echo: false
After converting my original [Two 2's post](../), I found myself much more pleased after making the import IHaskell.Display
diagrams it more reproducible. ```
After converting my original [Two 2's post](../), I grew pleased with making its diagrams
and content more reproducible.
However, I noticed some things which required further examination. However, I noticed some things which required further examination.
First, let's write out a double-width carry function more concretely in Haskell.
Balanced vs. Binary *κ*-adics ```{haskell}
----------------------------- -- | echo: true
-- Widened carry of a particular repeated amount
-- i.e., for carry2 2, the carry is 22 = 100
carry2 b = carry2' []
where carry2' zs (x:y:z:xs)
| q == 0 = carry2' (x:zs) (y:z:xs) -- try carrying at a higher place value
| otherwise = foldl (flip (:)) ys zs -- carry here
where ys = r : y-x+r : z+q : xs
(q, r) = x `quotRem` b
```
In the parent post, it was discussed that the integer four has a non-repeating expansion In the parent post, it was discussed that the integer four has a non-repeating expansion
when expressed as an *κ*-adic integer. when expressed as an *κ*-adic integer.
It followed in multiple ways from the repeating expansion of the integer two in the balanced ternary alphabet. Let's put this to the test by writing out each step for producing expansions of two and four.
A more unusual consequence of this is that despite the initial choice of alphabet, We'll also test these expansions by evaluating them at an approximation of $\kappa = \sqrt 3 + 1$.
[negative numerals could be cleared](../#all-positive) We should roughly get two and four at each step.
from the expansion by using an extra-greedy borrow.
There is only one significant difference in how the two are implemented: the choice of integer division function.
In Haskell, there exists both `quotRem` and `divMod`, with the two disagreeing on negative remainders:
::: {.row layout-ncol="2"}
```{haskell}
quotRem (-27) 5
```
```{haskell} ```{haskell}
divMod (-27) 5
```
:::
We can factor our choice out of our two digit-wide carry function by passing it as an argument:
```{haskell}
-- Widened carry of a particular repeated amount
-- i.e., for carry qr 2, the carry is 22 = 100
carry2 qr b = carry2' []
where carry2' zs (x:y:z:xs)
| q == 0 = carry' (x:zs) (y:z:xs) -- try carrying at a higher place value
| otherwise = foldl (flip (:)) ys zs -- carry here
where ys = r : y-x+r : z+q : xs
(q, r) = x `qr` b
```
Finally, let's show the iterates of applying this function to "4".
We happen to know the root for $\langle 2, 2|$ is $\sqrt 3 + 1$, so using an approximation,
we can check that we get a roughly constant value by evaluating at each step.
```{haskell}
-- | layout-ncol: 2
-- | code-fold: true -- | code-fold: true
-- | layout-ncol: 2
import IHaskell.Display -- Directly expand the integer `n`, using the `carry` showing each step for `count` steps
expandSteps count carry n = take count $ iterate carry $ n:replicate count 0
-- Horner evaluation on polynomials of ascending powers -- Horner evaluation on polynomials of ascending powers
hornerEval x = foldr (\c a -> a * x + c) 0 hornerEval x = foldr (\c a -> a * x + c) 0
-- Pair a polynomial with its evaluation at x -- Pair a polynomial with its evaluation at x
pairEval x = (,) <*> hornerEval x . map fromIntegral pairEval x = (,) <*> hornerEval x . map fromIntegral
-- Directly expand the integer `n`, using the `carry` showing each step for `count` steps adicTwoSteps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2 2) 2
expandSteps count carry n = take count $ iterate carry $ n:replicate count 0 adicFourSteps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2 2) 4
cendree4QuotRem10Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2 quotRem 2) 4 markdown "Iteratively carrying \"2\""
cendree4DivMod10Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2 divMod 2) 4 markdown "Iteratively carrying \"4\""
putStrLn . unlines . map show $ adicTwoSteps
putStrLn . unlines . map show $ adicFourSteps
```
Note that when an list is displayed in this post, it should be interpreted as an expansion
in increasing powers.
Expansions of *κ*-adics
-----------------------
In the original post, we ignored expansions other than the chaotic expansions of four.
Consider that we can use *two different* expansions for three, since we are using a balanced alphabet:
```{haskell}
-- | code-fold: true
-- | layout-ncol: 2
markdown "Increment two:"
markdown "Decrement three:"
adicThree = (1:) $ tail $ fst $ last adicTwoSteps
print adicThree
adicThree' = ((-1):) $ tail $ fst $ last adicFourSteps
print adicThree'
```
For convenience (and correctness), we'll retain the carry heads rather than truncating them.
How can we be sure that both of these are expansions of three?
Easy. Just negate every term of one of them, then add them together to see if they cancel.
```{haskell}
maybeZero = take 10 $ iterate (carry2 2) $ zipWith (+) adicThree (map negate adicThree')
putStrLn . unlines . map show $ maybeZero
```
As you can see, eventually we completely clear the number and just get list of zeros.
Which of these expansions is more valid?
I would argue that we should prefer expansions obtained by incrementing, since the natural numbers
are built in the same way.
This is flimsy, though. By doing this, negative one will never appear in the one's place.
It's also worth pointing out that we only have this choice at odd numbers.
At even numbers, the one's place is always zero.
It's easy to see why this is the case -- if there's a "2" in the one's place, it can be carried,
just like in binary.
Balanced vs. Binary *κ*-adics
-----------------------------
A more unusual consequence of the carry is that despite the initial choice of alphabet,
[negative numerals can be cleared](../#all-positive)
from the expansion by using an extra-greedy borrow.
There is only one significant difference in how the two are implemented:
the choice of integer division function.
In Haskell, there exists both `quotRem` and `divMod`, with the two disagreeing on negative remainders.
```{haskell}
-- | code-fold: true
-- | layout-ncol: 2
markdown "`quotRem`" markdown "`quotRem`"
markdown "`divMod`" markdown "`divMod`"
putStrLn . unlines . map show $ cendreeQuotRem10Steps
putStrLn . unlines . map show $ cendreeDivMod10Steps print $ quotRem (-27) 5
print $ divMod (-27) 5
``` ```
And fortunately, regardless of which function we pick, the iterates are all roughly four. We can factor our choice out of our two digit-wide carry function by passing it as an argument:
```{haskell}
-- | echo: true
carry2QR qr b = carry2QR' []
where carry2QR' zs (x:y:z:xs)
| q == 0 = carry2QR' (x:zs) (y:z:xs) -- try carrying at a higher place value
| otherwise = foldl (flip (:)) ys zs -- carry here
where ys = r : y-x+r : z+q : xs
(q, r) = x `qr` b
```
Now, let's compare the iterates of the two options by applying them to "4":
```{haskell}
-- | code-fold: true
-- | layout-ncol: 2
cendree4QuotRem10Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2QR quotRem 2) 4
cendree4DivMod10Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2QR divMod 2) 4
markdown "`quotRem`"
markdown "`divMod`"
putStrLn . unlines . map show $ cendree4QuotRem10Steps
putStrLn . unlines . map show $ cendree4DivMod10Steps
```
Fortunately, regardless of which function we pick, the evaluation roughly gives four at each step.
Note that since `quotRem` allows negative remainders, implementing the carry with it causes Note that since `quotRem` allows negative remainders, implementing the carry with it causes
negative numbers to show up in our expansions. negative numbers to show up in our expansions.
Conversely, negative numbers *cannot* show up if we use `divMod`. Conversely, negative numbers *cannot* show up if we use `divMod`.
@ -92,7 +171,7 @@ Conversely, negative numbers *cannot* show up if we use `divMod`.
### Chaos before Four ### Chaos before Four
Recall the series for two in the *κ*-adics: Recall again the series for two in the *κ*-adics:
$$ $$
2 = ...1\bar{1}1\bar{1}1\bar{1}100_{\kappa} 2 = ...1\bar{1}1\bar{1}1\bar{1}100_{\kappa}
@ -102,14 +181,16 @@ Since the `divMod` implementation clears negative numbers from expansions, we ca
The result is another chaotic series: The result is another chaotic series:
```{haskell} ```{haskell}
cendree2DivModCycleExpansion = take 11 $ iterate (carry2 divMod 2) $ take 15 $ 0:0:cycle [1,-1] cendree2DivModCycleExpansion = take 11 $
iterate (carry2QR divMod 2) $ take 15 $ 0:0:cycle [1,-1]
putStrLn . unlines . map show $ cendree2DivModCycleExpansion putStrLn . unlines . map show $ cendree2DivModCycleExpansion
``` ```
We get the same series if we expand 2 directly (which we can also use to check its validity): We get the same series if we expand 2 directly (which we can also use to check its validity):
```{haskell} ```{haskell}
cendree2DivMod15Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 15 (carry2 divMod 2) 2 cendree2DivMod15Steps = map (pairEval (sqrt 3 + 1)) $
expandSteps 15 (carry2QR divMod 2) 2
putStrLn . unlines . map show $ cendree2DivMod15Steps putStrLn . unlines . map show $ cendree2DivMod15Steps
``` ```
@ -117,7 +198,8 @@ We can *also* use this to get a series for negative one, a number which has a te
in the balanced alphabet. in the balanced alphabet.
```{haskell} ```{haskell}
cendreeNeg1DivMod15Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 15 (carry2 divMod 2) (-1) cendreeNeg1DivMod15Steps = map (pairEval (sqrt 3 + 1)) $
expandSteps 15 (carry2QR divMod 2) (-1)
putStrLn . unlines . map show $ cendreeNeg1DivMod15Steps putStrLn . unlines . map show $ cendreeNeg1DivMod15Steps
``` ```
@ -126,8 +208,9 @@ If we take the last iterate of this, increment the zeroth place value, and apply
we find that everything clears properly. we find that everything clears properly.
```{haskell} ```{haskell}
cendree0FromNeg1DivMod = (\(x:xs) -> (x + 1):xs) $ snd $ last cendreeNeg1DivMod15Steps cendree0FromNeg1DivMod = (\(x:xs) -> (x + 1):xs) $ fst $ last cendreeNeg1DivMod15Steps
cendree0IncrementSteps = map (pairEval (sqrt 3 + 1)) $ take 15 $ iterate (carry2 divMod 2) cendree0FromNeg1DivMod cendree0IncrementSteps = map (pairEval (sqrt 3 + 1)) $ take 15 $
iterate (carry2QR divMod 2) cendree0FromNeg1DivMod
putStrLn . unlines . map show $ cendree0IncrementSteps putStrLn . unlines . map show $ cendree0IncrementSteps
``` ```
@ -158,14 +241,17 @@ You should definitely see [this page](/interactive/adic/) for more information,
First, notice that with $b = 2$ and $p = 2$, switching between the "b-adic" option First, notice that with $b = 2$ and $p = 2$, switching between the "b-adic" option
and the "*κ*-adic" option appears cause some points to appear and disappear. and the "*κ*-adic" option appears cause some points to appear and disappear.
This is easiest to see when $c \approx 0.5$. It is easiest to see this when $c \approx 0.5$.
This corresponds with the intuition that these are subsets of the 2- and 3-adics.
Next, notice that when plotting the *κ*-adics, some self-similarity different from the 2- and 3-adics Next, notice that when plotting the *κ*-adics, there is some self-similarity different
can be observed for $c \approx 0.75$. from the 2- and 3-adics.
There appear to be four clusters of points, with the topmost and rightmost appearing to be To see this, try setting $c \approx 0.75$.
similar to one another. There appear to be four clusters, with the topmost and rightmost appearing to be similar to one another.
Within these two clusters, the rightmost portion of them appears to be the same shape Within these two clusters, the rightmost portion of them appears to be the same shape
as the larger figure. as the larger figure.
If you try switching between the *κ*-adic options, you can even see the smaller
and larger shapes changing in the same way as one another.
This is actually great news -- if you switch between the *κ*-adics and the "random binary" option, This is actually great news -- if you switch between the *κ*-adics and the "random binary" option,
you can see that the latter option tends to the same pattern as the 2-adics. you can see that the latter option tends to the same pattern as the 2-adics.