一、关于分形与混沌
关于分形的起源,要非常准确的找出来是非常困难的。研究动态系统、非线形数学、函数分析的科学家,已数不胜数。尽管分形的早期线索已非常古老,但这一学科却还很年轻。比如关于动态系统和细胞自动机的大部分工作可以追溯到冯-诺依曼;但是,直到Mandelbrot 才如此清楚地将自然现象和人工现象中的混沌及分形同自相似性联系在一起。大家如果对此感兴趣,可进一步查阅有关资料。下面我们看一看分形的概念。
什么是分形呢?考虑到此文的意图,我们无意给出它严格的定义,就我们的目的而言,一个分形就是一个图象,但这个图象有一个特性,就是无穷自相似性。什么又是自相似呢?在自然和人工现象中,自相似性指的是整体的结构被反映在其中的每一部分中。比如海岸线,常举的例子,你看它10公里的图象(曲线),和一寸的景象(曲线)是相似的,这就是自相似性。
与分形有着千差万屡的关系的,就是混沌。混沌一词来源与希腊词汇,原意即“张开咀”,但是在社会意义上,它又老爱和无序联系在一起。解释分形和混沌的联系,要注意到分形是分离吸引子和排斥吸引子产生的,因此某种意义上说,分形是混沌行为的视觉表现。
看这些东东是不是比较枯燥?呵呵,我也没办法给大家弄些美丽的图片看看---不过你可以到外面走走了,看看天上武汉的云是不是很漂亮?然后再回来,下一篇我将给大家说一点数学知识,并把我写的程序拿出来,谈谈分形的产生。
二,一点数学知识
怎么样,武汉的云还可以嘛!如果你想在计算机上实现它,我想分形法就是最好的选择。可惜我太菜,武汉的云也只能记在心中了。如果有谁实现了,请你一定分我一杯羹好吗:)?
另外,想必女士也不少的,我觉得她们要学习这方面的理论再合适不过。马克思
说女人天生就是美,虽然美天生不是女人:)。她们的感知能力是天生的。再说啦,冷冰冰的系统软件你不乐意,当然也就花花草草了:)---而且,薪金也不菲嘛!
好啦,不贫啦,言归正传,咱们看一看分形的产生。
首先要说明的是,这里介绍的数学知识,只是为了介绍分形概念的方便。如果你想详细了解这方面的知识,复变函数、概率、混沌系统等等一系列的东西,你最好去专门看一看。
1,吸引点和逃离点
这是描述分形产生的基本词汇。我们考虑这样一个函数f:
f: R -> R
x -> f(x)
函数和它自身的复合,比如f,记作f(f(x))。如果你将f再一次作用于结果,则记为f(f(f(x))),这样你就完成了一个函数f的复合迭代。很显然,在定义域的某一点上的函数迭代,有可能是发散的或收敛的。使迭代发散的点称为斥点;然而,如果迭代结果趋于某一个孤立的点,则该点称为吸引点。在迭代中,两者都不是的点,就称为中性点。
下面考察某些迭代函数或迭代几何过程的所有吸引点的集合。当迭代函数或迭代几何过程的吸引集是一个无限自相似集(也就是分形,understand?),那么这个吸引集就称为一个奇异吸引子。
2,分叉图
某些实函数的吸引子集合,比如一个简单的例子:
f(x)=x**2 +c //2是幂:)
对于某些实常数c进行函数迭代。假设从c=-1.1,x=0开始,你不妨拿个计数器:),进行迭代。重复作下去,你会发现一个有趣的现象:迭代结果在-1.0左右和0.1左右跳来跳去。如果迭代次数很多,比如200次,并且对一定范围内不同的c值都这样做,将会有一个非常美妙的令人惊讶的结果。
到底如何呢?呵呵,关键时候,偏要感冒---我可以把每次迭代的结果画成图,可惜没办法给你分享。---我只能干吧吧的说,对很多c的取值都这样做,将会得到一幅图形,即分叉图。
了感欣慰的是,后面我将给大家介绍程序的实现。你回去一试,不就ok了?
很显然,分叉图是一类简单而又有趣的分形。应用很多。
3,Sierpinski三角形
从上面的介绍中,你也许已发现分形产生的一个途径。另一条途径就是通过重复进行某个特殊的几何过程。这类分形叫做迭代函数系统(IFS)。
Sierpinski三角形是一个比较经典的例子。
我只能把它形成的过程说一说了,也不管那百闻不如一见的话。
(1)三角形,取三边的中点并相互连接---产生四个全等的小三角形;
(2)根据(1)对每一个小三角形如此迭代。
重复一定次数,就会产生一个奇异吸引子,也就是一个分形。
程序实现的技巧后面详细叙述。
分形是可递推产生的,我不在详细说了,比如Cantor集的例子,大家在一般书中应能找的到.我最后想说说IFS变换规则。它在分形算法的描述和程序的实现中非常重要。
4,迭代函数系统变换
产生Sierpinski三角形和其它一些分形的几何规则可以用一套包括滑动、伸展和旋转在内的运算来进行描述。这类数学运算称为仿射变换,通常用矩阵运算实现其编程。
如下表,给出了Sierpinski三角形的规则的矩阵编码形式:
--------1-------2-------3-------4--------5-------6---------概率值-----
1------0.5------0-------0------0.5------25-------1---------0.33------
2------0.5------0-------0------0.5------1--------50--------0.33------
3------0.5------0-------0------0.5------50-------50--------0.33------
如表中d[1,5]的位置是25;表最后一列有特殊的意义,表示这一行所进行的变换将要被用到的可能性或概率。
所谓的变换,到底是如何应用的呢?假设变换是将(x,y)映射到(x’,y’),你
看一看第i行所实施的的变换:
x’=d[i,1]x +d[i,2]y +d[i,5]
y’=d[i,3]y +d[i,4]y +d[i,6]
你就会明白。概率如何应用呢?你看:
i=random(3)+1 //在变换之前:)
不行了吗?
这些东东的应用也许我们都可以掌握,但发现这样的矩阵,并不是一件简单的事。我希望有志在这方面有所发展的,都好好找相关的数学理论书好好看一看。不要把时间都花在玩上嘛!书中自有黄金屋,书中自有……:)
下面看分叉图和Sierpinski三角形的程序实现(delphi6.0)。
三,程序例子
深入搞图形图象,数学还是挺重要的。下面,只是把上次说的数学知识用计算机实现
一下,大家如果回去自己写一写,看到那图案,如果你认为这些事是如此的有趣,立志要深入下去了,我将非常高兴。
程序画出了一个分叉图,一个Sierpinski三角形(delphi6.0)。在例子中,你要看它
们,都是通过操作windows菜单,即绘图函数分别在两个菜单的响应事件中。程序不麻烦,我就不多说了。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, ExtCtrls;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
Control1: TMenuItem;
picture1: TMenuItem;
picture2: TMenuItem;
exit1: TMenuItem;
Help1: TMenuItem;
Panel1: TPanel;
Image1: TImage;
procedure exit1Click(Sender: TObject);
procedure picture1Click(Sender: TObject);
procedure picture2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
var
c,x,y,scale:double;
i,j,k,MaxX,MaxY,x1,y1:integer;
d:array[1..6,1..6] of double;
{$R *.dfm}
procedure TForm1.exit1Click(Sender: TObject);
begin
close;
end;
//分叉图的实现
procedure TForm1.picture1Click(Sender: TObject);
begin
c:=-2.0;
MaxX:=800;
MaxY:=600;
scale:=55.0;
image1.Canvas.Brush.Color:=clwhite;
image1.Canvas.FloodFill(10,10,clgreen,fsBorder);
for i:=0 to MaxX do
begin
x:=0.0;
c:=c+2.25/MaxX;
for j:=0 to 40 do
begin
x:=x*x+c;
if j>5 then
image1.Canvas.Pixels[i,round(MaxY/2+x*scale)]:=clblue;
end;
end;
end;
//Sierpinski三角形
procedure TForm1.picture2Click(Sender: TObject);
var i,j:integer;
begin
d[1,1]:=0.5;d[1,2]:=0;d[1,3]:=0;d[1,4]:=0.5;d[1,5]:=25;d[1,6]:=1;
d[2,1]:=0.5;d[2,2]:=0;d[2,3]:=0;d[2,4]:=0.5;d[2,5]:=1;d[2,6]:=50;
d[3,1]:=0.5;d[3,2]:=0;d[3,3]:=0;d[3,4]:=0.5;d[3,5]:=50;d[3,6]:=50;
image1.Canvas.Brush.Color:=clwhite;
image1.Canvas.FloodFill(10,10,clgreen,fsBorder);
x:=1000;
y:=1000;
j:=2;
for i:=0 to 100000 do
begin
k:=random(3)+1;
x:=d[k,1]*x+d[k,2]*y+d[k,5];
y:=d[k,3]*x+d[k,4]*y+d[k,6];
x1:=round(x)*j+300;
y1:=round(y)*j+150;
image1.Canvas.Pixels[x1,y1]:=clblue;
end;
end;
end.
好啦,感谢你...大家共同努力哟!