revisions for 4.appendix
This commit is contained in:
parent
e5946df6ec
commit
fd57fa066e
@ -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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user