写于2017年7月30日。 阅读《复杂》一书时的笔记及延伸。 本文涉及到的生态学、数学、计算机科学部分都比较肤浅,若有错漏,欢迎斧正。javascript
原文php
咱们多少接触过这样一个问题:java
问:第n月时,一共有多少只兔子?算法
对,描述兔子数量的数列就是咱们熟悉的斐波那契数列,不少人都是经过这个问题了解递归的吧(也许吧,也多是Tower of Hanoi)?dom
不过兔子怎么可能“永不死去”呢!那咱们如今开始考虑兔子的出生率和死亡率。先从容易的来:每对兔子父母每一年生四只小兔,而后死去。若是一开始有两只兔子(第0年),那么第1年会有四只兔子,第二年会有8只兔子……每一年兔子的数量会翻一番。记第 t 年的兔子数量为 ,那么:
,即
。很显然,若是不受限制,兔子的数量会愈来愈多,最终撑满这个星球,乃至整个宇宙。性能
假如咱们考虑种群数量增加所受的限制呢?可想而知,若是种群数量愈来愈多,也许不少小兔子因为太过拥挤,缺乏食物和空间,没有繁殖就死去。整个种群的数量就不会呈现上述无限增加的状况了。生物学家用一种叫 logistic model 的简化方式来描述这种状况下的群体增加: 。 其中,
为这一代的种群数量,
为出生率,
为死亡率,
为承载能力。spa
举个例子,若是出生率为2,死亡率为0.4,承载力为32,第1代有20只兔子,套用上面的模型,那么第2代有12只兔子;再把这个结果代入计算,会得出第三代仍然有12只兔子;今后种群数量维持在12。code
若是咱们改变一些参数,好比把死亡率降到0.1,那么依据模型计算,第2代有14.25只兔子,第三代为15.01816只兔子(不要在乎兔子的数量为何能够是小数)。实际上咱们的计算过程是把这一代的计算结果代入模型公式,计算下一代的结果,这个重复不断的过程就是迭代,对模型进行迭代。cdn
由 logistic model 进行迭代计算仍是有些麻烦,咱们能够再进行一点简化:把出生率和死亡率合成一个变量 ,种群数量由承载率(当前种群数量与最大可能的种群数量的比率)
代替,
,因为当前种群数量老是介于0和
之间,因此
老是介于0和1之间。blog
那么咱们就能够把上面的logistic model的公式改写一下,因而咱们有: 。这个方程称为logistic map,是动力系统理论和混沌研究中的一个重要方程。
若是咱们让 值变化,那么logistic map就颇有趣了。
不妨先假定 ,咱们发现,无论
的初始值是什么(先用0.2试试吧),最后总会达到同一个固定的值:
不一样的初始值只会让到达0.5的速度有快有慢,但通过若干步骤后,都会到达0.5。那么这个0.5就称为不动点(fixed point)。
咱们把 的值调大,也许这样的不动点依而后存在,但到达不动点的速度会愈来愈慢。假如
,咱们再来看看,会发现状况彷佛不太同样了:
R=3.1,x0=0.2
的值最终会在0.5580141和0.7645665之间振荡。咱们称之为吸引子。
随着 值的变化,情形会更加复杂。我从wikipedia上把结论摘录以下:
彷佛有点枯燥,不过不要紧,咱们来画个图吧,经过图形来了解一下这个混沌系统。取一个超过3.5699, 不超过4的 值,这里咱们不妨取
,仍是令
初始值是0.2,那么迭代100次:
R=4,x0=0.2
一个感受,杂乱无章。对于每一个 的值,虽然它能惟一决定下一个
的值是什么,但它们却组合成一个看起来很是随机的轨迹。在计算机中,咱们甚至能够用它来生成伪随机数。所以,表面的随机性可能来自很是简单的肯定性系统。
不只如此,对于一个能产生混沌的 值,若是初始值有任何的不肯定性,那么必定时间后的轨迹就没法预测了。仍是刚刚的图,咱们考虑稍稍修改一下初始值,好比修改小数点后第10位,假定初始值是0.2000000001会怎么样?这与0.2很是接近,咱们把两条轨迹绘制到一块儿看看:
能够看出,大概在 时,两条轨迹已经分开,
的值已经没法预测了。实际上只要初始值有不肯定性,无论精确到小数点后多少位,最终都会在
大于某个值的时候变得没法预测。
接下来,咱们就来尝试使用logistic model的混沌特性来实现一种简单的伪随机算法。
function* RandomGenerator() {
let seed = .2;
function getNext(x) {
return 4 * x * (1 - x);
}
for (let i = 0; i < 30; i++) {
seed = getNext(seed);
}
while (true) {
seed = getNext(seed);
yield seed;
}
}
const randomGenerator = RandomGenerator();
function random () {
return randomGenerator.next().value;
}
复制代码
实际上一些常见的伪随机数生成算法,例如线性同余法,也是使用了相似的手段,经过迭代产生混沌系统。而这类的算法所追求的,我以为有三个方面的内容: