Lorenz系统是一个按Rayleigh-Bénard配置的大气对流简化模型,包含3个微分方程。Lorenz在1963年证明了这个系统中存在混沌(Lorenz认为由三变量非线性耦合微分方程描述的系统都能产生chaos,1975)。变量X、Y、Z分别表示循环流体的流速、上升和下降流体的温差和垂直温度剖面的畸变。其微分形式如下:
d x = − σ ( x − y ) dx\mathrm{=}-\sigma\left(x-y\right) dx=−σ(x−y) d y = r x − y − x z dy\mathrm{=}rx-y-xz dy=rx−y−xz d z = − β z + x y dz\mathrm{=}-\beta\ z+xy dz=−β z+xy其中控制参数 σ = 10 \sigma\mathrm{=}10 σ=10、 r = 28 r\mathrm{=}28 r=28、 β = 8 / 3 \beta\mathrm{=}8/3 β=8/3时也叫经典Lorenz系统,本次展示也是用这些参数。经典参数下Lorenz系统最大李亚普诺夫指数计算得2.12,系统最终将走向混沌。同时洛伦兹方程是耗散的,所有的轨迹最终进入吸收域(Viana,2000): Ω = { x ∈ R 3 : r x 2 + σ y 2 + σ ( z − 2 r ) 2 < β 2 r 2 β − 1 } \Omega\ \mathrm{=}\left\{ {x\in}\ \mathrm{R^3}: rx^2+σy^2+σ(z-2r)^2< \frac{β^2r^2}{β-1}\right\} Ω ={x∈ R3:rx2+σy2+σ(z−2r)2<β−1β2r2}这就是那个蝴蝶型的区域,Lorenz吸引子的每一条轨迹在空间上都不重合,并且总不会超出这个区域。
Rossler系统是与人为构造的与Lorenz类似可以产生混沌的系统,并没有实际的物理意义,因此不做过多赘述。其方程如下:
d x = − ( y + z ) dx=-\left(y+z\right) dx=−(y+z) d y = x + a y dy=x+ay dy=x+ay d z = b + z ( x − c ) dz=b+z\left(x-c\right) dz=b+z(x−c)
求解上述两个方程组,MATLAB提供ode函数求解,在精度要求不高时,与龙格库塔四阶算法差别不大。龙格库塔四阶算法在每个步长 h h h上使用 k 1 、 k 2 、 k 3 、 k 4 k_1、k_2、k_3、k_4 k1、k2、k3、k4四个分别代表开始斜率、考虑 k 1 k_1 k1的中点斜率、考虑 k 2 k_2 k2的中点斜率、考虑 k 3 k_3 k3的末端斜率,取加权平均 y ( n + 1 ) = y ( n ) + h 6 ∗ ( k 1 + 2 ∗ k 2 + 2 ∗ k 3 + k 4 ) y(n+1)=y(n)+\frac{h}{6}*(k_1+2*k_2+2*k_3+k_4) y(n+1)=y(n)+6h∗(k1+2∗k2+2∗k3+k4)这个方法的求解具有4阶精度,跟DDE方法(实质为三阶变步长的龙格库塔算法)精度相近,但是运算更快。其代码如下:
function [t,y]=rk4(f,tspan,y0,n)
%四阶Runge-Kutta算法
%f:dy/dt=f(t,y);求解区间tspan:[t0,tf];初值y0=y(t0)=[x0,y0,z0];n采样点数
h=(tspan(2)-tspan(1))/n;
t=tspan(1):h:tspan(2);
y=zeros(length(y0),length(t));
y(:,1)=y0;
for m=2:length(t)
k1=f(t(m-1),y(:,m-1));
k2=f(t(m-1)+h/2,y(:,m-1)+k1*h/2);
k3=f(t(m-1)+h/2,y(:,m-1)+k2*h/2);
k4=f(t(m-1)+h,y(:,m-1)+k3*h);
y(:,m)=y(:,m-1)+(k1+2*k2+2*k3+k4)*h/6;
end
t=t';
y=y';
end
其中需要首先传入一个函数的句柄,函数可由如下形式定义:
function dy_dt=lorenz(t,y)
%y=[x,y,z]储存三个变量的矩阵
p=10;
r=28;
b=8/3;
dx_dt=p*(y(2)-y(1));
dy_dt=r*y(1)-y(2)-y(1)*y(3);
dz_dt=y(1)*y(2)-b*y(3);
dy_dt=[dx_dt;dy_dt;dz_dt];
end
Rossler函数的定义相同,从Lorenz形式的方程和代码很容易写出,这里不做累述。值得一提的是,如果不是做半导体激光器速率方程那样时滞的仿真,实际上只需要简单一行代码调用ode45函数就可以出结果,但是ode函数是变步长的,因此传入的需要传入固定距离的长矩阵(见下文)。
运行后(完整代码见附录)即可得到蝴蝶型的吸引子。使用常规的frame方法保存图像如下:(用view函数将图像稍稍转了下)。与自带的ODE函数运行的结果几乎一致。
Rossler吸引子如下:
如何将chaos与“噪声”和“周期特别长的序列”中区别开,最大李指数是一种不错的方法。如果一个系统具有一个正的李指数,那么它就是混沌的;正的数值越大,系统越混沌。因此也有人(吕金虎,2002,如果没记错的话)认为李指数的倒数是系统可预测时间的测度,超过这个值,系统将不可预测。
此处参考Wolf博士的程序(at the University of Texas at Austin)。他用BASGEN生成数据库,与用FET生成的时间序列一起应用于监测邻近轨迹的散度来估计最大李指数。FET和BASGEN实际上都使用了延时重建和相空间重构的方法,因此实际上对结果影响较大的参数也就主要是嵌入维度、延时、演化时间,此处分别设为3,10,20。对采样出16384个点的Lorenz系统进行估计。对轨道的检测结果如下如下:
可以看出,在大部分的演化时间里,两个轨道紧紧贴合,发散程度低。下面是FET的输出,第5列是李雅普诺夫指数的估计。第5列是轨道角修正数值。
程序预测出的李指数结果为2.15,与计算值接近,因此Lorenz系统是混沌的。
(2023.7更新)
当然,MATLAB自带的程序也可以实现重构相空间与计算最大李指数。使用MATLAB自带的Lorenz数据,频率fs为100。使用phaseSpaceReconstruction函数使用平均互信息重构数据的相空间,得到维度为3,重构延时为10。数据量较大时重构的速度慢。此处lyapunovExponent的算法同样可以表示闭合相空间的轨迹分离率,计算得1.62。李指数是有单位的,由频率 f s fs fs决定,此处为 s − 1 s^{-1} s−1。如果两个点处于同一起点,那么经过平均1.62s后它们的轨道将完全分离。
%使用matlab自带的Lorenz数据
load('lorenzAttractorExampleData.mat','data','fs');
xdata = data(:,1);
[~,lag,dim] = phaseSpaceReconstruction(xdata)
eg=[80 150]
lyp=lyapunovExponent(xdata,fs,lag,dim,'ExpansionRange',eg);%取值
lyapunovExponent(xdata,fs,lag,dim,'ExpansionRange',eg);%绘图
参数ExpansionRange的选取,线性拟合越好的区间越合适。下图是一个特别大的区间[0 500],无法线性拟合,计算结果偏差就很大。
y0=[1;0;0];
tspan=[0,1e2];
[t1,y1]=rk4(@lorenz,tspan,y0,1e5);
[t2,y2]=ode45(@lorenz,tspan,y0);
plot3(y1(:,1),y1(:,2),y1(:,3));
figure();plot3(y2(:,1),y2(:,2),y2(:,3));
function [t,y]=rk4(f,tspan,y0,n)
%四阶Runge-Kutta算法
%f:dy/dt=f(t,y);求解区间tspan:[t0,tf];初值y0=y(t0)=[x0,y0,z0];n采样点数
h=(tspan(2)-tspan(1))/n;
t=tspan(1):h:tspan(2);
y=zeros(length(y0),length(t));
y(:,1)=y0;
for m=2:length(t)
k1=f(t(m-1),y(:,m-1));
k2=f(t(m-1)+h/2,y(:,m-1)+k1*h/2);
k3=f(t(m-1)+h/2,y(:,m-1)+k2*h/2);
k4=f(t(m-1)+h,y(:,m-1)+k3*h);
y(:,m)=y(:,m-1)+(k1+2*k2+2*k3+k4)*h/6;
end
t=t';
y=y';
end
function dy_dt=lorenz(t,y)
%y=[x,y,z]储存三个变量的矩阵
p=10;
r=28;
b=8/3;
dx_dt=p*(y(2)-y(1));
dy_dt=r*y(1)-y(2)-y(1)*y(3);
dz_dt=y(1)*y(2)-b*y(3);
dy_dt=[dx_dt;dy_dt;dz_dt];
end