迷你世界Laplace 数学 / 图版 M18 — 空间填充曲线

一条线填满正方形

一条线段和一个正方形,谁的点更多?康托尔的答案是一样多。十几年后,皮亚诺和希尔伯特找到了更出人意料的东西:一条连续的线,经过正方形里的每一个点。托盘里的铜丝是这条线的第五步。

向下滚动

01

一样多的点

1877 年,康托尔证明:线段上的点和正方形里的点可以一一配对,一个不多,一个不少。他在第二年发表了这个结果。

思路是交错数字。线上的点写成小数 t = 0.a₁a₂a₃a₄…,奇数位给横坐标,偶数位给纵坐标:(0.a₁a₃…, 0.a₂a₄…)。反过来也能拼回去。戴德金回信指出,有的数有两种小数写法,这样简单地交错并不完全成立;康托尔随后改正了证明。

他在给戴德金的信里写过一句「我看到了,但我不相信」。这句话常被当作惊讶;数学史家古维亚认为,他担心的是证明有没有漏洞。

这种配对不连续。线上紧挨着的 0.4999 和 0.5000,在正方形里一个靠近顶边,一个在底边上。1879 年,内托证明,线段和正方形之间不存在既一一对应、又连续的映射。

02

连续地经过每一点

放弃一一对应,只要连续:能不能让一条线经过正方形里的每一点?1890 年,皮亚诺给出了第一个例子。

他把线段分成 9 段,正方形分成 3 × 3 格,第几段对应第几格,相邻的段对应相邻的格;每一格再分成 9 格,一直分下去。他的定义全是三进制数字的运算,论文里没有一幅图。

托盘里的铜丝是第二步:81 格一笔走完,每一步都走到相邻的格子。这样得到的曲线叫空间填充曲线。

03

希尔伯特的图

第二年,希尔伯特在同一本期刊上发表了一篇两页的短文,配了图。他每次一分为四:线段四等分,正方形分成 2 × 2,四段依次对应四格,相邻的两段对应有公共边的两格。

每一格再一分为四,曲线在里面重复同样的 ∩ 形;第一格和最后一格里的要转向,前后才接得上。然后一直分下去。

第 n 步的铜丝穿过 4ⁿ 个格子的中心。每细分一步,原来每一格里的一小段换成一个小 ∩。

前面的铜杆是线段 [0, 1],它的颜色和托盘里的格子一一对应:线上哪一段,就是正方形里哪一块。

04

极限

在边长为 1 的正方形里,第 n 步的铜丝长 2ⁿ − 2⁻ⁿ,每多一步长一倍左右,没有上限。希尔伯特曲线不是哪一根铜丝,而是它们的极限。

同一个 t 的位置却会稳定下来。第 n 步的铜丝离极限处处不超过一个格子的对角线 √2 / 2ⁿ,所以各步一致地收敛,极限 H(t) 是连续的:t 变一点,H(t) 只变一点。

红珠停在 t = 0.3。每细分一步,它移动的距离越来越短,停在 H(0.3) 附近。

05

有的点经过三次

正方形里任取一点,每一步都能找到包含它的格子。这些格子对应的线段一段套着一段,缩到一个 t,H(t) 就是这一点。所以没有一个点漏掉。

但有的点被经过不止一次。正方形的中心是四个小方格共同的角,曲线经过它三次:t = 1/6、1/2、5/6,写成二进制是 0.0010101…、0.1 和 0.1101010…。

这不是这条曲线的缺陷。按内托的定理,连续地经过正方形每一点的曲线,一定有点被经过多次。

06

近的还是近的

线上相邻的一小段,落在正方形里是一小块。托盘里亮起的是连续的 64 个格子,它们总挤在一块大约 8 × 8 的地方。

在第 8 步的曲线上量:编号相差 k 的两个格子,相距从不超过 √(6k) 个格子。6 是希尔伯特曲线在这种量法下的确切常数(哈弗科特与范瓦尔德芬,2010)。

反过来不成立。正方形里紧挨着的两个格子,编号可能相差很远:中线两侧的格子,一个在曲线的前半段,一个在后半段。把正方形排成一条线,这种情况总会出现。

07

Z 序

把横坐标和纵坐标的二进制位交错排列,就得到 Z 序编号,也叫莫顿码。1966 年,IBM 加拿大公司的莫顿为一个地理数据库提出了它。这和康托尔交错数字是同一个想法,只是换成了二进制。

每四格走一个 Z 字,四个小 Z 组成一个大 Z。它算起来极快,但每走完一块就要跳到下一块:右边托盘里,铜丝在这些地方离开盘面,跨过去。最大的一跳几乎横穿整个正方形。

所以 Z 序的极限不是连续曲线。同样连续的 16 个编号,在希尔伯特曲线上总是一小块,在 Z 序里有时分成相隔很远的几块;读数是两边各自最远的两格相距多少。

因为简单,它用得很广。必应地图把地图图块的行号和列号按二进制位交错,得到图块的编号(quadkey)。

08

一族曲线

1900 年,摩尔把四条希尔伯特曲线首尾连起来,得到一条闭合的曲线:走完一圈,回到起点旁边。

皮亚诺的曲线每次一分为九,按蛇形走。按同样的思路,还可以把正方形分成三角形,或者分成大小不同的块。

龙形曲线来自折纸:把纸带对折,再对折,展开后每个折痕都折成直角。它不填满正方形,但从同一点出发、方向各转 90° 的四条龙形曲线,把方格纸上的格线各走一遍,互不重复(戴维斯与高德纳,1970)。

09

沿着曲线扫描

把灰度图变成只有黑白两色的点,一种办法是误差扩散:每个点取黑或白,把取整的差额留给下一个点。

按行扫描时,差额总往一个方向推,容易出现条纹。沿希尔伯特曲线走,下一个点总在附近,方向不断改变,差额就分散得更匀(维略与戈梅斯,1991)。

托盘里,红珠沿铜丝走过 4096 格,每过一格就定下黑或白。这里用的是最简单的版本:差额全部传给下一格。

10

地图和数据库

数据库按一维的顺序存放记录。把二维的位置按空间填充曲线编号,附近的地点大多存在相邻的位置,一次查询只要读几段连续的记录。

托盘里的红框是一次查询。框里的格子在线上分成若干段:两只托盘读出的是这个框的实际段数,希尔伯特曲线通常比 Z 序少。

1994 年,卡迈勒和法卢索斯按希尔伯特编号排列 R 树的节点,称为希尔伯特 R 树。矩阵和图像在内存里也常按 Z 序或希尔伯特顺序分块存放,让相邻的元素存得更近。

11

球面上的格子

谷歌的 S2 几何库这样给地球表面编号:把球面投到外切立方体的 6 个面上,每个面按希尔伯特曲线一分为四,最多分 30 层。

6 条希尔伯特曲线首尾相接,绕球一周成为一条闭合的曲线;相邻两个面的走向互为镜像,才能接上。每个格子的 64 位编号,就是它的中心在这条曲线上的位置。

第 30 层的格子平均 0.74 平方厘米,边长 6 到 9 毫米,一共约 6.9 × 10¹⁸ 个。为了让格子大小相近,立方体面上的坐标先经过一个二次函数,再投到球面上。

12

实验台

阶数从 1 到 8。在铜杆上拖动红珠,或在托盘里拖动,两边一起动。打开「邻域」,红珠前后各 k 格亮起:左边是希尔伯特曲线,右边是同样编号的 Z 序。

试一试在实验台上把阶数从 1 调到 8,红珠停在同一个 t。它在正方形里的位置会怎样变?为什么变化越来越小?

模型省略了什么

托盘里的铜丝是有限的某一步,真正的希尔伯特曲线是它们的极限,没有一根铜丝能做出来。铜丝在拐角处弯成圆角,数学上的折线是直角。第 7、8 步的格子太小,铜丝改为盘底的嵌线;Z 序在那两步只嵌出相邻的步子,跳跃省略。Z 序铜丝拱起来跨过去,只是为了画出跳跃,不属于数学定义。铜杆代表参数 t 的区间 [0, 1],不是铜丝的长度。格子和铜杆的颜色只用来对应位置。第一章的配对只取 4 位小数,落在边上的点,针插在离边几毫米处。抖动用的是最简单的误差扩散。钢球刻的是 S2 第 3 层,球面投影按 S2 的二次函数计算。

容易误解的地方

空间填充曲线不是「很密的折线」:每一步的折线都只是近似,极限才经过每一点,而且有些点经过不止一次。「点一样多」不等于「可以连续地一一对应」:康托尔的配对不连续,连续的又不能一一对应。Z 序的极限不连续;把 Z 序当作希尔伯特曲线的简化版并不准确。线上相近一定在正方形里相近,正方形里相近却不一定在线上相近。S2 的格子并不完全一样大,第 30 层的面积在 0.44 到 0.93 平方厘米之间。

资料来源

  1. G. Cantor(1878):Ein Beitrag zur Mannigfaltigkeitslehre,J. reine angew. Math. 84: 242–258
  2. F. Q. Gouvêa(2011):Was Cantor Surprised?,American Mathematical Monthly 118(3): 198–209
  3. E. Netto(1879):Beitrag zur Mannigfaltigkeitslehre,J. reine angew. Math. 86: 263–268
  4. G. Peano(1890):Sur une courbe, qui remplit toute une aire plane,Math. Ann. 36: 157–160
  5. D. Hilbert(1891):Über die stetige Abbildung einer Linie auf ein Flächenstück,Math. Ann. 38: 459–460
  6. E. H. Moore(1900):On certain crinkly curves,Trans. AMS 1: 72–90
  7. H. Sagan(1994):Space-Filling Curves,Springer
  8. H. Haverkort, F. van Walderveen(2010):Locality and bounding-box quality of two-dimensional space-filling curves,Computational Geometry 43(2): 131–147(希尔伯特曲线 WL₂ = 6,Z 序无界)
  9. G. M. Morton(1966):A computer oriented geodetic data base and a new technique in file sequencing,IBM Ltd., Ottawa
  10. Microsoft:Bing Maps Tile System(quadkey 按位交错)
  11. C. Davis, D. E. Knuth(1970):Number representations and dragon curves,J. Recreational Mathematics 3: 66–81, 133–149(收于 Knuth, Selected Papers on Fun and Games)
  12. L. Velho, J. de M. Gomes(1991):Digital halftoning with space filling curves,Computer Graphics 25(4): 81–90
  13. C. Faloutsos, S. Roseman(1989):Fractals for secondary key retrieval,PODS ’89: 247–252
  14. I. Kamel, C. Faloutsos(1994):Hilbert R-tree: An improved R-tree using fractals,VLDB ’94: 500–509
  15. B. Moon, H. V. Jagadish, C. Faloutsos, J. H. Saltz(2001):Analysis of the clustering properties of the Hilbert space-filling curve,IEEE TKDE 13(1): 124–141
  16. S. Chatterjee 等(1999):Recursive array layouts and fast parallel matrix multiplication,SPAA ’99: 222–231
  17. S2 Geometry:S2 Cells(S2 曲线、中心被经过三次的脚注)
  18. S2 Geometry:S2 Cell Statistics(各层格子面积)
  19. S2 Geometry Library 源代码(Apache-2.0)

数据

Every curve on the model is computed for this page: the Hilbert curve by the quadrant-by-quadrant conversion between index and cell, Z-order by interleaving bits, Peano and Moore recursively, the dragon from the paper-folding sequence. The S2 curve on the steel ball follows the orientation tables and the quadratic projection of the S2 Geometry Library (Google, Apache License 2.0), rewritten here; cell sizes are from the S2 cell statistics page. The worst-case locality constant 6 of the Hilbert curve is from Haverkort and van Walderveen (2010); the measurements on the page are our own. The trays, wires, rod and ball are our own model.

本页的文字、图片和模型采用 CC BY-NC 4.0 许可:可以免费用于教学和其他非商业用途,可以修改,请注明出自 world.lapla.si。上面列出的第三方素材仍按各自的许可。

延伸观看

  • 3Blue1Brown · YouTube · 英语 在 YouTube 打开

播放器来自 YouTube,按下播放后才加载。

数学 · 全部图版