鹤啸九天 自律更自由,平凡不平庸 Less is More

分形几何-fractal-geometry

Notes(温馨提示):

  1. ★ 首次阅读建议浏览:导航指南, 或划到本页末尾, 或直接点击跳转, 查看全站导航图
  2. 右上角工具条搜索文章,右下角二维码关注微信公众号(鹤啸九天),底栏分享、赞赏、评论
  3. ★ 转载请注明文章来源,知识点积累起来不容易,水滴石穿,绳锯木断,谢谢理解
  4. ★ 如有疑问,邮件讨论,欢迎贡献优质资料


分形几何

分形几何学的基本思想:

  • 客观事物具有自相似性的层次结构,局部和整体在形态,功能,信息,时间,空间等方面具有统计意义上的相似性,称为自相似性,自相似性是指局部是整体成比例缩小的性质。

分形理论

自然界的很多事物,例如树木、云彩、山脉、闪电、雪花以及海岸线等等都呈现出传统的几何学不能描述的形状。这些形状都有如下的特性:

  • 有着十分精细的不规则的结构
  • 整体与局部相似,例如一根树杈的形状和一棵树很像 分形几何学就是用来研究这样一类的几何形状的科学,借助计算机的高速计算和图像显示,使得我们可以更加深入地直观地观察分形几何。

视频

分形维

维度缺乏正式的定义是个问题

康托尔认为线段、正方形和立方体中的点集必须具有不同的势,就像一条10个点的线、一个10×10的点网格和一个10×10×10的点立方体有不同数量的点。然而,在1877年,他发现线段中的点与正方形(以及所有维度的立方体)中的点之间存在一一对应关系,这表明它们具有相同的势。凭借直觉,他证明了尽管维度不同,线、正方形和立方体都具有相同数量的无穷小的点。

康托尔意识到这一发现威胁到n维空间需要n个坐标来描述的直觉观念,因为n维立方体中的每个点都可以由一段区间中的一个数字唯一标识。因此,从某种意义上说,这些高维立方体相当于一维线段。然而,正如戴德金指出的那样,康托尔的函数是极不连续的——它本质上是将一条线段分成无限多个部分,然后将它们重新组合成一个立方体。

1890年,朱塞佩·皮亚诺 (Giuseppe Peano) 发现,可以将一维曲线缠绕得如此紧密且连续,以至于可以填充二维正方形中的每个点。这是第一条空间填充曲线(space-filling curve)。

  • 图

数学家需要证明维度是一个真实的概念。例如,当n≠ m时,n维和m维欧几里得空间的某些基本性质是不同的。这个目标被称为“维度不变性”(invariance of dimension)问题。

终于,1912年,在康托尔的发现之后将近半个世纪,多次证明维数不变性的尝试失败之后,布劳威尔(L.E.J. Brouwer)使用自己创造方法取得了成功。从本质上讲,他证明了不可能将一个更高维的物体放入较低维度的空间中,以及在不将物体分成许多部分(如康托尔所做的那样)、不允许物体与自身相交(如皮亚诺所做的那样)的情况下,使用较低维度的物体填满较高维度的空间。此外,大约在这个时候,布劳威尔等人给出了各种严格的定义,例如,可以根据球在n维空间中的边界是n-1维这一事实,帮助归纳地确定维数。

尽管布劳威尔的工作将维度概念置于强大的数学基础上,但它无助于增强我们对高维空间的直觉:对3维空间的熟悉太容易使我们误入歧途。正如托马斯·班乔夫 (Thomas Banchoff) 所写,“我们所有人都是对自己所在维度存有偏爱的奴隶。”

例如,假设我们将2n个半径为1的球体放置在边长为4的n维立方体中,然后将另一个球体放置在与它们中心相切的位置。随着n增加,中心球体的大小随之增加——它的半径为√n -1。但是,令人震惊的是,当n≥10时,这个球体会伸出立方体的边。中心球体随着维度的增加而变大,最终会突出到立方体外面。

高维空间中令人惊讶的现实导致统计和数据分析出现问题,统称为“维数灾难”(curse of dimensionality)。许多统计方法所需的样本点数量随维度增加呈指数增长。此外,随着维度增加,点形成聚类的概率会降低。因此,找到为高维数据降维的方法十分重要。

维度的故事并没有因为布劳威尔而终结。仅仅几年之后,费利克斯·豪斯多夫(Felix Hausdorff)提出了一个新的维度定义,之后的数学发展证明该定义对现代数学至关重要。

考虑维度的一种直观方式是,如果我们将d维物体均匀地缩放或放大k倍,它的大小会增加到kd倍。假设我们将一个点、一条线段、一个正方形和一个立方体放大3倍,点的尺寸不变(3^0=1),线段变成3倍(3^1=3),正方形变成9倍 (3^2=9),立方体变成27倍 (3^3=27)。

豪斯多夫定义的一个令人惊讶的结果是,物体可能具有非整数维度。几十年后,当伯努瓦·曼德尔布罗特(Benoit B. Mandelbrot)问道:“不列颠的海岸有多长?”时,结果证明非整数维度正是他所需要的。海岸线如此参差不齐,以至于无法用任何尺子精确测量——尺子越短,测量结果越大越精确。曼德尔布罗特认为,豪斯多夫维数提供了一种量化这种锯齿状海岸线的方法,并在 1975 年提出了术语“分形”来描述这种无限复杂的形状。

以迭代方式生成的科赫曲线(Koch curve)。我们从线段开始。在每个阶段,我们删除每个线段的中间三分之一,并用与删除的线段长度相等的两个线段替换它,无限次地重复此过程以获得科赫曲线。仔细研究它,你会发现它包含4个与整个曲线相同但大小只有三分之一的部分。因此,如果我们将这条曲线缩放3倍,我们将获得原始曲线的4个副本。这意味着其豪斯多夫维数d满足 3d=4,因此,d=log3(4)≈1.26。科赫曲线并不像皮亚诺曲线那样完全充满空间,所以它不是二维的,但它也不是一条一维线,而是1.26 维。

参考:集智俱乐部 几何、分形与时空:跨越百年的维度定义之旅

分形的重要概念

无边的奇迹源自简单规则的无限重复。

—— 分形之父 Benoit B. Mandelbrot

自相似性(Self-similarity)

自相似是指局部与整体在形态、功能、信息、时间、空间等方面具有统计意义上的相似性,比如树干和枝桠的自相似,大的旋涡和小旋涡的自相似等等。

无标度性(Scale-free)

所谓无标度性,是指当我们变换不同的尺度,都会发现系统还是那样,它没有变化(即自相似性),也就是标度不变性。比如我们所说的大漩涡套着小旋涡,它们发生在不同的尺度,但是却表现出相似性,这就称为无标度特性。

非线性(Nonlinear)

非线性就是和线性相对,线性是指成比例,而非线性则指输入和输出不成比例,比如抛物线就是非线性的。在复杂系统中,非线性是最重要的特性之一。

分形案例

【2021-9-1】分形几何图形绘制,参考:

【2022-8-30】计算机中要显示颜色,一般都是用R、G、B三个0-255范围内的整数来描述。

康托尔集(Cantor set)

分形的起源是康托尔集(Cantor set)。我们取一个线段,把它中间的1/3去掉得到两个分开的线段,再对剩下的两段进行相同的操作,得到4个线段,这样重复进行下去直到无穷,最后得到的图形集合就是康托尔集。

曼德勃罗集

曼德布洛特集合(Mandelbrot set),这是一种在复平面上组成分形的点的集合,以数学家伯努·瓦曼德布洛特(Benoît B. Mandelbrot)的名字命名。Mandelbrot集合与Julia集合有些相似的地方,例如他们都使用相同的复二次多项式来进行迭代。曼德布洛特集合可以用复二次多项式,曼德布洛特集主要是通过固定z0=0,不断迭代c得到的,产生一组发散数列,如果数列发散,则在二维平面内,将所有不属于集合内的点标记为黑色,属于集合内的点按照发散速度赋予不同的颜色,就可以得到经典的曼德布洛特集图像。

img

Python实现

import numpy as np
import pylab as pl
import time
from matplotlib import cm

def iter_point(c):
    z = c
    for i in xrange(1, 100): # 最多迭代100次
        if abs(z)>2: break # 半径大于2则认为逃逸
        z = z*z+c
    return i # 返回迭代次数

def draw_mandelbrot(cx, cy, d):
    """
    绘制点(cx, cy)附近正负d的范围的Mandelbrot
    """
    x0, x1, y0, y1 = cx-d, cx+d, cy-d, cy+d 
    y, x = np.ogrid[y0:y1:200j, x0:x1:200j]
    c = x + y*1j
    start = time.clock()
    mandelbrot = np.frompyfunc(iter_point,1,1)(c).astype(np.float)
    print "time=",time.clock() - start
    pl.imshow(mandelbrot, cmap=cm.jet, extent=[x0,x1,y0,y1])
    pl.gca().set_axis_off()

x,y = 0.27322626, 0.595153338

pl.subplot(231)
draw_mandelbrot(-0.5,0,1.5)
for i in range(2,7):    
    pl.subplot(230+i)
    draw_mandelbrot(x, y, 0.2**(i-1))
pl.subplots_adjust(0.02, 0, 0.98, 1, 0.02, 0)
pl.show()

C语言实现

// NOTE: compile with g++
// g++ create_image.cpp -o generate --std=c++11
#include <iostream>
#include <cmath>
#include <cstdlib>
#define DIM 1024
#define DM1 (DIM-1)
#define _sq(x) ((x)*(x)) // square
#define _cb(x) abs((x)*(x)*(x)) // absolute value of cube
#define _cr(x) (unsigned char)(pow((x),1.0/3.0)) // cube root
 
unsigned char GR(int,int);
unsigned char BL(int,int);

// 曼德勃罗集合
unsigned char RD(int i,int j){
   // Red 红色
  float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}
  return log(k)*47;
}
unsigned char GR(int i,int j){
   // Green 绿色
  float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}
  return log(k)*47;
}
unsigned char BL(int i,int j){
   // Blue 蓝色
  float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}
  return 128-log(k)*23;
}

// 波纹生成
unsigned char RD(int i,int j){
#define P 6.03
float s=3./(j+250),y=(j+sin((i*i+_sq(j-700)*5)/100./DIM+P)*15)*s;return (int((i+DIM)*s+y)%2+int((DIM*2-i)*s+y)%2)*127;}

unsigned char GR(int i,int j){
float s=3./(j+250);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM+P)*15)*s;
return (int(5*((i+DIM)*s+y))%2+int(5*((DIM*2-i)*s+y))%2)*127;}

unsigned char BL(int i,int j){
float s=3./(j+250);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM+P)*15)*s;
return (int(29*((i+DIM)*s+y))%2+int(29*((DIM*2-i)*s+y))%2)*127;}
 
void pixel_write(int,int);
FILE *fp;

int main(){ // 图片生成主函数
    //fp = fopen("test.png","wb");
    char file_name[] = "new.png";
    fp = fopen(file_name, "wb");
    //fp = fopen("MathPic.ppm","wb"); // PPM 图片可以使用 ps 打开
    printf("创建图片文件:%s\n", file_name);
    fprintf(fp, "P6\n%d %d\n255\n", DIM, DIM);
    for(int j=0;j<DIM;j++)
        for(int i=0;i<DIM;i++)
            pixel_write(i,j);
    fclose(fp);
    printf("图片生成完毕...请打开文件%s查看\n", file_name);
    return 0;
}
void pixel_write(int i, int j){
    static unsigned char color[3];
    color[0] = RD(i,j)&255;
    color[1] = GR(i,j)&255;
    color[2] = BL(i,j)&255;
    fwrite(color, 1, 3, fp);
}

Julia 集合

Julia集 和 Mandelbrot 集具有相同的数学表示形式,唯一的不同是,Julia集是通过固定c,不断迭代,计算z的值得到的,产生一组发散序列

同理,将所有不属于集合内的点标记为黑色,属于 集合内的点按照发散速度赋予不同的颜色,会得到不同的Julia集图像。

C语言实现

// NOTE: compile with g++
// g++ create_image.cpp -o generate --std=c++11
#include <iostream>
#include <cmath>
#include <cstdlib>
#define DIM 1024
#define DM1 (DIM-1)
#define _sq(x) ((x)*(x)) // square
#define _cb(x) abs((x)*(x)*(x)) // absolute value of cube
#define _cr(x) (unsigned char)(pow((x),1.0/3.0)) // cube root
 
unsigned char GR(int,int);
unsigned char BL(int,int);

// julia 集合
unsigned short red_fn(int i, int j){
#define D(x) (x-DIM/2.)/(DIM/2.)
float x=D(i),y=D(j),X,Y,n=0;while(n++<200&&(X=x*x)+(Y=y*y)<4){x=X-Y+.36237;y=2*x*y+.32;}return log(n)*256;}

unsigned short green_fn(int i, int j){
float x=D(i),y=D(j),X,Y,n=0;while(n++<200&&(x*x+y*y)<4){X=x;Y=y;x=X*X-Y*Y+-.7;y=2*X*Y+.27015;}return log(n)*128;}

unsigned short blue_fn(int i, int j){
float x=D(i),y=D(j),X,Y,n=0;while(n++<600&&(x*x+y*y)<4){X=x;Y=y;x=X*X-Y*Y+.36237;y=2*X*Y+.32;}return log(n)*128;}
 
void pixel_write(int,int);
FILE *fp;

int main(){ // 图片生成主函数
    //fp = fopen("test.png","wb");
    char file_name[] = "new.png";
    fp = fopen(file_name, "wb");
    //fp = fopen("MathPic.ppm","wb");
    printf("创建图片文件:%s\n", file_name);
    fprintf(fp, "P6\n%d %d\n255\n", DIM, DIM);
    for(int j=0;j<DIM;j++)
        for(int i=0;i<DIM;i++)
            pixel_write(i,j);
    fclose(fp);
    printf("图片生成完毕...请打开文件%s查看\n", file_name);
    return 0;
}
void pixel_write(int i, int j){
    static unsigned char color[3];
    color[0] = RD(i,j)&255;
    color[1] = GR(i,j)&255;
    color[2] = BL(i,j)&255;
    fwrite(color, 1, 3, fp);
}

科赫曲线 Koch curve

科赫曲线(Koch curve)是一种神奇的曲线,因为形态跟雪花很像,所以也称为科赫雪花,最早出现在海里格·冯·科赫(Helge von Koch)的论文中,通过下面这个动图,你知道科赫雪花是如何形成的吗?

  • 第一步:画一个等边三角形,并把每一边三等分;
  • 第二步:取三等分后的一边中间一段为边向外作正三角形,并把这“与主三角形靠近的一边”擦掉;
  • 第三步:重复上述步骤,画出更小的三角形;
  • 第四步:一直重复。

由上述步骤所画出的曲线叫做科赫曲线(Koch curve)。

谢尔宾斯基三角形 Sierpinski triangle

一个平面三角形的维度是二维的,但是在分形几何中,三角形有不同的维度计算方法。谢尔宾斯基三角形(Sierpinski triangle)也是一种分形典型示例,由波兰数学家谢尔宾斯基于1915年提出。它是自相似集的例子。它的豪斯多夫维数是

可以通过多种方法得到这个三角形,这里介绍其中的一种方法:

  • 第一步:取一个实心的三角形。(多数情况下使用等边三角形);
  • 第二步:沿三边中点的连线,将它分成四个小三角形;
  • 第三步:去掉中间的那一个小三角形;
  • 第四步:对其余三个小三角形重复步骤一。

分形树

用turtle动态绘制分形树

img

## 绘制分型树,末梢的树枝的颜色不同
import turtle

def draw_brach(brach_length):
    if brach_length > 5:
        if brach_length < 40:
            turtle.color('green')
        else:
            turtle.color('red')

        # 绘制右侧的树枝
        turtle.forward(brach_length)
        print('向前',brach_length)
        turtle.right(25)
        print('右转20')
        draw_brach(brach_length-15)
        # 绘制左侧的树枝
        turtle.left(50)
        print('左转40')
        draw_brach(brach_length-15)

        if brach_length < 40:
            turtle.color('green')
        else:
            turtle.color('red')

        # 返回之前的树枝上
        turtle.right(25)
        print('右转20')
        turtle.backward(brach_length)
        print('返回',brach_length)

def main():
    turtle.left(90)
    turtle.penup()
    turtle.backward(150)
    turtle.pendown()
    turtle.color('red')

    draw_brach(100)

    turtle.exitonclick()

if __name__ == '__main__':
    main()

樱花树

from turtle import *
from random import *
from math import *

def tree(n, l):
    pd() # 下笔
 # 阴影效果
 t = cos(radians(heading() + 45)) / 8 + 0.25
 pencolor(t, t, t)
    pensize(n / 3)
    forward(l) # 画树枝
 if n > 0:
        b = random() * 15 + 10 # 右分支偏转角度
 c = random() * 15 + 10 # 左分支偏转角度
 d = l * (random() * 0.25 + 0.7) # 下一个分支的长度
 # 右转一定角度,画右分支
 right(b)
        tree(n - 1, d)
 # 左转一定角度,画左分支
 left(b + c)
        tree(n - 1, d)

 # 转回来
 right(c)
 else:
 # 画叶子
 right(90)
        n = cos(radians(heading() - 45)) / 4 + 0.5
 pencolor(n, n*0.8, n*0.8)
        circle(3)
        left(90)

 # 添加0.3倍的飘落叶子
 if(random() > 0.7):
            pu()
 # 飘落
 t = heading()
            an = -40 + random()*40
 setheading(an)
            dis = int(800*random()*0.5 + 400*random()*0.3 + 200*random()*0.2)
            forward(dis)
            setheading(t)

 # 画叶子
 pd()
            right(90)
            n = cos(radians(heading() - 45)) / 4 + 0.5
 pencolor(n*0.5+0.5, 0.4+n*0.4, 0.4+n*0.4)
            circle(2)
            left(90)
            pu()
 #返回
 t = heading()
            setheading(an)
            backward(dis)
            setheading(t)
    pu()
    backward(l)# 退回
bgcolor(0.5, 0.5, 0.5) # 背景色
ht() # 隐藏turtle
speed(0) # 速度,1-10渐进,0最快
tracer(0, 0)
pu() # 抬笔
backward(100)
left(90) # 左转90度
pu() # 抬笔
backward(300) # 后退300
tree(12, 100) # 递归7层
done()

分形树叶

img

import numpy as np
import matplotlib.pyplot as pl
import time

# 蕨类植物叶子的迭代函数和其概率值
eq1 = np.array([[0,0,0],[0,0.16,0]])
p1 = 0.01

eq2 = np.array([[0.2,-0.26,0],[0.23,0.22,1.6]])
p2 = 0.07

eq3 = np.array([[-0.15, 0.28, 0],[0.26,0.24,0.44]])
p3 = 0.07

eq4 = np.array([[0.85, 0.04, 0],[-0.04, 0.85, 1.6]])
p4 = 0.85

def ifs(p, eq, init, n):
"""
    进行函数迭代
    p: 每个函数的选择概率列表
    eq: 迭代函数列表
    init: 迭代初始点
    n: 迭代次数

    返回值: 每次迭代所得的X坐标数组, Y坐标数组, 计算所用的函数下标    
    """

# 迭代向量的初始化
pos = np.ones(3, dtype=np.float)
pos[:2] = init

# 通过函数概率,计算函数的选择序列
p = np.add.accumulate(p)    
rands = np.random.rand(n)
select = np.ones(n, dtype=np.int)*(n-1)
for i, x in enumerate(p[::-1]):
select[rands<x] = len(p)-i-1

# 结果的初始化
result = np.zeros((n,2), dtype=np.float)
c = np.zeros(n, dtype=np.float)

for i in range(n):
eqidx = select[i] # 所选的函数下标
tmp = np.dot(eq[eqidx], pos) # 进行迭代
pos[:2] = tmp # 更新迭代向量

# 保存结果
result[i] = tmp
c[i] = eqidx

return result[:,0], result[:, 1], c

start = time.clock()
x, y, c = ifs([p1,p2,p3,p4],[eq1,eq2,eq3,eq4], [0,0], 100000)
time.clock() - start
pl.figure(figsize=(6,6))
pl.subplot(121)
pl.scatter(x, y, s=1, c="g", marker="s", linewidths=0)
pl.axis("equal")
pl.axis("off")
pl.subplot(122)
pl.scatter(x, y, s=1,c = c, marker="s", linewidths=0)
pl.axis("equal")
pl.axis("off")
pl.subplots_adjust(left=0,right=1,bottom=0,top=1,wspace=0,hspace=0)
pl.gcf().patch.set_facecolor("#D3D3D3")
pl.show()

Logistic Hills

效果:

unsigned char RD(int i,int j){    
    #define A float a=0,b,k,r,x
    #define B int e,o
    #define C(x) x>255?255:x
    #define R return
    #define D DIM
    R BL(i,j)*(D-i)/D;
}
unsigned char GR(int i,int j){      
    #define E DM1
    #define F static float
    #define G for(
    #define H r=a*1.6/D+2.4;x=1.0001*b/D
    R BL(i,j)*(D-j/2)/D;
}
unsigned char BL(int i,int j){
    F c[D][D];if(i+j<1){A;B;G;a<D;a+=0.1){G b=0;b<D;b++){H;G k=0;k<D;k++){x=r*x*(1-x);if(k>D/2){e=a;o=(E*x);c[e][o]+=0.01;}}}}}R C(c[j][i])*i/D;
}

其它分形图(分形龙、谢尔宾斯基三角等)

img

from math import sin, cos, pi
import matplotlib.pyplot as pl
from matplotlib import collections

class L_System(object):
def __init__(self, rule):
info = rule['S']
for i in range(rule['iter']):
ninfo = []
for c in info:
if c in rule:
ninfo.append(rule[c])
else:
ninfo.append(c)
info = "".join(ninfo)
self.rule = rule
self.info = info

def get_lines(self):
d = self.rule['direct']
a = self.rule['angle']
p = (0.0, 0.0)
l = 1.0
lines = []
stack = []
for c in self.info:
if c in "Ff":
r = d * pi / 180
t = p[0] + l*cos(r), p[1] + l*sin(r)
lines.append(((p[0], p[1]), (t[0], t[1])))
p = t
elif c == "+":
d += a
elif c == "-":
d -= a
elif c == "[":
stack.append((p,d))
elif c == "]":
p, d = stack[-1]
del stack[-1]
return lines

rules = [
{
"F":"F+F--F+F", "S":"F",
"direct":180,
"angle":60,
"iter":5,
"title":"Koch"
},
{
"X":"X+YF+", "Y":"-FX-Y", "S":"FX",
"direct":0,
"angle":90,
"iter":13,
"title":"Dragon"
},
{
"f":"F-f-F", "F":"f+F+f", "S":"f",
"direct":0,
"angle":60,
"iter":7,
"title":"Triangle"
},
{
"X":"F-[[X]+X]+F[+FX]-X", "F":"FF", "S":"X",
"direct":-45,
"angle":25,
"iter":6,
"title":"Plant"
},
{
"S":"X", "X":"-YF+XFX+", "Y":"+XF-YFY-FX+",
"direct":0,
"angle":90,
"iter":6,
"title":"Hilbert"
},
{
"S":"L--F--L--F", "L":"+R-F-R+", "R":"-L+F+",
"direct":0,
"angle":45,
"iter":10,
"title":"Sierpinski"
},

]

def draw(ax, rule, iter=None):
if iter!=None:
rule["iter"] = iter
lines = L_System(rule).get_lines()
linecollections = collections.LineCollection(lines)
ax.add_collection(linecollections, autolim=True)
ax.axis("equal")
ax.set_axis_off()
ax.set_xlim(ax.dataLim.xmin, ax.dataLim.xmax)
ax.invert_yaxis()

fig = pl.figure(figsize=(7,4.5))
fig.patch.set_facecolor("papayawhip")

for i in xrange(6):
ax = fig.add_subplot(231+i)
draw(ax, rules[i])

fig.subplots_adjust(left=0,right=1,bottom=0,top=1,wspace=0,hspace=0)
pl.show()

混沌

蝴蝶效应,逆天改命,这个视频或许会改变你的人生

什么是混沌

什么是混沌分形理论?详见混沌分形理论

  • 首先,混沌是指现实世界中存在的一种貌似混乱无序的复杂运动形态。但混沌不表示混乱,它是“一种更高层次的次序”。混沌的背后拥有精细的结构,这种精细的结构具有自相似性,称为分形。
  • 其次,复杂的事物都有简单的开始,一颗大树分解后就是一个个树杈,股市分解后就是一涨一跌,大道至简,复杂的事物由基本的分形迭代演化而成,部分和整体自相似,这就是分形,一颗大树是由无数的树杈叠加构成,从微观上看,这颗大树就是一大堆基本粒子,处于混沌态,但在树杈的基本分形规则之下构成大树。更微观上说,树杈的结构是遗传密码决定的,基因组排序不同,构成的生物也不同。为何会有这样的基因排序,因为这是生物长期自然选择进化的结果,植物生长靠吸收阳光获取能量,树杈的结构能以最小的阻力最快的速度接近阳光,吸收更多的光能,利于生存竞争和基因传承,吸收的能量大于耗散的能量,能量差为正,就是不断长大的过程,能量差为负,吸收小于耗散,就是不断衰老过程,直至能量差消失,回归平衡。
  • 最后,分形理论与混沌理论同属非线性理论,是从不同的角度同时表达的对动态复杂系统的研究。

混沌分形理论具有三项主要原则

  • 第一项,宇宙中的每个事物遵循最小阻力途径;
  • 第二项,最小阻力途径由潜在并通常不可见的结构所决定;
  • 第三项,这种潜在并通常不可见的结构能够被发现并能够改变。

【2022-11-5】混沌理论还有一个是发展特征,其有三个原则:

  • 1、能量永远会遵循阻力最小的途径。
  • 2、始终存在着通常不可见的根本结构,这个结构决定阻力最小的途径。
  • 3、这种始终存在而通常不可见的根本结构,不仅可以被发现,而且可以被改变。

混沌案例

洛伦兹混沌吸引子

logistic映射

双摆

元胞自动机

Python 实现最简单的元胞自动机

介绍

元胞自动机(cellular automata) 是离散而抽象的计算系统。元胞自动机在时间和空间上是离散的,最小单位是简单元胞(单元格)。每个元胞会产生有限数量的状态集,后续元胞由其邻域元胞的状态确定。这里所说的领域元胞,是指当前元胞的前一个元胞(记作元胞A)以及元胞A左右两个元胞。也就是说,邻域元胞总共包含三个元胞。给定初始层的状态,基于一定规则,我们可以不断更新下一层元胞的状态。通俗的讲,元胞自动机就是基于一定规则的“繁衍机器”。

示例

img

import time


def print_seq(seq, speed=0.5):
    for item in seq:
        if item:
            print('*', end='')
        else:
            print('-', end='')
    print('')
    time.sleep(speed)


class Cell:
    def __init__(self, deepth=31):
        self.ca = [0 if i != 31 else 1 for i in range(64)]
        self.ca_new = []
        self.deepth = deepth

    def process(self):
        print_seq(self.ca)
        for i in range(self.deepth):
            self._rule()
            print_seq(self.ca_new)
            self.ca = self.ca_new
            self.ca_new = []

    def _rule(self):
        for i in range(64):
            if 0 < i < 63:
                if self.ca[i - 1] == self.ca[i + 1]:
                    self.ca_new.append(0)
                else:
                    self.ca_new.append(1)
            elif i == 0:
                if self.ca[1]:
                    self.ca_new.append(1)
                else:
                    self.ca_new.append(0)
            else:
                if self.ca[62]:
                    self.ca_new.append(1)
                else:
                    self.ca_new.append(0)

def main():
    cell = Cell()
    cell.process()


if __name__ == '__main__':
    main()

图灵斑图

【2021-9-24】图灵YYDS!60年前不被看好的理论再次被证,这次是原子层面的

你以为,斑马的黑白条纹,贝壳的复杂花纹,都只是随便长长?并不!

这些自然界的重复图案,有相当一部分能用一组方程式描述。听上去有些离谱,但确实是图灵本人搞出来的——60年前,他对大自然进行一番研究后,给出了这组方程式。

  • 公式认为,任何重复的自然图案,都是通过两种具有特定特征的事物(如分子、细胞)进行相互作用而产生的。
    • 两种事物的特定特征为:速度不同、能在空间内传播、其中一种是催化剂。这种催化剂,能自动激活、并随后产生抑制剂,使得它比催化剂的传播速度更快,导致催化剂中途停止,最终生成相应的图案。
  • 只需要对反应扩散方程的不同条件进行约束,这两种事物,就能自发地组成斑纹、条纹、环纹、螺旋或斑点等图案。 这组方程式适用于不少自然界的图案,包括斑马、贝壳、鱼类、豹的条纹等。他们给这类图案统一起了个名字,叫图灵斑图 (turing pattern).但无论是斑马、豹、贝壳还是鱼类,基本都属于宏观尺度的图案,微观尺度上的图灵斑图研究少之又少。现在,来自斯坦福等高校的科学家终于发现,一种晶体生长的微观纹路,也可以用图灵斑图来描述,这种晶体名叫,它在特殊条件下的原子生长模式,与图灵方程式预测的形态非常相似,目前研究成果已经刊登到Nature Physics上。仅凭一组公式预测图案的图灵,60年后再次跨越了微观和宏观的界限。

结束


支付宝打赏 微信打赏

~ 海内存知已,天涯若比邻 ~

Share

Related Posts

下一篇 贫富认知

标题:数据库及SQL-database&sql-note

摘要:数据挖掘知识点、经验总结

标题:贫富认知

摘要:穷人一直穷,富人一直富吗?社会阶级会一直存在吗

站内可视化导航

文章可视化导读:鼠标划过图形块时,如果出现蓝色光环, 点击即可跳转到对应主题

Comments

--disqus--

    Content
    My Moment ( 微信公众号 )
    欢迎关注鹤啸九天