寫於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;
}
複製代碼
實際上一些常見的僞隨機數生成算法,例如線性同餘法,也是使用了相似的手段,經過迭代產生混沌系統。而這類的算法所追求的,我以爲有三個方面的內容: