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"
|
||||
categories:
|
||||
- algebra
|
||||
- python
|
||||
- haskell
|
||||
- interactive
|
||||
execute:
|
||||
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)
|
||||
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:
|
||||
|
||||
::: {.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}
|
||||
-- Widened carry of a particular repeated amount
|
||||
-- i.e., for carry qr 2, the carry is 22 = 100
|
||||
carry2' qr b = carry' []
|
||||
where carry' zs (x:y:z:xs)
|
||||
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
|
||||
@ -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.
|
||||
|
||||
```{haskell}
|
||||
{-| layout-ncol: 2 -}
|
||||
{-| code-fold: true -}
|
||||
-- | layout-ncol: 2
|
||||
-- | code-fold: true
|
||||
|
||||
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
|
||||
expandSteps count carry n = take count $ iterate carry $ n:replicate count 0
|
||||
|
||||
cendree4QuotRem10Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2' quotRem 2) 4
|
||||
cendree4DivMod10Steps = map (pairEval (sqrt 3 + 1)) $ expandSteps 10 (carry2' divMod 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 "`quotRem`"
|
||||
markdown "`divMod`"
|
||||
@ -101,14 +102,14 @@ 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 (carry2 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 (carry2 divMod 2) 2
|
||||
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.
|
||||
|
||||
```{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
|
||||
```
|
||||
|
||||
@ -126,7 +127,7 @@ If we take the last iterate of this, increment the zeroth place value, and apply
|
||||
|
||||
```{haskell}
|
||||
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
|
||||
```
|
||||
@ -139,27 +140,34 @@ Actually demonstrating this and proving it is left as an exercise.
|
||||
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.
|
||||
The Wikipedia article on the [*p*-adic valuation](https://en.wikipedia.org/wiki/P-adic_valuation)
|
||||
contains [a figure](https://commons.wikimedia.org/wiki/File:2adic12480.svg) whose description
|
||||
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*.
|
||||
In fact, since the expansions are in binary or (balanced) ternary, the integers should just
|
||||
be a subset of the 2-adics or 3-adics.
|
||||
|
||||
$$
|
||||
[...d_2 d_1 d_0]_p \mapsto e^{2\pi i [d_0] / p}
|
||||
+ c e^{2\pi i [d_1 d_0] / p^2}
|
||||
+ 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}}
|
||||
$$
|
||||
Still, wanted to see what these numbers actually "look" like, so I whipped up an interactive diagram.
|
||||
You should definitely see [this page](/interactive/adic/) for more information, but
|
||||
the gist is that *p*-adics can be sent into the complex plane in a fractal-like way.
|
||||
|
||||
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
|
||||
numbers and solenoids into Euclidean spaces" (DOI: 10.1007/BF02073866).
|
||||
```{ojs}
|
||||
// | 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
|
||||
-- i.e., for borrow2 qr 2, the borrow is 22 = 100
|
||||
-- `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 DivMod = divMod
|
||||
|
||||
cendreeEvens :: QRMethod -> Int -> Int -> IO ()
|
||||
cendreeEvens qr m n = writeFile fn $ unlines $ take m $ map show $ evensQR qr' n 2 $ truncadicQR qr' (n + 2) 2 $ 2:repeat 0
|
||||
cendreeEvens' :: QRMethod -> Int -> Int -> [[Int]]
|
||||
cendreeEvens' qr m n = take m $ evensQR qr' n 2 $ truncadicQR qr' (n + 2) 2 $ 2:repeat 0
|
||||
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