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"
description: |
Complex embeddings of irrational -adic expansions.
Additional notes on irrational -adic expansions, including complex embeddings thereof.
format:
html:
html-math-method: katex
date: "2021-02-09"
date-modified: "2025-02-12"
date: "2025-03-03"
categories:
- algebra
- haskell
- interactive
execute:
eval: false
---
```{haskell}
-- | echo: false
After converting my original [Two 2's post](../), I found myself much more pleased after making the
diagrams it more reproducible.
import IHaskell.Display
```
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.
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
when expressed as an *κ*-adic integer.
It followed in multiple ways from the repeating expansion of the integer two in the balanced ternary alphabet.
A more unusual consequence of this is that despite the initial choice of alphabet,
[negative numerals could 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:
::: {.row layout-ncol="2"}
```{haskell}
quotRem (-27) 5
```
Let's put this to the test by writing out each step for producing expansions of two and four.
We'll also test these expansions by evaluating them at an approximation of $\kappa = \sqrt 3 + 1$.
We should roughly get two and four at each step.
```{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
-- | 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
hornerEval x = foldr (\c a -> a * x + c) 0
-- Pair a polynomial with its evaluation at x
pairEval x = (,) <*> hornerEval x . map fromIntegral
-- 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
adicTwoSteps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2 2) 2
adicFourSteps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2 2) 4
cendree4QuotRem10Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2 quotRem 2) 4
cendree4DivMod10Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2 divMod 2) 4
markdown "Iteratively carrying \"2\""
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 "`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
negative numbers to show up in our expansions.
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
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}
@ -102,14 +181,16 @@ Since the `divMod` implementation clears negative numbers from expansions, we ca
The result is another chaotic series:
```{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
```
We get the same series if we expand 2 directly (which we can also use to check its validity):
```{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
```
@ -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.
```{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
```
@ -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.
```{haskell}
cendree0FromNeg1DivMod = (\(x:xs) -> (x + 1):xs) $ snd $ last cendreeNeg1DivMod15Steps
cendree0IncrementSteps = map (pairEval (sqrt 3 + 1)) $ take 15 $ iterate (carry2 divMod 2) cendree0FromNeg1DivMod
cendree0FromNeg1DivMod = (\(x:xs) -> (x + 1):xs) $ fst $ last cendreeNeg1DivMod15Steps
cendree0IncrementSteps = map (pairEval (sqrt 3 + 1)) $ take 15 $
iterate (carry2QR divMod 2) cendree0FromNeg1DivMod
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
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
can be observed for $c \approx 0.75$.
There appear to be four clusters of points, with the topmost and rightmost appearing to be
similar to one another.
Next, notice that when plotting the *κ*-adics, there is some self-similarity different
from the 2- and 3-adics.
To see this, try setting $c \approx 0.75$.
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
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,
you can see that the latter option tends to the same pattern as the 2-adics.