解決多維空間點索引需要解決2個問題,第一,如何把多維降為低維或者一維?第二,一維的曲線如何分形?
填充曲線(Space-filling curve)
在數學分析中,有這樣一個難題:能否用一條無限長的線,穿過任意維度空間里面的所有點? 常見的有: Z階曲線(Z-order curve)、皮亞諾曲線(Peano curve)、希爾伯特曲線(Hilbert curve),之后還有很多變種的空間填充曲線,龍曲線(Dragon curve)、 高斯帕曲線(Gosper curve)、Koch曲線(Koch curve)、摩爾定律曲線(Moore curve)、謝爾賓斯基曲線(Sierpiński curve)、奧斯古德曲線(Osgood curve)等
在1890年,Giuseppe Peano 發現了一條連續曲線,現在稱為 皮亞諾曲線(Peano curve),它可以穿過單位正方形上的每個點。他的目的是構建一個可以從單位區間到單位正方形的連續映射。 Peano 受到 Georg Cantor 早期違反直覺的研究結果的啟發,即單位區間中無限數量的點與任何有限維度集合中無限數量的點基數相同。 Peano 解決的問題實質就是,是否存在這樣一個連續的映射,一條能填充滿平面的曲線。如下圖就是他找到的一條曲線。一般來說,一維的東西是不可能填滿2維的方格的。但是皮亞諾曲線恰恰給出了反例。皮亞諾曲線是一條連續的但處處不可導的曲線。
皮亞諾曲線的構造方法如下:取一個正方形並且把它分出九個相等的小正方形,然后從左下角的正方形開始至右上角的正方形結束,依次把小正方形的中心用線段連接起來;下一步把每個小正方形分成九個相等的正方形,然后上述方式把其中中心連接起來……將這種操作手續無限進行下去,最終得到的極限情況的曲線就被稱作皮亞諾曲線。
一年后,即1891年,希爾伯特就作出了這條曲線,叫希爾伯特曲線(Hilbert curve)。如下圖就是1-6階的希爾伯特曲線。
- 如下圖,希爾伯特曲線填充滿3維空間示意圖。
在數學分析中,空間填充曲線是一個參數化的注入函數,它將單位區間映射到單位正方形,立方體,更廣義的,n維超立方體等中的連續曲線,隨着參數的增加,它可以任意接近單位立方體中的給定點。除了數學重要性之外,空間填充曲線也可用於降維,數學規划,稀疏多維數據庫索引,電子學和生物學。空間填充曲線的現在被用在互聯網地圖中。
分形
皮亞諾曲線的出現,說明了人們對維數的認識是有缺陷的,有必要重新考察維數的定義。這就是分形幾何考慮的問題。在分形幾何中,維數可以是分數叫做分維。多維空間降維以后,如何分形,也是一個問題。分形的方式有很多種,這里有一個列表,可以查看如何分形,以及每個分形的分形維數,即豪斯多夫分形維(Hausdorff fractals dimension)和拓撲維數。
Z階曲線(Z-order curve)
前幾單介紹的 Genhash 是一種地理編碼,由 Gustavo Niemeyer 發明的。它是一種分級的數據結構,把空間划分為網格。Genhash 屬於空間填充曲線中的 Z 階曲線(Z-order curve)的實際應用。
何為 Z 階曲線? 如下圖,這個曲線比較簡單,生成它也比較容易,只需要把每個 Z 首尾相連即可。
Z 階曲線同樣可以擴展到三維空間。只要 Z 形狀足夠小並且足夠密,也能填滿整個三維空間。
Geohash 能夠提供任意精度的分段級別。一般分級從 1-12 級。利用 Geohash 的字符串長短來決定要划分區域的大小,一旦選定 cell 的寬和高,那么 Geohash 字符串的長度就確定下來了。
地圖上雖然把區域划分好了,但是還有一個問題沒有解決,那就是如何快速的查找一個點附近鄰近的點和區域呢?
Geohash 有一個和 Z 階曲線相關的性質,那就是一個點附近的地方(但不絕對) hash 字符串總是有公共前綴,並且公共前綴的長度越長,這兩個點距離越近。由於這個特性,Geohash 就常常被用來作為唯一標識符。用在數據庫里面可用 Geohash 來表示一個點。Geohash 這個公共前綴的特性就可以用來快速的進行鄰近點的搜索。越接近的點通常和目標點的 Geohash 字符串公共前綴越長(特殊情況除外)
在前一章講 Geohash 編碼的時候,提到Geohash碼生成規划: “偶數位放經度,奇數位放緯度”。這個規則就是 Z 階曲線。看下圖:
x 軸就是緯度,y軸就是經度。經度放偶數位,緯度放奇數位就是這樣而來的。
Hilbert Curve 希爾伯特曲線
希爾伯特曲線一種能填充滿一個平面正方形的分形曲線(空間填充曲線),由大衛·希爾伯特在1891年提出。由於它能填滿平面,它的豪斯多夫維是2。取它填充的正方形的邊長為1,第n步的希爾伯特曲線的長度是2^n - 2^(-n)。
- 一階的希爾伯特曲線,生成方法就是把正方形四等分,從其中一個子正方形的中心開始,依次穿線,穿過其余3個正方形的中心。如下圖:
- 二階的希爾伯特曲線,生成方法就是把之前每個子正方形繼續四等分,每4個小的正方形先生成一階希爾伯特曲線。然后把4個一階的希爾伯特曲線首尾相連。
- 三階的希爾伯特曲線,生成方法就是與二階類似,先生成二階希爾伯特曲線。然后把4個二階的希爾伯特曲線首尾相連。
- n階的希爾伯特曲線的生成方法也是遞歸的,先生成n-1階的希爾伯特曲線,然后把4個n-1階的希爾伯特曲線首尾相連。
為何要選希爾伯特曲線
這么多空間填充曲線,為何要選希爾伯特曲線?因為希爾伯特曲線有非常好的特性,如下:
(1) 降維: 首先,作為空間填充曲線,希爾伯特曲線可以對多維空間有效的降維。如下圖就是希爾伯特曲線在填滿一個平面以后,把平面上的點都展開成一維的線了。
- 上圖里面的希爾伯特曲線只穿了16個點,怎么能代表一個平面呢?當然,當n趨近於無窮大的時候,n階希爾伯特曲線就可以近似填滿整個平面了。如下圖
(2) 穩定: 當n階希爾伯特曲線,n趨於無窮大的時候,曲線上的點的位置基本上趨於穩定。舉個例子,如下圖:
- 上圖左邊是希爾伯特曲線,右邊是蛇形的曲線。當n趨於無窮大的時候,兩者理論上都可以填滿平面。但是為何希爾伯特曲線更加優秀呢?
- 在蛇形曲線上給定一個點,當n趨於無窮大的過程中,這個點在蛇形曲線上的位置是時刻變化的。
-
- 這就造成了點的相對位置始終不定。再看看希爾伯特曲線,同樣是一個點,在n趨於無窮大的情況下:
- 從上圖可以看到,點的位置幾乎沒有怎么變化。所以希爾伯特曲線更加優秀。
(3) 連續
希爾伯特曲線是連續的,所以能保證一定可以填滿空間。
參考資料
- List of fractals by Hausdorff dimension : https://en.wikipedia.org/wiki/List_of_fractals_by_Hausdorff_dimension
- Z-order curve:https://en.wikipedia.org/wiki/Z-order_curve
- Geohash 在線演示:http://geohash.gofreerange.com/
- 希爾伯特曲線論文:http://www4.ncsu.edu/~njrose/pdfFiles/HilbertCurve.pdf
- 希爾伯特曲線在線演示:http://bit-player.org/extras/hilbert/hilbert-mapping.html
- Mapping the Hilbert curve:http://bit-player.org/2013/mapping-the-hilbert-curve
- 參考資料:https://juejin.im/post/5992720b518825484968bb1c