Skip to content

Instantly share code, notes, and snippets.

@marshareb
Created January 25, 2019 17:57
Show Gist options
  • Save marshareb/9e3e2196bcf4c0847429b49b4365b953 to your computer and use it in GitHub Desktop.
Save marshareb/9e3e2196bcf4c0847429b49b4365b953 to your computer and use it in GitHub Desktop.
Devils Staircase
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
fig = plt.figure()
ax = plt.axes(xlim=(0, 1), ylim=(0, 1))
line, = ax.plot([], [], lw=2)
def init():
line.set_data([], [])
return line,
# C_n in the Cantor set definition
def c(n):
if n == 0:
return [(0,1)]
else:
h = c(n-1)
k = []
for i in h:
k.append((i[0]/3, i[1]/3))
k.append((i[0]/3 + 2/3, i[1]/3 + 2/3))
return k
def complement(n):
h = c(n)
h = sorted(h, key = lambda x: x[1])
k = []
for i in range(len(h) - 1):
k.append((h[i][1], h[i+1][0]))
return k
def k(n):
h = []
for i in range(0,n+1):
for l in complement(i):
if (l,i-1) not in h:
h.append(l)
return sorted(set(h), key = lambda x : x[0])
def line_between(x1, x2, y1, y2, x):
m = (y2-y1)/(x2-x1)
b = (x1*y1-x2*y1)/(x2-x1)
return ((y2-y1)/(x2-x1))*x + (x1*y2-x2*y1)/(x1-x2)
def f(x, n):
intervals = k(n)
if x >= 0 and x < intervals[0][0]:
return line_between(0, intervals[0][0], 0, 1/2**(n), x)
if x <= 1 and x > intervals[-1][1]:
return line_between(intervals[-1][1], 1, (len(intervals))/(2**(n)), 1, x)
for i in range(len(intervals)):
if x >= intervals[i][0] and x <= intervals[i][1]:
return (i+1)/2**(n)
elif x < intervals[i][0]:
if intervals[i-1][1] < x:
return min(1,line_between(round(intervals[i-1][1],5), round(intervals[i][0],5), ((i)/2**(n)), ((i+1)/(2**(n))), x))
def connectpoints(x,y,p1,p2):
x1, x2 = x[p1], x[p2]
y1, y2 = y[p1], y[p2]
plt.plot([x1,x2],[y1,y2],'k-')
def animate(n):
print(n)
x = np.linspace(0, 1, 100)
h = k(n)
y = [f(i, n+1) for i in x]
line.set_data(x, y)
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=10, interval=200, blit=True)
'''
# In case you just want to plot the function itself.
x = np.linspace(0, 1, 100)
y = [f(i,4) for i in x]
plt.plot(x,y)
plt.show()
'''
# Saves the animation as a .gif. Used imagemagick since I'm on a linux distribution.
anim.save('cantor.gif', fps=1, writer='imagemagick')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment