add interactive section to 4.appendix
This commit is contained in:
parent
9786cb0f61
commit
e5946df6ec
1024
posts/polycount/4/appendix/cendree_DivMod_count_1024_256_digits.csv
Normal file
1024
posts/polycount/4/appendix/cendree_DivMod_count_1024_256_digits.csv
Normal file
File diff suppressed because it is too large
Load Diff
1024
posts/polycount/4/appendix/cendree_QuotRem_count_1024_256_digits.csv
Normal file
1024
posts/polycount/4/appendix/cendree_QuotRem_count_1024_256_digits.csv
Normal file
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,8 @@ date: "2021-02-09"
|
|||||||
date-modified: "2025-02-12"
|
date-modified: "2025-02-12"
|
||||||
categories:
|
categories:
|
||||||
- algebra
|
- algebra
|
||||||
- python
|
- haskell
|
||||||
|
- interactive
|
||||||
execute:
|
execute:
|
||||||
eval: false
|
eval: false
|
||||||
---
|
---
|
||||||
@ -30,7 +31,7 @@ A more unusual consequence of this is that despite the initial choice of alphabe
|
|||||||
[negative numerals could be cleared](../#all-positive)
|
[negative numerals could be cleared](../#all-positive)
|
||||||
from the expansion by using an extra-greedy borrow.
|
from the expansion by using an extra-greedy borrow.
|
||||||
|
|
||||||
These choices actually only differ in only one significant way: the choice of integer division function.
|
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:
|
In Haskell, there exists both `quotRem` and `divMod`, with the two disagreeing on negative remainders:
|
||||||
|
|
||||||
::: {.row layout-ncol="2"}
|
::: {.row layout-ncol="2"}
|
||||||
@ -43,13 +44,13 @@ divMod (-27) 5
|
|||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
We can factor our choice out of our two digit-wide carry function by presenting it as an argument:
|
We can factor our choice out of our two digit-wide carry function by passing it as an argument:
|
||||||
|
|
||||||
```{haskell}
|
```{haskell}
|
||||||
-- Widened carry of a particular repeated amount
|
-- Widened carry of a particular repeated amount
|
||||||
-- i.e., for carry qr 2, the carry is 22 = 100
|
-- i.e., for carry qr 2, the carry is 22 = 100
|
||||||
carry2' qr b = carry' []
|
carry2 qr b = carry2' []
|
||||||
where carry' zs (x:y:z:xs)
|
where carry2' zs (x:y:z:xs)
|
||||||
| q == 0 = carry' (x:zs) (y:z:xs) -- try carrying at a higher place value
|
| q == 0 = carry' (x:zs) (y:z:xs) -- try carrying at a higher place value
|
||||||
| otherwise = foldl (flip (:)) ys zs -- carry here
|
| otherwise = foldl (flip (:)) ys zs -- carry here
|
||||||
where ys = r : y-x+r : z+q : xs
|
where ys = r : y-x+r : z+q : xs
|
||||||
@ -61,8 +62,8 @@ We happen to know the root for $\langle 2, 2|$ is $\sqrt 3 + 1$, so using an app
|
|||||||
we can check that we get a roughly constant value by evaluating at each step.
|
we can check that we get a roughly constant value by evaluating at each step.
|
||||||
|
|
||||||
```{haskell}
|
```{haskell}
|
||||||
{-| layout-ncol: 2 -}
|
-- | layout-ncol: 2
|
||||||
{-| code-fold: true -}
|
-- | code-fold: true
|
||||||
|
|
||||||
import IHaskell.Display
|
import IHaskell.Display
|
||||||
|
|
||||||
@ -74,8 +75,8 @@ pairEval x = (,) <*> hornerEval x . map fromIntegral
|
|||||||
-- Directly expand the integer `n`, using the `carry` showing each step for `count` steps
|
-- 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
|
expandSteps count carry n = take count $ iterate carry $ n:replicate count 0
|
||||||
|
|
||||||
cendree4QuotRem10Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2' quotRem 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
|
cendree4DivMod10Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2 divMod 2) 4
|
||||||
|
|
||||||
markdown "`quotRem`"
|
markdown "`quotRem`"
|
||||||
markdown "`divMod`"
|
markdown "`divMod`"
|
||||||
@ -101,14 +102,14 @@ 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 (carry2 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 (carry2 divMod 2) 2
|
||||||
putStrLn . unlines . map show $ cendree2DivMod15Steps
|
putStrLn . unlines . map show $ cendree2DivMod15Steps
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -116,7 +117,7 @@ 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 (carry2 divMod 2) (-1)
|
||||||
putStrLn . unlines . map show $ cendreeNeg1DivMod15Steps
|
putStrLn . unlines . map show $ cendreeNeg1DivMod15Steps
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -126,7 +127,7 @@ If we take the last iterate of this, increment the zeroth place value, and apply
|
|||||||
|
|
||||||
```{haskell}
|
```{haskell}
|
||||||
cendree0FromNeg1DivMod = (\(x:xs) -> (x + 1):xs) $ snd $ last cendreeNeg1DivMod15Steps
|
cendree0FromNeg1DivMod = (\(x:xs) -> (x + 1):xs) $ snd $ last cendreeNeg1DivMod15Steps
|
||||||
cendree0IncrementSteps = map (pairEval (sqrt 3 + 1)) $ take 15 $ iterate (carry2' divMod 2) cendree0FromNeg1DivMod
|
cendree0IncrementSteps = map (pairEval (sqrt 3 + 1)) $ take 15 $ iterate (carry2 divMod 2) cendree0FromNeg1DivMod
|
||||||
|
|
||||||
putStrLn . unlines . map show $ cendree0IncrementSteps
|
putStrLn . unlines . map show $ cendree0IncrementSteps
|
||||||
```
|
```
|
||||||
@ -139,27 +140,34 @@ Actually demonstrating this and proving it is left as an exercise.
|
|||||||
Are these really -adic?
|
Are these really -adic?
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
Perhaps it is still unconvincing that expanding the integers in this way gives something that is
|
Perhaps it is still unconvincing that expanding the integers in this way gives something
|
||||||
indeed related to *p*-adics.
|
indeed related to *p*-adics.
|
||||||
The Wikipedia article on the [*p*-adic valuation](https://en.wikipedia.org/wiki/P-adic_valuation)
|
In fact, since the expansions are in binary or (balanced) ternary, the integers should just
|
||||||
contains [a figure](https://commons.wikimedia.org/wiki/File:2adic12480.svg) whose description
|
be a subset of the 2-adics or 3-adics.
|
||||||
provides a way to map *p*-adics into the complex numbers[^1].
|
|
||||||
The gist is to construct a Fourier series over truncations of numbers.
|
|
||||||
Each term of the series is weighted by a geometrically decreasing coefficient *c*.
|
|
||||||
|
|
||||||
$$
|
Still, wanted to see what these numbers actually "look" like, so I whipped up an interactive diagram.
|
||||||
[...d_2 d_1 d_0]_p \mapsto e^{2\pi i [d_0] / p}
|
You should definitely see [this page](/interactive/adic/) for more information, but
|
||||||
+ c e^{2\pi i [d_1 d_0] / p^2}
|
the gist is that *p*-adics can be sent into the complex plane in a fractal-like way.
|
||||||
+ c^2 e^{2\pi i [d_2 d_1 d_0] / p^2}
|
|
||||||
+ ... \\
|
|
||||||
f(d; p) = \sum_{n = 0}^N c^n e^{2\pi i \cdot [d_{n:0}] / p^{n + 1}}
|
|
||||||
$$
|
|
||||||
|
|
||||||
Assuming the first term dominates, one way of interpreting this is that we place numbers
|
|
||||||
around the unit circle according to their one's place.
|
|
||||||
Then, we offset each by smaller circles, each centered on the last, using more and more digits.
|
|
||||||
This produces a fractal pattern that looks like a wheel with *p* spokes.
|
|
||||||
At each point on where the spokes meet the rim, there is another wheel with *p* spokes, ad infinitum.
|
|
||||||
|
|
||||||
[^1]: Taken from the paper "Fractal geometry for images of continuous embeddings of p-adic
|
```{ojs}
|
||||||
numbers and solenoids into Euclidean spaces" (DOI: 10.1007/BF02073866).
|
// | echo: false
|
||||||
|
|
||||||
|
{{< include ./showAdicWithKappa.ojs >}}
|
||||||
|
```
|
||||||
|
|
||||||
|
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$.
|
||||||
|
|
||||||
|
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.
|
||||||
|
Within these two clusters, the rightmost portion of them appears to be the same shape
|
||||||
|
as the larger figure.
|
||||||
|
|
||||||
|
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.
|
||||||
|
Thus, even if the expansions for the integers are individually chaotic, together they possess a
|
||||||
|
much different structure than pure randomness.
|
||||||
|
|||||||
66
posts/polycount/4/appendix/showAdicWithKappa.ojs
Normal file
66
posts/polycount/4/appendix/showAdicWithKappa.ojs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
FileAttachments:
|
||||||
|
./cendree_DivMod_count_1024_256_digits.csv: ./cendree_DivMod_count_1024_256_digits.csv
|
||||||
|
./cendree_QuotRem_count_1024_256_digits.csv: ./cendree_QuotRem_count_1024_256_digits.csv
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Import expansions from file.
|
||||||
|
// Odd numbers are injected by replacing the first entry of each row with "1"
|
||||||
|
asIntegers = (x) => {
|
||||||
|
let xs = x.split("\n").map((y) => y.split(",").map((z) => +z))
|
||||||
|
return [...xs, ...(xs.map((ys) => ys.with(0, 1)))]
|
||||||
|
};
|
||||||
|
|
||||||
|
adicExpansionsDivMod = FileAttachment(
|
||||||
|
"./cendree_DivMod_count_1024_256_digits.csv"
|
||||||
|
).text().then(asIntegers);
|
||||||
|
adicExpansionsQuotRem = FileAttachment(
|
||||||
|
"./cendree_QuotRem_count_1024_256_digits.csv"
|
||||||
|
).text().then(asIntegers);
|
||||||
|
|
||||||
|
import { expansions as oldExpansions } with { base as base } from "../../../../interactive/p-adics/showAdic.ojs";
|
||||||
|
|
||||||
|
expansionsOrAdics = baseSelector == "b-adic"
|
||||||
|
? oldExpansions
|
||||||
|
: baseSelector == "κ-adic, balanced"
|
||||||
|
? adicExpansionsDivMod
|
||||||
|
: baseSelector == "κ-adic, binary"
|
||||||
|
? adicExpansionsQuotRem
|
||||||
|
: d3.range(adicExpansionsQuotRem.length / 10).map(() => d3.range(15).map(() => +(Math.random() > 0.5)))
|
||||||
|
|
||||||
|
import { plot } with {
|
||||||
|
expansionsOrAdics as expansions,
|
||||||
|
embedBase as embedBase,
|
||||||
|
geometric as geometric,
|
||||||
|
} from "../../../../interactive/p-adics/showAdic.ojs";
|
||||||
|
|
||||||
|
viewof baseSelector = Inputs.radio([
|
||||||
|
"b-adic",
|
||||||
|
"κ-adic, balanced",
|
||||||
|
"κ-adic, binary",
|
||||||
|
"Random Binary",
|
||||||
|
], {
|
||||||
|
value: "b-adic",
|
||||||
|
label: "Expansions",
|
||||||
|
});
|
||||||
|
|
||||||
|
viewof base = Inputs.range([2, 5], {
|
||||||
|
value: 2,
|
||||||
|
step: 1,
|
||||||
|
label: "Base of expansions (b)",
|
||||||
|
disabled: baseSelector != "b-adic",
|
||||||
|
});
|
||||||
|
|
||||||
|
viewof embedBase = Inputs.range([2, 5], {
|
||||||
|
value: 2,
|
||||||
|
step: 0.1,
|
||||||
|
label: "Embedding base (p)",
|
||||||
|
});
|
||||||
|
|
||||||
|
viewof geometric = Inputs.range([0.005, 0.995], {
|
||||||
|
value: 0.9,
|
||||||
|
step: 0.005,
|
||||||
|
label: "Geometric ratio (c)",
|
||||||
|
});
|
||||||
|
|
||||||
|
plot
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import Data.List (intercalate)
|
||||||
|
|
||||||
-- Widened borrow of a particular repeated amount
|
-- Widened borrow of a particular repeated amount
|
||||||
-- i.e., for borrow2 qr 2, the borrow is 22 = 100
|
-- i.e., for borrow2 qr 2, the borrow is 22 = 100
|
||||||
-- `qr` is an integer division function returning the quotient and remainder.
|
-- `qr` is an integer division function returning the quotient and remainder.
|
||||||
@ -65,7 +67,11 @@ data QRMethod = QuotRem | DivMod deriving Show
|
|||||||
qrMethod QuotRem = quotRem
|
qrMethod QuotRem = quotRem
|
||||||
qrMethod DivMod = divMod
|
qrMethod DivMod = divMod
|
||||||
|
|
||||||
cendreeEvens :: QRMethod -> Int -> Int -> IO ()
|
cendreeEvens' :: QRMethod -> Int -> Int -> [[Int]]
|
||||||
cendreeEvens qr m n = writeFile fn $ unlines $ take m $ map show $ evensQR qr' n 2 $ truncadicQR qr' (n + 2) 2 $ 2:repeat 0
|
cendreeEvens' qr m n = take m $ evensQR qr' n 2 $ truncadicQR qr' (n + 2) 2 $ 2:repeat 0
|
||||||
where qr' = qrMethod qr
|
where qr' = qrMethod qr
|
||||||
fn = "cendree_" ++ show qr ++ "_count_" ++ show m ++ "_" ++ show n ++ "_digits.txt"
|
|
||||||
|
cendreeEvens :: QRMethod -> Int -> Int -> IO ()
|
||||||
|
cendreeEvens qr m n = writeFile fn $ display $ cendreeEvens' qr m n
|
||||||
|
where display = unlines . map (intercalate "," . map show)
|
||||||
|
fn = "cendree_" ++ show qr ++ "_count_" ++ show m ++ "_" ++ show n ++ "_digits.csv"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user