数学曲线
一、蝴蝶曲线
极坐标:
python代码:
import numpy as np
import matplotlib.pyplot as plt
t = np.arange(0.0, 12*np.pi, 0.01)
x = np.sin(t)*(np.e**np.cos(t) - 2*np.cos(4*t)-np.sin(t/12)**5)
y = np.cos(t)*(np.e**np.cos(t) - 2*np.cos(4*t)-np.sin(t/12)**5)
plt.figure(figsize=(8,6))
plt.axis('off')
plt.plot(x,y,color='blue',linewidth = '2')
plt.savefig("butter.jpg",dpi=400)
二、心形曲线
python程序:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
font=FontProperties(fname='/Library/Fonts/Songti.ttc',size=10)
x_coords = np.linspace(-100, 100, 500)
y_coords = np.linspace(-100, 100, 500)
points = [ ]
for y in y_coords:
for x in x_coords:
if ((x*0.03)**2+(y*0.03)**2-1)**3-(x*0.03)**2*(y*0.03)**3 <= 0:
points.append({"x": x, "y": y})
heart_x = list(map(lambda point: point["x"], points))
heart_y = list(map(lambda point: point["y"], points))
plt.figure("heart", figsize=(6,15))
plt.subplot(521)
plt.scatter(heart_x, heart_y, s=10, alpha=0.5)
plt.title("普通",fontproperties=font)
plt.axis('off')
cmap =[("autumn","橙色-热情洋溢"),("cool","紫色-优雅宁静"),("magma","晚霞-醇厚脱俗"),("rainbow","彩虹-绚丽幻想"),("Reds","炽热-热烈奔放"),("spring","青春-充满朝气"),("viridis","翡翠-平静柔和"),("gist_rainbow","五彩缤纷-多姿多彩")]
for i in range(len(cmap)):
plt.subplot(522+i)
plt.scatter(heart_x, heart_y, s=10, alpha=0.5, c=range(len(heart_x)), cmap=cmap[i][0])
plt.title(cmap[i][1],fontproperties=font)
plt.axis('off')
# plt.show()
plt.savefig("heart.jpg",dpi=400)
三、Mandelbrot集合
曼德博集合可以用复二次多项式来定义:
其中c是一个复数参数。
从z=0开始对f_{c}(z)进行迭代:
- z_{n+1}=z_{n}^{2}+c,n=0,1,2,...
- z_{0}=0
- z_{1}=z_{0}^{2}+c=c
- z_{2}=z_{1}^{2}+c=c^{2}+c
每次迭代的值依序如以下序列所示:(0,f_{c}(0),f_{c}(f_{c}(0)),f_{c}(f_{c}(f_{c}(0))),\ldots )
不同的参数c可能使序列的绝对值逐渐发散到无限大,也可能收敛在有限的区域内。曼德博集合M就是使序列不延伸至无限大的所有复数c的集合。
曼德博集合有一些特性和定理,可参考:曼德博集合
python代码
import numpy as np
import matplotlib.pylab as plt
MAXITERS,RADIUS = 200,100
def color(z, i):
v = np.log2(i + 1 - np.log2(np.log2(abs(z)))) / 5
if v < 1.0: return v**4, v**2.5, v
else:
v = max(0, 2-v)
return v, v**1.5, v**3
def iterate(c):
z = 0j
for i in range(MAXITERS):
if z.real*z.real + z.imag*z.imag > RADIUS: return color(z, i)
z = z*z + c
return 0, 0, 0
xmin,xmax, ymin,ymax,width,height=-2.1, 0.8, -1.16, 1.16, 800, 640
y, x = np.ogrid[ymin: ymax: height*1j, xmin: xmax: width*1j]
z = x + y*1j
R, G, B = np.asarray(np.frompyfunc(iterate, 1, 3)(z)).astype(np.float)
img = np.uint8(np.stack((R, G, B), axis=2) * 255)
plt.figure("Mandelbrot")
plt.imshow(img)
plt.axis('off')
plt.title('Mandelbrot')
# plt.show()
plt.savefig("Mandelbrot.jpg",dpi=400)
四、Newton分形
牛顿分形就是分形的一种,它与解方程的牛顿法(跟优化中的牛顿法是不同的方法)紧密相关。假如需要求解方程f(x) = 0。
其中,x的定义域是整个复平面。如何求解这个方程的解呢?我们可以用牛顿法。牛顿法是一种数值解法,我们首先会估算一个“比较好”的初始值x_0,然后使用迭代公式:
牛顿法可以确保,如果初始猜测值在根附近,那么迭代必然收敛。而且牛顿法是个二阶方法,收敛速度相当的快。下图是迭代一步的示意图
在x_1处沿着方向\frac{f(x_1)}{f'(x_1)}下降,与x轴的交点即为x_2,循环往复就能得到方程的根。
学过中学数学的我们都知道, n次方程在复数域上有n
个根,那么用牛顿法收敛的根就可能有n个目标。牛顿法收敛到哪个根取决于迭代的起始值。根据最后的收敛结果,我们把所有收敛到同一个根的起始点画上同一种颜色,最终就形成了牛顿分形图。
python代码
import numpy as np
import matplotlib.pyplot as plt
from numba import jit
# define functions manually, do not use numpy's poly1d funciton!
@jit('complex64(complex64)', nopython=True)
def f(z):
# z*z*z is faster than z**3
# return z*z*z - 1
return z**5 + 0.25*z*z + 1.17
@jit('complex64(complex64)', nopython=True)
def df(z):
# return 3*z*z
return 5*z**4 + 0.5*z
@jit('float64(complex64)', nopython=True)
def iterate(z):
num = 0
while abs(f(z)) > 1e-4:
w = z - f(z)/df(z)
num += np.exp(-1/abs(w-z))
z = w
return num
imgsize = 600
y, x = np.ogrid[1: -1: imgsize*2j, -1: 1: imgsize*2j]
z = x + y * 1j
img = np.frompyfunc(iterate, 1, 1)(z).astype(np.float)
fig = plt.figure(figsize=(imgsize/100.0, imgsize/100.0), dpi=100)
ax = fig.add_axes([0, 0, 1, 1], aspect=1)
ax.axis('off')
ax.imshow(img, cmap='hot')
fig.savefig('newton.jpg')
五、洛伦茨吸引子
含时间参数的形式:
\sigma称为普兰特尔数,\rho 称为瑞利数。所有的\sigma,\rho,\beta>0,但通常\sigma=10,\beta=8/3,\rho不定。若\rho<1,则吸引子为原点,没有任何其他稳定点。1≤\rho<13.927时,螺线轨迹接近两点(这相当于存在阻尼振子),两点的位置由下列式子决定:x=\pm \sqrt{b(\rho-1)},y=\pm \sqrt{b(\rho-1)}、z=\rho-1 。
python代码:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation
from scipy.integrate import odeint
from mpl_toolkits.mplot3d import Axes3D
# number of particles.
num_particles = 20
# constants for Lorenz system.
alpha, beta,gamma = 10.0, 8/3.0, 28.0
def derivative(point, t):
# return the tangent direction at (x,y,z)
x, y, z = point
return [alpha * (y - x),x * (gamma - z) - y,x * y - beta * z]
fig = plt.figure(figsize=(6.4, 4.8), dpi=100)
ax = fig.add_axes([0, 0, 1, 1], projection='3d', xlim=(-25, 25), ylim=(-35, 35), zlim=(5, 55))
ax.view_init(30, 0)
ax.axis('off')
lines, points = [], []
colors = plt.cm.gist_ncar(np.linspace(0, 1, num_particles))
for c in colors:
lines.extend(ax.plot([], [], '-', c=c))
points.extend(ax.plot([], [], 'o', c=c))
x0 = -15 + 30 * np.random.random((num_particles, 3))
t = np.linspace(0, 40, 10001)
x_t = np.array([odeint(derivative, point, t) for point in x0])
def init():
for line, point in zip(lines, points):
line.set_data([], [])
line.set_3d_properties([])
point.set_data([], [])
point.set_3d_properties([])
return lines + points
def animate(i):
i = 2*i % x_t.shape[1] # accelarate the animation.
for line, point, x_j in zip(lines, points, x_t):
x, y, z = x_j[:i].T
line.set_data(x, y)
line.set_3d_properties(z)
# note that plot() receives a list parameter so we have
# to write x[-1:] instead of x[-1]!
point.set_data(x[-1:], y[-1:])
point.set_3d_properties(z[-1:])
ax.view_init(30, 0.3*i)
fig.canvas.draw()
return lines + points
anim = FuncAnimation(fig, animate, init_func=init, interval=20, frames=2000, blit=True)
anim.save('lorenz.mp4', writer='ffmpeg', fps=30, dpi=200,bitrate=1000, codec='libx264', extra_args=['-crf', '10'])
六、羊角螺线
羊角螺线(clothoid),又称欧拉螺线(Euler spiral),是形式为
的曲线,其中C(t)、S(t)为Fresnel积分:
上面参数方程的参数t,也是螺线于该点的曲率:\kappa (t)=2t。两个螺线的中心位于\frac {\sqrt {\pi }}{2},\frac {\sqrt {\pi }}{2}
由于此螺线的曲率与长度成正比,故常用于公路工程或铁路工程,以缓和直路线与圆曲路线之间的曲率变化(向心力变化)。在光学上,近场衍射(Fresnel衍射)中会应用Fresnel积分。
python代码:
import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate
import math
t = np.arange(-10,10,0.01)
s = map(lambda i:integrate.quad(lambda x:math.sin(pow(x,2)),0,i),t)
c = map(lambda i:integrate.quad(lambda x:math.cos(pow(x,2)),0,i),t)
s = [i[0] for i in list(s)]
c = [i[0] for i in list(c)]
plt.figure(figsize=(4,3))
plt.axis('off')
plt.plot(c,s, color='red',linewidth = '1')
plt.savefig("butter.jpg",bbox_inches='tight', transparent=True,dpi=400)