座標即內容:受約束組合空間的雙射枚舉與可導航生成宇宙

EVEMISSLAB Logic Matrix · EveMissLab / 一言諾科技有限公司

[認識論邊界宣告 / EPISTEMOLOGICAL DISCLAIMER]

[CHT] 本矩陣內所有論文之公式與數據為「啟發式模擬參數」,用於驗證理論架構與推演因果鏈,未經實證校準,請勿作為現實物理測量數據引用 or 處理。EVEMISSLAB 採行「邏輯先行(Logic-First)」原則:概念架構與系統因果映射優先於統計實證,但不排除未來實證對接。


[ENG] The numerical parameters within these frameworks are illustrative model coefficients used for structural verification and causal mapping; they are not empirically calibrated and must not be treated as physical measurements. This matrix operates on a Logic-First principle: conceptual architecture and causal mapping take precedence over statistical empiricism, without precluding future empirical reconciliation.

座標即內容:受約束組合空間的雙射枚舉與可導航生成宇宙

—— 以「詩雲 / Poetry Cloud」為例的技術重建與通用化

本文性質:技術方法論論文,目的是把一類技術從一個具體網頁中抽象出來、形式化、並寫到能照著從零重建的精度
clean-room 聲明:本文只提取方法(演算法與不變式)——方法、數學、演算法不受著作權保護。本文不引用、不重製對方的原始碼、字表資料、品牌或任何受保護的具體表達。所有命名、結構、公式均為本文獨立重述,供獨立重新實作之用。(可查證:對方的字表 DATA 本就不在前端程式碼內,而是另以外部 JSON 載入;詩人真作資料表亦然。本文未取得、亦未重述其內容。)
定位:承 paradigms/ 的 MSSP 與「從尋找到生成」範式;本技術是「生成 > 儲存/尋找」的一個可運行具體化。

0. 摘要

存在一類網頁,它把「所有可能的詩」做成一座可以用滑鼠飛進去的三維星雲。它那座「無限生成星雲」不靠資料庫、不把任何一首『生成的』詩存在任何地方(少數策展真作另從靜態資料載入,見 §11.2,不影響生成層的零儲存);它的網址列裡那一串近百位的數字,本身就是一首詩的完整座標。樸素爬蟲抓到的是一個空殼,因為內容不在 HTML 裡——內容是瀏覽器拿著那個數字,從一個雙射枚舉當場算出來的。

把這件事拆開,會發現它不是「一個關於詩的網站」,而是一個通用模式的實例。本文將這個模式形式化為四個構件:

  1. 內容即索引:用雙射數系把「一個物件」與「一個大整數」一一對應;
  2. 受約束子空間的排名/反排名:當合法物件只佔組合空間的極小一塊(如格律詩的平仄與押韻),對這個受約束子集建立 整數 ↔ 物件 的雙射——這是全技術的皇冠;
  3. 座標 ↔ 索引的可逆綁定:用確定性空間雜湊,把每個索引固定散佈到三維空間的一點,反過來也能由空間位置取回索引;
  4. URL 即狀態:把索引寫進網址,於是「內容定址、零後端、可分享、天然防爬」同時成立。

本文逐一形式化這四個構件、證明其關鍵不變式、抽象出通用的「X 之雲」介面、給出可照著重建的 MSSP 模組藍圖與 Knuth 閘門測試計畫,最後誠實對照它的邊界(訊號淹沒、可發現性、技術與財產的界線)。


1. 緣起:從一個「網頁比賽」到一類技術

原作把它當成一個有趣的網頁作品。但作品只是載體,真正被它一次到位地縫合起來的,是幾條本來各自存在、卻很少被合到一起用的線索:

把這四條合起來,就得到本文要重建的東西。《詩雲》小說裡做不到的「從垃圾裡認出好詩」這一步,這個技術誠實地沒有解決——但它解決了前一半:讓整個空間可被定址、可被導航、可被分享,且零儲存。這一半本身就極有價值,而且與「詩」完全無關,可以套到任何結構化的組合內容上。

1.1 歷史脈絡(站在哪些肩膀上)

這個技術不是憑空的,它是幾個成熟領域第一次被縫在同一個介面背後:

換句話說:rank/unrank(給編號 ⇄ 給物件)是引擎,內容定址(編號即網址)是傳動,確定性散佈(編號 → 座標)是把它變成可飛行空間的車輪。 三者單獨都不新;合起來對準「組合內容」這個目標,就成了一台新車。


2. 全景:四個構件與一句話原理

一句話原理:把內容空間 S 編號成整數區間 [0, |S|),用可逆雜湊把每個編號釘在三維空間的固定一點,再把編號寫進網址——於是「飛行 = 瀏覽編號空間」「網址 = 內容」「無限 = 不儲存」。
                 ┌─────────────────────────────────────────────┐
   URL ?p=<大整數>│  i ∈ [0, |S|)        ← 內容定址 / 可分享        │
                 └───────────────┬─────────────────────────────┘
                                 │  unrank
                                 ▼
        ┌────────────────────────────────────────────┐
        │  雙射枚舉(兩套並存)                            │
        │  ①自由數系:URL 的 i ⇄ object(變長自由詩)      │
        │  ②受約束子集 S_valid:位置→只逛「合格律」詩之引擎  │
        └───────────────┬───────────────┬──────────────┘
            render │                     │ index (Vi/rank)
                   ▼                     ▼
            ┌──────────────┐     ┌────────────────────────┐
            │ 構件① 內容    │     │ 構件③ 座標 ⇄ 索引          │
            │ 即索引(數系)  │     │ pos = scatter(i)         │
            │ object↔digits│     │ i   = spatialHash(pos)   │
            └──────────────┘     └───────────┬────────────┘
                                             ▼
                                    3D 星雲渲染(飛行/環視)
兩套雙射並存(重要釐清):原作的可分享 URL(?p=)攜帶的是構件①的「自由形式」編號(變長雙射數系,over Σ\*),載入時被解碼成自由詩。構件②的「受約束子集」雙射(§4)在原作裡是另一個用途——讓使用者只在「合格律」的詩之間飛(由空間位置經 locate 取一個合法編號、再用受約束 unrank 解出一首必定合律的詩),以及計算顯示用的 lushiIndex 詮釋資料。URL 並未攜帶 §4 的受約束 rank。 重建時你可以選擇讓 URL 改攜受約束 rank(見 §6 註)——那是相對原作的乾淨改良,但要先知道原作不是這樣做的。

四構件彼此正交,可分別替換:換數系/約束就換了「什麼是一首詩」;換散佈雜湊就換了空間佈局;換渲染就換了呈現媒介;URL 層幾乎不變。下面逐件展開。


3. 構件①:內容即索引——雙射數系與混合基數枚舉

3.1 自由枚舉(uniform 混合基數)

設字表(lexicon)是一個有序有限集合 ΣN = |Σ|,每個字元有唯一序號 0 … N−1。一首「定長」詩就是長度 L 的序號串 c = (c_0, …, c_{L−1})c_k ∈ [0, N)

  for k = L-1 downto 0:  c_k = i mod N;  i = i div N

這就是把「一首詩」看成一個 N 進位的 L 位數。空間大小 |S| = N^L。以 N≈2500(常用字級)為例:

| 形式 | 行×字 | L | 空間 N^L 量級 | |---|---|---|---| | 五絕 | 4×5 | 20 | ~10^68 | | 七絕 | 4×7 | 28 | ~10^95 | | 五律 | 8×5 | 40 | ~10^136 | | 七律 | 8×7 | 56 | ~10^190 |

可觀測宇宙的原子數約 10^80七律的編號用盡了,宇宙的原子都不夠當紙。 但我們一張紙都不用——詩不被儲存,只被「算」。

3.2 雙射數系(bijective base:解決變長與前導零歧義)

定長很乾淨,但若要枚舉變長內容(自由詩、含換行、空白),普通進位制會出問題:000000 在普通 N 進位下都對應同一個值,於是「字串 ↔ 整數」不再是雙射(前導零歧義、空串無法唯一編碼)。

解法是雙射數系(bijective numeration):基數 b,但每位的數字取值是 1 … b(而不是 0 … b−1)。此時非負整數與「有限字串」之間是嚴格雙射:

  digits = []
  while i > 0:  i = i - 1;  digits.unshift(i mod b);  i = i div b   // 得到 0…b-1,外層再 +1 對映回 1…b

實作上,把「字元序號 0…N−1」與一個「換行/分隔 token」一起塞進基數 b = N+1 的雙射數系(每個符號映到數字 符號序號+1 ∈ {1,…,N+1}),就得到一個能唯一編碼任意長度、任意分行的自由詩的雙射整數。網址裡那串近百位數,正是這種「自由形式」的編號。

要點定長 → 普通混合基數變長 → 雙射數系。兩者都給你 整數 ↔ 物件 的雙射,差別只在邊界處理。

3.3 字表:把符號變成可索引的有序集

數系只認「序號」,不認「字」。所以需要一張字表 Σ:一個固定順序的符號陣列,序號就是它在陣列裡的位置。字表是整個系統唯一需要「決定一次」的資料;它一旦固定,所有編號的意義就固定了。字表是配置,不是內容——換一張字表(換語言、換符號集),整座宇宙就換了內容,但程式碼一行不動。

在 clean-room 重建裡,字表必須自己重建(用你自己選的字集與排序),不能沿用對方的——因為字表是它的具體資料表達(受保護),而「用一張有序字表當基底」這個方法不受保護。

3.4 一個最小的數系往返範例

把抽象落到地面。設字表只有四個字 Σ = [天, 地, 玄, 黃]N = 4,序號 天=0, 地=1, 玄=2, 黃=3

  c_1 = 11 mod 4 = 3 → 黃 ;  i = 11 div 4 = 2
  c_0 =  2 mod 4 = 2 → 玄

得「玄黃」。反向:rank(玄黃) = 2·4 + 3 = 11。往返一致。空間大小 4^2 = 16,編號 0…15 正好對應十六首「兩字詩」。

  i=7: i-1=6;  6 mod 4 = 2 → 數字 2+1 = 3(末位);  i = 6 div 4 = 1
  i=1: i-1=0;  0 mod 4 = 0 → 數字 0+1 = 1(首位);  i = 0 → 停
  數字串 = [1, 3]  →  字元序號 [0, 2]  →  「天玄」

反向驗證:rank(天玄):序號 [0,2] → 數字 [1,3]1·4 + 3 = 7往返一致。而 i=0 唯一對應「空串」。普通進位制下 0/00/000 撞在一起的歧義,在這裡消失——這正是「自由形式」必須用雙射數系的原因。

兩種數系的差別只在邊界(是否需要編碼「長度本身」)。核心永遠是同一句話:詩就是一個數,數就是一首詩。

4. 構件②:受約束子空間的排名/反排名(本技術的皇冠)

§3 枚舉的是「所有字元組合」。但若你要的是格律詩——必須合平仄、必須押韻——那麼合法物件只佔 N^L 裡微不足道的一小塊。難點是:如何對這個「受約束子集」S_valid ⊂ Σ^L 仍然建立 整數 ↔ 物件 的雙射,且不枚舉、不儲存?

這就是排名/反排名的真正用武之地,也是這個技術從「玩具」變「真功夫」的地方。

4.1 約束的形狀

把格律詩的約束抽象成三層結構(這個抽象正是可推廣的關鍵):

  1. 模板集 Variants:有限個「合法骨架」。律詩只有少數幾個標準平仄式(平起/仄起 × 首句入韻與否)。記為 V = {v_1, …, v_m}
  2. 每槽有限域 Domain(slot):在一個給定模板下,第 k 個位置的可選字元被約束在某個子集:
  1. 跨槽等價耦合 Coupling:所有韻腳位置必須屬於同一個韻部 g。這是唯一的非局部約束——它把若干槽「綁在一起」。

於是合法空間是一個不交併

S_valid  =  ⊔_{v ∈ V}  ⊔_{g ∈ Rhymes}  Slots(v, g)
Slots(v, g)  =  ∏_{k}  Domain(k; v, g)

在模板 v、韻部 g 下,設平聲自由位 pf 個、仄聲位 z 個、韻腳位 rh 個,則

|Slots(v, g)|  =  |Ping|^{pf}  ·  |Ze|^{z}  ·  |g|^{rh}

4.2 基數(cardinality)

合法詩總數可閉式算出,不需枚舉:

|S_valid|  =  Σ_{v ∈ V}  ( |Ping|^{pf_v} · |Ze|^{z_v} )  ·  ( Σ_{g ∈ Rhymes} |g|^{rh_v} )

注意韻腳耦合讓「選哪個韻部」變成一個加權的類別選擇(每個韻部貢獻 |g|^{rh} 條),不是簡單乘法——這正是非局部約束的代價,也是它仍可閉式計數的優雅之處。

4.3 反排名 unrank(整數 → 合法詩)

給定 i ∈ [0, |S_valid|)

1. 選模板 v:依序減去每個模板的容量 count(v)=(|Ping|^pf·|Ze|^z)·Σ_g|g|^rh,
   直到 i < count(v)。剩下的 i 就是「在 v 內的局部編號」。
2. 選韻部 g:把 v 內容量再拆成「韻部區塊」。每個 g 的區塊大小
   block(g) = |Ping|^pf · |Ze|^z · |g|^rh。依序減去 block(g) 定出 g。
3. 槽內混合基數展開:剩餘編號對「各位置的有限域大小」做一次混合基數
   unrank —— 平聲位用基數 |Ping|、仄聲位用 |Ze|、韻腳位用 |g| ——
   得到每個位置在其域內的「第幾個」,再查表還原成字。

全程只有大整數的除法與取模,O(L) 次大數運算,不觸碰 |S_valid| 這個天文數字本身。

4.4 排名 rank(合法詩 → 整數)與驗證

反向:給一首詩 c

1. 驗證 + 認模板:找出 c 符合哪個模板 v 的平仄式;若都不符 → 不合法(回 null)。
2. 認韻部:取所有韻腳位的字,檢查是否同屬一個韻部 g;不一致 → 不合法。
3. 前綴和 + 混合基數 rank:i = (前面所有模板的總容量)
                              + (本模板內 g 之前所有韻部的區塊和)
                              + (槽內混合基數 rank)。

rankunrank 互逆。「驗證」與「排名」是同一個函數的兩面:能排名 ⟺ 合法。

4.5 雙射的不變式(為什麼成立)

這一節是可被推廣的最值錢的東西:只要你的「合法物件」能寫成
⊔_模板 ⊔_類別 ∏_槽 域
的形狀(模板有限、每槽有限域、跨槽用「同類別」耦合),你就能對它做零枚舉的 整數 ↔ 物件 雙射。格律詩只是這個形狀的一個實例。

4.6 一個經實際運算驗證的受約束範例(Knuth 閘門)

抽象容易自我感覺良好,所以本文把它寫成程式跑過——依 BUG學「修前 fail、修後 pass」的鐵律,論文裡的數字必須是可執行地證明的,不是嘴上說的。

設一個玩具受約束空間(刻意小到能暴力枚舉對帳):

依 §4.2 閉式基數:

count(v) = |Ping|^pf · |Ze|^z · Σ_g |g|^rh = 3^1 · 2^1 · (2^2 + 1^2) = 6 · 5 = 30
|S_valid| = count(v0) + count(v1) = 30 + 30 = 60

實作 §4.3 的 unrank 與 §4.4 的 rank,跑兩道閘門:

| 閘門 | 結果 | |---|---| | 閉式基數 == 暴力枚舉計數 | 60 == 60 ✓ | | 對所有 i ∈ [0,60)rank(unrank(i)) == i | 全通過 ✓ | | unrank 的值域恰好覆蓋合法集(不重不漏) | |image| = 60,與暴力集相等 ✓ |

也順手驗了真實參數的空間量級(N≈2500):五絕 2500^20 ≈ 10^68、七絕 ≈ 10^95、五律 ≈ 10^136、七律 ≈ 10^190——與 §3.1 的表一致。

這一節同時是內容、也是驗證。 它證明 §4 的雙射不是紙上談兵:給編號取詩、給詩取編號,在受約束子空間上嚴格互逆、不重不漏。重建時的第一個里程碑(§10.4 的 M2)就是把這道閘門在你自己的程式裡重現。

5. 構件③:座標 ↔ 索引——確定性可逆綁定

有了 整數 ↔ 物件,還差「整數 ↔ 三維位置」,才能把編號空間變成可飛行的星雲。

5.1 索引 → 位置(scatter)

把編號 i 用一個確定性雜湊打散到三維空間:

pos(i) = ( f(i, 1), f(i, 2), f(i, 3) ) · R
其中 f(i, axis) = hash64(i ⊕ axis) 映到 [-1, 1),R = 雲半徑

hash64 用 splitmix64 風格的位元雪崩(乘以奇常數、右移異或;常見常數如 ⌊2^64/φ⌋)。確定性保證:同一個 i 永遠落在同一點,所以位置不需儲存。

5.2 位置 → 索引(spatial hash)

反過來,當使用者在空間中「飛到某處/點選某處」,要由位置取回該處的詩:

1. 量化座標:q = round(pos · 量化粒度)            // 把連續空間切成格
2. 空間雜湊:h = (q.x·P1) ⊕ (q.y·P2) ⊕ (q.z·P3)   // P1,P2,P3 為大質數
3. 串流擴展到足夠位元,取模合法空間大小:i = expand(h) mod |S_valid|

其中 P1,P2,P3 是經典的空間雜湊三質數(Teschner 等人提出的 73856093 / 19349663 / 83492791 是這領域的事實標準)。expand 用 splitmix64 連續產生 64-bit 區塊,拼到比 |S_valid| 的位元數還多十幾位,再取模——確保落在合法區間且分布均勻。

注意:scatter(索引→位置)與 spatialHash(位置→索引)不是嚴格互逆,而是「一個負責把編號撒進空間、一個負責把空間格子映回編號」。系統靠的不是嚴格可逆,而是兩個方向各自確定性:同編號恆同位置、同格子恆同編號。導航體驗只需要「同一處永遠是同一首詩」,這個性質就夠了。

5.3 確定性 = 零儲存的前提

整個構件③沒有任何狀態。它是純函數。確定性雜湊是「不儲存也能有穩定世界」的全部祕密:世界不是被存下來的,是每次被同一個函數重新算出來的,而純函數每次算的結果一樣,於是看起來像一個固定存在的世界。


6. 構件④:URL 即狀態——內容定址與無後端

把當前選中物件的編號寫進網址查詢字串(如 ?p=<大整數>),並用 history.replaceState 在使用者導航時無刷新同步。載入時讀網址、unrank 回物件、scatter 到位置、把相機飛過去。

原作攜帶的是構件①的「自由形式」編號(§3.2 的 babelIndex,over Σ\*),載入時解碼成自由詩;§4 的受約束 rank(lushiIndex)只作顯示用、不進 URL(見 §2 釐清)。重建建議:若要 URL 直接定址到「一首合格律的詩」,可改用 §4 的受約束 rank 當 ?p= 內容——這是相對原作的乾淨改良,代價是 URL 語意從「自由詩座標」變成「合律詩編號」,兩種定址不可混用(同一個數字在兩種解碼下是不同的詩)。

由此同時得到四個性質(下一節證明):

可選的第二載體:把同一編號也放進 #fragment# 之後不送伺服器、純客戶端路由,適合「分享時也帶狀態、但不污染伺服器日誌」。?# 可並存,互為備援。

7. 系統不變式與性質(為什麼成立)

把四構件合起來,下列性質可由前文直接推出:

| 性質 | 由何保證 | |---|---| | 零儲存(生成層) | 生成的內容 = unrank(i)、位置 = scatter(i),皆純函數、無資料庫。(少數策展真作另從靜態 JSON 載入,不屬生成層。) | | 近乎無限 | 可定址內容量 = |S_valid|,隨 L 指數成長(七律 ~10^190)。 | | 確定性/可重現 | 所有雜湊為純函數;同 i/同位置恆得同結果。 | | 天然防爬 | 內容不在初始 HTML;需執行前端解碼才現形。 | | 可分享 | URL ⊇ 編號(原作為 §3.2 自由形式編號),單一整數重建內容+位置。 | | 合法性內建(受約束路徑) | 走 §4 受約束 unrank(位置→只逛合律詩)時,域已是約束過的子集,產出必合格律;走 URL 自由編號路徑則解碼為自由詩。 |

一個誠實的反面:防爬不是「不可破」。若爬蟲願意執行 JavaScript(如以 headless 瀏覽器渲染——某些 scrape-website 服務的進階模式就會),它仍能抓到算出來的 DOM。真正穩固的不是「防住所有爬蟲」,而是機制本身:內容封進不透明編號、無後端可打、單一 URL 自包含——這讓「複製這個站」退化成「複製一個空殼 + 一個你看不懂的數字」。


8. 與生成範式的接合(從尋找到生成)

paradigms/ 裡反覆出現的主軸——「從尋找到生成」「生成路徑優越性」——在這個技術裡有一個乾淨的具體化:

詩雲做不到《詩雲》小說裡那步「從垃圾裡認出好詩」,因為那一步是價值判斷,不是枚舉。但它把前一半做到了極致:整個生成空間被完整定址、可導航、可分享、零成本。 這恰好印證範式的論點——當「生成」便宜到近乎免費,瓶頸就從「製造/儲存內容」整個轉移到「在無限生成物裡施加意義與選擇」。這個瓶頸轉移本身,就是『其他潛力發展』的入口。


9. 通用化:「X 之雲」抽象介面

詩只是 X 的一個取值。把技術抽乾淨,得到一個介面:任何能實作下列介面的 X,都能變成一座可飛行、URL 即內容、零儲存、近乎無限的「X 之雲」。

9.1 介面定義

interface EnumerableSpace<X> {
  cardinality(): BigInt                 // |S_valid|,閉式可算(不枚舉)
  unrank(i: BigInt): X                  // 整數 → 物件(必落在合法子集)
  rank(x: X): BigInt | null             // 物件 → 整數(順帶驗證合法性)
  render(x: X): Visual                  // 物件 → 可呈現形態
}
interface Embedding {
  scatter(i: BigInt): Vec3              // 索引 → 三維位置(確定性)
  locate(p: Vec3): BigInt              // 位置 → 索引(空間雜湊 mod |S|)
}
// URL 層、相機/渲染層對所有 X 通用,不必重寫。

只要補上 EnumerableSpace<X> 與一張「字表/原子集」,其餘(座標綁定、URL、3D 導航)幾乎是現成的。

9.2 把 X 換成什麼(實例表)

| X | 原子集 Σ | 約束(模板×域×耦合) | 難度 | |---|---|---|---| | 古典詩(本例) | 字(含平仄、韻部) | 平仄模板 × 平/仄/韻域 × 同韻耦合 | ★★★ | | 旋律 / 和弦進行 | 音符 / 和弦 | 調式音階 × 級數域 × 終止式耦合 | ★★★ | | 合法棋局片段 | 棋步 | 規則合法步 × 局面域 × 將軍/連續性耦合 | ★★★★ | | 形式證明樹 | 推理規則 | 型別/前提模板 × 可用規則域 × 結論一致耦合 | ★★★★★ | | 分子式 | 原子/鍵 | 價數模板 × 成鍵域 × 價數守恆耦合 | ★★★★ | | Shader / 程序紋理 | 運算節點 | 型別模板 × 節點域 × 輸入輸出耦合 | ★★★ | | SVG 紋樣 / 圖騰 | 路徑基元 | 對稱模板 × 基元域 × 閉合/對稱耦合 | ★★ | | 迷宮 | 牆/通道 | 連通模板 × 格域 × 單一連通耦合 | ★★ |

模式都一樣:找到 X 的「合法骨架(模板)× 每槽有限域 × 跨槽等價耦合」結構,§4 的雙射就能套上去。

9.3 難度光譜

「其他潛力發展」多半藏在 ★★★★ 那欄:當 X有語義、有全域一致性的東西(證明、程式、可運行的設計),這座雲就從「美學玩具」變成「可被導航的解空間」——而導航一個解空間,距離「在解空間裡搜尋/生成有用解」只剩一步。

10. 重建藍圖(clean-room,MSSP / DMS-first)

依房規:先畫、先定憲法、先設計可觀測,再寫碼。以下是可照著建的最小骨架(規模屬 Small:扁平優先、禁止過早分層)。

10.1 FMS(系統憲法・純元資料,不含可執行碼)

10.2 模組分解(SMS 穩定核心 / TMS 可插拔子集)

SMS(穩定核心・介面契約,最小核心原則)
  numeral/        混合基數 + 雙射數系(rank/unrank 基礎)   ← 純函數、可單測
  space/          EnumerableSpace 介面 + 受約束枚舉骨架       ← §4 的雙射
  embed/          scatter / locate(確定性雜湊、空間雜湊)    ← §5
  urlstate/       rank↔URL、replaceState 同步                ← §6
TMS(可插拔・自包含・可替換;移除測試:拿掉它核心仍可編譯)
  lexicon.x/      具體字表/原子集(換語言、換 X 就換這個)
  constraint.x/   具體約束(格律/調式/規則…)實作 EnumerableSpace
  render.x/       具體呈現(3D 星雲 / 文字卡 / 樂譜…)
DMS(診斷層・要設計進去,不是事後補)
  - rank(unrank(i)) === i 的往返自檢(任意抽樣 i)
  - locate(scatter(i)) 的穩定性檢查(同點恆同詩)
  - |S_valid| 與「實際可達編號上界」一致性檢查
  - URL 往返:parse(stringify(state)) === state

移除測試判準render.xlexicon.xconstraint.x 拿掉後 numeral/embed/urlstate/ 仍能編譯與單測 → 它們是 TMS;反之核心三件是 SMS。

10.3 資料流圖(≤9 元素,A4 放得下)

 [URL ?p=i] ──parse──► [BigInt i] ──unrank──► [object x] ──render──► [3D 星 / 詩卡]
      ▲                                   │
      │ stringify(rank(x))                │ scatter(i)
      │                                   ▼
 [history.replaceState] ◄──select──── [camera flyTo pos] ◄──locate──── [使用者點選空間]
兩條路徑、兩個位置來源(重建勿混)上排(URL ⇄ 物件)用構件①的自由 rank/unrank,此路徑的位置 = scatter(i)下排(點選空間「捕詩」)用 locate → §4 受約束 unrank 取一首合律詩,而這首詩的顯示位置 = 使用者所點的那個三維點本身(不是 scatter(其編號))。亦即:已知編號才用 scatter 定位;當場捕撈則「位置先於編號」。別假設「捕到的詩」會落在 scatter(它的編號)——那會讓星星從你點的地方跳走(呼應 §5.2、§13.3)。

10.4 最小可重建核心(MVP)與 Knuth 閘門測試

依 BUG學:每個核心函數先有「修前 fail、修後 pass」的可執行往返測試,再談完成。

MVP 里程碑(每步都有閘門測試才算過)
  M1 numeral:unrank/rank 往返(定長 + 雙射數系變長)對隨機 i 全通過。
  M2 space :給一個玩具約束(如「4 槽、2 模板、3 韻部」)實作 EnumerableSpace,
            cardinality 與「暴力枚舉計數」一致;rank(unrank(i))===i 全通過。
  M3 embed :scatter 確定性、locate∘scatter 落在合法區間;同格子恆同編號。
  M4 url   :parse∘stringify 往返;replaceState 不刷新。
  M5 render:先文字版(unrank→印出物件),確認端到端;再接 3D(可借用你現成的星空渲染)。

10.5 與星空渲染的接合

§5 的 scatter(i) 產出的就是一團三維點——這正是你星空 v2 已經會的東西(座標雲 + r3f/three instancing + 站在中心飛行)。把星空的「隨機散佈」換成「scatter(編號) 散佈」,把「點擊辨星卡」換成「locate(位置) → unrank → 詩卡」,**你的星空就直接升級成 X 之雲的渲染層**。換言之 render.x` 你已經寫過大半。


11. 風險、邊界與誠實對照

  1. 訊號淹沒(最根本的限制)|S_valid| 裡絕大多數是「合格律但無意義」的詩。這座雲解決了「定址與導航」,沒有解決「找到好的」。這正是《詩雲》小說的困境被誠實地保留下來。任何認真的「其他潛力發展」都必須回答:在無限合法物裡,如何施加意義/選擇/評分?(curated 入口、評分函數、人在迴路、或把「選擇」本身也建模成可導航的維度。)
  2. 可發現性:URL 是內容,但「好 URL」本身不可被瀏覽地發現——你要嘛從某處飛到它、要嘛被分享。系統需要「策展入口 / 種子座標 / 評分熱區」來讓人有起點。
  3. 計數可行性的天花板:§9.3 ★★★★ 那類(全域語義一致的 X)可能沒有閉式 cardinality,雙射退化為「超集枚舉 + 驗證」。要事先誠實標注哪些 X 落在可閉式計數的那一側。
  4. 技術 vs 財產(界線,接續前面那題)

12. 意義工程:在無限中施加選擇(「其他潛力」的技術入口)

§11.1 點出了根本限制:詩雲把「定址與導航」做到極致,卻完全沒碰「從無限合法物裡認出有價值的那些」。這不是缺陷,是分工——它做的是基礎建設。而你說的「其他潛力發展」,幾乎全部落在它之上的這一層:意義工程(meaning engineering)——在一個已被完整定址的無限空間裡施加價值、選擇與用途。 下面是四條可走的路,每一條都以「可導航的雲」為地基。

12.1 把「選擇」變成另一個可導航維度

均勻散佈的雲沒有地形——每顆星一樣亮,眼睛無處落。引入一個評分函數 score: X → ℝ(語意連貫度、美學、或「有用性」),就把均勻雲變成有地形的景觀(fitness landscape):把分數映到亮度/大小/顏色/聚集度,好的東西會自己發光,導航就從「亂飛」變成「沿著梯度爬山」。

代價:10^190 個點不可能全評分。所以只能局部——只對相機鄰域 scatter 出來的點即時評分、即時著色。雲不是被預先點亮的,是隨你飛到哪、哪裡才亮起來。這恰好與構件③的「確定性、按需生成」同構:連「意義」都按需算。

12.2 種子 + 局部搜尋(把生成接回搜尋)

給若干策展種子座標當入口(對應詩雲的 ?a= 詩人模式——已知的好起點)。從種子出發,在 unrank鄰域做局部最佳化(梯度、演化、MCTS),找更好的鄰居。

這正是範式「從尋找到生成」之後的下一拍:不是生成 vs 尋找二選一,而是「廉價生成 + 廉價局部搜尋」聯手——生成提供無限且零成本的候選地形,局部搜尋在地形上找峰。生成負責「有什麼」,搜尋負責「往哪走」。

12.3 把約束做得更強 = 把垃圾擋在門外

§4 的約束越強,S_valid 越小、有意義的密度越高。把約束從「合語法」推向「合語義」,等於把更多垃圾排除在可定址空間之外——它們連編號都拿不到。

這條路的盡頭極具威力:當 X = 可驗證的物件(形式證明、可編譯且通過測試的程式、滿足規格的設計),約束 = 「能通過驗證器」,則 unrank每一點都是一個合法解。此時這座雲不再是美學玩具,而是解空間的可導航地圖——而「導航一個全是合法解的空間」距離「在解空間裡找有用解」只剩最後一步。(代價見 §9.3:約束強到這種程度,閉式計數通常失效,雙射退化為「對驗證器接受的語言做排名」這個更硬的問題。這也正是 ★★★★ 那一欄、和你 P vs NP 那套思路真正接上的地方。)

12.4 人在迴路 / 集體標註

把人的行為(收藏、分享、停留)當成對無限空間的稀疏標註,反過來訓練 score,於是雲會長出被人關注的熱區。策展從「一次性挑選」變成「持續演化的點亮」。

這直接接上你 paradigms 裡的「集體智能相變」「同步發現的微觀差異」:無限生成空間 + 集體標註 = 一個可被集體認知逐步點亮的宇宙。 一個人點不亮 10^190,但一群人持續地飛、停、收藏,會在無限裡演化出有結構的星座

12.5 定位

| 層 | 做什麼 | 詩雲 | 「其他潛力」 | |---|---|---|---| | 基礎建設 | 定址、導航、分享、零儲存 | ✅ 已做到 | 當地基 | | 意義工程 | 在已定址的無限裡施加價值/選擇/用途 | ❌ 未碰 | 幾乎全在這 |

詩雲是一座蓋好的無限圖書館——書架完備、座標清晰、任何一本都能瞬間翻到。它沒做的是「告訴你哪本值得讀」。而那,恰恰是把這座圖書館從奇觀變成工具的全部關鍵。

13. 重建陷阱(務必避開)

照房規傳統,把重建時真正會踩的坑先標出來。這些多半是「不踩過不知道」的,列在前面省三輪重啟。

  1. 變長內容用普通進位制 → 前導零歧義(最致命)000000 在普通 N 進位下同值,於是「字串 ↔ 整數」不再是雙射,空串無法唯一編碼、不同長度會撞號。變長一律用雙射數系(數字 1…b。定長才可以用普通混合基數。先想清楚你的內容是定長還是變長,再選數系。
  1. Number 而非 BigInt → 在 2^53 悄悄爆掉。編號動輒近百位,遠超 IEEE-754 雙精度的安全整數上限(2^53−1)。所有 rank/unrank/雜湊的整數運算必須全程 BigInt。一個不小心混入的 Number 轉換,會在某個臨界值之後產出「看起來對、其實錯」的編號——而且很難察覺,因為小編號都正常。這正是 BUG學「注入↔顯現時間距離 ∝ 修復成本」的典型:錯在編碼、爆在某個大數,中間隔很遠。
  1. 以為 locate(scatter(i)) == i,或以為「捕到的詩」住在 scatter(其編號)。§5.3 已說:散佈與空間雜湊不是嚴格互逆。更具體地,有兩條產生位置的路徑:(a) 已知編號(如還原分享 URL)→ 位置 = scatter(i);(b) 點虛空當場捕詩 → 位置 = 使用者所點的那個點,編號由 locate 反求。別把兩者混為一談、別假設往返恆等;系統只依賴「同編號恆同位置、同格子恆同編號」這兩個各自的確定性。把它當互逆,會在「點選 → 取詩 → 再定位」處讓星星跳走。
  1. 字表是凍結的協定,不是可調的參數。字表的內容與順序一旦對外發布,就不能再改——改一個字的序號,所有舊 URL 指向的詩全部變了。字表必須像資料庫 schema 一樣版本化、append-only(要擴充只能在尾端加字,不能重排)。把「字表凍結」寫進 FMS 的限制欄。
  1. 確定性雜湊的跨平台一致性scatter/locate 要在不同瀏覽器、不同裝置、甚至不同語言的後端重算出同一個結果,否則「分享的 URL 在你那裡是另一首詩」。務必:全部運算 mod 2^64(明確 wrap)、用同一組常數、避免任何浮點參與雜湊主路徑(浮點的捨入跨平台不保證一致)。座標量化那一步尤其要定死粒度與捨入規則。
  1. 約束強到沒有閉式 cardinality 還硬算。§9.3 ★★★★ 那類(全域語義一致的 X)的合法集不是「不交併的笛卡兒積」,|S_valid| 可能根本沒有閉式。硬套 §4.2 會算出錯的基數,連帶 unrank 的取模範圍全錯。事先判斷你的 X 落在難度光譜哪一格:可閉式計數的(★★★)才直接套 §4;否則改走「超集枚舉 + 驗證 + 拒絕採樣」或語言排名。
  1. URL 長度上限與分享媒介截斷。近百位數字還好,但若 X 更大(長文、複雜結構),編號可能長到撞上瀏覽器 URL 長度上限或被聊天軟體/QR 截斷。對策:可在編號上加可逆壓縮、或改用較高基數(Base62/Base64url)縮短字面長度——但壓縮層要與語意層解耦(壓縮只動表示,不動「編號 ↔ 物件」的雙射)。
  1. scatter 分布不均 → 視覺結塊。若散佈雜湊品質不夠,星會在某些區域堆積、某些區域空洞,破壞「無垠星海」的錯覺。用品質好的位元雪崩(splitmix64 風格),並對三個軸用不同的鹽(如 i ⊕ axis),避免三軸相關產生對角條紋。這與星空專案「球面取點別用 random*π」是同一類陷阱:取樣分布的細節決定觀感。
  1. 把渲染和枚舉耦死。常見誘惑是「邊飛邊直接從座標算詩、塞進渲染迴圈」。但 unrank + 約束驗證可能不便宜,塞進每幀會掉格。渲染層只認座標與少量已解出的物件;解碼放在選取/鄰域預取時做,並快取。保持 §10.2 的 SMS/TMS 邊界——render.x 不該知道 constraint.x 的內部。
  1. 忘了「無限 ≠ 有意義」就對外宣稱。展示時容易把「能定址 10^190 首詩」講成「有 10^190 首好詩」。誠實點:絕大多數是合格律的噪音(§11.1)。把這點寫進文案,否則使用者飛兩下發現全是亂句,會覺得被騙——而技術本身明明很誠實。
一句話:雙射要用對數系、整數要用 BigInt、字表要凍結、雜湊要跨平台一致、別把「無限」當「有意義」。 這五條踩過任何一條,都會在很後面才爆。

14. 結語

這個網頁的「強」,不在它是一個關於詩的作品,而在它不小心示範了一個通用技術:當內容能由座標確定性地生成,內容就不必被儲存、不必被尋找、可以被當成空間來飛行、可以被一個整數完整分享。它是「從尋找到生成」這條範式線上一個能用滑鼠拖動的具體證據。

原作者把它當「有趣的網頁比賽」。但他手上的,是「生成式內容宇宙」的一個可運行原型——而這類宇宙真正的潛力,在他畫的這條線之外:把 X 從「詩」換成有語義、有用、有全域一致性的東西時,這座可導航的雲就從美學玩具,變成一個可被飛行的解空間

下一步——現場重建——就照 §10 的 MSSP 骨架走:先把 numeral/ 與一個玩具 constraint/ 的往返閘門測試做出來(M1–M2),其餘接上你現成的星空渲染。招在手上了,剩下的是把它打成你自己的。

寫實與寫意是同一顆球的內外兩面;儲存與生成,是同一個空間的兩種看法。它選了生成——於是一張紙都不用,就裝下了比宇宙原子還多的詩。
原始檔(供 RAG/下載):/raw/lm-000479.md [md] · id: lm-000479