Skip to content

Commit 6ea8fb2

Browse files
committed
fixed treeplot() after thanksgiving refactor
1 parent 9997f67 commit 6ea8fb2

File tree

9 files changed

+45
-41
lines changed

9 files changed

+45
-41
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Mandelbrot"
22
uuid = "52854307-bbd1-4ac7-933f-adc0936abe8a"
33
authors = ["Jeffrey Wack"]
4-
version = "0.2.0"
4+
version = "0.3.0"
55

66
[deps]
77
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ This package implements several algorithms related to complex quadratic dynamics
55
- The external angles of a hyperbolic component can be calculated from an angled internal address, describing the path to this component from zero. [Read about internal addresses.](https://arxiv.org/abs/math/9411238)
66
- A combinatorial description of a Hubbard trees can be generated from a kneading sequence, and when oriented in the plane can produce external angles. [Read about Hubbard trees.](https://www.mat.univie.ac.at/~bruin/papers/bkafsch.pdf)
77

8-
This package is a work in progress. Currently, KneadingSequence, AngledInternalAddress, HubbardTree, and OrientedHubbardTree can be constructed. To run the spider algorithm use parameter().
8+
This package is a work in progress. To see what it can do, run treeplot(theta) where theta is a rational number with an odd denominator. The external ray of the Mandelbrot set with angle theta lands at a hyperbolic component, and this will plot the Hubbard tree corresponding to this hyperbolic component. Note that in Julia, rational numbers are declared with two slashes, as "3//5".
99

1010
[![Build Status](https://github.com/jeffwack111/Spiders.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/jeffwack111/Spiders.jl/actions/workflows/CI.yml?query=branch%3Amain)

src/HubbardTrees.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#Henk Bruin, Alexandra Kafll, Dierk Schleicher
44
abstract type AbstractHubbardTree <: Graph end
55

6-
function criticalpoint(H::AbstractHubbardTree)
6+
function criticalpoint(H)
77
return first(filter(x->x[1]==KneadingSymbol('*'),vertices(H)))
88
end
99

@@ -154,8 +154,9 @@ function findone(f,A)
154154
end
155155
end
156156

157-
function isbetween(htree::AbstractHubbardTree,a,b,c)
158-
zero = htree.criticalpoint
157+
#is this for some reason better than a graph search?
158+
function isbetween(htree,a,b,c)
159+
zero = criticalpoint(htree)
159160
K = shift(zero)
160161
(type,vertex) = iteratetriod(K,(a,b,c))
161162
if type == "flat" && vertex == a

src/Mandelbrot.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,4 @@ include("showrays.jl")
4242
include("showspider.jl")
4343
include("showtree.jl")
4444

45-
4645
end

src/angledoubling.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ function numembeddings(theta::Rational)
340340
return numembeddings(internaladdress(theta))
341341
end
342342

343-
function period(theta::Rational)
343+
function period(theta::RationalAngle)
344344
return orbit(theta).period
345345
end
346346

src/dynamicrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function dynamicrays(c::Complex,angle::BinaryExpansion,R::Real,res::Int,depth::I
4646
radii = collect(LinRange(R,sqrt(R),res))
4747

4848
#similar to standard spider but is outer
49-
rays = Sequence{Vector{ComplexF64}}([exp(2im*pi*Rational(theta)).*radii for theta in orb.items],orb.preperiod)
49+
rays = Sequence{Vector{ComplexF64}}([exp(2im*pi*RationalAngle(theta).value).*radii for theta in orb.items],orb.preperiod)
5050

5151
for jj in 1:depth
5252
for (target,source) in goesto(rays)

src/embedtrees.jl

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
struct HyperbolicComponent
2-
criticalpoint::Sequence
3-
adj::Dict{KneadingSequence,Vector{KneadingSequence}}
4-
boundary::Vector{KneadingSequence}
2+
htree::OrientedHubbardTree
53
onezero::Dict{KneadingSequence, Union{Nothing,Digit{2}}}
6-
angle::Rational
4+
angle::RationalAngle
75
rays::Dict{BinaryExpansion,Vector{ComplexF64}}
86
parameter::ComplexF64
97
vertices::Dict{KneadingSequence, ComplexF64} #maps each vertex in the tree to a point in the plane
@@ -17,7 +15,7 @@ function HyperbolicComponent(OHT::OrientedHubbardTree)
1715

1816
criticalorbit = orbit(OHT.criticalpoint) #This is a sequence orbit
1917

20-
theta = Rational(first(criticalanglesof(OZ,OHT)))
18+
theta = RationalAngle(first(criticalanglesof(OZ,OHT)))
2119
c = parameter(standardspider(theta),250)
2220

2321
#critical orbit
@@ -37,8 +35,8 @@ function HyperbolicComponent(OHT::OrientedHubbardTree)
3735
end
3836
end
3937

40-
merge!(rays,dynamicrays(c,BinaryExpansion(1//2),100,10,40))
41-
merge!(rays,dynamicrays(c,BinaryExpansion(0//1),100,10,40))
38+
merge!(rays,dynamicrays(c,BinaryExpansion(RationalAngle(1//2)),100,10,40))
39+
merge!(rays,dynamicrays(c,BinaryExpansion(RationalAngle(0//1)),100,10,40))
4240

4341
paramorbit = [0.0+0.0im]
4442
n = period(theta)
@@ -50,16 +48,24 @@ function HyperbolicComponent(OHT::OrientedHubbardTree)
5048

5149
zvalues = Dict{Sequence,ComplexF64}()
5250
for node in keys(OHT.adj)
53-
if star() in node.items #then it is in the critical orbit
54-
idx = findone(x->x==star(),node.items)
51+
if KneadingSymbol('*') in node.items #then it is in the critical orbit
52+
idx = findone(x->x==KneadingSymbol('*'),node.items)
5553
push!(zvalues,Pair(node,paramorbit[mod1(n-idx+2,n)]))
5654
else
5755
list = [rays[angle][end] for angle in anglelist[node]]
5856
push!(zvalues,Pair(node,sum(list)/length(list)))
5957
end
6058
end
6159
E = standardedges(OHT.adj,OHT.criticalpoint,zvalues)
62-
return HyperbolicComponent(OHT.criticalpoint,OHT.adj,OHT.boundary,OZ,theta,rays,c,zvalues,E)
60+
return HyperbolicComponent(OHT,OZ,theta,rays,c,zvalues,E)
61+
end
62+
63+
function HyperbolicComponent(theta::Rational)
64+
H0 = HyperbolicComponent(OrientedHubbardTree(theta))
65+
for ii in 1:5
66+
refinetree!(H0)
67+
end
68+
return H0
6369
end
6470

6571
function Base.show(io::IO,H::HyperbolicComponent)
@@ -79,8 +85,8 @@ function standardedges(adj,zero,zvalues)
7985
end
8086

8187
function longpath(EHT, start, finish)
82-
nodes = nodepath(EHT.adj, start, finish)
83-
edges = edgepath(EHT.adj, start, finish)
88+
nodes = nodepath(EHT.htree, start, finish)
89+
edges = edgepath(EHT.htree, start, finish)
8490

8591
edgevectors = EHT.edges
8692

src/showtree.jl

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,24 @@ end
44

55
function Makie.plot!(myplot::TreePlot)
66
EHT = myplot.EHT[]
7-
(EdgeList,Nodes) = adjlist(EHT.adj)
8-
criticalorbit = orbit(EHT.criticalpoint)
7+
(EdgeList,Nodes) = adjlist(EHT.htree.adj)
8+
criticalorbit = orbit(EHT.htree.criticalpoint)
99

1010
labels = []
1111
nodecolors = []
1212
for node in Nodes
1313
firstchar = node.items[1]
14-
if firstchar == star()
14+
if firstchar == KneadingSymbol('*')
1515
push!(nodecolors,"black")
16-
elseif firstchar == A() #we are fully in one of the 4 regions
16+
elseif firstchar == KneadingSymbol('A') #we are fully in one of the 4 regions
1717
if EHT.onezero[node] == Digit{2}(0)
1818
push!(nodecolors,"blue")
1919
elseif EHT.onezero[node] === nothing
2020
push!(nodecolors,"turquoise")
2121
elseif EHT.onezero[node] == Digit{2}(1)
2222
push!(nodecolors,"green")
2323
end
24-
elseif firstchar == B()
24+
elseif firstchar == KneadingSymbol('B')
2525
if EHT.onezero[node] == Digit{2}(0)
2626
push!(nodecolors,"red")
2727
elseif EHT.onezero[node] === nothing
@@ -81,6 +81,9 @@ function Makie.plot!(myplot::TreePlot)
8181
return myplot
8282
end
8383

84+
function treeplot(theta::Rational)
85+
return treeplot(HyperbolicComponent(theta))
86+
end
8487

8588
function plottree!(scene, H::HubbardTree)
8689

src/spidermap.jl

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
struct Spider
2-
angle::Rational
3-
orbit::Sequence{Rational}
2+
angle::RationalAngle
3+
orbit::Sequence{RationalAngle}
44
kneading_sequence::KneadingSequence
55
legs::Vector{Vector{ComplexF64}}
66
end
@@ -10,7 +10,7 @@ function Base.show(io::IO, S::Spider)
1010
return println("A "*repr(S.angle)*"-spider with kneading sequence "*repr(S.kneading_sequence)*" and "*repr(npoints)*" points.")
1111
end
1212

13-
function standardspider(theta::Rational)
13+
function standardspider(theta::RationalAngle)
1414
orb = orbit(theta)
1515
K = thetaitinerary(theta,orb) #the kneading sequence is calculated like so to avoid recalculating the orbit of theta
1616
legs = standardlegs(orb)
@@ -21,17 +21,12 @@ function standardlegs(orbit::Sequence)
2121
r = collect(LinRange(100,1,10)) #NOTE - it may be better to keep this as a 'linrange' but I don't understand what that means
2222
legs = Vector{ComplexF64}[]
2323
for theta in orbit.items
24-
push!(legs,(cos(theta*2*pi)+1.0im*sin(theta*2*pi)) .* r)
24+
push!(legs,(cos(theta.value*2*pi)+1.0im*sin(theta.value*2*pi)) .* r)
2525
end
2626
legs[1] = legs[1] .- legs[1][end]
2727
return legs
2828
end
2929

30-
function standardlegs(angle::Rational)
31-
info = SpiderInfo(angle)
32-
return standardlegs(info)
33-
end
34-
3530
function grow!(legs::Vector{Vector{ComplexF64}},scale::Real,num::Int)
3631
#Get the arrow pointing from the second to last point to the last point
3732
for leg in legs
@@ -72,11 +67,11 @@ function mapspider!(S::Spider)
7267
#this angle lays in region A by definition.
7368

7469
if a/2 < theta1 && theta1 < (a+1)/2
75-
cregion = A()
76-
dregion = B()
70+
cregion = KneadingSymbol('A')
71+
dregion = KneadingSymbol('B')
7772
else
78-
cregion = B()
79-
dregion = A()
73+
cregion = KneadingSymbol('B')
74+
dregion = KneadingSymbol('A')
8075
end
8176

8277
for ii in 2:n-1
@@ -106,7 +101,7 @@ function mapspider!(S::Spider)
106101
thetau = (angle(u)/(2*pi)+1)%1
107102

108103
if abs2(thetau - a/2) < abs2(thetau - (a+1)/2)
109-
if cregion == A()
104+
if cregion == KneadingSymbol('A')
110105
if S.kneading_sequence.items[end] == '2'
111106
newLegs[end] = path_sqrt(S.legs[1]./λ)
112107
else
@@ -120,7 +115,7 @@ function mapspider!(S::Spider)
120115
end
121116
end
122117
else
123-
if cregion == A()
118+
if cregion == KneadingSymbol('A')
124119
if S.kneading_sequence.items[end] == '1'
125120
newLegs[end] = path_sqrt(S.legs[1]./λ)
126121
else
@@ -183,7 +178,7 @@ function parameter(S0::Spider,max_iter::Int)
183178
for ii in 1:max_iter
184179
mapspider!(S)
185180
c = S.legs[2][end]/2
186-
println(repr(c)*" delta "*repr(abs(c-c_last)))
181+
#println(repr(c)*" delta "*repr(abs(c-c_last)))
187182
if abs(c-c_last)<(1e-15)
188183
return c
189184
end

0 commit comments

Comments
 (0)