談到隨機,多數開發者應該會想到random之類的函式,先前我在專欄文章〈你的程式夠「亂」嗎?〉談過,程式庫提供的隨機亂數是假的,都是偽隨機,是基於確定性的演算,只能用於隨機性要求沒那麼高的場合,對於安全之類需求就不適用,必須追尋真正的隨機事件,像是硬碟等真實裝置的雜訊,或者密碼學安全偽隨機數。

random?stochastic!

就我個人的想法而言,萬物皆有規律,只不過在人類發掘出規律之前,對於無法理解的現象稱為隨機罷了;近來有個CVE-2022-38392安全漏洞就蠻有趣的,誰能想像到〈播放Janet Jackson音樂影片造成數款老舊筆電掛點〉,除此之外,利用硬碟聲音與廢熱來推測並傳送資料的傳說,也時有所聞!

相對於追求真正的隨機事件,另一個方向是令接下來的事件不具確定性、卻也沒有完全的自由度,例如高斯雜訊(Gaussian noise),雖然雜訊依舊是隨機的,沒辦法預測會生成什麼值,然而將雜訊加以統計,會呈現高斯分布,也就是常態分布。

在這邊我想探討的不是random,而是stochastic,兩者中文都翻為隨機,彼此卻有所不同。我是在試圖理解L-system時,首次接觸到stochastic這個形容詞,在先前〈碎形與L-system〉就談過Stochastic L-system,在維基百科〈L-system〉條目裡,也有〈Stochastic grammars〉的說明,這是指衍生規則的選擇會有不確定性,然而,不確定性會受到指定的機率影響。

方才提及了雜訊,可想而知的是,Perlin雜訊、Worley雜訊、藍雜訊等,也是隨機過程(stochastic process)的產物,至於隨機過程這個詞,基本上,也不是嚴謹定義的名詞,這邊採取的是《The Information: A History, a Theory, a Flood》裡第855頁的談到的:

neither deterministic (the next event can be calculated with certainty) nor random (the next event is totally free)

隨機過程的結合

方才談到,在人類發掘出規律之前,對於無法理解的現象,我們通常會將其稱為隨機;然而,隨機過程的下個事件,並沒有完全的自由度,若能掌握、善用其中非自由的部分,其實就能進行相對應現象之模擬,只是在不同領域當中,會有不同的應用。而我特別喜愛在圖像創作或3D建模時,運用隨機過程,讓程式所生成的作品各不相同,卻又擁有特定的風貌。

思考隨機過程裡非自由的部分該如何結合,則是另一種挑戰。我在先前〈自然噪聲與碎形〉談到的碎形布朗運動,是結合的方式之一,除了將Perlin雜訊不斷地疊加,我們也可以結合不同雜訊進行疊加,例如結合Worley雜訊,這就可以構成〈雜訊結合雜訊〉裡看到的漣漪效果。

思考隨機過程裡非自由的部分如何結合,有時會需要靈感及一些經驗,這也是我經常觀摩他人作品的原因,有時甚至是觀察自然現象。就像近來我發布的作品〈巨岩迷陣〉,靈感的來源就是看到世界自然遺產之一的巨人堤道(Giant's Causeway),如果你在網路上搜尋,就可以看到堤道的圖片。

當我第一眼看到巨人堤道,直覺想到這類似Voronoi圖,而這就是在運用經驗了,當然石柱高低各有高低起伏,我們可以透過Perlin雜訊模擬。就我而言,想模擬巨人堤道建立3D模型並不是難事,但我想讓圖樣更有趣一些,例如,讓那些柱狀節理(Columnar jointing)構成迷宮如何?

畫迷宮並不是難事,但迷宮必須能轉換為柱狀節理;不過,在轉換成柱狀節理之前,又必須將迷宮晶格化;若我們要將迷宮晶格化,就想到了先前〈淺談圖片取樣〉談過的,將取樣點作為Voronoi分割的依據。等等!這表示我必須將迷宮輸出為圖片,再做圖片取樣嗎?

其實,最終需要的是像素資訊,只要能將迷宮轉換為像素就可以了。先前我在〈趣拼王氏磚〉裡談過,迷宮裡的每個區塊可以對應至王氏磚,最後只要定義16個像素陣列,將迷宮轉為代表王氏磚的像素陣列,就能得到迷宮圖,後續也就能進行圖片取樣了。

迷宮偏差/熵值遮罩

巨岩迷陣〉靈感來自巨人堤道,經驗則來自過去對Voronoi等隨機過程的應用。完成繪製之後的滿足感,讓我思考著:迷宮還有沒有其他隨機過程的結合方式?

在運用一些關鍵字進行搜尋之後,我發現了Kevin Giovinazzo的〈Generating mazes from pictures, or "Masking Entropy"〉,在這之前,我從來沒想過可以這樣運用迷宮偏差(bias)。

我在先前〈迷宮產生演算法之美妙〉曾經談過二元樹演算,也談過只能往上、往右打通路徑的迷宮演算,其偏差顯而易見,因為不論你怎麼改變生成細胞的順序,最後所生成的迷宮,其根節點一定是在右上角。

為了令迷宮看起來更為混沌,通常是要避免偏差,此時如果我們採用〈遞迴回溯迷宮〉,就是上下左右四個鄰居的選取通常會透過random之類函式,不偏袒任何一個鄰居。

如果選擇鄰居時特意製造偏好呢?例如,一律先選同列鄰居?那麼,所產生的迷宮就會有完全的水平偏差,走道幾乎都是水平連通,就不像迷宮了,Kevin Giovinazzo的文件稱此時熵為零,而文件裡的熵並非精確定義,也不是夏農熵(Shannon entropy)之類的概念,只是代表混亂程度,為了能像個迷宮,讓同列鄰居的選擇機率高就可以了,那麼,多數的走道會是水平連通,能構成不同風格的迷宮。

在構造迷宮時,透過遮罩(Mask)來構造不同形狀的迷宮,是常見的方式;從另一角度來看,遮罩也算是給予迷宮偏差的一種方式,因為遮罩裡被標示無法行走的區塊,可視為被選擇為路徑的機會為零;如果套用了遮罩的迷宮,進一步將區塊對應至王氏磚,迷宮也就可以依趙16塊磚的不同而變化,像是〈Maze in 迷宮〉這個作品。

從這個角度來看,若遮罩裡被標示的區塊並非無法行走,而是偏好選擇同列鄰居,相對地,未被標示的區塊則是偏好選擇同行鄰居呢?水平與垂直通路會構成明顯的視覺差異,若標示區塊時,使用Perlin雜訊、Worley雜訊,或甚至是特定圖樣(例如文字),那麼,最後構成的迷宮,也會有明顯而相對應的圖樣。

因為是基於遮罩,只不過遮罩標示處有不同的選擇偏好,而非可通行或不可通行,Kevin Giovinazzo才會稱為熵值遮罩(Masking Entropy)吧!

混沌 vs. 規律

就可視化而言,透過迷宮展示隨機過程,雖然可以有驚人的視覺效果,但這並不表示,隨機過程只能應用在圖像或3D建模,在其他領域當中,如統計模型或物理模擬,隨機過程也是非常重要的運用。我在先前〈程式猴與基因演算法〉談過的基因演算法、適應度,就是混沌裡的規律,一旦找到了正確的方向,猴子打出《莎士比亞全集》就成為可能。

只不過思考隨機過程這類問題時,我往往會有個疑惑,或說是特別的感受:究竟我是在混沌中找出規律?還是在規律裡摻雜混沌?或者兩者都有呢?不斷地思考這交錯不明的關係,也正是探究隨機過程的樂趣所在吧!

專欄作者

熱門新聞

Advertisement