feat: add tools script to find interesting places
This commit is contained in:
+1
-1
@@ -3,4 +3,4 @@ Cargo.lock
|
|||||||
dist
|
dist
|
||||||
frames*
|
frames*
|
||||||
out.mp4
|
out.mp4
|
||||||
|
__pycache__
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
# Deep-zoom locations
|
||||||
|
|
||||||
|
Beautiful deep Mandelbrot locations, all computed with `find_deep.py` and checked with a
|
||||||
|
`--headless` render. Every one is an exact minibrot nucleus (Newton's method at
|
||||||
|
`2·depth + 60` digits), not a coordinate copied from somewhere, so the digits are right all
|
||||||
|
the way down.
|
||||||
|
|
||||||
|
## How to use them
|
||||||
|
|
||||||
|
Each location has two views on the same centre:
|
||||||
|
|
||||||
|
- **Minibrot:** half-height ≈ 3× the minibrot's size. A tiny copy of the whole set sits in
|
||||||
|
concentric colour bands, and there are more bands the deeper it is.
|
||||||
|
- **Embedded Julia set:** half-height ≈ size^0.75, about ¾ of the way down in log-zoom.
|
||||||
|
This is where each location looks unique. The minibrots all look alike.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo run --release -- --view=RE,IM,HALF_HEIGHT # interactive
|
||||||
|
cargo run --release -- --headless --view=RE,IM,HALF_HEIGHT --export-path shot.png
|
||||||
|
# zoom video from the full set down to a minibrot, piped to ffmpeg (see Makefile):
|
||||||
|
cargo run --release -- --headless --view=-0.75,0,1.5 --to-view=RE,IM,HALF_HEIGHT \
|
||||||
|
--fps 60 --duration 60 --export-path - | make hevc-nvenc
|
||||||
|
```
|
||||||
|
|
||||||
|
Pass negative coordinates as `--view=-0.77...` (with the `=`): clap would read `--view -0.77...` as a flag.
|
||||||
|
Iterations scale with depth automatically (about 90k at 10⁻¹⁰⁰ and 270k at 10⁻³⁰⁰), which is
|
||||||
|
enough for these periods.
|
||||||
|
|
||||||
|
## Infinite spirals (Misiurewicz points)
|
||||||
|
|
||||||
|
These are the anchor points. Zoom straight into one and the same spiral repeats forever,
|
||||||
|
at any depth. Every minibrot below sits just beside one of them.
|
||||||
|
|
||||||
|
| Region | Point | Preperiod, period | Looks like |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Seahorse valley | `-0.7756837680090537974694835039347410457282465046158` `0.13646736829469012473327440961784876519777211159247` | 24, 2 | Two-armed spirals of seahorses, repeating at every depth. |
|
||||||
|
| Elephant valley | `0.29207386191445391799971751769220573408040189143315` `0.015770917211390118082469028230338337682600488632339` | 32, 3 | Three-armed spirals of elephant trunks. |
|
||||||
|
| Top antenna | `-0.10110375797210418675706890936004723524958119917843` `0.95629400795235409290719434118824484558046591980423` | 38, 4 | Four-armed branch points on the upper antenna, with thin dendrites instead of spirals. |
|
||||||
|
|
||||||
|
## Seahorse valley
|
||||||
|
|
||||||
|
### Seahorse valley, minibrot at 3.7e-41 (period 1034)
|
||||||
|
|
||||||
|
The embedded Julia set is a pale double spiral: two S-shaped arms of tiny seahorses wind into a bright centre, with a third lace band sweeping around them. The best one for a short video, and it renders in seconds.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# embedded Julia set
|
||||||
|
--view=-0.77568376800905379745347652613832924487504096622022,0.13646736829469012473375311880735014411233827361594,1e-30
|
||||||
|
# minibrot
|
||||||
|
--view=-0.77568376800905379745347652613832924487504096622022,0.13646736829469012473375311880735014411233827361594,1.1e-40
|
||||||
|
```
|
||||||
|
|
||||||
|
### Seahorse valley, minibrot at 1.14e-101 (period 2868)
|
||||||
|
|
||||||
|
At the Julia depth there's a dark blue field with a glowing core and lace threads crossing it.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# embedded Julia set
|
||||||
|
--view=-0.77568376800905379746948350393474104572824650461579342765769586746577714101553375163935420167637213972439444483,0.13646736829469012473327440961784876519777211159246218448277041663416833530840062457397927487282583495378053495,1e-76
|
||||||
|
# minibrot
|
||||||
|
--view=-0.77568376800905379746948350393474104572824650461579342765769586746577714101553375163935420167637213972439444483,0.13646736829469012473327440961784876519777211159246218448277041663416833530840062457397927487282583495378053495,3.4e-101
|
||||||
|
```
|
||||||
|
|
||||||
|
### Seahorse valley, minibrot at 1.37e-200 (period 5895)
|
||||||
|
|
||||||
|
Two filaments cross in an X over a warm brown background, with a small dark spiral where they meet.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# embedded Julia set
|
||||||
|
--view=-0.77568376800905379746948350393474104572824650461580039479495200140066601722281958989488315936878225494657853849784368247991666558116221905228489656259693587754973261632614186930985854124920967267440737850057557,0.13646736829469012473327440961784876519777211159246769640780019540083566597481550087544861124417865661202932094564677695883049019713653069907950852152823160218141353878979871215911794286224832089496659451498185,1e-150
|
||||||
|
# minibrot
|
||||||
|
--view=-0.77568376800905379746948350393474104572824650461580039479495200140066601722281958989488315936878225494657853849784368247991666558116221905228489656259693587754973261632614186930985854124920967267440737850057557,0.13646736829469012473327440961784876519777211159246769640780019540083566597481550087544861124417865661202932094564677695883049019713653069907950852152823160218141353878979871215911794286224832089496659451498185,4.1e-200
|
||||||
|
```
|
||||||
|
|
||||||
|
### Seahorse valley, minibrot at 1.83e-300 (period 8922)
|
||||||
|
|
||||||
|
Faint cream threads, and a spiral wound so tight it reads as a point. Period 8922, so the minibrot needs a long render.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# embedded Julia set
|
||||||
|
--view=-0.775683768009053797469483503934741045728246504615800394794952001400666017222819589894883159368782255028252296689050972508942991790804637379375064948276511044167168394677127466362472192356953918438738697548775738756167744421444715134058363508346750264411321139485834882343906172015818621107808449401958194265462,0.136467368294690124733274409617848765197772111592467696407800195400835665974815500875448611244178656625706823059759836009902469392551108149827753781145338163746214967880988693412636771323356061132825037923307975359146666033691080243216637006179374407866237575096209504710178751614036006531433101633993532313930,1e-225
|
||||||
|
# minibrot
|
||||||
|
--view=-0.775683768009053797469483503934741045728246504615800394794952001400666017222819589894883159368782255028252296689050972508942991790804637379375064948276511044167168394677127466362472192356953918438738697548775738756167744421444715134058363508346750264411321139485834882343906172015818621107808449401958194265462,0.136467368294690124733274409617848765197772111592467696407800195400835665974815500875448611244178656625706823059759836009902469392551108149827753781145338163746214967880988693412636771323356061132825037923307975359146666033691080243216637006179374407866237575096209504710178751614036006531433101633993532313930,5.5e-300
|
||||||
|
```
|
||||||
|
|
||||||
|
## Elephant valley
|
||||||
|
|
||||||
|
### Elephant valley, minibrot at 1.29e-100 (period 782)
|
||||||
|
|
||||||
|
A cream-coloured double S-spiral, like the seahorse one but with fatter, beaded arms.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# embedded Julia set
|
||||||
|
--view=0.2920738619144539179997175176922057340804018914331633820622644536373359023331882946705674169275530423410817910,0.01577091721139011808246902823033833768260048863232968822435568049949556139801802963232184866659058960379114747,1e-75
|
||||||
|
# minibrot
|
||||||
|
--view=0.2920738619144539179997175176922057340804018914331633820622644536373359023331882946705674169275530423410817910,0.01577091721139011808246902823033833768260048863232968822435568049949556139801802963232184866659058960379114747,3.9e-100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Elephant valley, minibrot at 1.43e-199 (period 1585)
|
||||||
|
|
||||||
|
A single huge spiral arm made of blue beads curling across the whole frame.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# embedded Julia set
|
||||||
|
--view=0.2920738619144539179997175176922057340804018914331538397786950546981063169810374784665382516408545756138262706218874924432355556243165250541700374639889797148498919340003273815669351046658761147565052417000965,0.01577091721139011808246902823033833768260048863233880759961760295375606839216565332458201188913912642954367433579737643167232896069795830226759356080847862646789481028238105648099709502522309228500630759855757,1e-149
|
||||||
|
# minibrot
|
||||||
|
--view=0.2920738619144539179997175176922057340804018914331538397786950546981063169810374784665382516408545756138262706218874924432355556243165250541700374639889797148498919340003273815669351046658761147565052417000965,0.01577091721139011808246902823033833768260048863233880759961760295375606839216565332458201188913912642954367433579737643167232896069795830226759356080847862646789481028238105648099709502522309228500630759855757,4.3e-199
|
||||||
|
```
|
||||||
|
|
||||||
|
### Elephant valley, minibrot at 3.82e-300 (period 2395)
|
||||||
|
|
||||||
|
A spiral galaxy: several beaded arms around a pinwheel centre. One of the prettiest frames here.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# embedded Julia set
|
||||||
|
--view=0.292073861914453917999717517692205734080401891433153839778695054698106316981037478466538251640854575589843066619974864800862332115945960921998657430606126553202998390050225413256445451049563878137878839982267258218894836912449161037745627504826537881261626243871678392881757578278459983842286413975991353319739,0.0157709172113901180824690282303383376826004886323388075996176029537560683921656533245820118891391263013273917522825544701901299061542128984468742890308365571942081484001405437827548345359998503228665872823816067983725089244499770271352539008763406229496083105636482420467114597267096082878888045800333807911146,1e-225
|
||||||
|
# minibrot
|
||||||
|
--view=0.292073861914453917999717517692205734080401891433153839778695054698106316981037478466538251640854575589843066619974864800862332115945960921998657430606126553202998390050225413256445451049563878137878839982267258218894836912449161037745627504826537881261626243871678392881757578278459983842286413975991353319739,0.0157709172113901180824690282303383376826004886323388075996176029537560683921656533245820118891391263013273917522825544701901299061542128984468742890308365571942081484001405437827548345359998503228665872823816067983725089244499770271352539008763406229496083105636482420467114597267096082878888045800333807911146,1.1e-299
|
||||||
|
```
|
||||||
|
|
||||||
|
## Top antenna
|
||||||
|
|
||||||
|
### Top antenna, minibrot at 6.11e-101 (period 245)
|
||||||
|
|
||||||
|
A dark branching dendrite like a frost cross, with four-way junctions.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# embedded Julia set
|
||||||
|
--view=-0.10110375797210418675706890936004723524958119917842627217950669362738928440088634862532432662296073501093701563,0.95629400795235409290719434118824484558046591980423293884325556254155313535666457147658005358708674409029391915,1e-75
|
||||||
|
# minibrot
|
||||||
|
--view=-0.10110375797210418675706890936004723524958119917842627217950669362738928440088634862532432662296073501093701563,0.95629400795235409290719434118824484558046591980423293884325556254155313535666457147658005358708674409029391915,1.8e-100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Top antenna, minibrot at 5.28e-200 (period 473)
|
||||||
|
|
||||||
|
A chain of six-armed snowflakes linked by thin filaments.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# embedded Julia set
|
||||||
|
--view=-0.10110375797210418675706890936004723524958119917842839398761868801597328463328677019373309617158827470368429189213012997868613724029746440432852247903869013157556141380437202406412221853553594880182186959159214,0.95629400795235409290719434118824484558046591980423399388630140415938010604675760901574969597486831722998038561988250849596064882005832681021199867736493316924923123916964900533995659228499205141785254396348248,1e-149
|
||||||
|
# minibrot
|
||||||
|
--view=-0.10110375797210418675706890936004723524958119917842839398761868801597328463328677019373309617158827470368429189213012997868613724029746440432852247903869013157556141380437202406412221853553594880182186959159214,0.95629400795235409290719434118824484558046591980423399388630140415938010604675760901574969597486831722998038561988250849596064882005832681021199867736493316924923123916964900533995659228499205141785254396348248,1.6e-199
|
||||||
|
```
|
||||||
|
|
||||||
|
### Top antenna, minibrot at 8.34e-301 (period 705)
|
||||||
|
|
||||||
|
A single twelve-armed star, very symmetric. The antenna minibrots have short periods (245-705), so these are the fastest deep renders.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# embedded Julia set
|
||||||
|
--view=-0.1011037579721041867570689093600472352495811991784283939876186880159732846332867701937330961715882746718394428627914481009391257007785408536971203165750666758077852384490279260184029373211737264310068845597273991782305778295187471341711226626762421910644338164121042775094463557363347706110614218633830535086184,0.9562940079523540929071943411882448455804659198042339938863014041593801060467576090157496959748683171680339080646917869452781885502668216669916185990922330667568398963038228431738928191227884090004548615469303071899797403388188723954061899156655653387543351937028936674153437083087070219108726088551230849901498,1e-225
|
||||||
|
# minibrot
|
||||||
|
--view=-0.1011037579721041867570689093600472352495811991784283939876186880159732846332867701937330961715882746718394428627914481009391257007785408536971203165750666758077852384490279260184029373211737264310068845597273991782305778295187471341711226626762421910644338164121042775094463557363347706110614218633830535086184,0.9562940079523540929071943411882448455804659198042339938863014041593801060467576090157496959748683171680339080646917869452781885502668216669916185990922330667568398963038228431738928191227884090004548615469303071899797403388188723954061899156655653387543351937028936674153437083087070219108726088551230849901498,2.5e-300
|
||||||
|
```
|
||||||
|
|
||||||
|
## Finding more
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./find_deep.py --list # known regions
|
||||||
|
./find_deep.py seahorse 250 # minibrot of size ~1e-500 near the seahorse point
|
||||||
|
./find_deep.py seahorse 100 0.2,0.7 # a different minibrot at the same depth
|
||||||
|
./find_deep.py -0.1011,0.9563,38,4 80 # any Misiurewicz point, given as re,im,k,p
|
||||||
|
```
|
||||||
|
|
||||||
|
A disk of radius 10⁻ᴰ around a Misiurewicz point holds a minibrot of size about 10⁻²ᴰ.
|
||||||
|
Newton sometimes fails to converge (elephant at depth 100 with the default offset did). The
|
||||||
|
script detects this from the size and asks for a different offset. Needs `mpmath`.
|
||||||
Executable
+145
@@ -0,0 +1,145 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Find deep Mandelbrot minibrots near a Misiurewicz point.
|
||||||
|
|
||||||
|
Misiurewicz points (preperiodic c, f^(k+p)(0) = f^k(0)) have self-similar
|
||||||
|
spirals at every depth. A disk of radius r = 10^-D around one contains a
|
||||||
|
minibrot of size ~r^2, found by:
|
||||||
|
|
||||||
|
1. the ball-period method: the first n where the disk's image covers 0
|
||||||
|
gives the period p of a nucleus inside it;
|
||||||
|
2. Newton's method on f^p(0) = 0 at high precision for the nucleus;
|
||||||
|
3. the standard size estimate (Heiland-Allen) for its scale.
|
||||||
|
|
||||||
|
Zooming at the nucleus shows spirals, then an embedded Julia set (around
|
||||||
|
size^0.75), then the minibrot (half-height ~3x size).
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
find_deep.py REGION DEPTH [OFFSET_RE,OFFSET_IM]
|
||||||
|
find_deep.py --list
|
||||||
|
|
||||||
|
REGION is a name from REGIONS or "re,im,k,p" for any Misiurewicz point.
|
||||||
|
OFFSET (default 0.6,0.3, in units of r) picks a different minibrot at the
|
||||||
|
same depth. If the printed size is far below 10^-(2*DEPTH), Newton didn't
|
||||||
|
converge: try another offset.
|
||||||
|
|
||||||
|
Needs mpmath (pip install mpmath).
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from mpmath import log10, mp, mpc, mpf
|
||||||
|
|
||||||
|
# name: (approximate seed, preperiod k, period p). The exact point is
|
||||||
|
# refined by Newton at the requested precision.
|
||||||
|
REGIONS = {
|
||||||
|
"seahorse": (("-0.77568377", "0.13646737"), 24, 2),
|
||||||
|
"elephant": (("0.2925", "0.0149"), 32, 3),
|
||||||
|
"antenna": (("-0.1011", "0.9563"), 38, 4),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def converged(d):
|
||||||
|
return abs(d) < mpf(10) ** (-mp.dps + 20)
|
||||||
|
|
||||||
|
|
||||||
|
def misiurewicz(c, k, p, steps=200):
|
||||||
|
"""Newton on f^(k+p)(0) - f^k(0) = 0."""
|
||||||
|
for _ in range(steps):
|
||||||
|
z = dz = mpc(0)
|
||||||
|
zk = dzk = None
|
||||||
|
for i in range(1, k + p + 1):
|
||||||
|
dz = 2 * z * dz + 1
|
||||||
|
z = z * z + c
|
||||||
|
if i == k:
|
||||||
|
zk, dzk = z, dz
|
||||||
|
d = (z - zk) / (dz - dzk)
|
||||||
|
c -= d
|
||||||
|
if converged(d):
|
||||||
|
break
|
||||||
|
return c
|
||||||
|
|
||||||
|
|
||||||
|
def period_in_ball(c, r, maxit=1_000_000):
|
||||||
|
"""First n where the disk of radius r around c maps onto a disk containing 0."""
|
||||||
|
z = dz = mpc(0)
|
||||||
|
for n in range(1, maxit):
|
||||||
|
dz = 2 * z * dz + 1
|
||||||
|
z = z * z + c
|
||||||
|
if abs(z) < abs(dz) * r:
|
||||||
|
return n
|
||||||
|
if abs(z) > 4:
|
||||||
|
return None
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def nucleus(c, p, steps=200):
|
||||||
|
"""Newton on f^p(0) = 0."""
|
||||||
|
for _ in range(steps):
|
||||||
|
z = dz = mpc(0)
|
||||||
|
for _ in range(p):
|
||||||
|
dz = 2 * z * dz + 1
|
||||||
|
z = z * z + c
|
||||||
|
d = z / dz
|
||||||
|
c -= d
|
||||||
|
if converged(d):
|
||||||
|
break
|
||||||
|
return c
|
||||||
|
|
||||||
|
|
||||||
|
def size(c, p):
|
||||||
|
"""Approximate size of the minibrot with nucleus c and period p."""
|
||||||
|
z = mpc(0)
|
||||||
|
l = b = mpc(1)
|
||||||
|
for _ in range(1, p):
|
||||||
|
z = z * z + c
|
||||||
|
l = 2 * z * l
|
||||||
|
b = b + 1 / l
|
||||||
|
return abs(1 / (b * l * l))
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
if len(argv) >= 1 and argv[0] == "--list":
|
||||||
|
for name, ((re, im), k, p) in REGIONS.items():
|
||||||
|
print(f"{name:10} ~{re}{'+' if not im.startswith('-') else ''}{im}i M({k},{p})")
|
||||||
|
return 0
|
||||||
|
if len(argv) not in (2, 3):
|
||||||
|
print(__doc__, file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
region, depth = argv[0], int(argv[1])
|
||||||
|
if region in REGIONS:
|
||||||
|
(re, im), k, p = REGIONS[region]
|
||||||
|
else:
|
||||||
|
re, im, k, p = region.split(",")
|
||||||
|
k, p = int(k), int(p)
|
||||||
|
off_re, off_im = argv[2].split(",") if len(argv) == 3 else ("0.6", "0.3")
|
||||||
|
|
||||||
|
mp.dps = 2 * depth + 60
|
||||||
|
m = misiurewicz(mpc(re, im), k, p)
|
||||||
|
r = mpf(10) ** (-depth)
|
||||||
|
c0 = m + r * mpc(off_re, off_im)
|
||||||
|
period = period_in_ball(c0, r)
|
||||||
|
if period is None:
|
||||||
|
print("no period found (the disk escapes)", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
n = nucleus(c0, period)
|
||||||
|
s = size(n, period)
|
||||||
|
if s < mpf(10) ** (-2 * depth - 10):
|
||||||
|
print(f"size {mp.nstr(s, 3)} is implausibly small: Newton didn't converge, "
|
||||||
|
"try another offset", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
digits = int(-log10(s)) + 10
|
||||||
|
log_s = float(log10(s))
|
||||||
|
re_s = mp.nstr(n.real, digits, strip_zeros=False)
|
||||||
|
im_s = mp.nstr(n.imag, digits, strip_zeros=False)
|
||||||
|
print(f"# {region} depth={depth} period={period} size={mp.nstr(s, 3)}")
|
||||||
|
print("# minibrot:")
|
||||||
|
print(f"--view={re_s},{im_s},{mp.nstr(3 * s, 2)}")
|
||||||
|
print(f"# embedded Julia set on the way down:")
|
||||||
|
print(f"--view={re_s},{im_s},1e{round(0.75 * log_s)}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main(sys.argv[1:]))
|
||||||
Reference in New Issue
Block a user