Notes [notes]

Lemma First homology of a short chain complex over a PID [LNMK]

Let

C2→∂2C1→∂1C0C_2 \xrightarrow{\partial_2} C_1 \xrightarrow{\partial_1} C_0

be a chain complexDefinitionChain complex2026-10-04 · Lîm Tsú-thuàn of free finite rank RR-modules over a principal ideal domain RR. Then

H1(C∙)≅Rb⊕R/(a1)⊕⋯⊕R/(an)H_1(C_\bullet) \cong R^b \oplus R/(a_1) \oplus \cdots \oplus R/(a_n)

where a1,…,an∈Ra_1, \dots, a_n \in R are the invariant factors of ∂2\partial_2 and where b=rankker⁡∂1−nb = \text{rank} \ker \partial_1 - n.

Example Real projective plane [local-0]

Take R=ZR = \mathbb{Z} and the real projective plane RP2\mathbb{R}P^2 as a Δ\Delta-complexDefinitionDelta complex2026-10-04 · Lîm Tsú-thuàn: two vertices v,wv, w, three edges a,b,ca, b, c, and two triangles U,LU, L.

figure tex6340

Order the vertices of each triangle [v0,v1,v2][v_0, v_1, v_2] so that v0v1=cv_0 v_1 = c in both, v1v2=a,v0v2=bv_1 v_2 = a, v_0 v_2 = b in UU, and v1v2=b,v0v2=av_1 v_2 = b, v_0 v_2 = a in LL. Then

∂2U=a−b+c∂2L=−a+b+c\partial_2 U = a - b + c \qquad \partial_2 L = -a + b + c

In the bases U,LU, L and a,b,ca, b, c, the Smith normal form of ∂2\partial_2 is

(1−1−1111)→R2+R1, R3−R1(1−10002)→C2+C1, R2↔R3(100200)\begin{pmatrix} 1 & -1 \\ -1 & 1 \\ 1 & 1 \end{pmatrix} \xrightarrow{R_2 + R_1,\ R_3 - R_1} \begin{pmatrix} 1 & -1 \\ 0 & 0 \\ 0 & 2 \end{pmatrix} \xrightarrow{C_2 + C_1,\ R_2 \leftrightarrow R_3} \begin{pmatrix} 1 & 0 \\ 0 & 2 \\ 0 & 0 \end{pmatrix}

so the invariant factors are a1=1,a2=2a_1 = 1, a_2 = 2 and n=2n = 2. For bb, we have ∂1a=∂1b=w−v\partial_1 a = \partial_1 b = w - v and ∂1c=0\partial_1 c = 0, so ∂1\partial_1 has rank 11

rankker⁡∂1=rank C1−rank ∂1=3−1=2\text{rank} \ker \partial_1 = \text{rank}\ C_1 - \text{rank}\ \partial_1 = 3 - 1 = 2

Hence, b=2−2=0b = 2 - 2 = 0. Now applied the theorem

H1(RP2)≅Z2−2⊕Z/(1)⊕Z/(2)≅Z/2H_1(\mathbb{R}P^2) \cong \mathbb{Z}^{2-2} \oplus \mathbb{Z}/(1) \oplus \mathbb{Z}/(2) \cong \mathbb{Z}/2

Core concepts in Simplicial Homology [GYD9]

Definition Boundary and interior of Δn\Delta^n [23BZ]

The boundary of Δn\Delta^n is

∂Δn:=⋃i=0n[v0,…,v^i,…,vn]\partial \Delta^n := \bigcup^n_{i=0} [v_0, \dots, \widehat{v}_i, \dots, v_n]

The interior of Δn\Delta^n is Δn∖∂Δn\Delta^n \setminus \partial \Delta^n.

Definition Delta complex [WBTD]

A Δ\Delta-complex is a topological space XX with a family of maps

{σαn:Δn→X}\{ \sigma^n_\alpha : \Delta^n \to X \}

for each n≥0n \ge 0 such that (Δn\Delta^n is the standard nn-simplex)

  1. Each interior restriction of map σαn\sigma^n_\alpha is injective
  2. Each point x∈Xx \in X lies in the image of interior restriction of σαn\sigma^n_\alpha for exactly one σαn\sigma^n_\alpha
  3. Each ii-boundary restriction of σαn\sigma^n_\alpha is equal to some σβn−1\sigma^{n-1}_\beta where we identify the ii-boundary with a Δn−1\Delta^{n-1} by the unique linear homeomorphism that preserves the order of the vertices
  4. A subspace A⊆XA \subseteq X is open if and only if (σαn)−1(A)⊆Δn(\sigma^n_\alpha)^{-1}(A) \subseteq \Delta^n is open for all σαn\sigma^n_\alpha

Definition nn-simplex of a Δ\Delta-complex [K5BK]

We refer to a map σαn:Δn→X\sigma^n_\alpha : \Delta^n \to X as an nn-simplex of the Δ\Delta-complexDefinitionDelta complex2026-10-04 · Lîm Tsú-thuàn XX.

Definition Skeleta [8CBL]

A Δ\Delta-complex XX comes with a filtration by skeleta X0⊆⋯⊆Xk⊆⋯⊆XX^0 \subseteq \cdots \subseteq X^k \subseteq \cdots \subseteq X where the kk-skeleton XkX^k is the union of all images of simplices of dimension at most kk.

Example Skeleta of T2T^2 [local-0]

Take the Δ\Delta-complex structure on the torus T2T^2 with one vertex vv, three edges a,b,ca, b, c and two triangles U,LU, L. Slide kk to see the kk-skeleton, and drag the torus to rotate it.

k = 0

Definition Dimension of a Δ\Delta-complex [5MJV]

A Δ\Delta-complex XX is called kk-dimensional if Xk=XX^k = X and Xk−1≠XX^{k-1} \ne X; and it is called infinite dimensional if there is no such kk.

Definition Finite type and finite Δ\Delta-complex [2A0Q]

We say that XX is of finite type if for each k≥0k \ge 0, it has only finitely many kk-simplices. We say XX is finite if it has only finitely many simplices altogether.

Definition nn-th simplicial chain module and nn-chains [Q5M5]

Let XX be a Δ\Delta-complexDefinitionDelta complex2026-10-04 · Lîm Tsú-thuàn. The nn-th simplicial chain module CnΔ(X)C^\Delta_n(X) is the free Z\mathbb{Z}-module with basis

{σαn:Δn→X}\{ \sigma^n_\alpha : \Delta^n \to X \}

Accordingly, each element of the nn-th simplicial chain module is a formal Z\mathbb{Z}-linear combination

∑αkασαn\sum_\alpha k_\alpha \sigma^n_\alpha

with finitely many nonzero coefficients. We call them simplicial nn-chains in XX.

Definition Boundary homomorphism (also known as differential) [EFJB]

The boundary homomorphism ∂n:CnΔ(X)→Cn−1Δ(X)\partial_n : C^\Delta_n(X) \to C^\Delta_{n-1}(X)Definitionnn-th simplicial chain module and nn-chains2026-10-04 · Lîm Tsú-thuàn for n≥1n \ge 1 is defined on the basis by

∂n(σαn):=∑i=0n(−1)iσαn∣[v0,…,v^i,…,vn]\partial_n(\sigma^n_\alpha) := \sum^n_{i=0} (-1)^i \sigma^n_\alpha\vert_{[v_0, \dots, \widehat{v}_i, \dots, v_n]}

i.e. Alternatively add each restriction σαn∣[v0,…,v^i,…,vn]\sigma^n_\alpha\vert_{[v_0, \dots, \widehat{v}_i, \dots, v_n]}. Recall the third condition of Δ\Delta-complexDefinitionDelta complex2026-10-04 · Lîm Tsú-thuàn.

Lemma We have ∂n−1∘∂n=0\partial_{n-1} \circ \partial_n = 0 [URFG]

The composition CnΔ(X)→∂nCn−1Δ(X)→∂n−1Cn−2Δ(X)C^\Delta_n(X) \xrightarrow{\partial_n} C^\Delta_{n-1}(X) \xrightarrow{\partial_{n-1}} C^\Delta_{n-2}(X)DefinitionBoundary homomorphism (also known as differential)2026-10-04 · Lîm Tsú-thuàn is the zero map.

Definition nn-th homology [7XRX]

The nn-th homology group of a chain complexDefinitionChain complex2026-10-04 · Lîm Tsú-thuàn (C∙,∂∙)(C_\bullet, \partial_\bullet) is the RR-module

Hn(C∙):=ker⁡∂n/im⁡∂n+1H_n(C_\bullet) := \ker \partial_n / \operatorname{im} \partial_{n+1}

Definition nn-th simplicial homology [DDAF]

The nn-th simplicial homology group of a Δ\Delta-complex XX is the Z\mathbb{Z}-module

HnΔ(X):=Hn(C∙Δ(X))H^\Delta_n(X) := H_n(C^\Delta_\bullet(X))

Definition Chain complex [O7WN]

An algebraic chain complex (C∙,∂∙)(C_\bullet, \partial_\bullet) is a sequence of RR-modules over a commutative ring RR

⋯→Cn+1→∂n+1Cn→∂nCn−1→⋯\cdots \to C_{n+1} \xrightarrow{\partial_{n+1}} C_n \xrightarrow{\partial_n} C_{n-1} \to \cdots

indexed over n∈Zn \in \mathbb{Z} and connected by homomorphisms ∂n\partial_n satisfying the condition ∂n∘∂n+1=0\partial_n \circ \partial_{n+1} = 0Every nn-boundary is an nn-cycle.

關於漫畫epub [YSRC]

  • 按照epub規格,只需要寫page-progression-direction="rtl",但實際上大部分閱讀軟體需要設定pre-paginated才能把書設定成RTL
  • 漫畫書商產出的頁面通常是每頁一個xhtml裡面一個img,然後直接設定(長寬是圖片像素長寬),避免圖片被裁切
  • epub不可以設定成reflowable,否則有些閱讀器會讓圖片變成可點選(點了會放大圖片,然後就會無法翻頁)

MacOS網路雜記 [YUFB]

執行

ipconfig set en0 DHCP

MacOS header那邊內建的wifi UI就會壞掉(一直顯示一個驚嘆號在中間),可見這個UI的開發者應該沒有考慮到外部程式也會動到網路設定的部分xd

ifconfig awdl0 up/down

可以開關AirDrop,如果是遠端遊戲的話關掉會改善很多

Non-linear spine [A17O]

在Pattern Unification的概念中,有一類等式依賴non-linear spine,會沒有general solution,例如

?0 x x=?x?0\ x\ x \overset{?}{=} x

這裡至少有兩組答案:

λx.λy.x\lambda x. \lambda y. x

跟

λx.λy.y\lambda x. \lambda y. y

Proxmox與Intel I-219v [RKU5]

前幾天遇到proxmox cluster每幾個小時就斷線,但重插網路線就會恢復,最後查到是網卡的問題https://tech.gillyb.net/proxmox-losing-network-with-intel-i-219v/。可以觀察dmesg有無

e1000e: Detected Hardware Unit Hang

確認。最後用

ethtool -K eno1 tso off gso off

關閉tso與gso之後,到目前都沒有遇到問題了xd

Theorem Computably (recursively) inseparable sets [FW2E]

Consider the following two subsets of the natural numbers:

A={n∈N∣ϕn(n) terminates with result 0}B={n∈N∣ϕn(n) terminates with result 1}\begin{gather*} A = \{ n \in \N \mid \phi_n(n)\text{ terminates with result }0 \} \\ B = \{ n \in \N \mid \phi_n(n)\text{ terminates with result }1 \} \end{gather*}

There is no Turing machine which terminates on all inputs and separates AA from BB.

Proof [local-0]

Suppose we are given a Turing machine ee terminates with result 00 or 11 on all inputs, such that e(n)=0e(n) = 0 when n∈An \in A and e(n)=1e(n) = 1 when n∈Bn \in B. Consider the algorithm FF that returns a Turing machine for a given natural number:halt(k)halt(k) is the machine that terminates with result kk on every input.

F(n):={halt(1) when e(n)=0halt(0) when e(n)=1F(n) := \begin{cases} halt(1) \text{ when } e(n) = 0 \\ halt(0) \text{ when } e(n) = 1 \end{cases}

Because ee terminates on all inputs, so does FF. By construction e(F(n))≠e(n)e(F(n)) \ne e(n) for each input nn: Consider the case that e(n)=0e(n) = 0, then F(n)=halt(1)F(n) = halt(1). halt(1)∈Bhalt(1) \in B because

ϕ⌜halt(1)⌝(⌜halt(1)⌝)=halt(1)(⌜halt(1)⌝)=1\phi_{\ulcorner halt(1) \urcorner}(\ulcorner halt(1) \urcorner) = halt(1)(\ulcorner halt(1) \urcorner) = 1

but then e(F(n))=e(halt(1))=1≠0=e(n)e(F(n)) = e(halt(1)) = 1 \ne 0 = e(n). The same argument applies to e(n)=1e(n) = 1.

By the second recursion theoremhttps://www.math.ucla.edu/~ynm/lectures/2009csl.pdf, there exists a Turing machine ff realizing FF applied to its own Gödel number, that is, ϕ⌜f⌝≃ϕ⌜F(f)⌝\phi_{\ulcorner f \urcorner} \simeq \phi_{\ulcorner F(f) \urcorner}. Because F(f)F(f) is halt(0)halt(0) or halt(1)halt(1), both constant, ϕ⌜f⌝\phi_{\ulcorner f \urcorner} is constant as well, say with value kk. Hence

ϕ⌜f⌝(⌜f⌝)=k=ϕ⌜F(f)⌝(⌜F(f)⌝)\phi_{\ulcorner f \urcorner}(\ulcorner f \urcorner) = k = \phi_{\ulcorner F(f) \urcorner}(\ulcorner F(f) \urcorner)

so either both ff and F(f)F(f) lie in AA, or both lie in BB. In either case e(f)=e(F(f))e(f) = e(F(f)). However, e(n)≠e(F(n))e(n) \ne e(F(n)) for all nn.

資料庫其實很快 [tr-QE7I]

之前的tr在分析檔案之後把每個地址的metadata放到 _tmp/<addr>.metadata.json 裡面,而且使用 for/async,實際用我的部落格測量發現需要80.x ms,找文件查證發現其實寫入port對Racket future來說是不安全的(future-unsafe operation)https://docs.racket-lang.org/guide/parallelism.html,所以Racket其實什麼也沒做

反而還要付出runtime overhead,for線性寫完全部檔案也不過50.x ms

我最近突然想到何不放進SQLitehttps://www.sqlite.org/裡面,然後就發現

一次transaction把全部metadata寫入,只需要4.7ms!

不過這部分對全體建構時間改善就沒什麼意義了,畢竟這部分不是熱路徑,我改用SQLite也只是想減輕維護負擔

基於檔案內容判斷是否進行建置的必要性 [tr-1XYR]

tr最早的實現是

  1. 把使用者放在 content 目錄裡面的 .scrbl 檔案夾進一個適當的上下文裡面,然後輸出到 _tmp 目錄
  2. 建構階段幫每一個地址開啟一個racket subprocess輸出HTML

這個實現的缺點就是慢到不行,而且如果用racket的 for/async(平行執行)常常會超出系統開啟行程的限制然後炸掉,用 for 線性執行則是需要好幾分鐘才能建構好網站,但相應的這個方法必定會進行修改

改善效能的過程中發現這個用行程調用的過程不是必須的,racket提供的 dynamic-rerequire 正好可以做到這件事,以我的網站來說建構時間降到分鐘以下的等級

接下來就是改正快取正確性,之前的快取我也是單純比較mtime(這個錯誤每個建構系統都會犯至少一次xd)。現在的版本是查看檔案原始內容,建立hash然後把一些元資料放到 _tmp/cache/<hash> 裡面

快取這裏還有一些坑,要注意把外部依賴放到變更監控裡面,所以除了一開始就遇到的 @include,我後來又加上 @tr/depends 讓使用者自己宣告一些隱藏的檔案依賴(會影響到目前卡片的建置的外部檔案變更)

但從這邊開始監控檔案的連續建置就開始出問題了,有時候修改會沒有觸發新的建構。最後用property-based test才慢慢調查到問題正在於 dynamic-rerequire,最後發現誒怎麼 dynamic-rerequire 也是比較mtimehttps://github.com/racket/racket/blob/2b83c3f3480b94c63a0c5e252b42cc1245b12c7f/racket/collects/racket/rerequire.rkt#L177來判斷要不要觸發重新載入。所以為了確保 dynamic-rerequire 在tr判斷內容有變化的時候一定會執行,我選擇把hash也放到生成的暫時檔名中。這樣內容變化就蘊含檔名變化,新的檔案就一定會觸發建構

更仔細考慮的話,目前的機制都缺乏對退出訊號的處理,所以可能遇到任意時機的中斷,不過這就留待未來處理了

用CSS計算nesting [tr-01YZ]

這是最近對tr的小修正:在渲染HTML的時候就計算並鎖死前綴數字會出問題,因為一張卡片可以被不同卡片含入(transclusion),這導致渲染結果對其他卡片來說都不正確

所以正確的解決之道是利用CSS Counters動態計算

模擬選舉演算法 [C6J7]

延續選舉演算法提到的規則,模擬一直運作下去的集群:leader定期送出心跳,一旦有節點逾時沒收到leader心跳(也可能是因為根本還沒有leader)就會轉為candidate發起選舉。讀者可以慢慢觀察leader、candidate、follower之間的轉換

你可以自己觸發故障:點一下節點可以讓它離線、上線;點一下節點之間的線可以讓那條線路故障、恢復。可以自由組合,包括同時弄掉好幾個節點看cluster在什麼情況下選不出leader。想暫停看某個瞬間可以按Pause

Follower Candidate Leader 節點離線(點節點切換) 線路故障(點線切換)

Colimit作為Coend [S2W7]

Coend是functor P:Cop×C→DP : C^{op} \times C \to D 上的一種construction,回憶一下Profunctor我們知道這種functor對左邊逆變、對右邊共變,因此對任意 f:x→yf : x \to y 有

figure tex10615

如果考慮對所有co-wedge P(−,−)→dP(-,-) \to d 有一個universal construction,換句話說以下交換圖成立

figure tex10616

∫x∈CP(x,x)\int^{x \in C} P(x,x) 這個universal construction被稱為coend。給定functor FF 我們能定義一個profunctor PP

P(x,y):=F(y)P(f,g):=F(g)P(x,y) := F(y) P(f,g) := F(g)

現在假設profunctor PP 有universal construction,然後我們把 PP 按照定義機械替換成 FF

figure tex10617

就可以看到如果 FF 有colimit這樣的universal construction,必定與 ∫x∈CF(x)\int^{x \in C} F(x) 重疊,所以colimit可以用coend表示

∫x∈CF(x)=lim→⁡F\int^{x \in C} F(x) = \varinjlim F

視Profunctor為Hom functor的generalization [2323]

Profunctor的概念是一種跨越不同範疇的Hom functor的擴充,我們先看基本定義

Definition Profunctor [local-0]

A profunctor PP is a functor of the form

P:Cop×D→SetsP : C^{op} \times D \to \text{Sets}

這時候我們可以看到,重點在對於一個product category be functorial,這表示我們可以把 P(c,d)P(c, d) 視為一個擬似morphism!這句話的意思是對於 c′→cc' \to c 跟 d→d′d \to d',我們可以視每個 P(c,d)P(c,d) 的元素為一個連接 cc 跟 dd 的morphism,只是它跨越不同範疇

figure tex6340

為什麼呢?因為對一個product category be functorial就是對兩個組成範疇be functorial,表示對於 f:c′→cf : c' \to c 我們有

P(f,−):P(c,−)→P(c′,−)P(f, -) : P(c, -) \to P(c', -)

對於 f:d→d′f : d \to d' 我們有

P(−,f):P(−,d)→P(−,d′)P(-, f) : P(-, d) \to P(-, d')

這完全滿足了Hom functor的需求,因此事實上我們可以更正式的說以下構造是一個範疇:

  1. 取 CC 與 DD 的objects為objects
  2. 取 CC 與 DD 的morphisms與所有 P(−,=)P(-, =) 的元素為morphisms

這又稱為a collage (or cograph) of two categories CC and DD

Tool JetKVM [55O9]

總之就是個遠端控制電腦的產品

Log Replication [6PAS]

基於選舉演算法取得leader之後,每次client發起的command應該要被leader複製到followers上

leader會向所有節點發起新增log的請求,收到過半節點ack才會回覆client這個修改成功

Raft特別要求如果有新的command但節點沒有跟上,就會拒絕並要求leader把舊的logs都複製給它,然後才會同意新的command,這表示所有節點的過半數節點有最新的logs狀態時集群才能服務client

選舉演算法 [5X6Y]

這裡簡要紀錄選舉演算法的想法

節點角色 [local-0]

節點的角色應該是以下三種之一

  • Follower
  • Candidate
  • Leader

我們希望leader至多只有一個,只有有leader的集群才會對外提供服務

任期 [local-1]

任期可以叫term或是generation clock,用來這是第幾輪的決策,每個節點都要有這個資訊

日誌 [local-2]

日誌的每個entry應該包含

  • 索引(index),每次新增entry都應該嚴格遞增的數字
  • 任期(term),entry寫入時的任期
  • 指令(command),要進行什麼操作

狀態轉換 [local-5]

節點啟動時可以不知道leader是誰,我們可以設定為

  • term為1
  • 角色為follower
  • 設定定時任務檢查leader發送的heartbeat訊號

如果定時任務歸零時沒有收到leader發送的heartbeat訊號,就發起選舉;反之,重設定時任務

發起選舉 [local-3]

發起選舉可以定義為

  1. 把節點的term加一
  2. 轉換為candidate
  3. 投給自己
  4. 要求其他節點投給自己
  5. 等待有限時間N

現在會有幾種可能

  • 在N時間內有過半節點投給自己。這時候表示自己就是leader,轉換狀態並設定循環任務不斷發送heartbeat訊號給所有節點
  • 在N時間後沒有得到過半節點的票,逾時再次發起選舉(回到最前面)
  • 在N時間內收到leader廣播的heartbeat,而且這個leader的term比自己大。這時候就轉變為follower,更新term並紀錄誰是leader
  • 在N時間內收到其他candidate要求投給它的投票訊息,而且該投票訊息的term比自己大。這時候也轉為follower,更新term

由於candidate把term加一了才繼續,舊的領導者(比如斷線之後再連回來)的heartbeat就不會影響candidate跟其他節點

處理投票請求 [local-4]

收到投票請求的時候需要按照以下順序決策,以下的同意就表示同時要轉換為follower狀態

  1. candidate的term小於當前節點的term:回覆拒絕
  2. candidate的term大於當前節點的term:回覆同意
  3. candidate的term跟當前節點一樣時要繼續攤開
    1. 已經投過票了:請求candidate就是已經投過的candidate,回覆同意;反之回覆拒絕
    2. candidate的log index大於自己:回覆同意
    3. 其餘情況都回覆拒絕

之所以要看log index,是要避免狀態比較落後的節點成為leader,以免資料遺失

原則上就是

  • 任期高者不投給任期低者
  • log index高者不投給log index低者
  • 每個任期只投一張票(否則過半就沒有意義)

leader如果直接看到比自己大的term(無論是heartbeat還是投票訊息),都應該放棄leader身份轉換為follower

現在我們來看逾時後投票的效果

架一個自用的Rama叢集 [rama-cluster]

Rama是Red Planet Labs創造的分散式程式平台,用Java跟Clojure寫成。這裡紀錄我把1.9.0的release解開、啟動rama cluster的過程。release zip檔案解壓出來的內容

.
├── lib
├── LICENSE.txt
├── log4j2.properties
├── logs
├── rama
├── rama.jar
├── rama.yaml
└── README.md

常駐行程 [local-0]

Rama叢集由三個常駐行程組成:

  • Zookeeper:存叢集metadata。Rama透過一層叫Metastore的抽象使用它,記錄哪個節點該跑哪些module worker、以及replication的leader election
  • Conductor:CLI的接口,同時提供web版的Cluster UI,負責管理模組部署
  • Supervisor:每台工作機跑一個,負責處理實際執行運算的worker process的調度

各自要獨立執行:

# 內建的單機 ZK,官方標注不適合正式環境
nohup ./rama devZookeeper >/dev/null 2>&1 &
nohup ./rama conductor >/dev/null 2>&1 &
nohup ./rama supervisor >/dev/null 2>&1 &

listening ports

2000   zookeeper
1973   conductor        <- CLI client 只需要這個
8888   cluster UI
3000   supervisor HTTP  ┐
3001   worker           ├ supervisor.port.range 的前幾個 port
3002   worker           ┘

Conductor的UI開在8888,裡面有相當豐富的runtime telemetry。要讓那些數字有東西可看,要先部署內建的monitoring模組,也順手設定一下遙測的保留期避免把磁碟吃光:

./rama deploy --action launch --systemModule monitoring --tasks 4 --threads 2 --workers 1
./rama monitoringConfig --setRetention 60,90000

Problem port range的寬度限制 [local-1]

Supervisor會拿 supervisor.port.range 的第一個 port 開自己的HTTP server,worker則往後依序取用。如果預設的 [3000, 4000] 跟機器上其他東西撞到,就需要更改這個設定

我改成 [3100, 4000],結果每一個CLI指令都開始噴 Invalid config,連唯讀的 confValue 都不能用了,表示config驗證發生在所有指令的共同路徑上

文件說明只有說「port allocation range,預設 3000, 4000」,沒講到限制。試出來的結果是這樣:

[3000, 4000]   OK
[3100, 4100]   OK
[4000, 5000]   OK
[3100, 3200]   INVALID
[3001, 4000]   INVALID

所以range的寬度可能是必須恰好等於 1000,起點沒有限制。所以正確的閃避方式是平移整段ports

supervisor.port.range: [3100, 4100]

Problem Java version [local-2]

文件寫的支援範圍是Java 8/11/17/21,我機器上是 26。實測下來所有功能都正常,唯一的問題是RocksDB的JNI會噴warning

WARNING: java.lang.System::loadLibrary has been called by org.rocksdb.RocksDB
WARNING: Restricted methods will be blocked in a future release

現在只是警告,但未來的 JDK 會直接封鎖

Zookeeper 是必要的嗎? [local-3]

是的,對真正的cluster來說沒有免ZK的模式

  1. 只是要開發、測試 module:用 InProcessCluster,把 Rama 當成 Maven 依賴拉進專案,InProcessCluster.create() 會在 process 內模擬一整個叢集,API 跟真叢集完全相同。不需要 ZK、不需要 CLI、不需要任何 daemon。官方建議的開發流程就是用 IPC 開發測試,再用 CLI 部署到真叢集
  2. 自用的小叢集:ZK 要有,但不需要是額外的機器。內建的 devZookeeper 就是一個單機 ZK,跟 Conductor 擠同一台就好。它沒有 HA,ZK 掛了叢集就失去協調能力,自用場景通常還可以接受;不然就是要自己開一個獨立的 Apache ZooKeeper

所以ZK是必要的元件,但不一定需要額外的機器

從別台機器部署 [local-4]

這是我最想確認的使用方式:把叢集跑在別的機器上,然後從筆電下部署指令

client 端的 rama.yaml 只需要一行。我把設定刪到只剩 conductor.host,conductorReady、moduleStatus、deploy --action update 都還是能用

再來我讓 zookeeper.servers 指向一個不存在的host,上面的指令包含deploy在內照樣成功。也就是說CLI client完全不需要管Zookeeper,它只跟Conductor對話,module的jar是上傳給Conductor、再由Conductor散佈出去的

兩個要注意的地方:rama.yaml 這個檔案本身必須存在而且非空,空檔案會得到錯誤訊息 Could not find rama.yaml on classpath;另外client端的release版本必須跟叢集完全一致

所以一組最小的遠端配置是這樣。叢集那台,Conductor、Supervisor、ZK 都在上面執行:

conductor.host:
  internal: "localhost"
  external: "10.0.0.1"     # cluster 對外的 IP
local.dir: "/var/rama"
zookeeper.servers: ["localhost"]
worker.child.opts: "-Xmx4096m"

Client的設定只需要

conductor.host: "10.0.0.1"

License [local-5]

內建的免費license上限是2 台 Supervisor 節點,Conductor跟Zookeeper不計。用 rama licenseInfo 可以看到 num-nodes: 2,有效期到2117年

所以自用的天花板就是兩台工作機。再往上要跟 RPL 買 license,拿到以後用 rama upsertLicense --licensePath xxx.edn 裝上去

常用指令 [local-6]

# 部署自己的 module
rama deploy \
  --action launch \
  --jar target/app.jar \
  --module com.foo.MyModule \
  --tasks 64 \
  --threads 16 \
  --workers 8 \
  --replicationFactor 2

# 程式改動之後重新部署
rama deploy --action update \
  --jar target/app.jar \
  --module com.foo.MyModule

rama scaleExecutors --module com.foo.MyModule --threads 90 --workers 30
rama moduleStatus com.foo.MyModule
rama destroy --module com.foo.MyModule

rama repl --module com.foo.MyModule
rama runClj my.ns /path/to.jar
rama backup / supportBundle
rama shutdownCluster

--tasks 必須是 2 的次方,而且要滿足 tasks >= threads >= workers。這個約束在 deploy 跟 scaleExecutors 都適用

Video The Unreasonable Effectiveness of Constructive Data Modeling [Z4CE]

類型系統的用途是義務擴散機

什麼是CPS? [IAVH]

CPS是continuation passing style的縮寫,是一種編寫程式的風格,要理解這個概念,我們可以從為什麽要傳遞continuation開始。在循序式的語言(包含指令語言)裡面,continuation是明明白白寫出來的

  • 要嘛是下一行
  • 要嘛是jump到第 kk 行

但有一種情況沒有寫,就是procedure。procedure從continuation的角度來看,是個一進一出的結構。在很多指令語言裡面都有calling convention,就是針對procedure的最佳化,因為這要求一進的時候復用現在的stack,輸入會放在特定的位置,一出的時候要把輸出寫到特定的registers

那可以多進多出嗎?可以,但我們先暫時轉向沒有明顯continuation的案例,並且討論函數式語言這種特例

在函數式語言裡面,允許傳遞lambda(匿名函數)以及其他各種高階運算式作為值,這其實給後端帶來了很大的複雜性,比如

let x := if a 1 2
in x

請問 if a 1 2 的continuation是什麼呢?是

let x := ♢ in x
♢ 用來表示任意運算式

那我們是不是可以把這寫成lambda?

\♢. let x := ♢ in x

這是合法的函數式寫法嗎?是。那我們可不可以說

let x := if a 1 2
in x

等於

let k := \♢. let x := ♢ in x
in if a (k 1) (k 2)

答案還是可以。我們把這種把未來要執行的程式顯式提取出來的寫法,稱之為CPS

call/cc也就是這麼實現的。問題是,這樣傳遞的continuation通通都是同色的。比如你用call/cc做了個檔案資源清理,但呼叫的SQL連線程式丟了個exception(也用call/cc實現),這個檔案就不會被清掉了!這是資源洩漏,是非常嚴重的問題,所以scheme發展出 dynamic-wind 這個函數,用來保證裡面的運算不管發生什麼continuation跳轉都還是會執行

而且我們發現,傳統的continuation實作往往決定了一個任意的界線,例如頂層宣告以外的續延都不會被捕捉;而且我們又需要解決同色問題,所以我們發展了一些技術來處理這些

  • delimited continuation:與其捕捉「所有剩下的計算(並設立任意的界線)」,不如先用prompt標出捕捉界線,abort會被prompt擋住
  • 而不同用途的跳轉(exception、generator、async)可以用不同的prompt tag捕捉,他們就不會互相影響
  • continuation mark這個功能則是可以把資料放到continuation frame上,之後用 current-marks 沿著當下的continuation讀回來,並且保證tail call不會讓mark累積

當然,這些技術又細分成能不能多次abort,能不能多次resume等等,在runtime速度跟功能上做出取捨

最後CPS如果變成一種強制的形式,那就提供了一種優雅的編譯框架,因此這也是一種編譯理論技術。CPS變換強制把每個不明顯的control flow都打包成函數閉包,然後顯式的傳遞。做完之後有幾個性質會同時成立:每個中間值都有名字、每個呼叫都在tail position(所以call就是jump,return就是call傳進來的 k)、β\beta 化簡可以無條件使用,編譯器可以用這個IR解釋橫跨全局的控制流程,用來實現如exception等等高階控制流運算

Osiris: replicated logs [K4RQ]

Osiris是RabbitMQ使用的底層logs儲存機制,在 mix.exs 的 deps array 裡面加上

{:osiris, github: "rabbitmq/osiris", tag: "v1.13.1"}

來使用,hex.pm上面的同名專案是別的專案注意不要搞錯了。由於Osiris沒有公開API,要注意接下來講的用法未來可能被改變

準備一個資料夾給osiris,用Application env提供然後用 ensure_all_started 啟動osiris app

data_dir = ~c"/tmp/osiris"
File.mkdir_p!(data_dir)
:ok = Application.put_env(:osiris, :data_dir, data_dir)
{:ok, _apps} = Application.ensure_all_started(:osiris)

提供設定檔,單機上 leader_node 選目前的節點就可以了

config = %{
  name: "my_stream",
  epoch: 1,
  leader_node: node(),
  replica_nodes: []
}
{:ok, %{leader_pid: leader}} = :osiris.start_cluster(config)

寫入需要4個參數:osiris cluster的leader PID、writer ID、訊息序號、內容

writer_id = <<"writer-1">>
:ok = :osiris.write(leader, writer_id, 1, <<"hello">>)
:ok = :osiris.write(leader, writer_id, 2, <<"osiris">>)

成功寫入disk後會回一個 :osiris_written 訊息,所以寫入方要等這個消息傳過來,可以設定一個等待時限(這邊是5秒)

receive do
  {:osiris_written, _name, ^writer_id, seqs} ->
    IO.inspect(seqs, label: "written")
after
  5_000 -> exit(:write_timeout)
end

讀取需要建立reader,會得到一個stream state,接下來就是用 read_chunk_parsed 解析出logs的內容

{:ok, log0} = :osiris.init_reader(leader, :first, {:my_reader, []})
{entries, log1} = :osiris_log.read_chunk_parsed(log0)
IO.inspect(entries, label: "chunk 1")

讀到 :end_of_stream 之後可以關閉logs

case :osiris_log.read_chunk_parsed(log1) do
  {:end_of_stream, log2} ->
    IO.puts("end of stream")
    :osiris_log.close(log2)

  {more, log2} ->
    IO.inspect(more, label: "chunk 2")
    :osiris_log.close(log2)
end

最後關閉cluster

:ok = :osiris.stop_cluster(config)

Theorem Left/right adjoints preserve (co)/limits [0IGM]

We have

HomC(X, R lim←⁡D)≅HomC(X,lim←⁡RD)\text{Hom}_{\mathcal{C}}(X,\ R\ \varprojlim D) \cong \text{Hom}_{\mathcal{C}}(X, \varprojlim RD)

and

HomD(Llim→⁡X,Y)≅HomD(lim→⁡LX,Y)\text{Hom}_{\mathcal{D}}(L \varinjlim X, Y) \cong \text{Hom}_{\mathcal{D}}(\varinjlim LX, Y)

Proof [local-0]

Only prove right adjoints preserve limits here, left adjoints case is dual.

It basically invokes Hom-functors preserve limits twice

HomC(X, R lim←⁡D)≅  HomD(L X,lim←⁡D)by adjunction  ≅  lim←⁡j HomD(L X,Dj)representable preserves limits  ≅  lim←⁡j HomC(X,R Dj)by adjunction  ≅  HomC(X,lim←⁡RD)representable preserves limits\begin{aligned} \text{Hom}_{\mathcal{C}}(X,\ R\ \varprojlim D) &\cong\;\text{Hom}_\mathcal{D}(L\ X, \varprojlim D) && \text{by adjunction} \\ &\;\cong\;\varprojlim_j\ \text{Hom}_\mathcal{D}(L\ X, D_j) && \text{representable preserves limits} \\ &\;\cong\;\varprojlim_j\ \text{Hom}_\mathcal{C}(X, R\ D_j) && \text{by adjunction} \\ &\;\cong\;\text{Hom}_\mathcal{C}(X, \varprojlim RD) && \text{representable preserves limits} \end{aligned}

Counterexample 關於sieve的組合封閉 [HZSP]

如果我們考慮以下交換圖與 R⪧XR \mathbin{⪧} X

figure tex10192

h∈Rh \in R 不足以推導出 f∈Rf \in R。對於sieve我們只能說如果 f∈Rf \in R 那 h∈Rh \in R

Definition J-sheaf [ZUQN]

Let (C,J)(\mathcal{C}, J) be a site, a JJ-sheaf on C\mathcal{C} is a presheaf P:Cop→SetP : \mathcal{C}^{op} \to \text{Set} such that for each JJ-covering sieve S⪧JXS \mathbin{⪧}_J X and for each family

{xf∈P(dom(f))∣f∈S}\{ x_f \in P(\text{dom}(f)) \mid f \in S \}

such that for each f∈Sf \in S and for each morphism gg that's C\mathcal{C}-composable with ff

P(g)(xf)=xf∘gP(g)(x_f) = x_{f \circ g}

, there exists a unique element x∈P(X)x \in P(X) such that

xf=P(f)(x)x_f = P(f)(x)

for all f∈Sf \in S.

Proposition For any sieve RR in JJ, bigger sieve S⊇RS \supseteq R also in JJ [7R33]

Let JJ be a Grothendieck topology on a category C\mathcal{C}. If R⪧JUR \mathbin{⪧}_J U and S⪧US \mathbin{⪧} U is a sieve on UU containing RR, then S⪧JUS \mathbin{⪧}_J U.

Proof [local-0]

The key is this: By definition of sieve, for any element f∈Rf \in R, the set f∗(R)f^*(R) is a maximal sieve of dom(f)\text{dom}(f)! Because let's see

f∗(R)={g∣f∘g∈R}f^*(R) = \{ g \mid f \circ g \in R \}

because elements of RR are closed under composition, f∗(R)f^*(R) is the maximal sieve of dom(f)\text{dom}(f):

f∗(R)={g∣cod(g)=dom(f)}=Mdom(f)f^*(R) = \{g \mid \text{cod}(g) = \text{dom}(f) \} = M_{\text{dom}(f)}

Because all elements of RR also belongs to SS, we have f∗(R)⊆f∗(S)f^*(R) \subseteq f^*(S); but f∗(R)f^*(R) is the maximal sieve of dom(f)\text{dom}(f), hence f∗(R)=f∗(S)f^*(R) = f^*(S).

Recall that maximal sieve of UU belongs to J(U)J(U), implies that for any f∈Rf \in R, we have f∗(S)⪧Jdom(f)f^*(S) \mathbin{⪧}_J \text{dom}(f). We apply property (iii), conclude that S⪧JUS \mathbin{⪧}_J U.

Proposition Natural transformations pair of adjunctions [31KN]

Let L,L′L, L' be two left adjoints, and their right adjoints are R,R′R, R' respectively, a natural transformation α:L→L′\alpha : L \to L' has a correspondence β:R′→R\beta : R' \to R.

Proof [local-0]

We can construct

figure tex6800

Definition Site [84R3]

A site is a pair (C,J)(\mathcal{C}, J) consisting of a category C\mathcal{C} and a Grothendieck topology JJ on C\mathcal{C}.

Definition Grothendieck topology [ZD97]

A Grothendieck topology JJ on a category C\mathcal{C} is an assignment JJ sending any object X∈CX \in \mathcal{C} to a collection J(X)J(X) of sieves on C\mathcal{C} such that the following properties are satisfied.

Before we view the properties

  • we denote S∈J(X)S \in J(X) with S⪧JXS \mathbin{⪧}_J X or X⪦JSX \mathbin{⪦}_J S.
  • We need to define maximal sieve.

Definition Maximal sieve [IGSL]

In a category C\mathcal{C}, a maximal sieve of an object X∈CX \in \mathcal{C} is defined as

MX:={f∣cod(f)=X}M_X := \{ f \mid \text{cod}(f) = X \}

Property Maximality axiom [BEIE]

Property Pullback stability [FXZI]

If S⪧JXS \mathbin{⪧}_J X and f:Y→Xf : Y \to X, then

f∗(S)⪧JYf^*(S) \mathbin{⪧}_J Y

f∗(S)f^*(S) defined by

f∗(S):={g:Z→Y∣f∘g∈S}f^*(S) := \{ g : Z \to Y \mid f \circ g \in S \}

We can represent it as

figure tex32615

Property Transitivity [MACB]

Let S⪧XS \mathbin{⪧} X be a sieve on XX, and T⪧JXT \mathbin{⪧}_J X be a sieve in J(X)J(X). If for all f∈Tf \in T we have f∗(S)⪧Jdom(f)f^*(S) \mathbin{⪧}_J \text{dom}(f), then S⪧JXS \mathbin{⪧}_J X.

Definition Sieve [FG8Y]

A sieve SS on an object XX of a category C\mathcal{C} is a family of morphisms with codomain XX such that closed under composition: If f∈Sf \in S then for any composable gg we have f∘g∈Sf \circ g \in S.

We denote S⪧XS \mathbin{⪧} X or X⪦SX \mathbin{⪦} S.

Frames與complete Heyting algebras不同之處 [TJ21]

Theorem 3.10.2 Topology via Logic [WBA7]

Let AA be a lattice, then AA is a frame iff it is a complete Heyting algebra. See Topology via logic

Also check Theorem 3.5.2, that a frame is a complete lattice and hence has infinite meets.

可見frame就是complete Heyting algebra,那為什麼還要提供兩個名詞來稱呼他們呢?這是因為 the category of frames Frm\text{Frm} 跟 the category of complete Heyting algebras cHa\text{cHa} 裡面的morphisms不一樣!

具體來說

Definition Frame homomorphism [local-0]

A map f:A→Bf : A \to B is a frame homomorphism iff

  • preserving finite meets f(a∧b)=f(a)∧f(b)f(a \wedge b) = f(a) \wedge f(b)
  • preserving arbitrary joins f(⋁i∈Iai)=⋁i∈If(ai)f(\bigvee_{i\in I} a_i) = \bigvee_{i\in I} f(a_i)

Definition complete Heyting algebra homomorphism [local-1]

A map f:A→Bf : A \to B is a cHa homomorphism iff

  • preserving arbitrary meets f(⋀i∈Iai)=⋀i∈If(ai)f(\bigwedge_{i\in I} a_i) = \bigwedge_{i\in I} f(a_i)
  • preserving arbitrary joins f(⋁i∈Iai)=⋁i∈If(ai)f(\bigvee_{i\in I} a_i) = \bigvee_{i\in I} f(a_i)
  • monotone (preserving Heyting implication) f(a⇒b)=f(a)⇒f(b)f(a \Rightarrow b) = f(a) \Rightarrow f(b)

把complete lattice視為小範疇那我們就能利用範疇論的技巧 left/right adjoint functors preserves co/limits 證明他們不一樣

Proposition cHa homomorphism has left/right adjoints [local-3]

cHa homomorphism has a left adjoint and a right adjoint

Proof [local-2]

  • preserves meets (limits) 所以它是right adjoint,因此有left adjoint
  • preserves joins (colimits) 所以它是left adjoint,因此有right adjoint

所以相應的frame homomorphism有right adjoint但不一定有left adjoint

Idea Generate HTMLs for local cards? [tr-47YA]

tr currently produces _build/XXXX/index.html for each XXXX.scrbl in content, however, it doesn't produce HTML for local cards (write as @tr/card{...}). But _build/XXXX/ indeed has space for them, e.g. _build/XXXX/0/index.html.

Of course, this might introduce new problems

  • tr-notes previously assumes there are only root-level HTMLs, would these new URIs be a problem?
  • How to extract these HTMLs? e.g. @include{...} includes pure HTML, how such forms interact with this new behaviour?
  • Should local cards hence be first-class citizen? e.g. Should we compute relationship between cards? Still file based? Or local address also counted in?

Regular type的導數是它的one-hole context [ag-93PB]

Details [local-0]

The Derivative of a Regular Type is its Type of One-Hole Contexts筆記

核心觀察:對一個regular type(多項式 functor)微分 ∂\partial 得到的型別恰好就是它的「一個洞的context」,把類型視為limit與colimit構成的多項式,求導規則跟微積分一樣。這裡只用單變數functor:唯一的變數 var 表示 x

data Poly : 𝓤₀ ̇ where
  𝟘ᵖ  : Poly
  𝟙ᵖ  : Poly
  var : Poly
  _⊕_ : Poly → Poly → Poly
  _⊗_ : Poly → Poly → Poly

infixr 40 _⊕_
infixr 50 _⊗_

Definition Poly的解釋 [local-1]

Definition 對型別微分 [local-2]

Example btree′=2×btree\text{btree}' = 2 \times \text{btree} [local-3]

我們先看案例 btree X=1+X2\text{btree}\ X = 1 + X^2

  B : Poly
  B = 𝟙ᵖ ⊕ (var ⊗ var)

  _ : ∂ B = 𝟘ᵖ ⊕ ((𝟙ᵖ ⊗ var) ⊕ (var ⊗ 𝟙ᵖ))
  _ = refl

  ∂B-≃ : {X : 𝓤₀ ̇ } → ⟦ ∂ B ⟧ X ≃ (X + X)
  ∂B-≃ = qinveq to (from , from-to , to-from)
    where
    to : {X : 𝓤₀ ̇ } → ⟦ ∂ B ⟧ X → X + X
    to (inl ())
    to (inr (inl (⋆ , x))) = inl x
    to (inr (inr (x , ⋆))) = inr x

    from : {X : 𝓤₀ ̇ } → X + X → ⟦ ∂ B ⟧ X
    from (inl x) = inr (inl (⋆ , x))
    from (inr x) = inr (inr (x , ⋆))

    from-to : {X : 𝓤₀ ̇ } → (c : ⟦ ∂ B ⟧ X) → from (to c) = c
    from-to (inl ())
    from-to (inr (inl (⋆ , x))) = refl
    from-to (inr (inr (x , ⋆))) = refl

    to-from : {X : 𝓤₀ ̇ } → (v : X + X) → to (from v) = v
    to-from (inl x) = refl
    to-from (inr x) = refl

  ∂B-= : is-univalent 𝓤₀ → (X : 𝓤₀ ̇ ) → ⟦ ∂ B ⟧ X = (X + X)
  ∂B-= ua X = eqtoid ua _ _ ∂B-≃

Definition Plugging in [local-4]

Types on Scott's graph model [A3Q8]

基本上概念大致上就是在universal domain P(N)\mathcal{P}(\mathbb{N}) 中,我們可以用PERs定義出一系列classes,而這些classes的表現就如同我們想要的types,而且可以表示dependent types跟System F那種polymorphic types

X:TX : T 表示 XX 的類型是 TT,定義成 X[T]XX [ T ] X(因為型別是PER)

這裡只聊到型別部分,關於graph model本身的運作、拓樸,可以參考Scott的論文Data Types as Lattices

PER: 正確處理 exponentiation [ag-KA1U]

From Denotational Semantics, looking backward - looking forward

Partial Equivalences as Types: First attempts的編碼有個缺點:exponentiation A => B 是定在函數 𝓟 ℕ → 𝓟 ℕ 上的關係,而不是一個 𝓟 ℕ 的關係,所以無法表示 A => B => A。這就是缺點的根源:A => B 不再是一個 Rel,因此 A => B => A 不合乎其型別的定義。

關鍵是 pairing : ℕ × ℕ ≃ ℕ,有了配對,一個 F : 𝓟 ℕ 就能被看成 ℕ 上的關係,用 P(ω)P(\omega) application 把函數放回 𝓟 ℕ。這樣 _=>_ 就封閉成 Rel → Rel → Rel,缺點消失,A => B => A 也跟著是 PER

Details [local-0]

  {-# OPTIONS --safe --without-K #-}
  open import MLTT.Spartan
  open import MLTT.List using (List; []; _∷_; member; in-head; in-tail)
  open import UF.Base using (ap₂)
  open import UF.Equiv
  open import UF.FunExt
  open import UF.Powerset
  open import UF.Subsingletons
  open import UF.SubtypeClassifier
  open import UF.PropTrunc
  open import Naturals.Binary using (pairing)
  open import Naturals.Properties using (succ-lc; positive-not-zero)

  module ag-KA1U
    (pt : propositional-truncations-exist)
    (fe : Fun-Ext)
    (pe : propext 𝓤₀)
    where

  open PropositionalTruncation pt
  open import ag-U75Z using (_[_]_; is-PER)

Definition Relation [local-1]

我們需要讓「函數」也住在 𝓟 ℕ 裡,這樣 _=>_ 才會是封閉的 Rel → Rel → Rel

關鍵是 pairing : ℕ × ℕ ≃ ℕ,取它的正向映射 ⌜ pairing ⌝ 把一對碼壓成一個碼。因為它是equivalence,所以是injective

encode : ℕ × ℕ → ℕ
encode = ⌜ pairing ⌝

encode-lc : {a b : ℕ × ℕ} → encode a = encode b → a = b
encode-lc = equivs-are-lc encode (⌜⌝-is-equiv pairing)

graph model的application不是輸入單一個編碼餵,而是餵一個**有限的編碼集合**。我們用 List ℕ 表示有限集合,用 encode 把它壓成一個 ℕ

codeList : List ℕ → ℕ
codeList []       = 0
codeList (x ∷ xs) = succ (encode (x , codeList xs))

codeList-lc : (l l′ : List ℕ) → codeList l = codeList l′ → l = l′
codeList-lc []       []        e = refl
codeList-lc []       (y ∷ ys)  e = 𝟘-elim (positive-not-zero _ (e ⁻¹))
codeList-lc (x ∷ xs) []        e = 𝟘-elim (positive-not-zero _ e)
codeList-lc (x ∷ xs) (y ∷ ys)  e = ap₂ _∷_ (ap pr₁ q) (codeList-lc xs ys (ap pr₂ q))
  where
  q : (x , codeList xs) = (y , codeList ys)
  q = encode-lc (succ-lc e)

「有限集合 l 被 X 包含」:l 裡每個編碼都在 X 裡

_⊆ₗ_ : List ℕ → 𝓟 ℕ → 𝓤₀ ̇
l ⊆ₗ X = (k : ℕ) → member k l → k ∈ X

定義graph model的application:F ⊙ X 收集所有 m,使得存在一個有限近似 l ⊆ X,而 F 把 l(壓成的碼)送到 m

_⊙_ : 𝓟 ℕ → 𝓟 ℕ → 𝓟 ℕ
(F ⊙ X) m = (∃ l ꞉ List ℕ , (encode (codeList l , m) ∈ F) × (l ⊆ₗ X)) , ∃-is-prop
infixl 60 _⊙_

於是現在改用 F : 𝓟 ℕ → 𝓟 ℕ 的編碼版本 𝓟 ℕ,再靠 _⊙_ 取回作用。沿用記號與定義,並根據新的 Rel 定義我們需要的helpers

PER-symm : {A : Rel} → (is-PER A) → symmetric A
PER-symm per-A = per-A .pr₁
PER-trans : {A : Rel} → (is-PER A) → transitive A
PER-trans per-A = per-A .pr₂

Definition Exponentiation [local-2]

把 F X 換成 F ⊙ X 後PER的證明基本上一樣

A=>B-is-PER-if-A-B-are-PERs : {A B : Rel}
     → is-PER A
     → is-PER B
     → is-PER (A => B)
A=>B-is-PER-if-A-B-are-PERs {A}{B} per-A per-B = I , II
  where
  I : symmetric (A => B)
  I F G F[A=>B]G X Y X[A]Y = goal
    where
    Y[A]X : Y [ A ] X
    Y[A]X = PER-symm per-A X Y X[A]Y

    apply : (F ⊙ Y) [ B ] (G ⊙ X)
    apply = F[A=>B]G Y X Y[A]X

    goal : (G ⊙ X) [ B ] (F ⊙ Y)
    goal = PER-symm per-B (F ⊙ Y) (G ⊙ X) apply
  II : transitive (A => B)
  II F G H F[A=>B]G G[A=>B]H X Y X[A]Y = goal
    where
    apply₁ : (F ⊙ X) [ B ] (G ⊙ Y)
    apply₁ = F[A=>B]G X Y X[A]Y

    Y[A]X : Y [ A ] X
    Y[A]X = PER-symm per-A X Y X[A]Y

    Y[A]Y : Y [ A ] Y
    Y[A]Y = PER-trans per-A Y X Y Y[A]X X[A]Y

    apply₂ : (G ⊙ Y) [ B ] (H ⊙ Y)
    apply₂ = G[A=>B]H Y Y Y[A]Y

    goal : F ⊙ X [ B ] H ⊙ Y
    goal = PER-trans per-B (F ⊙ X) (G ⊙ Y) (H ⊙ Y) apply₁ apply₂

因為封閉,套疊兩次得到 A => B => A 也是PER

A=>B=>A-is-PER : {A B : Rel}
     → is-PER A
     → is-PER B
     → is-PER (A => B => A)
A=>B=>A-is-PER per-A per-B =
  A=>B-is-PER-if-A-B-are-PERs per-A (A=>B-is-PER-if-A-B-are-PERs per-B per-A)

_=>_ 的型別現在是 Rel → Rel → Rel,缺點消失。但還有一個問題:A => B => A 既然關聯的是 𝓟 ℕ,那 fst : 𝓟 ℕ → 𝓟 ℕ → 𝓟 ℕ 活在host裡面是無法使用的,也必須被編碼成一個 𝓟 ℕ,這裡我們稱之為 K

box : ℕ → ℕ
box p = encode (codeList [] , p)

K : 𝓟 ℕ
K k = (∃ p ꞉ ℕ , k = encode (codeList (p ∷ []) , box p)) , ∃-is-prop

核心引理:K ⊙ X 再作用任何 U 的結果是 X

K-const : (X U : 𝓟 ℕ) → ((K ⊙ X) ⊙ U) = X
K-const X U = subset-extensionality pe fe to-X from-X
  where
  to-X : ((K ⊙ X) ⊙ U) ⊆ X
  to-X r = ∥∥-rec (∈-is-prop X r) I
    where
    I : (Σ l ꞉ List ℕ , (encode (codeList l , r) ∈ (K ⊙ X)) × (l ⊆ₗ U)) → r ∈ X
    I (l , kx , _) = ∥∥-rec (∈-is-prop X r) II kx
      where
      II : (Σ l₂ ꞉ List ℕ , (encode (codeList l₂ , encode (codeList l , r)) ∈ K) × (l₂ ⊆ₗ X)) → r ∈ X
      II (l₂ , ∈K , l₂⊆X) = ∥∥-rec (∈-is-prop X r) III ∈K
        where
        III : (Σ p ꞉ ℕ , encode (codeList l₂ , encode (codeList l , r)) = encode (codeList (p ∷ []) , box p)) → r ∈ X
        III (p , eq) = transport (_∈ X) (ap pr₂ inner ⁻¹) p∈X
          where
          outer : (codeList l₂ , encode (codeList l , r)) = (codeList (p ∷ []) , box p)
          outer = encode-lc eq

          inner : (codeList l , r) = (codeList [] , p)
          inner = encode-lc (ap pr₂ outer)

          l₂=p∷[] : l₂ = (p ∷ [])
          l₂=p∷[] = codeList-lc l₂ (p ∷ []) (ap pr₁ outer)

          p∈X : p ∈ X
          p∈X = l₂⊆X p (transport (member p) (l₂=p∷[] ⁻¹) in-head)

  from-X : X ⊆ ((K ⊙ X) ⊙ U)
  from-X r r∈X = ∣ [] , kx-mem , (λ k ()) ∣
    where
    kx-mem : encode (codeList [] , r) ∈ (K ⊙ X)
    kx-mem = ∣ (r ∷ []) , ∣ r , refl ∣ , sing-sub ∣
      where
      sing-sub : (r ∷ []) ⊆ₗ X
      sing-sub k in-head      = r∈X
      sing-sub k (in-tail ())
於是最後一個問題可以寫成
main : {A B : Rel} → K [ A => B => A ] K
main {A}{B} X Y X[A]Y U V U[B]V =
  transport (λ b → ((K ⊙ X) ⊙ U) [ A ] b) (K-const Y V ⁻¹)
    (transport (λ a → a [ A ] Y) (K-const X U ⁻¹) X[A]Y)

PER as types: product [ag-NN5N]

Details [local-0]

首先我們需要針對程式的projection 1跟projection 2

Fst Snd : 𝓟 ℕ → 𝓟 ℕ
Fst X n = X (encode (0 , n))
Snd X n = X (encode (1 , n))

Definition Product [local-1]

Product of PER依然是PER [local-2]

PER as types: sum [ag-MM24]

Details [local-0]

  {-# OPTIONS --safe --without-K #-}
  open import MLTT.Spartan
  open import UF.Powerset
  open import UF.PropTrunc
  open import UF.FunExt
  open import UF.Subsingletons
  open import UF.DiscreteAndSeparated using (ℕ-is-set)
  open import Naturals.Properties using (positive-not-zero)

  module ag-MM24
    (pt : propositional-truncations-exist)
    (fe : Fun-Ext)
    (pe : propext 𝓤₀)
    where

  open import ag-U75Z using (_[_]_; is-PER)
  open import ag-KA1U pt fe pe using (Rel; PER-symm; PER-trans)
  open import ag-NN5N pt fe pe using (Fst; Snd)

tag 取成 singleton:{ m } 就是只含 m 的集合

{_} : ℕ → 𝓟 ℕ
{ m } n = (m = n) , ℕ-is-set

X = ({0} , X0) 可以表示成 Fst X = { 0 } 且 Snd X = X0,inr同理

is-inl is-inr : 𝓟 ℕ → 𝓤₁ ̇
is-inl X = Fst X = { 0 }
is-inr X = Fst X = { 1 }

輔助引理證明不可能既是inl又是inr

inl-and-inr-is-impossible : (X : 𝓟 ℕ) → is-inl X → is-inr X → 𝟘
inl-and-inr-is-impossible X p q =
  positive-not-zero 0 (transport (0 ∈_) (p ⁻¹ ∙ q) refl)

Definition Sum [local-1]

Sum of PER依然是PER [local-2]

A +ᵣ B 依然是PER。symmetric跟transitivity的同向情況都是per component;混合情況用 inl-and-inr-is-impossible 推出矛盾排除

  A+B-is-PER : {A B : Rel}
       → is-PER A
       → is-PER B
       → is-PER (A +ᵣ B)
  A+B-is-PER {A}{B} per-A per-B = I , II
    where
    I : symmetric (A +ᵣ B)
    I X Y (inl (lX , lY , XA)) =
      inl (lY , lX , PER-symm per-A (Snd X) (Snd Y) XA)
    I X Y (inr (rX , rY , XB)) =
      inr (rY , rX , PER-symm per-B (Snd X) (Snd Y) XB)
    II : transitive (A +ᵣ B)
    II X Y Z (inl (lX , _ , XA)) (inl (_ , lZ , YA)) =
      inl (lX , lZ , PER-trans per-A (Snd X) (Snd Y) (Snd Z) XA YA)
    II X Y Z (inr (rX , _ , XB)) (inr (_ , rZ , YB)) =
      inr (rX , rZ , PER-trans per-B (Snd X) (Snd Y) (Snd Z) XB YB)
    II X Y Z (inl (_ , lY , _)) (inr (rY , _ , _)) =
      𝟘-elim (inl-and-inr-is-impossible Y lY rY)
    II X Y Z (inr (_ , rY , _)) (inl (lY , _ , _)) =
      𝟘-elim (inl-and-inr-is-impossible Y lY rY)

PER as types: dependent product & sum [ag-BQXB]

Details [local-0]

依賴型別由一族 B : 𝓟 ℕ → Rel 給出。要讓它在 A 的商空間上良好定義,需要 B 在 A:U [ A ] V 時滿足 B U = B V

dependent sum:Fst X 由 A 分類,Snd X 由 B (Fst X) 分類

Σᵣ : (A : Rel) → (𝓟 ℕ → Rel) → Rel
Σᵣ A B X Y = (Fst X [ A ] Fst Y) × (Snd X [ B (Fst X) ] Snd Y)
infixr 55 Σᵣ

dependent product:把 F 作用在被 A 分類的 X 上,結果由 B X 分類

Πᵣ : (A : Rel) → (𝓟 ℕ → Rel) → Rel
Πᵣ A B F G = (X Y : 𝓟 ℕ) → X [ A ] Y → (F ⊙ X) [ B X ] (G ⊙ Y)
infixr 50 Πᵣ

Dependent sum of PER依然是PER [local-1]

Per component提出證明,依賴的部分要靠 B U = B V 把證明在 B (Fst X) 與 B (Fst Y) 之間搬移

  Σ-is-PER : {A : Rel} {B : 𝓟 ℕ → Rel}
       → is-PER A
       → ((U : 𝓟 ℕ) → is-PER (B U))
       → ({U V : 𝓟 ℕ} → U [ A ] V → B U = B V)
       → is-PER (Σᵣ A B)
  Σ-is-PER {A}{B} per-A per-B resp = I , II
    where
    I : symmetric (Σᵣ A B)
    I X Y (p , q) =
      PER-symm per-A (Fst X) (Fst Y) p ,
      PER-symm (per-B (Fst Y)) (Snd X) (Snd Y)
        (transport (λ R → Snd X [ R ] Snd Y) (resp p) q)
    II : transitive (Σᵣ A B)
    II X Y Z (p₁ , q₁) (p₂ , q₂) =
      PER-trans per-A (Fst X) (Fst Y) (Fst Z) p₁ p₂ ,
      PER-trans (per-B (Fst X)) (Snd X) (Snd Y) (Snd Z) q₁
        (transport (λ R → Snd Y [ R ] Snd Z) (resp p₁ ⁻¹) q₂)

Dependent product of PER依然是PER [local-2]

結構與 _=>_ 相同,只是每次套用後都要把型別 B Y 搬回 B X

  Π-is-PER : {A : Rel} {B : 𝓟 ℕ → Rel}
       → is-PER A
       → ((U : 𝓟 ℕ) → is-PER (B U))
       → ({U V : 𝓟 ℕ} → U [ A ] V → B U = B V)
       → is-PER (Πᵣ A B)
  Π-is-PER {A}{B} per-A per-B resp = I , II
    where
    I : symmetric (Πᵣ A B)
    I F G F[Π]G X Y X[A]Y = goal
      where
      Y[A]X : Y [ A ] X
      Y[A]X = PER-symm per-A X Y X[A]Y

      apply : (F ⊙ Y) [ B Y ] (G ⊙ X)
      apply = F[Π]G Y X Y[A]X

      apply' : (F ⊙ Y) [ B X ] (G ⊙ X)
      apply' = transport (λ R → (F ⊙ Y) [ R ] (G ⊙ X)) (resp Y[A]X) apply

      goal : (G ⊙ X) [ B X ] (F ⊙ Y)
      goal = PER-symm (per-B X) (F ⊙ Y) (G ⊙ X) apply'
    II : transitive (Πᵣ A B)
    II F G H F[Π]G G[Π]H X Y X[A]Y = goal
      where
      apply₁ : (F ⊙ X) [ B X ] (G ⊙ Y)
      apply₁ = F[Π]G X Y X[A]Y

      Y[A]X : Y [ A ] X
      Y[A]X = PER-symm per-A X Y X[A]Y

      Y[A]Y : Y [ A ] Y
      Y[A]Y = PER-trans per-A Y X Y Y[A]X X[A]Y

      apply₂ : (G ⊙ Y) [ B Y ] (H ⊙ Y)
      apply₂ = G[Π]H Y Y Y[A]Y

      apply₂' : (G ⊙ Y) [ B X ] (H ⊙ Y)
      apply₂' = transport (λ R → (G ⊙ Y) [ R ] (H ⊙ Y)) (resp Y[A]X) apply₂

      goal : (F ⊙ X) [ B X ] (H ⊙ Y)
      goal = PER-trans (per-B X) (F ⊙ X) (G ⊙ Y) (H ⊙ Y) apply₁ apply₂'

退化成非依賴時 [local-3]

Polymorphic types [ag-8LAS]

Details [local-0]

Polymorphic type量化的不是元素,而是型別(PER)本身。一支program住在 ∀X. T(X) 裡的意思是不管 X 是哪個型別,它都住在 T(X) 裡。在這裡型別就是 PER,所以這恰好是把所有instance F A 取交集

(M , N) 屬於 ∀ᵣ F iff對每個PER A 都有 M [ F A ] N

交集量化了所有 Rel,落在比 Rel 高一階的universe,但Agda的universe是predicative的,所以要提供一個新名字 Rel⁺

Rel⁺ : 𝓤₂ ⁺ ̇
Rel⁺ = 𝓟 ℕ → 𝓟 ℕ → 𝓤₂ ̇

∀ᵣ : (Rel → Rel) → Rel⁺
∀ᵣ F M N = (A : Rel) → is-PER A → M [ F A ] N

PER的交集依然是PER [local-1]

Elimination就是instantiation [local-2]

Polymorphic types [ag-8LAS]

Details [local-0]

Polymorphic type量化的不是元素,而是型別(PER)本身。一支program住在 ∀X. T(X) 裡的意思是不管 X 是哪個型別,它都住在 T(X) 裡。在這裡型別就是 PER,所以這恰好是把所有instance F A 取交集

(M , N) 屬於 ∀ᵣ F iff對每個PER A 都有 M [ F A ] N

交集量化了所有 Rel,落在比 Rel 高一階的universe,但Agda的universe是predicative的,所以要提供一個新名字 Rel⁺

Rel⁺ : 𝓤₂ ⁺ ̇
Rel⁺ = 𝓟 ℕ → 𝓟 ℕ → 𝓤₂ ̇

∀ᵣ : (Rel → Rel) → Rel⁺
∀ᵣ F M N = (A : Rel) → is-PER A → M [ F A ] N

PER的交集依然是PER [local-1]

Elimination就是instantiation [local-2]

PER as types: dependent product & sum [ag-BQXB]

Details [local-0]

依賴型別由一族 B : 𝓟 ℕ → Rel 給出。要讓它在 A 的商空間上良好定義,需要 B 在 A:U [ A ] V 時滿足 B U = B V

dependent sum:Fst X 由 A 分類,Snd X 由 B (Fst X) 分類

Σᵣ : (A : Rel) → (𝓟 ℕ → Rel) → Rel
Σᵣ A B X Y = (Fst X [ A ] Fst Y) × (Snd X [ B (Fst X) ] Snd Y)
infixr 55 Σᵣ

dependent product:把 F 作用在被 A 分類的 X 上,結果由 B X 分類

Πᵣ : (A : Rel) → (𝓟 ℕ → Rel) → Rel
Πᵣ A B F G = (X Y : 𝓟 ℕ) → X [ A ] Y → (F ⊙ X) [ B X ] (G ⊙ Y)
infixr 50 Πᵣ

Dependent sum of PER依然是PER [local-1]

Per component提出證明,依賴的部分要靠 B U = B V 把證明在 B (Fst X) 與 B (Fst Y) 之間搬移

  Σ-is-PER : {A : Rel} {B : 𝓟 ℕ → Rel}
       → is-PER A
       → ((U : 𝓟 ℕ) → is-PER (B U))
       → ({U V : 𝓟 ℕ} → U [ A ] V → B U = B V)
       → is-PER (Σᵣ A B)
  Σ-is-PER {A}{B} per-A per-B resp = I , II
    where
    I : symmetric (Σᵣ A B)
    I X Y (p , q) =
      PER-symm per-A (Fst X) (Fst Y) p ,
      PER-symm (per-B (Fst Y)) (Snd X) (Snd Y)
        (transport (λ R → Snd X [ R ] Snd Y) (resp p) q)
    II : transitive (Σᵣ A B)
    II X Y Z (p₁ , q₁) (p₂ , q₂) =
      PER-trans per-A (Fst X) (Fst Y) (Fst Z) p₁ p₂ ,
      PER-trans (per-B (Fst X)) (Snd X) (Snd Y) (Snd Z) q₁
        (transport (λ R → Snd Y [ R ] Snd Z) (resp p₁ ⁻¹) q₂)

Dependent product of PER依然是PER [local-2]

結構與 _=>_ 相同,只是每次套用後都要把型別 B Y 搬回 B X

  Π-is-PER : {A : Rel} {B : 𝓟 ℕ → Rel}
       → is-PER A
       → ((U : 𝓟 ℕ) → is-PER (B U))
       → ({U V : 𝓟 ℕ} → U [ A ] V → B U = B V)
       → is-PER (Πᵣ A B)
  Π-is-PER {A}{B} per-A per-B resp = I , II
    where
    I : symmetric (Πᵣ A B)
    I F G F[Π]G X Y X[A]Y = goal
      where
      Y[A]X : Y [ A ] X
      Y[A]X = PER-symm per-A X Y X[A]Y

      apply : (F ⊙ Y) [ B Y ] (G ⊙ X)
      apply = F[Π]G Y X Y[A]X

      apply' : (F ⊙ Y) [ B X ] (G ⊙ X)
      apply' = transport (λ R → (F ⊙ Y) [ R ] (G ⊙ X)) (resp Y[A]X) apply

      goal : (G ⊙ X) [ B X ] (F ⊙ Y)
      goal = PER-symm (per-B X) (F ⊙ Y) (G ⊙ X) apply'
    II : transitive (Πᵣ A B)
    II F G H F[Π]G G[Π]H X Y X[A]Y = goal
      where
      apply₁ : (F ⊙ X) [ B X ] (G ⊙ Y)
      apply₁ = F[Π]G X Y X[A]Y

      Y[A]X : Y [ A ] X
      Y[A]X = PER-symm per-A X Y X[A]Y

      Y[A]Y : Y [ A ] Y
      Y[A]Y = PER-trans per-A Y X Y Y[A]X X[A]Y

      apply₂ : (G ⊙ Y) [ B Y ] (H ⊙ Y)
      apply₂ = G[Π]H Y Y Y[A]Y

      apply₂' : (G ⊙ Y) [ B X ] (H ⊙ Y)
      apply₂' = transport (λ R → (G ⊙ Y) [ R ] (H ⊙ Y)) (resp Y[A]X) apply₂

      goal : (F ⊙ X) [ B X ] (H ⊙ Y)
      goal = PER-trans (per-B X) (F ⊙ X) (G ⊙ Y) (H ⊙ Y) apply₁ apply₂'

退化成非依賴時 [local-3]

PER as types: sum [ag-MM24]

Details [local-0]

  {-# OPTIONS --safe --without-K #-}
  open import MLTT.Spartan
  open import UF.Powerset
  open import UF.PropTrunc
  open import UF.FunExt
  open import UF.Subsingletons
  open import UF.DiscreteAndSeparated using (ℕ-is-set)
  open import Naturals.Properties using (positive-not-zero)

  module ag-MM24
    (pt : propositional-truncations-exist)
    (fe : Fun-Ext)
    (pe : propext 𝓤₀)
    where

  open import ag-U75Z using (_[_]_; is-PER)
  open import ag-KA1U pt fe pe using (Rel; PER-symm; PER-trans)
  open import ag-NN5N pt fe pe using (Fst; Snd)

tag 取成 singleton:{ m } 就是只含 m 的集合

{_} : ℕ → 𝓟 ℕ
{ m } n = (m = n) , ℕ-is-set

X = ({0} , X0) 可以表示成 Fst X = { 0 } 且 Snd X = X0,inr同理

is-inl is-inr : 𝓟 ℕ → 𝓤₁ ̇
is-inl X = Fst X = { 0 }
is-inr X = Fst X = { 1 }

輔助引理證明不可能既是inl又是inr

inl-and-inr-is-impossible : (X : 𝓟 ℕ) → is-inl X → is-inr X → 𝟘
inl-and-inr-is-impossible X p q =
  positive-not-zero 0 (transport (0 ∈_) (p ⁻¹ ∙ q) refl)

Definition Sum [local-1]

Sum of PER依然是PER [local-2]

A +ᵣ B 依然是PER。symmetric跟transitivity的同向情況都是per component;混合情況用 inl-and-inr-is-impossible 推出矛盾排除

  A+B-is-PER : {A B : Rel}
       → is-PER A
       → is-PER B
       → is-PER (A +ᵣ B)
  A+B-is-PER {A}{B} per-A per-B = I , II
    where
    I : symmetric (A +ᵣ B)
    I X Y (inl (lX , lY , XA)) =
      inl (lY , lX , PER-symm per-A (Snd X) (Snd Y) XA)
    I X Y (inr (rX , rY , XB)) =
      inr (rY , rX , PER-symm per-B (Snd X) (Snd Y) XB)
    II : transitive (A +ᵣ B)
    II X Y Z (inl (lX , _ , XA)) (inl (_ , lZ , YA)) =
      inl (lX , lZ , PER-trans per-A (Snd X) (Snd Y) (Snd Z) XA YA)
    II X Y Z (inr (rX , _ , XB)) (inr (_ , rZ , YB)) =
      inr (rX , rZ , PER-trans per-B (Snd X) (Snd Y) (Snd Z) XB YB)
    II X Y Z (inl (_ , lY , _)) (inr (rY , _ , _)) =
      𝟘-elim (inl-and-inr-is-impossible Y lY rY)
    II X Y Z (inr (_ , rY , _)) (inl (lY , _ , _)) =
      𝟘-elim (inl-and-inr-is-impossible Y lY rY)

PER as types: product [ag-NN5N]

Details [local-0]

首先我們需要針對程式的projection 1跟projection 2

Fst Snd : 𝓟 ℕ → 𝓟 ℕ
Fst X n = X (encode (0 , n))
Snd X n = X (encode (1 , n))

Definition Product [local-1]

Product of PER依然是PER [local-2]

PER: 正確處理 exponentiation [ag-KA1U]

From Denotational Semantics, looking backward - looking forward

Partial Equivalences as Types: First attempts的編碼有個缺點:exponentiation A => B 是定在函數 𝓟 ℕ → 𝓟 ℕ 上的關係,而不是一個 𝓟 ℕ 的關係,所以無法表示 A => B => A。這就是缺點的根源:A => B 不再是一個 Rel,因此 A => B => A 不合乎其型別的定義。

關鍵是 pairing : ℕ × ℕ ≃ ℕ,有了配對,一個 F : 𝓟 ℕ 就能被看成 ℕ 上的關係,用 P(ω)P(\omega) application 把函數放回 𝓟 ℕ。這樣 _=>_ 就封閉成 Rel → Rel → Rel,缺點消失,A => B => A 也跟著是 PER

Details [local-0]

  {-# OPTIONS --safe --without-K #-}
  open import MLTT.Spartan
  open import MLTT.List using (List; []; _∷_; member; in-head; in-tail)
  open import UF.Base using (ap₂)
  open import UF.Equiv
  open import UF.FunExt
  open import UF.Powerset
  open import UF.Subsingletons
  open import UF.SubtypeClassifier
  open import UF.PropTrunc
  open import Naturals.Binary using (pairing)
  open import Naturals.Properties using (succ-lc; positive-not-zero)

  module ag-KA1U
    (pt : propositional-truncations-exist)
    (fe : Fun-Ext)
    (pe : propext 𝓤₀)
    where

  open PropositionalTruncation pt
  open import ag-U75Z using (_[_]_; is-PER)

Definition Relation [local-1]

我們需要讓「函數」也住在 𝓟 ℕ 裡,這樣 _=>_ 才會是封閉的 Rel → Rel → Rel

關鍵是 pairing : ℕ × ℕ ≃ ℕ,取它的正向映射 ⌜ pairing ⌝ 把一對碼壓成一個碼。因為它是equivalence,所以是injective

encode : ℕ × ℕ → ℕ
encode = ⌜ pairing ⌝

encode-lc : {a b : ℕ × ℕ} → encode a = encode b → a = b
encode-lc = equivs-are-lc encode (⌜⌝-is-equiv pairing)

graph model的application不是輸入單一個編碼餵,而是餵一個**有限的編碼集合**。我們用 List ℕ 表示有限集合,用 encode 把它壓成一個 ℕ

codeList : List ℕ → ℕ
codeList []       = 0
codeList (x ∷ xs) = succ (encode (x , codeList xs))

codeList-lc : (l l′ : List ℕ) → codeList l = codeList l′ → l = l′
codeList-lc []       []        e = refl
codeList-lc []       (y ∷ ys)  e = 𝟘-elim (positive-not-zero _ (e ⁻¹))
codeList-lc (x ∷ xs) []        e = 𝟘-elim (positive-not-zero _ e)
codeList-lc (x ∷ xs) (y ∷ ys)  e = ap₂ _∷_ (ap pr₁ q) (codeList-lc xs ys (ap pr₂ q))
  where
  q : (x , codeList xs) = (y , codeList ys)
  q = encode-lc (succ-lc e)

「有限集合 l 被 X 包含」:l 裡每個編碼都在 X 裡

_⊆ₗ_ : List ℕ → 𝓟 ℕ → 𝓤₀ ̇
l ⊆ₗ X = (k : ℕ) → member k l → k ∈ X

定義graph model的application:F ⊙ X 收集所有 m,使得存在一個有限近似 l ⊆ X,而 F 把 l(壓成的碼)送到 m

_⊙_ : 𝓟 ℕ → 𝓟 ℕ → 𝓟 ℕ
(F ⊙ X) m = (∃ l ꞉ List ℕ , (encode (codeList l , m) ∈ F) × (l ⊆ₗ X)) , ∃-is-prop
infixl 60 _⊙_

於是現在改用 F : 𝓟 ℕ → 𝓟 ℕ 的編碼版本 𝓟 ℕ,再靠 _⊙_ 取回作用。沿用記號與定義,並根據新的 Rel 定義我們需要的helpers

PER-symm : {A : Rel} → (is-PER A) → symmetric A
PER-symm per-A = per-A .pr₁
PER-trans : {A : Rel} → (is-PER A) → transitive A
PER-trans per-A = per-A .pr₂

Definition Exponentiation [local-2]

把 F X 換成 F ⊙ X 後PER的證明基本上一樣

A=>B-is-PER-if-A-B-are-PERs : {A B : Rel}
     → is-PER A
     → is-PER B
     → is-PER (A => B)
A=>B-is-PER-if-A-B-are-PERs {A}{B} per-A per-B = I , II
  where
  I : symmetric (A => B)
  I F G F[A=>B]G X Y X[A]Y = goal
    where
    Y[A]X : Y [ A ] X
    Y[A]X = PER-symm per-A X Y X[A]Y

    apply : (F ⊙ Y) [ B ] (G ⊙ X)
    apply = F[A=>B]G Y X Y[A]X

    goal : (G ⊙ X) [ B ] (F ⊙ Y)
    goal = PER-symm per-B (F ⊙ Y) (G ⊙ X) apply
  II : transitive (A => B)
  II F G H F[A=>B]G G[A=>B]H X Y X[A]Y = goal
    where
    apply₁ : (F ⊙ X) [ B ] (G ⊙ Y)
    apply₁ = F[A=>B]G X Y X[A]Y

    Y[A]X : Y [ A ] X
    Y[A]X = PER-symm per-A X Y X[A]Y

    Y[A]Y : Y [ A ] Y
    Y[A]Y = PER-trans per-A Y X Y Y[A]X X[A]Y

    apply₂ : (G ⊙ Y) [ B ] (H ⊙ Y)
    apply₂ = G[A=>B]H Y Y Y[A]Y

    goal : F ⊙ X [ B ] H ⊙ Y
    goal = PER-trans per-B (F ⊙ X) (G ⊙ Y) (H ⊙ Y) apply₁ apply₂

因為封閉,套疊兩次得到 A => B => A 也是PER

A=>B=>A-is-PER : {A B : Rel}
     → is-PER A
     → is-PER B
     → is-PER (A => B => A)
A=>B=>A-is-PER per-A per-B =
  A=>B-is-PER-if-A-B-are-PERs per-A (A=>B-is-PER-if-A-B-are-PERs per-B per-A)

_=>_ 的型別現在是 Rel → Rel → Rel,缺點消失。但還有一個問題:A => B => A 既然關聯的是 𝓟 ℕ,那 fst : 𝓟 ℕ → 𝓟 ℕ → 𝓟 ℕ 活在host裡面是無法使用的,也必須被編碼成一個 𝓟 ℕ,這裡我們稱之為 K

box : ℕ → ℕ
box p = encode (codeList [] , p)

K : 𝓟 ℕ
K k = (∃ p ꞉ ℕ , k = encode (codeList (p ∷ []) , box p)) , ∃-is-prop

核心引理:K ⊙ X 再作用任何 U 的結果是 X

K-const : (X U : 𝓟 ℕ) → ((K ⊙ X) ⊙ U) = X
K-const X U = subset-extensionality pe fe to-X from-X
  where
  to-X : ((K ⊙ X) ⊙ U) ⊆ X
  to-X r = ∥∥-rec (∈-is-prop X r) I
    where
    I : (Σ l ꞉ List ℕ , (encode (codeList l , r) ∈ (K ⊙ X)) × (l ⊆ₗ U)) → r ∈ X
    I (l , kx , _) = ∥∥-rec (∈-is-prop X r) II kx
      where
      II : (Σ l₂ ꞉ List ℕ , (encode (codeList l₂ , encode (codeList l , r)) ∈ K) × (l₂ ⊆ₗ X)) → r ∈ X
      II (l₂ , ∈K , l₂⊆X) = ∥∥-rec (∈-is-prop X r) III ∈K
        where
        III : (Σ p ꞉ ℕ , encode (codeList l₂ , encode (codeList l , r)) = encode (codeList (p ∷ []) , box p)) → r ∈ X
        III (p , eq) = transport (_∈ X) (ap pr₂ inner ⁻¹) p∈X
          where
          outer : (codeList l₂ , encode (codeList l , r)) = (codeList (p ∷ []) , box p)
          outer = encode-lc eq

          inner : (codeList l , r) = (codeList [] , p)
          inner = encode-lc (ap pr₂ outer)

          l₂=p∷[] : l₂ = (p ∷ [])
          l₂=p∷[] = codeList-lc l₂ (p ∷ []) (ap pr₁ outer)

          p∈X : p ∈ X
          p∈X = l₂⊆X p (transport (member p) (l₂=p∷[] ⁻¹) in-head)

  from-X : X ⊆ ((K ⊙ X) ⊙ U)
  from-X r r∈X = ∣ [] , kx-mem , (λ k ()) ∣
    where
    kx-mem : encode (codeList [] , r) ∈ (K ⊙ X)
    kx-mem = ∣ (r ∷ []) , ∣ r , refl ∣ , sing-sub ∣
      where
      sing-sub : (r ∷ []) ⊆ₗ X
      sing-sub k in-head      = r∈X
      sing-sub k (in-tail ())
於是最後一個問題可以寫成
main : {A B : Rel} → K [ A => B => A ] K
main {A}{B} X Y X[A]Y U V U[B]V =
  transport (λ b → ((K ⊙ X) ⊙ U) [ A ] b) (K-const Y V ⁻¹)
    (transport (λ a → a [ A ] Y) (K-const X U ⁻¹) X[A]Y)

Partial Equivalences as Types: First attempts [ag-U75Z]

From Denotational Semantics, looking backward - looking forward

這裡嘗試用agda表示Partial Equivalences as Types

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import UF.Equiv
open import UF.Powerset
open import UF.SubtypeClassifier

module ag-U75Z where

我們用agda表示relation

Rel : 𝓤₁ ̇
Rel = 𝓟 ℕ → 𝓟 ℕ → 𝓤₀ ̇

定義一個輔助閱讀的表達記號 X [ R ] Y

_[_]_ : {X : 𝓤 ̇ } → X → (X → X → 𝓥 ̇ ) → X → 𝓥 ̇
x [ R ] y = R x y

一個relation是PER表示它是symmetric且transitive

is-PER : {X : 𝓤 ̇} → (X → X → 𝓥 ̇) → 𝓤 ⊔ 𝓥  ̇
is-PER R = symmetric R × transitive R

提取用的helpers

PER-symm : {A : Rel} → (is-PER A) → symmetric A
PER-symm per-A = per-A .pr₁
PER-trans : {A : Rel} → (is-PER A) → transitive A
PER-trans per-A = per-A .pr₂

現在可以定義PER的exponentiation

_=>_ : Rel → Rel → (𝓟 ℕ → 𝓟 ℕ) → (𝓟 ℕ → 𝓟 ℕ) → 𝓤₁ ̇
(A => B) F G = (X Y : 𝓟 ℕ) → X [ A ] Y → (F X) [ B ] (G Y)
infixr 50 _=>_

我們希望證明exponentiation依然是一個PER(當然也因此是type)

A=>B-is-PER-if-A-B-are-PERs : {A B : Rel}
     → is-PER A
     → is-PER B
     → is-PER (A => B)
A=>B-is-PER-if-A-B-are-PERs {A}{B} per-A per-B = I , II
  where
  I : symmetric (A => B)
  I F G F[A=>B]G X Y X[A]Y = goal
    where
    Y[A]X : Y [ A ] X
    Y[A]X = PER-symm per-A X Y X[A]Y

    swap : Y [ A ] X → (F Y) [ B ] (G X)
    swap = F[A=>B]G Y X

    apply : (F Y) [ B ] (G X)
    apply = swap Y[A]X

    goal : (G X) [ B ] (F Y)
    goal = PER-symm per-B (F Y) (G X) apply
  II : transitive (A => B)
  II F G H F[A=>B]G G[A=>B]H X Y X[A]Y = goal
    where
    apply₁ : (F X) [ B ] (G Y)
    apply₁ = F[A=>B]G X Y X[A]Y

    Y[A]X : Y [ A ] X
    Y[A]X = PER-symm per-A X Y X[A]Y

    Y[A]Y : Y [ A ] Y
    Y[A]Y = PER-trans per-A Y X Y Y[A]X X[A]Y

    apply₂ : (G Y) [ B ] (H Y)
    apply₂ = G[A=>B]H Y Y Y[A]Y

    goal : F X [ B ] H Y
    goal = PER-trans per-B (F X) (G Y) (H Y) apply₁ apply₂

確認這真的表示了函數類型的概念

this-is-really-function-type : {A B : Rel}
  → (F : 𝓟 ℕ → 𝓟 ℕ) → F [ A => B ] F
  → ((X : 𝓟 ℕ) → X [ A ] X → F X [ B ] F X)
this-is-really-function-type {A}{B} F F:A=>B X X:A = F:A=>B X X X:A

編碼的缺點 [local-0]

我本來覺得用 𝓟 ℕ → 𝓟 ℕ → 𝓤₀ ̇ 表示relation就好,這個編碼也成功的回答了前兩個問題。但當我們需要表示 A => B => A 時,因為 B => A 不是一個 𝓟 ℕ,所以程式就寫不出來了,比如第三個問題

fst : 𝓟 ℕ → 𝓟 ℕ → 𝓟 ℕ
fst x y = x

main : {A B : Rel} → fst [ A => B => A ] fst

Lemma HoTT 2.1.4 [violet-EVW3]

\import std/id

\universe 𝓤S 𝓤

\operator "\x ⋅ \y" => trans x y
  \associativity: \left

Unit laws [local-0]

\let trans-refl-l{A : universe 𝓤} -> {x : A} -> {y : A} -> (p : x = y) -> (refl ⋅ p) = p (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (p : Id x y) -> Id (trans refl p) p) {Auniverse 𝓤 : 𝓤universe S 𝓤} {xA yA : Auniverse 𝓤} (px = y (i.e. Id x y) : xA = yA) : (refl ⋅ p{A : universe 𝓤} -> {x : A} -> {y : A} -> {z : A} -> (_ : x = y) -> (_ : y = z) -> x = z (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> {z : A} -> (_ : Id x y) -> (_ : Id y z) -> Id x z)) = px = y (i.e. Id x y) => refl
\let trans-refl-r{A : universe 𝓤} -> {x : A} -> {y : A} -> (p : x = y) -> (p ⋅ refl) = p (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (p : Id x y) -> Id (trans p refl) p) {Auniverse 𝓤 : 𝓤universe S 𝓤} {xA yA : Auniverse 𝓤} : (px = y (i.e. Id x y) : xA = yA) -> (px = i (i.e. Id x i) ⋅ refl) = px = i (i.e. Id x i) \where
  trans-refl-r px = y (i.e. Id x y) <= \elim p$-2 = $-3 (i.e. Id $-2 $-3)
  | trans-refl-r{A : universe 𝓤} -> {x : A} -> {y : A} -> (p : x = y) -> (p ⋅ refl) = p (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (p : Id x y) -> Id (trans p refl) p) refl{A : universe 𝓤} -> {x : A} -> x = x (i.e. {A : universe 𝓤} -> {x : A} -> Id x x) => refl{A : universe 𝓤} -> {x : A} -> x = x (i.e. {A : universe 𝓤} -> {x : A} -> Id x x)

Inverse laws [local-1]

\let trans-sym-l{A : universe 𝓤} -> {x : A} -> {y : A} -> (p : x = y) -> ((sym p) ⋅ p) = refl (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (p : Id x y) -> Id (trans (sym p) p) refl) {Auniverse 𝓤 : 𝓤universe S 𝓤} {xA yA : Auniverse 𝓤} : (px = y (i.e. Id x y) : xA = yA) -> ((sym{A : universe 𝓤} -> {x : A} -> {y : A} -> (_ : x = y) -> y = x (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (_ : Id x y) -> Id y x) px = i (i.e. Id x i)) ⋅ px = i (i.e. Id x i)) = refl \where
  trans-sym-l px = y (i.e. Id x y) <= \elim p$-2 = $-3 (i.e. Id $-2 $-3)
  | trans-sym-l{A : universe 𝓤} -> {x : A} -> {y : A} -> (p : x = y) -> ((sym p) ⋅ p) = refl (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (p : Id x y) -> Id (trans (sym p) p) refl) refl{A : universe 𝓤} -> {x : A} -> x = x (i.e. {A : universe 𝓤} -> {x : A} -> Id x x) => refl{A : universe 𝓤} -> {x : A} -> x = x (i.e. {A : universe 𝓤} -> {x : A} -> Id x x)

\let trans-sym-r{A : universe 𝓤} -> {x : A} -> {y : A} -> (p : x = y) -> (p ⋅ (sym p)) = refl (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (p : Id x y) -> Id (trans p (sym p)) refl) {Auniverse 𝓤 : 𝓤universe S 𝓤} {xA yA : Auniverse 𝓤} : (px = y (i.e. Id x y) : xA = yA) -> (px = i (i.e. Id x i) ⋅ (sym{A : universe 𝓤} -> {x : A} -> {y : A} -> (_ : x = y) -> y = x (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (_ : Id x y) -> Id y x) px = i (i.e. Id x i))) = refl \where
  trans-sym-r px = y (i.e. Id x y) <= \elim p$-2 = $-3 (i.e. Id $-2 $-3)
  | trans-sym-r{A : universe 𝓤} -> {x : A} -> {y : A} -> (p : x = y) -> (p ⋅ (sym p)) = refl (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (p : Id x y) -> Id (trans p (sym p)) refl) refl{A : universe 𝓤} -> {x : A} -> x = x (i.e. {A : universe 𝓤} -> {x : A} -> Id x x) => refl{A : universe 𝓤} -> {x : A} -> x = x (i.e. {A : universe 𝓤} -> {x : A} -> Id x x)

Involution [local-2]

\let sym-sym{A : universe 𝓤} -> {x : A} -> {y : A} -> (p : x = y) -> (sym (sym p)) = p (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (p : Id x y) -> Id (sym (sym p)) p) {Auniverse 𝓤 : 𝓤universe S 𝓤} {xA yA : Auniverse 𝓤} : (px = y (i.e. Id x y) : xA = yA) -> (sym{A : universe 𝓤} -> {x : A} -> {y : A} -> (_ : x = y) -> y = x (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (_ : Id x y) -> Id y x) (sym{A : universe 𝓤} -> {x : A} -> {y : A} -> (_ : x = y) -> y = x (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (_ : Id x y) -> Id y x) px = i (i.e. Id x i))) = px = i (i.e. Id x i) \where
  sym-sym px = y (i.e. Id x y) <= \elim p$-2 = $-3 (i.e. Id $-2 $-3)
  | sym-sym{A : universe 𝓤} -> {x : A} -> {y : A} -> (p : x = y) -> (sym (sym p)) = p (i.e. {A : universe 𝓤} -> {x : A} -> {y : A} -> (p : Id x y) -> Id (sym (sym p)) p) refl{A : universe 𝓤} -> {x : A} -> x = x (i.e. {A : universe 𝓤} -> {x : A} -> Id x x) => refl{A : universe 𝓤} -> {x : A} -> x = x (i.e. {A : universe 𝓤} -> {x : A} -> Id x x)

Associativity [local-3]

\let trans-assoc{A : universe 𝓤} -> {w : A} -> {x : A} -> {y : A} -> {z : A} -> (p : w = x) -> (q : x = y) -> (r : y = z) -> ((p ⋅ q) ⋅ r) = (p ⋅ (q ⋅ r)) (i.e. {A : universe 𝓤} -> {w : A} -> {x : A} -> {y : A} -> {z : A} -> (p : Id w x) -> (q : Id x y) -> (r : Id y z) -> Id (trans (trans p q) r) (trans p (trans q r))) {Auniverse 𝓤 : 𝓤universe S 𝓤} {wA xA yA zA : Auniverse 𝓤}
  : (pw = x (i.e. Id w x) : wA = xA) -> (qi = y (i.e. Id i y) : xA = yA) -> (ry = z (i.e. Id y z) : yA = zA)
    -> (pw = i (i.e. Id w i) ⋅ qi = y (i.e. Id i y) ⋅ ry = z (i.e. Id y z)) = (pw = i (i.e. Id w i) ⋅ (qi = y (i.e. Id i y) ⋅ ry = z (i.e. Id y z))) \where
  trans-assoc pw = x (i.e. Id w x) qx = y (i.e. Id x y) ry = z (i.e. Id y z) <= \elim p$-2 = $-3 (i.e. Id $-2 $-3)
  | trans-assoc{A : universe 𝓤} -> {w : A} -> {x : A} -> {y : A} -> {z : A} -> (p : w = x) -> (q : x = y) -> (r : y = z) -> ((p ⋅ q) ⋅ r) = (p ⋅ (q ⋅ r)) (i.e. {A : universe 𝓤} -> {w : A} -> {x : A} -> {y : A} -> {z : A} -> (p : Id w x) -> (q : Id x y) -> (r : Id y z) -> Id (trans (trans p q) r) (trans p (trans q r))) refl{A : universe 𝓤} -> {x : A} -> x = x (i.e. {A : universe 𝓤} -> {x : A} -> Id x x) q r => refl{A : universe 𝓤} -> {x : A} -> x = x (i.e. {A : universe 𝓤} -> {x : A} -> Id x x)

Tool Soufflé [souffle]

Soufflé is a variant of Datalog for tool designers crafting analyses in Horn clauses. Soufflé synthesizes a native parallel C++ program from a logic specification.

Local operator 與 Nucleus [ag-X72H]

Local operator 跟 Nucleus 有什麼關聯?

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import UF.Base
open import UF.Equiv
open import UF.FunExt
open import UF.PropTrunc
open import UF.Subsingletons
open import UF.SubtypeClassifier
open import UF.SubtypeClassifier-Properties
open import UF.Size
open import UF.Logic
open import UF.Subsingletons-FunExt
open import UF.EquivalenceExamples

module ag-X72H
  (pt : propositional-truncations-exist)
  (fe : Fun-Ext)
  (pe : propext 𝓤)
  (ρ  : propositional-resizing (𝓤 ⁺) 𝓤)
  where

open Conjunction
open Universal   fe
open Implication fe

open import ag-V2O7 pt fe pe ρ
open import ag-5W9X pt fe pe ρ
open import ag-GY8B pt fe pe ρ
open import ag-95LU pt fe pe ρ
open import ag-GK6B pt fe pe ρ
open import ag-3HBW pt fe pe ρ
open is-local-operator

Ω 𝓤 本身就是一個 frame(the initial frame 𝟎-𝔽𝕣𝕞)

  1. Ω 𝓤
  2. order 是 ⇒
  3. meet 是 ∧

於是 Nucleus Ωᶠ 正好可與 is-local-operator 對照

open import Locales.Frame        pt fe
open import Locales.InitialFrame pt fe
open import Locales.Sublocale.Nucleus pt fe

Ωᶠ : Frame (𝓤 ⁺) 𝓤 𝓤
Ωᶠ = 𝟎-𝔽𝕣𝕞 pe

Nucleus 的 inflationary + idempotent + meet-preserving 可以推得 local operator 的 monotone + unit + idempotent,單調性由 nuclei-are-monotone 提供

nucleus-to-local-operator : (n : Nucleus Ωᶠ) → is-local-operator (pr₁ n)
nucleus-to-local-operator n@(j , inf , idm , _) .mono p q p⇒q =
  nuclei-are-monotone Ωᶠ n (p , q) p⇒q
nucleus-to-local-operator n@(j , inf , idm , _) .unit = inf ⊤
nucleus-to-local-operator n@(j , inf , idm , _) .idem p = idm p

local operator 可以推得 Nucleus

local-operator-to-nucleus :
  (j : Ω 𝓤 → Ω 𝓤)
  → is-local-operator j
  → Nucleus Ωᶠ
local-operator-to-nucleus j j-is-local-op =
  j , inflationary , idempotent , meet-preserving
  where
  inflationary : is-inflationary Ωᶠ j holds
  inflationary x = LO-infl j-is-local-op x

  idempotent : is-idempotent Ωᶠ j holds
  idempotent x = idem j-is-local-op x

  I : (p : Ω 𝓤) → L j p = j p
  I p = Ω-extensionality pe fe ⇒-dir ⇐-dir
    where
    ⇒-dir : (L j p ⇒ j p) holds
    ⇒-dir ljp = εL j p ljp (j p) (inflationary p , idempotent p)
    ⇐-dir : (j p ⇒ L j p) holds
    ⇐-dir jp = ηL j p II
      where
      II : (L⁺ j p) holds
      II q (p⇒q , jq⇒q) = jq⇒q (mono j-is-local-op p q p⇒q jp)

  is-meet-preserving : (Ω 𝓤 → Ω 𝓤) → 𝓤 ⁺ ̇
  is-meet-preserving j = (p q : Ω 𝓤) → j (p ∧ q) = j p ∧ j q
  meet-preserving : is-meet-preserving j
  meet-preserving p q =
    j (p ∧ q)      =⟨ (I (p ∧ q)) ⁻¹ ⟩
    L j (p ∧ q)    =⟨ L-preserves-arg-∧ (j , j-is-local-op .mono) p q ⟩
    L j p ∧ L j q  =⟨ ap₂ _∧_ (I p) (I q) ⟩
    j p ∧ j q      ∎

所以從 monotone 也可以得到 Nucleus

L-nucleus : (m : Mon) → Nucleus Ωᶠ
L-nucleus m =
  local-operator-to-nucleus (L (monotone-function m))
                            (L-is-local-operator m)

is-local-operator 也是 proposition

is-local-operator-is-prop : (j : Ω 𝓤 → Ω 𝓤) → is-prop (is-local-operator j)
is-local-operator-is-prop j = equiv-to-prop unfold Fields-is-prop
  where
  Fields : 𝓤 ⁺ ̇
  Fields =   is-monotone j holds
           × (⊤ {𝓤} ⇒ j ⊤) holds
           × ((p : Ω 𝓤) → (j (j p) ⇒ j p) holds)

  unfold : is-local-operator j ≃ Fields
  unfold = qinveq (λ r → mono r , unit r , idem r)
                  ( (λ (m , u , i) → record { mono = m ; unit = u ; idem = i })
                  , (λ _ → refl) , (λ _ → refl) )

  Fields-is-prop : is-prop Fields
  Fields-is-prop = ×-is-prop (holds-is-prop (is-monotone j))
                (×-is-prop (holds-is-prop (⊤ {𝓤} ⇒ j ⊤))
                           (Π-is-prop fe (λ p → holds-is-prop (j (j p) ⇒ j p))))

型別 Loc 與 Nucleus Ωᶠ 等價

Loc : 𝓤 ⁺ ̇
Loc = Σ j ꞉ (Ω 𝓤 → Ω 𝓤) , is-local-operator j

Loc-≃-Nucleus : Loc ≃ Nucleus Ωᶠ
Loc-≃-Nucleus = Σ-cong predicates-agree
  where
  predicates-agree : (j : Ω 𝓤 → Ω 𝓤)
    → is-local-operator j ≃ is-nucleus Ωᶠ j holds
  predicates-agree j =
    logically-equivalent-props-are-equivalent
      (is-local-operator-is-prop j)
      (holds-is-prop (is-nucleus Ωᶠ j))
      ([⇒]) ([⇐])
    where
    [⇒] : is-local-operator j → is-nucleus Ωᶠ j holds
    [⇒] j-lo =
      pr₂ (local-operator-to-nucleus j j-lo)

    [⇐] : is-nucleus Ωᶠ j holds → is-local-operator j
    [⇐] n = nucleus-to-local-operator (j , n)

Proposition L(f)L(f) 保持元素的 meet [ag-3HBW]

LL 保持有限 meet 是運算子格上的 meet,這裡要證明的是 L(f)L(f) 是否保持 frame 元素的 meet,也就是

L(f)(p∧q)=L(f)(p)∧L(f)(q)L(f)(p \land q) = L(f)(p) \land L(f)(q)

這正是 L(f)L(f) 是不是 nucleus 的關鍵條件

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc
open import UF.Subsingletons
open import UF.SubtypeClassifier
open import UF.Size
open import UF.Logic

module ag-3HBW
  (pt : propositional-truncations-exist)
  (fe : Fun-Ext)
  (pe : propext 𝓤)
  (ρ  : propositional-resizing (𝓤 ⁺) 𝓤)
  where

open Conjunction
open Universal   fe
open Implication fe

open import ag-V2O7 pt fe pe ρ
open import ag-5W9X pt fe pe ρ
open import ag-GY8B pt fe pe ρ
open import ag-95LU pt fe pe ρ
open is-local-operator

⊤ ⇒ s 等於 s 成立。

⊤⇒ : (s : Ω 𝓤) → (⊤ {𝓤} ⇒ s) = s
⊤⇒ s = Ω-extensionality pe fe (λ ⊤⇒s → ⊤⇒s ⊤-holds) (λ sh _ → sh)

(⇐) 方向:L f p ∧ L f q → L f (p ∧ q)

L-preserves-arg-∧-⇐ : (f : Ω 𝓤 → Ω 𝓤) (p q : Ω 𝓤)
                    → (L f p holds × L f q holds)
                    → L f (p ∧ q) holds
L-preserves-arg-∧-⇐ f p q (L[f][p] , L[f][q]) = ηL f (p ∧ q) I
  where
  L[p] = εL f p L[f][p]
  L[q] = εL f q L[f][q]

  I : (L⁺ f (p ∧ q)) holds
  I s (p∧q⇒s , fs⇒s) = L[q] s (q⇒s , fs⇒s)
    where
    -- 在 L f p 代入 r := (q ⇒ s),取得 q ⇒ s
    q⇒s : (q ⇒ s) holds
    q⇒s = L[p] (q ⇒ s) (uncurried , f⟨q⇒s⟩⇒)
      where
      uncurried : (p ⇒ (q ⇒ s)) holds
      uncurried ph qh = p∧q⇒s (ph , qh)

      -- f (q ⇒ s) ⇒ (q ⇒ s):q 成立時 (q ⇒ s) = s,故 f (q ⇒ s) = f s
      f⟨q⇒s⟩⇒ : (f (q ⇒ s) ⇒ (q ⇒ s)) holds
      f⟨q⇒s⟩⇒ y qh = fs⇒s (transport (λ - → f - holds) ⟨q⇒s⟩=s y)
        where
        ⟨q⇒s⟩=s : (q ⇒ s) = s
        ⟨q⇒s⟩=s = ap (_⇒ s) (holds-gives-equal-⊤ pe fe q qh) ∙ ⊤⇒ s

(⇒) 方向:由 L f 的單調性(因為 L(f) 是 local operator)配上 p ∧ q ⇒ p、p ∧ q ⇒ q。

L-preserves-arg-∧-⇒ : (m : Mon) (p q : Ω 𝓤)
   → L (monotone-function m) (p ∧ q) holds
   → (L (monotone-function m) p holds × L (monotone-function m) q holds)
L-preserves-arg-∧-⇒ m p q lf[p∧q] = mn (p ∧ q) p pr₁ lf[p∧q]
                                   , mn (p ∧ q) q pr₂ lf[p∧q]
  where
  mn = L-is-local-operator m .mono

合併得到

L-preserves-arg-∧ : (m : Mon) (p q : Ω 𝓤)
   → L (monotone-function m) (p ∧ q)
   = L (monotone-function m) p ∧ L (monotone-function m) q
L-preserves-arg-∧ m p q =
  Ω-extensionality pe fe (L-preserves-arg-∧-⇒ m p q)
                         (L-preserves-arg-∧-⇐ (monotone-function m) p q)

Basic Subtoposes of the Effective Topos:Proposition 1.2 [ECDG]

Lee 與 van Oosten 閱讀筆記,Proposition 1.2

為什麼要在意 local operator?因為一個 topos E\mathcal{E} 的子拓樸(subtopos)跟 E\mathcal{E} 上的 local operator 一一對應:子拓樸就是對有限極限封閉、且包含函子有保持有限極限左伴隨的全子範疇,而這樣的資料剛好被 Ω\Omega 上的某類自映射編碼。所以「構造並區分 local operator」等於「構造並區分子拓樸」。

舞台上的角色:Ω\Omega 是子物件分類子,Mon\text{Mon} 是 Ω→Ω\Omega \to \Omega 的單調自映射,Loc\text{Loc} 則是 local operator。論文指出 Mon\text{Mon} 與 Loc\text{Loc} 都是 internal locale,因為 Proposition 1.2 這個 Topos Theory 的一個 folklore 結果:包含映射 Loc↪Mon\text{Loc} \hookrightarrow \text{Mon} 有一個左伴隨 LL 保持有限 meet

首先看用到的四個定義

Definition Mon(單調自映射) [ag-V2O7]

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc
open import UF.Subsingletons
open import UF.SubtypeClassifier
open import UF.Size
open import UF.Logic

module ag-V2O7
  (pt : propositional-truncations-exist)
  (fe : Fun-Ext)
  (pe : propext 𝓤)
  (ρ  : propositional-resizing (𝓤 ⁺) 𝓤)
  where

open Conjunction
open Universal   fe
open Implication fe

Monotone map 是 Ω 的自映射 f : Ω → Ω,滿足 p ⇒ q 蘊涵 f p ⇒ f q

is-monotone : (Ω 𝓤 → Ω 𝓤) → Ω (𝓤 ⁺)
is-monotone f = Ɐ p ꞉ Ω 𝓤 , Ɐ q ꞉ Ω 𝓤 , (p ⇒ q) ⇒ (f p ⇒ f q)

Mon 代表所有 monotone maps 的 type

Mon : 𝓤 ⁺ ̇
Mon = Σ f ꞉ (Ω 𝓤 → Ω 𝓤) , is-monotone f holds

我們定義一個輔助函數讓之後的證明可讀一點

monotone-function : Mon → (Ω 𝓤 → Ω 𝓤)
monotone-function m = pr₁ m

Definition Local operator [ag-5W9X]

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc
open import UF.Subsingletons
open import UF.SubtypeClassifier
open import UF.Size
open import UF.Logic

module ag-5W9X
  (pt : propositional-truncations-exist)
  (fe : Fun-Ext)
  (pe : propext 𝓤)
  (ρ  : propositional-resizing (𝓤 ⁺) 𝓤)
  where

open Conjunction
open Universal   fe
open Implication fe

open import ag-V2O7 pt fe pe ρ

Local operator 是一個 Ω 自映射 j : Ω → Ω,滿足

  1. 單調(mono)
  2. 保持 ⊤(unit)
  3. 冪等(idem)

三個條件定義在 record 中

record is-local-operator (j : Ω 𝓤 → Ω 𝓤) : 𝓤 ⁺ ̇ where
  field
    mono : is-monotone j holds
    unit : (⊤ {𝓤} ⇒ j ⊤) holds
    idem : (p : Ω 𝓤) → (j (j p) ⇒ j p) holds

Definition ΩΩ\Omega^\Omega 的逐點序 ≼ [ag-UAEO]

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc
open import UF.Subsingletons
open import UF.SubtypeClassifier
open import UF.Size
open import UF.Logic

module ag-UAEO
  (pt : propositional-truncations-exist)
  (fe : Fun-Ext)
  (pe : propext 𝓤)
  (ρ  : propositional-resizing (𝓤 ⁺) 𝓤)
  where

open Conjunction
open Universal   fe
open Implication fe

ΩΩ\Omega^\Omega 的元素之間我們可以用 pointwise 的方式定義一個順序 f ≼ g:對每個 p,f p ⇒ g p

_≼_ : (Ω 𝓤 → Ω 𝓤) → (Ω 𝓤 → Ω 𝓤) → Ω (𝓤 ⁺)
f ≼ g = Ɐ p ꞉ Ω 𝓤 , f p ⇒ g p

後面談 L 是左伴隨時就是用這個順序。

Definition Left adjoint LL [ag-GY8B]

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc
open import UF.Subsingletons
open import UF.SubtypeClassifier
open import UF.Size
open import UF.Logic

module ag-GY8B
  (pt : propositional-truncations-exist)
  (fe : Fun-Ext)
  (pe : propext 𝓤)
  (ρ  : propositional-resizing (𝓤 ⁺) 𝓤)
  where

open Conjunction
open Universal   fe
open Implication fe

Proposition 1.2 的左伴隨 L 定義為 L(f)(p) = ∀q. (((p → q) ∧ (f q → q)) → q)

但因為類型論的關係,它落在 Ω (𝓤 ⁺) 上(L⁺)

L⁺ : (Ω 𝓤 → Ω 𝓤) → Ω 𝓤 → Ω (𝓤 ⁺)
L⁺ f p = Ɐ q ꞉ Ω 𝓤 , ((p ⇒ q) ∧ (f q ⇒ q)) ⇒ q

論文裡 Ω 是 impredicative,全稱量化後仍落在 Ω;所以要靠 propositional resizing 把它放回去 Ω 𝓤 得到 L

L : (Ω 𝓤 → Ω 𝓤) → Ω 𝓤 → Ω 𝓤
L f p = resize         ρ (L⁺ f p holds) (holds-is-prop (L⁺ f p))
      , resize-is-prop ρ (L⁺ f p holds) (holds-is-prop (L⁺ f p))

ηL、εL 是在兩種 size 之間搬動證明的轉換器。讀法上,(L⁺ f p) holds 展開後就是

(q : Ω 𝓤) → (p ⇒ q) holds × (f q ⇒ q) holds → q holds

後面所有證明都先用 εL 把 L f p 拆成上面的 universal property、再用 ηL 把證明包回去。

ηL : (f : Ω 𝓤 → Ω 𝓤) (p : Ω 𝓤) → (L⁺ f p) holds → (L f p) holds
ηL f p = to-resize ρ (L⁺ f p holds) (holds-is-prop (L⁺ f p))

εL : (f : Ω 𝓤 → Ω 𝓤) (p : Ω 𝓤) → (L f p) holds → (L⁺ f p) holds
εL f p = from-resize ρ (L⁺ f p holds) (holds-is-prop (L⁺ f p))

有了這些定義,可以開始證明 Proposition 1.2。第一步:L 把每個 Mon 成員都變成 Loc 的成員。

Theorem L(f)L(f) 是一個 local operator [ag-95LU]

Proposition 1.2 的核心:只要 ff 是 monotone,套上 LL 之後就變成一個 local operator。換句話說 LL 把 Mon\text{Mon} 成員升級成 Loc\text{Loc} 成員

Proof [local-0]

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc
open import UF.Subsingletons
open import UF.SubtypeClassifier
open import UF.Size
open import UF.Logic

module ag-95LU
  (pt : propositional-truncations-exist)
  (fe : Fun-Ext)
  (pe : propext 𝓤)
  (ρ  : propositional-resizing (𝓤 ⁺) 𝓤)
  where

open Conjunction
open Universal   fe
open Implication fe

open import ag-V2O7 pt fe pe ρ
open import ag-5W9X pt fe pe ρ
open import ag-GY8B pt fe pe ρ
open is-local-operator
L-is-local-operator : (m : Mon) → is-local-operator (L (monotone-function m))

每個欄位對應 local operator 的一個條件,每個都需要「εL 拆開 → 操作 → ηL 包裝」

(i) 單調:給定 p ⇒ q,把目標裡的 q ⇒ r 沿著 p ⇒ q 前接成 p ⇒ r,再餵回 L f p

L-is-local-operator (f , fm) .mono p q p⇒q lfp = ηL f q goal
  where
  goal : (L⁺ f q) holds
  goal r (q⇒r , fr⇒r) = εL f p lfp r (p⇒r , fr⇒r)
    where
    p⇒r : (p ⇒ r) holds
    p⇒r p = q⇒r (p⇒q p)

(ii) ⊤ ⇒ L f ⊤:此時 q 直接由 ⊤ ⇒ q 得到

L-is-local-operator (f , fm) .unit _ = ηL f ⊤ goal
  where
  goal : (L⁺ f ⊤) holds
  goal q (⊤⇒q , fq⇒q) = ⊤⇒q ⊤-holds

(iii) 冪等 L f (L f p) ⇒ L f p:在外層代入 q := L f p。關鍵的小引理 f (L f p) ⇒ L f p 正好用到 f 的單調性

L-is-local-operator (f , f-is-monotone) .idem p ll =
  εL f (L f p) ll (L f p) (id-L , f∘L⇒Lf)
  where
  id-L : (L f p ⇒ L f p) holds
  id-L x = x

  f∘L⇒Lf : (f (L f p) ⇒ L f p) holds
  f∘L⇒Lf f[L[f[p]]] = ηL f p I
    where
    I : (L⁺ f p) holds
    I q (p⇒q , fq⇒q) = fq⇒q f[q]
      where
      -- 把 (p ⇒ q), (f q ⇒ q) 餵給 L f p
      Lfp⇒q : (L f p ⇒ q) holds
      Lfp⇒q L[f[p]] = εL f p L[f[p]] q (p⇒q , fq⇒q)

      -- f 單調表示 L f p ⇒ q 可以變成 f (L f p) ⇒ f q
      f[q] : f q holds
      f[q] = f-is-monotone (L f p) q Lfp⇒q f[L[f[p]]]

第二步是伴隨。需要一個關於任意 local operator 的小引理:

Lemma Local operator 是 inflationary [ag-GK6B]

任何 local operator jj 都是 inflationary 的,也就是 p⇒j pp \Rightarrow j\ p

Proof [local-0]

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc
open import UF.Subsingletons
open import UF.SubtypeClassifier
open import UF.Size
open import UF.Logic

module ag-GK6B
  (pt : propositional-truncations-exist)
  (fe : Fun-Ext)
  (pe : propext 𝓤)
  (ρ  : propositional-resizing (𝓤 ⁺) 𝓤)
  where

open Conjunction
open Universal   fe
open Implication fe

open import ag-5W9X pt fe pe ρ
open is-local-operator

證明方式:若 p 成立則 p = ⊤(用到 propext),再由 unit 得到 j ⊤。

LO-infl : {j : Ω 𝓤 → Ω 𝓤} → is-local-operator j → (p : Ω 𝓤) → (p ⇒ j p) holds
LO-infl {j} j-is-local-op p p-holds = transport (λ - → j - holds) ⊤=p j⊤
  where
  -- p 成立,故 p = ⊤
  ⊤=p : ⊤ = p
  ⊤=p = (holds-gives-equal-⊤ pe fe p p-holds) ⁻¹

  -- 由 unit
  j⊤ : j ⊤ holds
  j⊤ = unit j-is-local-op ⋆

Proposition L⊣Loc↪MonL \dashv \text{Loc} \hookrightarrow \text{Mon} [ag-XCL4]

LL 是包含映射 Loc↪Mon\text{Loc} \hookrightarrow \text{Mon} 的左伴隨

Proof [local-0]

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc
open import UF.Subsingletons
open import UF.SubtypeClassifier
open import UF.Size
open import UF.Logic

module ag-XCL4
  (pt : propositional-truncations-exist)
  (fe : Fun-Ext)
  (pe : propext 𝓤)
  (ρ  : propositional-resizing (𝓤 ⁺) 𝓤)
  where

open Conjunction
open Universal   fe
open Implication fe

open import ag-V2O7 pt fe pe ρ
open import ag-5W9X pt fe pe ρ
open import ag-UAEO pt fe pe ρ
open import ag-GY8B pt fe pe ρ
open import ag-GK6B pt fe pe ρ
open is-local-operator

(→) 對任意 local operator j,若 f ≼ j 則 L f ≼ j,在 L f p 裡代入 q := j p

L-adjunction-→ :
  (m : Mon) {j : Ω 𝓤 → Ω 𝓤} → is-local-operator j
  → (monotone-function m ≼ j) holds → (L (monotone-function m) ≼ j) holds
L-adjunction-→ (f , _) {j} j-is-local-op f≼j p L[f][p] = εL f p L[f][p] (j p) (p⇒jp , fjp⇒jp)
  where
  p⇒jp : (p ⇒ j p) holds
  p⇒jp = LO-infl j-is-local-op p

  fjp⇒jp : (f (j p) ⇒ j p) holds
  fjp⇒jp x = idem j-is-local-op p (f≼j (j p) x)

(←):伴隨的單位是 f ≼ L f,要用到 f 的單調性。

f≼Lf : ((f , f-is-monotone) : Mon) → (f ≼ L f) holds
f≼Lf (f , f-is-monotone) p f[p] = ηL f p I
  where
  I : (L⁺ f p) holds
  I q (p⇒q , fq⇒q) = fq⇒q f[q]
    where
    f[q] : f q holds
    f[q] = f-is-monotone p q p⇒q f[p]

L-adjunction-← : (m : Mon) {j : Ω 𝓤 → Ω 𝓤} → is-local-operator j
              → (L (monotone-function m) ≼ j) holds → (monotone-function m ≼ j) holds
L-adjunction-← m {j} j-is-local-op Lf≼j p fp = Lf≼j p (f≼Lf m p fp)

第三步:除了是左伴隨,LL 還保持有限 meet。

Proposition LL 保持有限 meet [ag-V7YV]

Proposition 1.2 的另一半:LL 保持有限 meet。有限 meet 等於頂元素 ⊤\top 加上二元 meet ∧\land

Proof [local-0]

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc
open import UF.Subsingletons
open import UF.SubtypeClassifier
open import UF.Size
open import UF.Logic

module ag-V7YV
  (pt : propositional-truncations-exist)
  (fe : Fun-Ext)
  (pe : propext 𝓤)
  (ρ  : propositional-resizing (𝓤 ⁺) 𝓤)
  where

open Conjunction
open Universal   fe
open Implication fe

open import ag-UAEO pt fe pe ρ
open import ag-GY8B pt fe pe ρ

(⇐) 方向:由 L f p 與 L g p 可以得出 L (f ∧ g) p。

L-preserves-∧-⇐ : (f g : Ω 𝓤 → Ω 𝓤) (p : Ω 𝓤)
               → (L f p holds × L g p holds)
               → L (λ x → f x ∧ g x) p holds
L-preserves-∧-⇐ f g p (Lfp , Lgp) = ηL (λ x → f x ∧ g x) p I
  where
  Lf = εL f p Lfp
  Lg = εL g p Lgp

  I : (L⁺ (λ x → f x ∧ g x) p) holds
  I s (p⇒s , fs∧gs⇒s) = Lf s (p⇒s , fs⇒s)
    where
    fs⇒s : f s holds → s holds
    fs⇒s fs = Lg s (p⇒s , gs⇒s)
      where
      gs⇒s : g s holds → s holds
      gs⇒s gs = fs∧gs⇒s (fs , gs)

(⇒) 方向由 L-operator-mono(一個輔助證明:f ≼ g 蘊涵 L f ≼ L g)配上 f ∧ g ≼ f、f ∧ g ≼ g 得到。

L-operator-mono : (f g : Ω 𝓤 → Ω 𝓤)
                → (f ≼ g) holds
                → (L f ≼ L g) holds
L-operator-mono f g f≼g p lfp = ηL g p I
  where
  I : (L⁺ g p) holds
  I q (p⇒q , gq⇒q) = εL f p lfp q (p⇒q , fq⇒q)
    where
    fq⇒q : (f q ⇒ q) holds
    fq⇒q x = gq⇒q (f≼g q x)

L-preserves-∧-⇒ : (f g : Ω 𝓤 → Ω 𝓤) (p : Ω 𝓤)
               → L (λ x → f x ∧ g x) p holds
               → (L f p holds × L g p holds)
L-preserves-∧-⇒ f g p lfgp = to-f , to-g
  where
  to-f : L f p holds
  to-f = L-operator-mono (λ x → f x ∧ g x) f (λ q → pr₁) p lfgp

  to-g : L g p holds
  to-g = L-operator-mono (λ x → f x ∧ g x) g (λ q → pr₂) p lfgp

兩個方向合併就得到逐點的等式 L (f ∧ g) p = L f p ∧ L g p

L-preserves-∧ : (f g : Ω 𝓤 → Ω 𝓤) (p : Ω 𝓤)
             → L (λ x → f x ∧ g x) p = L f p ∧ L g p
L-preserves-∧ f g p = Ω-extensionality pe fe (L-preserves-∧-⇒ f g p)
                                             (L-preserves-∧-⇐ f g p)

為什麼UIP跟univalence不能並存 [ag-WN45]

{-# OPTIONS --without-K #-}
open import MLTT.Spartan
open import MLTT.Bool
open import UF.Base
open import UF.Equiv
open import UF.Retracts
open import UF.Univalence

module ag-WN45 (ua : is-univalent 𝓤₀) where

首先,我們知道 not 是自己的反函數,也就是說 not 有 section 也有 retraction,這導致 not 是一個 Bool 的 equivalence

equiv-not : Bool ≃ Bool
equiv-not = not , sec , ret
  where
  I : (x : Bool) → not (not x) = x
  I true = refl
  I false = refl

  sec : has-section not
  sec = not , I
  ret : is-section not
  ret = not , I

對於 equivalence e,我們知道取其路徑函數會等於 ⌜ e ⌝,因此我們反過來從函數去取其路徑。藉由 UIP,我們迫使所有路徑都等於 refl,又從 Idtofun refl 得出 id,因此證明了 not = id

postulate UIP : {X : 𝓤 ̇ } → (x y : X) → (p q : x = y) → p = q

equiv-id : Bool ≃ Bool
equiv-id = id , (id , λ x → refl) , id , λ x → refl

not-=-id : not = id
not-=-id =
  not                                     =⟨by-definition⟩
  ⌜ equiv-not ⌝                           =⟨ (Idtofun-eqtoid ua equiv-not) ⁻¹ ⟩
  Idtofun (eqtoid ua Bool Bool equiv-not) =⟨ ap Idtofun uip-claim ⟩
  Idtofun refl                            =⟨by-definition⟩
  id ∎
  where
  not-path : Bool = Bool
  not-path = eqtoid ua Bool Bool equiv-not

  uip-claim : not-path = refl
  uip-claim = UIP Bool Bool not-path refl

到這邊就已經歸結出一個荒謬的結果,我們接著看怎麼把這個結果用來導出 𝟘 證明這樣會導致系統不一致。

  1. 根據定義 false = id false
  2. 藉由 not = id 把 id false 改成 not false
  3. 根據定義 not false = true

得出了 false = true,然而我們知道 true ≠ false

false-is-true : false = true
false-is-true =
  false     =⟨by-definition⟩
  id false  =⟨ happly not-=-id true ⟩
  not false =⟨by-definition⟩
  true ∎

ua-negates-UIP : 𝟘
ua-negates-UIP = true-is-not-false (false-is-true ⁻¹)

Mastodon 私訊加密 [software-3UST]

Proposition Integer with arithmetic progression topology is not locally compact [1OV1]

Z\mathbb{Z} with arithmetic progression topology is not locally compact.

如果不是試著證明我也不會發現 Topology — A Categorical Approach 的 Example 1.5 定義是錯的xd

Proof [local-0]

If KK is a compact neighborhood of 00, then K⊇S(a,0)=aZK \supseteq S(a, 0) = a\mathbb{Z}. Since S(a,0)S(a, 0) is clopen, it is a closed subspace of KK, hence compact.

But S(a,0)≅(Z,Furstenberg)S(a, 0) \cong (\mathbb{Z}, \text{Furstenberg}), via

n↦ann \mapsto an

and (Z,Furstenberg)(\mathbb{Z}, \text{Furstenberg}) is not compact: the cover

{aZ}∪{Z∖pZ∣p prime,p∤a}\{a\mathbb{Z}\} \cup \{\mathbb{Z} \setminus p\mathbb{Z} \mid p \text{ prime}, p \nmid a\}

has no finite subcover (any finite subfamily misses p1p2⋯pkp_1 p_2 \cdots p_k for primes outside the chosen set). Contradiction.

Normalization 問題 [I3KA]

在正確處理單位的算術系統一文中,討論過要怎麼用 type system 幫我們限制單位的正確性,在檢查的時候,我發現我沒有處理到像是

[] = [(Second , 0)]

這樣的問題。除此之外,這個 List 也應該要能夠忽視順序的影響,確保

(Kilogram , negsucc 0) ∷ (Second , negsucc 0) ∷ []
=
(Second , negsucc 0) ∷ (Kilogram , negsucc 0) ∷ []

的成立。就根本來說,原因是因為 List (Unit × ℤ) 並不是我們想表示的代數的正確 model,使得一個值具有多個表達方式。確保一個值只有一個表達方式,是一種正規形式問題。因此這裡我想討論數個可能的修正方案,並觀察他們的差異與優劣

對 List 取 quotient [ag-YGG9]

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan hiding (_+_)
open import MLTT.List
open import MGS.MLTT using (has-decidable-equality)
open import UF.FunExt
open import UF.Base using (ap₂; happly)
open import UF.Subsingletons
open import UF.Subsingletons-FunExt
open import UF.Sets
open import UF.Sets-Properties
open import Quotient.Type
open import Integers.Type
open import Integers.Addition
open import Integers.Negation

module ag-YGG9
  (fe : Fun-Ext)
  (sq : general-set-quotients-exist (λ 𝓥 → 𝓥))
  where
open general-set-quotients-exist sq

data Unit : 𝓤₀ ̇ where
  Meter Kilogram Second : Unit

Unit-≟ : has-decidable-equality Unit
Unit-≟ Meter    Meter    = inl refl
Unit-≟ Kilogram Kilogram = inl refl
Unit-≟ Second   Second   = inl refl
Unit-≟ Meter    Kilogram = inr λ ()
Unit-≟ Meter    Second   = inr λ ()
Unit-≟ Kilogram Meter    = inr λ ()
Unit-≟ Kilogram Second   = inr λ ()
Unit-≟ Second   Meter    = inr λ ()
Unit-≟ Second   Kilogram = inr λ ()

最直覺的想法是繼續用 List (Unit × ℤ) 為 raw representation,但需要定義等價類取 quotient 去掉那些我們不想要的情況。為此我們需要定義指數在所有單位相同來決定的等價關係

exp : Unit → List (Unit × ℤ) → ℤ
exp u [] = pos 0
exp u ((v , n) ∷ xs) with Unit-≟ u v
... | inl _ = n + exp u xs
... | inr _ = exp u xs

us₁ ≈ us₂ 若且唯若 exp u us₁ = exp u us₂ 對所有 u 成立

_≈_ : List (Unit × ℤ) → List (Unit × ℤ) → 𝓤₀ ̇
us₁ ≈ us₂ = (u : Unit) → exp u us₁ = exp u us₂

≈-prop : is-prop-valued _≈_
≈-prop us₁ us₂ = Π-is-prop fe (λ u → ℤ-is-set)

≈-refl : reflexive _≈_
≈-refl us u = refl

≈-sym : symmetric _≈_
≈-sym us vs h u = (h u) ⁻¹

≈-trans : transitive _≈_
≈-trans us vs ws h k u = h u ∙ k u

≋ : EqRel (List (Unit × ℤ))
≋ = _≈_ , ≈-prop , ≈-refl , ≈-sym , ≈-trans

Units : 𝓤₀ ̇
Units = List (Unit × ℤ) / ≋

這邊證明了單位 u 在兩個 List 中的指數相加跟對 concat 起來的 List 計算 u 的指數一定是同一個數字

exp-++ : (u : Unit) (xs ys : List (Unit × ℤ))
       → exp u (xs ++ ys) = exp u xs + exp u ys
exp-++ u []              ys = ℤ-zero-left-neutral (exp u ys) ⁻¹
exp-++ u ((v , n) ∷ xs) ys with Unit-≟ u v
... | inl _ = ap (n +_) (exp-++ u xs ys) ∙ ℤ+-assoc n (exp u xs) (exp u ys) ⁻¹
... | inr _ = exp-++ u xs ys

再來證明 concat 是遵守 ≈ 關係的

++-resp : {us₁ us₁' us₂ us₂' : List (Unit × ℤ)}
        → us₁ ≈ us₁' → us₂ ≈ us₂' → (us₁ ++ us₂) ≈ (us₁' ++ us₂')
++-resp {us₁} {us₁'} {us₂} {us₂'} h k u =
  exp u (us₁ ++ us₂)    =⟨ exp-++ u us₁ us₂ ⟩
  exp u us₁ + exp u us₂ =⟨ ap₂ _+_ (h u) (k u) ⟩
  exp u us₁' + exp u us₂' =⟨ exp-++ u us₁' us₂' ⁻¹ ⟩
  exp u (us₁' ++ us₂') ∎

這邊定義一個 helper,實現 raw representation 乘上 Units 得到 Units 的運算,這可以幫助我們簡化等一下要定義的完整單位乘法

*-unit-r : List (Unit × ℤ) → Units → Units
*-unit-r xs = mediating-map/ ≋ (/-is-set ≋)
                (λ ys → η/ ≋ (xs ++ ys))
                (λ {ys} {ys'} k →
                   η/-identifies-related-points ≋
                     (++-resp {xs} {xs} (≈-refl xs) k))

定義最後的單位乘法

*-unit : Units → Units → Units
*-unit = mediating-map/ ≋ (Π-is-set fe (λ _ → /-is-set ≋))
           *-unit-r
           λ {xs} {xs'} h → dfunext fe (λ q → resp-left q h)
  where
  resp-left : (q : Units) {xs xs' : List (Unit × ℤ)}
            → xs ≈ xs' → *-unit-r xs q = *-unit-r xs' q
  resp-left q {xs} {xs'} h =
    /-induction ≋ (λ q → /-is-set ≋ {*-unit-r xs q} {*-unit-r xs' q})
      on-list
      q
    where
    on-list : (ys : List (Unit × ℤ))
            → *-unit-r xs (η/ ≋ ys) = *-unit-r xs' (η/ ≋ ys)
    on-list ys =
      *-unit-r xs (η/ ≋ ys) =⟨ universality-triangle/ ≋ (/-is-set ≋) _ _ ys ⟩
      η/ ≋ (xs  ++ ys)      =⟨ η/-identifies-related-points ≋
                                  (++-resp {xs} {xs'} {ys} {ys} h (≈-refl ys)) ⟩
      η/ ≋ (xs' ++ ys)      =⟨ universality-triangle/ ≋ (/-is-set ≋) _ _ ys ⁻¹ ⟩
      *-unit-r xs' (η/ ≋ ys) ∎

我們構造一些案例

1m : Units
1m = η/ ≋ ((Meter , pos 1) ∷ [])

1s : Units
1s = η/ ≋ ((Second , pos 1) ∷ [])

1/s : Units
1/s = η/ ≋ ((Second , negsucc 0) ∷ [])

這裏證明了純量 1 確實是單位乘法的 identity

ε : Units
ε = η/ ≋ []

*-unit-η : (xs ys : List (Unit × ℤ))
         → *-unit (η/ ≋ xs) (η/ ≋ ys) = η/ ≋ (xs ++ ys)
*-unit-η xs ys =
  *-unit (η/ ≋ xs) (η/ ≋ ys)
    =⟨ happly
          (universality-triangle/ ≋ (Π-is-set fe (λ _ → /-is-set ≋)) _ _ xs)
          (η/ ≋ ys) ⟩
  *-unit-r xs (η/ ≋ ys) =⟨ universality-triangle/ ≋ (/-is-set ≋) _ _ ys ⟩
  η/ ≋ (xs ++ ys) ∎

ε-is-unit-of-* : (xs : List (Unit × ℤ)) → *-unit ε (η/ ≋ xs) = *-unit (η/ ≋ xs) ε
ε-is-unit-of-* xs =
  *-unit ε (η/ ≋ xs) =⟨ *-unit-η [] xs ⟩
  η/ ≋ ([] ++ xs) =⟨ ap (λ - → η/ ≋ -) ([]-right-neutral xs) ⟩
  η/ ≋ (xs ++ []) =⟨ *-unit-η xs [] ⁻¹ ⟩
  *-unit (η/ ≋ xs) ε ∎

單位取消確實如想像中一樣運作

cancel : *-unit 1s 1/s = ε
cancel =
  *-unit 1s 1/s =⟨ *-unit-η _ _ ⟩
  η/ ≋ (((Second , pos 1) ∷ []) ++ ((Second , negsucc 0) ∷ []))
    =⟨ η/-identifies-related-points ≋ I ⟩
  η/ ≋ [] ∎
  where
  I : ((Second , pos 1) ∷ (Second , negsucc 0) ∷ []) ≈ []
  I Meter    = refl
  I Kilogram = refl
  I Second   = refl

不同單位確實有被等價類分開

different-units : (u₁ u₂ : Unit) → ¬ (u₁ = u₂) → ¬ (((u₁ , pos 1) ∷ []) ≈ ((u₂ , pos 1) ∷ []))
different-units Meter    Meter    ne h = ne refl
different-units Meter    Kilogram ne h = pos-succ-not-zero 0 (h Meter)
different-units Meter    Second   ne h = pos-succ-not-zero 0 (h Meter)
different-units Kilogram Meter    ne h = pos-succ-not-zero 0 (h Kilogram)
different-units Kilogram Kilogram ne h = ne refl
different-units Kilogram Second   ne h = pos-succ-not-zero 0 (h Kilogram)
different-units Second   Meter    ne h = pos-succ-not-zero 0 (h Second)
different-units Second   Kilogram ne h = pos-succ-not-zero 0 (h Second)
different-units Second   Second   ne h = ne refl

不過這個方法雖然概念上很直觀,但就如同你直接看到的,寫起來非常複雜。

從構造就拒絕錯誤 [ag-SPBG]

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan hiding (_+_)
open import MLTT.Maybe
open import MGS.MLTT using (has-decidable-equality)
open import Integers.Type
open import Integers.Addition

module ag-SPBG where

data Unit : 𝓤₀ ̇ where
  Meter Kilogram Second : Unit

Unit-≟ : has-decidable-equality Unit
Unit-≟ Meter    Meter    = inl refl
Unit-≟ Kilogram Kilogram = inl refl
Unit-≟ Second   Second   = inl refl
Unit-≟ Meter    Kilogram = inr λ ()
Unit-≟ Meter    Second   = inr λ ()
Unit-≟ Kilogram Meter    = inr λ ()
Unit-≟ Kilogram Second   = inr λ ()
Unit-≟ Second   Meter    = inr λ ()
Unit-≟ Second   Kilogram = inr λ ()

為了讓構造出來的 List 裡面的單位只有一種正確排列方式,我們可以幫單位附上順序,這個順序其實並不重要,只是需要有一個來確保 List 只有一種排列方法,從而去除因為排列順序不同而無法被定義等價認出來的不同表達方式([A, B] 跟 [B, A] 兩種構造)

_<Unit_ : Unit → Unit → 𝓤₀ ̇
Meter    <Unit Meter    = 𝟘
Meter    <Unit Kilogram = 𝟙
Meter    <Unit Second   = 𝟙
Kilogram <Unit Meter    = 𝟘
Kilogram <Unit Kilogram = 𝟘
Kilogram <Unit Second   = 𝟙
Second   <Unit _        = 𝟘

<Unit-trans : (u v w : Unit) → u <Unit v → v <Unit w → u <Unit w
<Unit-trans Meter    Kilogram Second   _ _ = ⋆
<Unit-trans Meter    Kilogram Kilogram _ ()
<Unit-trans Meter    Kilogram Meter    _ ()
<Unit-trans Meter    Second   _        _ ()
<Unit-trans Kilogram Second   _        _ ()
<Unit-trans Meter    Meter    _        () _
<Unit-trans Kilogram Meter    _        () _
<Unit-trans Kilogram Kilogram _        () _
<Unit-trans Second   _        _        () _

data Tri (u v : Unit) : 𝓤₀ ̇ where
  is-< : u <Unit v → Tri u v
  is-≡ : u = v → Tri u v
  is-> : v <Unit u → Tri u v

tri : (u v : Unit) → Tri u v
tri Meter    Meter    = is-≡ refl
tri Meter    Kilogram = is-< ⋆
tri Meter    Second   = is-< ⋆
tri Kilogram Meter    = is-> ⋆
tri Kilogram Kilogram = is-≡ refl
tri Kilogram Second   = is-< ⋆
tri Second   Meter    = is-> ⋆
tri Second   Kilogram = is-> ⋆
tri Second   Second   = is-≡ refl

單位定了順序之後,這裏規定 List 中的單位必須按照特定順序排列,確保每個組合單位的表示形式只有一種

data _<?_ : Maybe Unit → Unit → 𝓤₀ ̇ where
  no-bd : ∀ {u} → Nothing <? u
  bd    : ∀ {v u} → v <Unit u → Just v <? u

接著在 cons 中我們規定 ¬ (n = pos 0) 因此不會出現 3 s⁰ 這種可以直接寫成 3 的情況

data UL (lb : Maybe Unit) : 𝓤₀ ̇ where
  []   : UL lb
  cons : (u : Unit) → lb <? u
       → (n : ℤ) → ¬ (n = pos 0)
       → UL (Just u)
       → UL lb

Units : 𝓤₀ ̇
Units = UL Nothing

<?-trans : ∀ {lb u v} → lb <? u → u <Unit v → lb <? v
<?-trans no-bd      _   = no-bd
<?-trans (bd w<u)   u<v = bd (<Unit-trans _ _ _ w<u u<v)

weaken : ∀ {lb u} → lb <? u → UL (Just u) → UL lb
weaken bd' []                          = []
weaken bd' (cons v (bd u<v) n nz rest) = cons v (<?-trans bd' u<v) n nz rest

insert : ∀ {lb} (u : Unit) → lb <? u → (n : ℤ) → ¬ (n = pos 0)
         → UL lb → UL lb
insert u ord n nz []                          = cons u ord n nz []
insert u ord n nz (cons v ord' m nz' rest)   with tri u v
... | is-< u<v     = cons u ord n nz (cons v (bd u<v) m nz' rest)
... | is-> v<u     = cons v ord' m nz' (insert u (bd v<u) n nz rest)
... | is-≡ refl    with ℤ-is-discrete (n + m) (pos 0)
...   | inl _      = weaken ord rest
...   | inr nz-sum = cons u ord (n + m) nz-sum rest

*-unit : ∀ {lb} → UL lb → Units → Units
*-unit []                   ys = ys
*-unit (cons u _ n nz rest) ys = insert u no-bd n nz (*-unit rest ys)

構造一些案例來看看這種實現

1m : Units
1m = cons Meter no-bd (pos 1) (λ ()) []

1s : Units
1s = cons Second no-bd (pos 1) (λ ()) []

1/s : Units
1/s = cons Second no-bd (negsucc 0) (λ ()) []

對消就會得到純量

cancel : *-unit 1s 1/s = []
cancel = refl

另外也嘗試證明比較複雜的案例

m³ : Units
m³ = cons Meter no-bd (pos 3) (λ ()) []

1m³s : Units
1m³s =
  cons Meter no-bd (pos 3) (λ ())
    (cons Second (bd ⋆) (pos 1) (λ ()) [])

m³-×̇-1s : *-unit m³ 1s = 1m³s
m³-×̇-1s = refl

這個方法的缺點是我們被迫仔細的構造構造子,構造複雜也難用,並創造了一個內容無關緊要的 strict order 與大量的輔助函數來處理這些問題。但比起另外兩個方案,這個方案並不需要 function extensionality,並且證明可以仰賴定義等價。

用函數表示 [ag-FKSF]

{-# OPTIONS --safe --without-K --no-exact-split #-}
open import MLTT.Spartan hiding (_+_)
open import UF.FunExt
open import Integers.Type
open import Integers.Addition
open import Integers.Negation

module ag-FKSF (fe : Fun-Ext) where

data Unit : 𝓤₀ ̇ where
  Meter Kilogram Second : Unit

這裏把組合單位定義成一個函數 u:今天問 u Meter 就會知道公尺這個單位的次方是多少

UL : (X : 𝓤 ̇ ) → 𝓤 ̇
UL X = X → ℤ

Units : 𝓤₀ ̇
Units = UL Unit

這個定義的好處之一是沒有單位的定義非常簡單:

ε-unit : Units
ε-unit _ = pos 0

單位相乘只需要把自己的指數相加即可

*-unit : Units → Units → Units
*-unit us₁ us₂ u = us₁ u + us₂ u

要取單位的乘法反元素可以定義成加法反元素

⁻¹-unit : Units → Units
⁻¹-unit us u = - us u

也就是說,我們根本就是借用了 ℤ 的代數來用,從而大幅簡化了定義。我們可以構造一些範例來看看

1m : Units
1m Meter = pos 1
1m _ = pos 0

1s : Units
1s Second = pos 1
1s _ = pos 0

m³ : Units
m³ Meter = pos 3
m³ _ = pos 0

1/s : Units
1/s = ⁻¹-unit 1s

證明這確實有用

cancel-pointwise : *-unit 1s 1/s = ε-unit
cancel-pointwise = dfunext fe I
  where
  I : (u : Unit) → *-unit 1s 1/s u = ε-unit u
  I Meter    = refl
  I Kilogram = refl
  I Second   = refl

1m³s : Units
1m³s Meter = pos 3
1m³s Second = pos 1
1m³s _ = pos 0

m³-×̇-1s : *-unit m³ 1s = 1m³s
m³-×̇-1s = dfunext fe I
  where
  I : (u : Unit) → *-unit m³ 1s u = 1m³s u
  I Meter = refl
  I Kilogram = refl
  I Second = refl

這個方案的好處是他構造寫起來最直覺,在概念上很漂亮(對函數詢問特定單位的指數次方是多少),但證明的複雜性跟 quotient 版本相當。

結語 [local-0]

對所有我們能夠想到儲存方式,但表示方式具有歧意的狀況,都可以用類似的方案解決。但方案三這種直接去找理想的 model 的做法不一定能成功,混用三種方案也是有可能的,熟悉理論的多種模型會對避免粗暴的使用方案一有很大的幫助。

Structural Interface 的設計限制 [G9M2]

前幾日跟朋友探討他新寫的程式語言的特性設計時,討論到他希望 interface 與 record 都是 structural 時,發現了一些小小的設計限制,所以在這裡紀錄下來。

Go 的兩個特性 [local-0]

  • struct 是 nominal:兩個欄位相同的 struct 依然是不同型別
  • interface 是 structural:只看 method set 自動匹配,不需顯式宣告

兩者看起來是各自獨立的設計選擇,然而

如果 struct 是 structural [local-1]

interface Hello { hello() }
type T = struct {}
func (t *T) hello() { ... }
  1. structural rule 下 T 只是形狀 {} 的一個參考用標籤,並不會被型別系統認知到
  2. structural subtyping 下,所有 record 在結構上都包含空欄位集,所以全部都得到了 hello() 的實現
  3. 結合 structural interface 認為有方法就算實作,就等於所有 record 類型都實現了 Hello
  4. 若其他類型也各自定義 hello(),要使用哪個就由 method resolution 演算法決定,這個結果通常是非常不穩定的(更不用說這裡還需要底下實現紀錄是哪個 record 實現了 method,與類型系統設計不匹配,讓 resolution 的結果更難被理解與信任)

所以 Go 選擇 nominal struct 是出於真正的約束所限,一但選擇 structural interface 就需要對其他部分做出讓步。

單位乘法通用化 [ag-4AP1]

用 Agda 實現單位正確的算術 的 *-unit 其實可以進一步通用化,我們只關心拿來當單位的類型是不是有可判定的相等,所以程式可以寫成

{-# OPTIONS --safe --without-K #-}
module ag-4AP1 where

open import MLTT.Spartan hiding (_+_)
open import MLTT.List
open import MGS.MLTT using (has-decidable-equality)
open import Integers.Type
open import Integers.Addition
open import ag-OW40
generalized-_-unit : {A : 𝓤 ̇ }
  → has-decidable-equality A
  → List (A × ℤ) → List (A × ℤ) → List (A × ℤ)
generalized-_-unit {_}{A} dec us₁ us₂ = foldr step us₁ us₂
  where
  step : A × ℤ → List (A × ℤ) → List (A × ℤ)
  step (u , n) [] = (u , n) ∷ []
  step (u , n) ((v , m) ∷ xs) with dec u v
  ... | inr _ = (v , m) ∷ step (u , n) xs
  ... | inl _ with ℤ-≟ (n + m) (pos 0)
  ...   | inl _ = xs
  ...   | inr _ = (u , n + m) ∷ xs

記錄一下 zoxide 在 fish 裡要怎麼設定 [E891]

先安裝 fisher:

curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisher

再安裝 icezyclon/zoxide.fish

fisher install icezyclon/zoxide.fish

這樣就可以把 cd 當成 z 使用了

Example frame 的 oppsite 不必是 frame [6CPF]

Topology via logic

ΩR\Omega \mathbb{R} 這個 frame 的基本 basis 是一些傳統的實數線上的開集 (a−ϵ,a+ϵ)(a - \epsilon, a + \epsilon),然後基於這些 basis 根據 frame 規則(有限 meet、無限 join)長出這個結構。並且我們可以看到

  1. ≤\le 是 ⊆\subseteq
  2. true\text{true} 是 R\mathbb{R}
  3. false\text{false} 是 ∅\emptyset
  4. ∧\wedge 是 ∩\cap
  5. ∨\vee 是 ∪\cup

這個案例的重點在,ΩRop\Omega \mathbb{R}^{op} 並不是一個 frame。證明的重點在展示它並不滿足 distribute law:

如果 ΩRop\Omega \mathbb{R}^{op} 滿足 distribute law,那麼我們就會得到等式

x∪(⋂Y)=⋂{x∪yi∣yi∈Y}x \cup (\bigcap Y) = \bigcap \{ x \cup y_i \mid y_i \in Y \}
ΩR\Omega \mathbb{R} 的 distribute law 是 x∩(⋃Y)=⋃{x∩yi∣yi∈Y}x \cap (\bigcup Y) = \bigcup \{ x \cap y_i \mid y_i \in Y \}

然而考慮 ⋂Y=∅\bigcap Y = \emptyset,那我們可以得到 x∪∅=xx \cup \emptyset = x。接著我們考慮 x∩yix \cap y_i 得到一群 xix_i,然而因為 ⋂Y=∅\bigcap Y = \emptyset,所以 ⋂(xi)i∈I=∅\bigcap (x_i)_{i \in I} = \emptyset。這表示 ⋃{x∩yi∣yi∈Y}=∅\bigcup \{ x \cap y_i \mid y_i \in Y \} = \emptyset,等式並不成立,因此 ΩRop\Omega \mathbb{R}^{op} 並不是一個 frame

Example CwF 標準案例 [ag-A3OG]

基於 CwF 的結構與規範 現在可以討論 CwF 最常被拿出來講的案例

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan
open import ag-T2O7

module ag-A3OG {𝓤 : Universe} where
open CwFStructure
open CwFLaws
open CwF

str : CwFStructure
str .Con = 𝓤 ̇
str .Sub Γ Δ = Γ → Δ
str .idSub = id
str ._○_ = _∘_
str .ε = 𝟙
str .εSub _ = ⋆
str .Ty Γ = Γ → 𝓤 ̇
str ._[_] A σ x = A (σ x)
str .Tm Γ A = (x : Γ) → A x
str ._⁅_⁆ t σ x = t (σ x)
str ._₊_ Γ A = Σ x ꞉ Γ , A x
str .⟨_,_⟩ σ t δ = σ δ , t δ
str .p = pr₁
str .q = pr₂

law : CwFLaws str
law .idl = refl
law .idr = refl
law .○-assoc = refl
law .εSub-unique = refl
law .ty[id] = refl
law .ty[○] = refl
law .tm[id] = refl
law .tm[○] = refl
law .p,-β = refl
law .q,-β = refl
law .p,q-η = refl
law .,○-distrib = refl

TypeCwF : CwF
TypeCwF .structure = str
TypeCwF .laws = law

Definition CwF 的結構與規範 [ag-T2O7]

學習 https://github.com/martinescardo/TypeTopology/pull/434 中的 CwF 部分

這裡可以跟 Display map category 捕捉了類型論的什麼面向? 一起看

{-# OPTIONS --safe --without-K #-}
module ag-T2O7 where

open import MLTT.Spartan
open import UF.Base

CwF 的基本結構

record CwFStructure : (𝓤 ⊔ 𝓥)⁺ ̇ where
  field

有一個 Contexts 構成的範疇(Category of contexts)

  1. 這個範疇的元素是 contexts
  2. 關於 context Γ 跟 context Δ 我們可以討論他們的 morphism Sub Γ Δ,叫做 substitution
  3. 每個 context Γ 都有自己到自己的 morphism,也就是 identity
  4. 如果有兩個 substitutions 有合適的 type,我們就能把它們串起來
  5. Contexts 範疇有 terminal object,就是空的 context ε
    Con : 𝓤 ̇
    Sub : Con → Con → 𝓥 ̇
    idSub : {Γ : Con} → Sub Γ Γ
    _○_ : {Γ Δ Θ : Con} → Sub Δ Θ → Sub Γ Δ → Sub Γ Θ

    ε : Con
    εSub : {Γ : Con} → Sub Γ ε
  1. 有一系列 indexed by context 的 collection 叫做 Ty,表示 types
  2. 每個 morphism 都給出了 type 逆變
    -- Type functor
    Ty : Con → 𝓤 ̇
    _[_] : {Γ Δ : Con} → Ty Γ → Sub Δ Γ → Ty Δ
  1. 有一系列 indexed by context A 跟 Ty A 的 collection 叫做 Tm,表示 terms
  2. 每個 morphism 都給出了 term 逆變
    -- Term functor
    Tm : (Γ : Con) → Ty Γ → 𝓥 ̇
    _⁅_⁆ : {Γ Δ : Con} {A : Ty Γ} → Tm Γ A → (σ : Sub Δ Γ) → Tm Δ (A [ σ ])

我們可以擴充手上的 context

如果我們有一個 context Γ 跟一個 type T 我們可以得到 Γ, T,一個基於原本 context 擴充的新 context

    _₊_ : (Γ : Con) → Ty Γ → Con

如果有一個 Sub Δ Γ,那每個 term u ∈ Tm Δ (A [ σ ]) 都教了我們要怎麼建立從 Δ 到 Γ 的擴充 Γ, u : A 的 morphism

    ⟨_,_⟩ : {Γ Δ : Con} {A : Ty Γ}
          → (σ : Sub Δ Γ) → Tm Δ (A [ σ ]) → Sub Δ (Γ ₊ A)

我們總是能從 Γ, A 取出 Γ 部分

    p : {Γ : Con} {A : Ty Γ} → Sub (Γ ₊ A) Γ

我們總是能從 Γ, u : A 取出 u 這個 term,類型取 A [ p ]

    q : {Γ : Con} {A : Ty Γ} → Tm (Γ ₊ A) (A [ p ])

CwF 的 laws

CwF 不只是結構,還需要滿足一些互動上的 laws,才能合理的排除掉並不能解釋 type theory 的那些範疇

record CwFLaws {𝓤 : Universe} {𝓥 : Universe}
  (S : CwFStructure {𝓤} {𝓥})
  : (𝓤 ⊔ 𝓥)⁺ ̇ where
  open CwFStructure S
  field

identity substitution 跟任何 substitution σ 結合都是 σ(當然前提是可以結合的那些)

    idl : {Γ Δ : Con} {σ : Sub Γ Δ}
        → idSub ○ σ = σ
    idr : {Γ Δ : Con} {σ : Sub Γ Δ}
        → σ ○ idSub = σ

要求結合有 associativity

    ○-assoc : {Γ Δ Θ Ξ : Con} {σ : Sub Θ Ξ} {τ : Sub Δ Θ} {ρ : Sub Γ Δ}
            → (σ ○ τ) ○ ρ = σ ○ (τ ○ ρ)

要求去 empty context 的 substitution 是唯一的。這是因為具體的 contexts 中我們觀察到這件事一定成立,但對很多範疇來說這並不成立,因此 CwF 定義這點就能消除大量無意義的 models

    εSub-unique : {Γ : Con} {σ : Sub Γ ε}
                → σ = εSub
  1. Type A 經過 identity substitution 應該不變
  2. 對 type 的替換與 context morphism 的組合具有交換性
    ty[id] : {Γ : Con} {A : Ty Γ}
           → A [ idSub ] = A
    ty[○]  : {Γ Δ Θ : Con} {A : Ty Γ} {σ : Sub Δ Γ} {τ : Sub Θ Δ}
           → A [ σ ○ τ ] = A [ σ ] [ τ ]
  1. Term t 經過 identity substitution 應該不變
  2. 對 term 的替換與 context morphism 的組合具有交換性(需要連帶考慮 type 的變化)
    tm[id] : {Γ : Con} {A : Ty Γ} {t : Tm Γ A}
           → transport (Tm Γ) ty[id]
             (t ⁅ idSub ⁆) = t
    tm[○] : {Γ Δ Θ : Con} {A : Ty Γ} {t : Tm Γ A} {σ : Sub Δ Γ} {τ : Sub Θ Δ}
           → transport (Tm Θ) ty[○]
             (t ⁅ σ ○ τ ⁆) = t ⁅ σ ⁆ ⁅ τ ⁆

這邊是 type/term substitution 跟 context extension 之間的關係,其實翻譯成實際上的使用都是一些很直覺的規範

    p,-β : {Γ Δ : Con} {A : Ty Γ} {σ : Sub Δ Γ} {t : Tm Δ (A [ σ ])}
         → p ○ ⟨ σ , t ⟩ = σ
    q,-β : {Γ Δ : Con} {A : Ty Γ} {σ : Sub Δ Γ} {t : Tm Δ (A [ σ ])}
         → transport (Tm Δ) {(A [ p ]) [ ⟨ σ , t ⟩ ]} (ty[○] ⁻¹ ∙ ap (A [_]) p,-β)
          (q ⁅ ⟨ σ , t ⟩ ⁆) = t
    p,q-η : {Γ Δ : Con} {A : Ty Γ} {σ : Sub Δ Γ} {t : Tm Δ (A [ σ ])}
          → ⟨ p , q ⟩ = idSub {Γ ₊ A}
    ,○-distrib : {Γ Δ Θ : Con} {A : Ty Γ} {σ : Sub Δ Γ} {t : Tm Δ (A [ σ ])} {τ : Sub Θ Δ}
               → ⟨ σ , t ⟩ ○ τ = ⟨ σ ○ τ , transport (Tm Θ) {(A [ σ ]) [ τ ]} {A [ σ ○ τ ]} (ty[○] ⁻¹)
                                           (t ⁅ τ ⁆) ⟩

最後把 structure 跟 laws 兩個接在一起

record CwF : (𝓤 ⊔ 𝓥)⁺ ̇ where
  field
    structure : CwFStructure {𝓤} {𝓥}
    laws : CwFLaws structure

  open CwFStructure structure public
  open CwFLaws laws public

How to install hut (CLI tool for sr.ht) [4V6X]

First clone the repository hut at anyplace you want on your computer

git clone https://git.sr.ht/~xenrox/hut

There are some dependencies you need to install first

  1. The Go programming language
  2. brew install scdoc for scdoc

then cd hut and run

make
sudo make install

Lexical scoping與dynamic scoping的對偶 [958P]

從是否與environment無關這點來看,lexical scope與dynamic scope之間是有一個對偶關係的:

  • 對dynamic的abstraction而言,在哪裡建立都一樣;然而application的時候結果就會跟著environment變化而變化
  • 反過來,對lexical的abstraction而言environment是會影響closure到底 capture 到什麼的,所以不是environment無關;但對application來說,已經建立的closure在哪裡執行都一樣

也就是說 Landin 他們發現的是,人們預期 function application 是 environment 無關的。因此這也就成了大部分程式語言的選擇。

但這不意味著沒有其他的選擇,有一個程式語言Kernel 就是利用dynamic scope的語意設計出不需要phase distinction的macro system。而諸多類似algebraic effect的跳轉系統,也可以說是應用了dynamic scope

在 guix 上用 patchelf 設定正確的連結器 [A05P]

預設很多 executable 會使用連結器 /lib64/ld-linux-x86-64.so.2,但 Guix 這東西會被放到 store 裡面,所以很多 executable 就無法執行,這時候就需要用

readelf -l  | grep interpreter

指令找出現在使用的是哪一個。用

find /gnu/store -name "ld-linux-x86-64.so.2" | head -5

指令找到系統上有什麼。最後用

patchelf --set-interpreter /gnu/store/.../ld-linux-x86-64.so.2 

設定一個新的給 executable 使用,這時候就可以執行程式了。

從公理系統到natural deduction [EGRZ]

邏輯公理系統是歷史上花了不少力氣整理出來的一組極簡規則,但卻不方便使用。而 natural deduction 改善並與我們日常的思考方式對齊,使它成為更方便的推理工具。現代我們可以用 agda 表述這些概念並更輕鬆的研究他們

邏輯公理系統 [ag-L7FN]

這裡寫的是 Mathematical Logic and Computation §2.2 定義的 Axiomatic Systems。就像書中講的,這套系統很不好用,也不好學,不過在歷史上我們就是這樣實現的

{-# OPTIONS --safe --without-K --no-level-universe #-}
module ag-L7FN where

open import MLTT.Sigma
open import MLTT.Plus-Type

data Proposition : 𝓤₀  ̇ where
  ⊥ : Proposition
  _∧_ _∨_ _⇒_ : Proposition → Proposition → Proposition
infixr 30 _⇒_
infixl 40 _∧_ _∨_

variable A B C : Proposition

data ⊢ : Proposition → 𝓤₀  ̇ where
  PC1 : ⊢ (A ⇒ (B ⇒ A))
  PC2 : ⊢ ((A ⇒ (B ⇒ C)) ⇒ ((A ⇒ B) ⇒ (A ⇒ C)))
  PC3 : ⊢ (A ⇒ (B ⇒ A ∧ B))
  PC4 : ⊢ (A ∧ B ⇒ A)
  PC5 : ⊢ (A ∧ B ⇒ B)
  PC6 : ⊢ (A ⇒ A ∨ B)
  PC7 : ⊢ (B ⇒ A ∨ B)
  PC8 : ⊢ ((A ⇒ C) ⇒ ((B ⇒ C) ⇒ (A ∨ B ⇒ C)))
  PC9 : ⊢ (⊥ ⇒ A)

  MP : ⊢ A → ⊢ (A ⇒ B) → ⊢ B

現在我們定義了邏輯語言跟它遵循的公理,我們只打算證明一個案例來了解如何用公理證明,這個問題來自 Mathematical Logic and Computation 的 proposition 2.3.6,由於第四個涉及 context 擴充而這裡沒有處理所以略過

record proposition-2-3-6 : 𝓤₀  ̇ where
  field
    I : ⊢ A → ⊢ B → ⊢ (A ∧ B)
    II : ⊢ (A ∧ B) → ⊢ A × ⊢ B
    III : ⊢ A + ⊢ B → ⊢ (A ∨ B)

  proof : proposition-2-3-6
  proof .I A-holds B-holds = MP B-holds (MP A-holds PC3)
  proof .II A-and-B-holds = MP A-and-B-holds PC4 , MP A-and-B-holds PC5
  proof .III (inl A-holds) = MP A-holds PC6
  proof .III (inr B-holds) = MP B-holds PC7

要感受這種證明風格可以有多繁瑣可以參考這裡

natural deduction [ag-M036]

這邊我引入了 context,另外我沒有定義所有規則,只有定義有用到的部分而已

{-# OPTIONS --safe --without-K --no-level-universe #-}
module ag-M036 where

open import MLTT.Sigma
open import MLTT.Plus-Type
open import MLTT.NaturalNumbers

data Proposition : Set where
  ⊥ : Proposition
  _∧_ _∨_ _⇒_ : Proposition → Proposition → Proposition
infixr 30 _⇒_
infixl 40 _∧_ _∨_

data Context : ℕ → Set where
  ∅ : Context 0
  _▸_ : {l : ℕ} → Context l → Proposition → Context (succ l)
infix 20 _▸_

variable
  A B C : Proposition
  l : ℕ
  Γ : Context l

data _⊢_ : {l : ℕ} (Γ : Context l) → Proposition → Set where
  var : Γ ▸ A ⊢ A
  intro-⇒ : Γ ▸ A ⊢ B
            -----------
            → Γ ⊢ A ⇒ B
  intro-∧ : Γ ⊢ A
            → Γ ⊢ B
            -----------
            → Γ ⊢ (A ∧ B)
  elim-∧₁ : Γ ⊢ (A ∧ B)
            -----------
            → Γ ⊢ A
  elim-∧₂ : Γ ⊢ (A ∧ B)
            -----------
            → Γ ⊢ B
  intro-∨₁ : Γ ⊢ A
             -----------
             → Γ ⊢ A ∨ B
  intro-∨₂ : Γ ⊢ B
             -----------
             → Γ ⊢ A ∨ B
  elim-∨ : Γ ⊢ A ∨ B
           → Γ ▸ A ⊢ C
           → Γ ▸ B ⊢ C
           -----------
           → Γ ⊢ C
infix 10 _⊢_

再次證明 2.3.6 的問題

record proposition-2-3-6 : Set where
  field
    I : Γ ⊢ A → Γ ⊢ B → Γ ⊢ (A ∧ B)
    II : Γ ⊢ (A ∧ B) → (Γ ⊢ A) × (Γ ⊢ B)
    III : (Γ ⊢ A) + (Γ ⊢ B) → Γ ⊢ (A ∨ B)
    IV : Γ ⊢ (A ∨ B) → Γ ▸ A ⊢ C → Γ ▸ B ⊢ C → Γ ⊢ C

  proof : proposition-2-3-6
  proof .I A-holds B-holds = intro-∧ A-holds B-holds
  proof .II A-and-B-holds = elim-∧₁ A-and-B-holds , elim-∧₂ A-and-B-holds
  proof .III (inl A-holds) = intro-∨₁ A-holds
  proof .III (inr B-holds) = intro-∨₂ B-holds
  proof .IV A-or-B-holds GA⊢C GB⊢C = elim-∨ A-or-B-holds GA⊢C GB⊢C

不過當然,可以看到問題幾乎就是用了定義而已,所以我們再找個問題證明看看

I : ∅ ⊢ A ∧ B ⇒ B ∧ A
I = intro-⇒ (intro-∧ (elim-∧₂ var) (elim-∧₁ var))

natural deduction 的好處就是把很多直覺的推導過程內建到規則中,幾乎就是我們日常使用的邏輯規則。而它也具有可讀性,它的證明樹的結構接近我們的思考,不需要記誦一堆看起來很任意的 axiom schemas。

induction principle 的生成 [VGOA]

這裡參考的是 Code Generation for Higher Inductive Types 中的紀錄

首先我們規範 inductive data types 的 form 如下

data D(a1:A1)…(an:An):I1→⋯→Im→Type wherec1:Δ1→D a1…an e11…e1m…cr:Δr→D a1…an er1…erm\begin{aligned} \text{data } &D (a_1 : A_1) \dots (a_n : A_n) : I_1 \to \cdots \to I_m \to \text{Type where} \\ &c_1 : \Delta_1 \to D\ a_1 \dots a_n\ e_{11} \dots e_{1m} \\ &\dots \\ &c_r : \Delta_r \to D\ a_1 \dots a_n\ e_{r1} \dots e_{rm} \end{aligned}

我們會生成以下形式的 induction principle

Dind:(a1:A1)→⋯→(an:An)→(i1:I1)→⋯→(im:Im)→(target:D a1…an i1…im)→(C:(i1:I1)→⋯→(im:Im)→D a1…an i1…im→Type)→(f1:Δ1′→C e11…e1m (c1 Δ1))…→(fr:Δr′→C er1…erm (cr Δr))→C i1…im target\begin{aligned} D_{ind} &: (a_1 : A_1) \to \dots \to (a_n : A_n) \\ &\to (i_1 : I_1) \to \dots \to (i_m : I_m) \\ &\to (\text{target} : D\ a_1 \dots a_n\ i_1 \dots i_m) \\ &\to (C : (i_1 : I_1) \to \dots \to (i_m : I_m) \to D\ a_1 \dots a_n\ i_1 \dots i_m \to \text{Type}) \\ &\to (f_1 : \Delta_1' \to C\ e_{11} \dots e_{1m}\ (c_1\ \Delta_1)) \\ &\quad \dots \\ &\to (f_r : \Delta_r' \to C\ e_{r1} \dots e_{rm}\ (c_r\ \Delta_r)) \\ &\to C\ i_1 \dots i_m\ \text{target} \end{aligned}

aia_i 跟 iji_j 的差別就是,iji_j 涉及到使用者可以實例化的部分,比如

data Vec (A : Type) : Nat -> Type where
  nil : Vec A 0
  cons : {n : Nat} -> A -> Vec A n -> Vec A (suc n)

這個案例中的 a1:A1a_1 : A_1 就是 A : Type,而 i1:I1i_1 : I_1 是 _ : Nat。這裡 nil 的 Δ\Delta 是空的,而 cons 的 Δ\Delta 是 {n : Nat}, (_ : A), (_ : Vec A n)。

而 eije_{ij} 分別是 0 跟 suc n,這就是使用者可以選擇不同 witness 填入的部分。

在 Δ\Delta 的生成部分可以看到特定標記成了 Δ′\Delta',這個意思是說

  1. 如果 (y:B)∈Δ(y : B) \in \Delta 而且 B=D a…e…B = D\ a \dots e \dots,那 Δ′\Delta' 中應該生成 (y : B), (y' : C e ... y)
  2. 如果 (y:B)∈Δ(y : B) \in \Delta 而且 B=ψ→D a…e…B = \psi \to D\ a \dots e \dots,那 Δ′\Delta' 中應該生成 (y : B), (y' : Ψ -> C e ... (y Ψ))
  3. 除此之外 Δ′\Delta' 只需要把 Δ\Delta 中的 binding (y:B)(y : B) 複製一遍就好了

所以 Vec 得到的 induction principle 就應該是

Vec.ind : (A : Type) -> (i : Nat) -> (target : Vec A i)
        -> (C : (i : Nat) -> D A i -> Type)
        -> (case_nil : C 0 nil)
        -> (case_cons : {n : Nat}
                        -> (a : A)
                        -> (as : Vec A n)
                        -> (as' : C n as)
                        -> C (suc n) (cons {n} a as))
        -> C i target

Proposition natural transformation可以視為end [C07X]

令 C,DC, D 為category,而 F,G:C→DF, G : C \to D 為functor。則所有 F⇒GF \Rightarrow G 構成的the set of natural transformations [C,D](F,G)[C, D](F, G) 可以視為end

[C,D](F,G)=∫X∈CHomD(F(X),G(X))[C, D](F, G) = \int_{X \in C} \text{Hom}_D(F(X), G(X))

Proof [local-0]

利用coend對偶可以看出end應該長這樣:

figure tex8919

由於 HomC(F(−),G(=))\text{Hom}_C(F(-), G(=)) 可以視為profunctor,因此由universal property我們可以得到

figure tex8920

可是從集合 11 導出的這個大方塊就是naturality的定義,所以natural transformation確實是一個end

另一個證明方式是展開可以看到end的元素定義成的collection剛好就是一個natural transformation。參見 nlab

Theorem Vaughan (1977) [L3M8]

Rectangles, curves, and Klein bottles, related to Status of the smooth rectangular Peg problem

Every Jordan curve has an inscribed rectangle.

Theorem Nonexistence of an embedded Klein surface [local-0]

No continuous embedding of the Klein surface into R3\mathbb{R}^3. This is a standard result from algebraic topology. Using Alexander duality to compute homology, we produce a contradiction.

Proof [local-1]

Given a Jordan curve JJ, the set of unordered and unequal pairs of points in JJ, denoted SS, is an open Möbius band. Because every unequal unordered pair of points in the circle determines a unique point in RP2\mathbb{R}P^2: Take the two tangent lines to the circle at these points and intersect them.

If tangent lines are parallel, than it indicates the infinite point of RP2\mathbb{R}P^2:

Therefore, SS are the points of the complement of the closed unit disk in the projective plane, hence an open Möbius band.

Consider a map ϕ:S→R3\phi : S \to \mathbb{R}^3 defined by

ϕ: S→R3ϕ(a,b)= (a+b2,∣a−b∣)\begin{aligned} &\phi &:& \ &S \to \mathbb{R}^3 \\ &\phi(a, b) &=& \ &\left( \frac{a+b}{2}, |a - b| \right) \end{aligned}

Geometrically, ϕ\phi maps the ordered pair to a point encoding the midpoint of the segment ab‾\overline{ab} (2D) and the length of the segment (1D).

If ϕ(a1,b1)=ϕ(a2,b2)\phi(a_1, b_1) = \phi(a_2, b_2), then these four points form an inscribed rectangle. Hence we just need to prove that the map ϕ\phi is not injective!

Consider K=ϕ(S)∪ϕ(∂S)∪ρ(ϕ(S))K = \phi(S) \cup \phi(\partial S) \cup \rho(\phi(S)) where ρ\rho reflects the shape in the XY-plane. This is a Klein surface by gluing two Möbius strips at their boundary.

If ϕ\phi is injective, then KK can be embedded into R3\mathbb{R}^3, which contradicts the theorem that nonexistence of an embedded Klein surface into R3\mathbb{R}^3.

Proposition 微分方程式 x′=axx' = ax 解形式一定是 keatke^{at} [EMGT]

令 dx/dt=axdx / dt = a x,則其所有解之形式皆為

keatke^{at}

其中 k∈Rk \in \mathbb{R}

Proof [local-0]

令 u(t)u(t) 為一解,則 du/dt=u′(t)=au(t)du / dt = u'(t) = au(t)。計算

ddt(u(t)e−at)=u′(t)e−at+u(t)(−ae−at)=au(t)e−at−au(t)e−at=0\begin{aligned} \frac{d}{d t}(u(t) e^{-at}) &= u'(t) e^{-at} + u(t)(-a e^{-at}) \\ &= au(t) e^{-at} - au(t) e^{-at} = 0 \end{aligned}

因此 u(t)e−atu(t) e^{-at} 是常數,可以寫成

u(t)eat=k∈R\frac{u(t)}{e^{at}} = k \in \mathbb{R}

因此 u(t)=keatu(t) = k e^{at}

Model mapping TT to untyped LC [ag-000Y]

{-# OPTIONS --without-K #-}
open import MLTT.Spartan hiding (Π; zero; succ)
open import UF.FunExt
open import ag-000V
open import ag-000W

module ag-000Y (fe : Fun-Ext) where

A model mapping TT to untyped lambda calculus.

module LC-TT {𝓤 𝓥 : Universe} (l : LC {𝓥}) where
  open LC
  open TT
  open TT-sorts
  open TT-ctors

  ex-sorts : TT-sorts {𝓤} {𝓥}
  ex-sorts .Ty = 𝟙
  ex-sorts .Tm _ = l .Λ

  ex-ctors : TT-ctors ex-sorts
  ex-ctors .Π A B = ⋆
  ex-ctors .lam f = l .lambda f
  ex-ctors .app f x = l .apply f x
  ex-ctors .lam-app = l .η _
  ex-ctors .app-lam {a}{b}{f} =
    (λ x → l .apply (l .lambda f) x) =⟨ dfunext fe (λ x → l .β f x) ⟩
    (λ x → f x) =⟨ refl ⟩
    f ∎
  ex-ctors .U = ⋆
  ex-ctors .El _ = ⋆
  ex-ctors .Nat = ⋆
  ex-ctors .zero = zeroΛ l
  ex-ctors .succ x = succΛ l x
  ex-ctors .elim-Nat X ze su n = recΛ l ze su n
  ex-ctors .elim-Nat-zero = recΛβ-zero l
  ex-ctors .elim-Nat-succ = recΛβ-succ l

  ex : TT {𝓤} {𝓥}
  ex .sorts = ex-sorts
  ex .ctors = ex-ctors

SOGAT of type theory with Π\Pi-types, a Tarski universe, and natural numbers [ag-000W]

Learn from https://github.com/kontheocharis/erasure-agda
{-# OPTIONS --safe --without-K --confluence-check #-}
module ag-000W where

open import MLTT.Spartan hiding (Π; zero; succ)

coe : {X X' : 𝓤 ̇ } → X = X' → X → X'
coe = transport id

TT 要用的 sorts,以及如果 Type 相等,可以轉換 term 用的 helper coeTm

record TT-sorts : (𝓤 ⊔ 𝓥)⁺  ̇ where
  field
    Ty : 𝓤 ̇
    Tm : Ty → 𝓥 ̇

  coeTm : ∀ {A B : Ty} → A = B → Tm A → Tm B
  coeTm p a = coe (ap Tm p) a

TT 的 SOGAT

module _ (sorts : TT-sorts {𝓤} {𝓥}) where
  open TT-sorts sorts

  private
    variable
      A B C : Ty
      X Y Z : Tm _ → Ty
      t u v : Tm _
      f g h : (a : Tm _) → Tm _
      eq : _ = _

  record TT-ctors : (𝓤 ⊔ 𝓥)⁺  ̇ where
    field
      -- Pi types
      Π : (A : Ty) → (Tm A → Ty) → Ty
      lam : ((a : Tm A) → Tm (X a)) → Tm (Π A X)
      app : Tm (Π A X) → (a : Tm A) → Tm (X a)
      lam-app : lam (app t) = t
      app-lam : app (lam f) = f

      -- Universe
      U : Ty
      El : Tm U → Ty

      -- Natural numbers
      Nat : Ty
      zero : Tm Nat
      succ : Tm Nat → Tm Nat
      elim-Nat : (X : Tm Nat → Ty)
        → (Tm (X zero))
        → ((n : Tm Nat) → Tm (X n) → Tm (X (succ n)))
        → (n : Tm Nat) → Tm (X n)

      -- Computation for elim-Nat
      elim-Nat-zero : ∀ {mz ms} → elim-Nat X mz ms zero = mz
      elim-Nat-succ : ∀ {mz ms n} → elim-Nat X mz ms (succ n) = ms n (elim-Nat X mz ms n)

record TT : (𝓤 ⊔ 𝓥)⁺  ̇ where
  field
    sorts : TT-sorts {𝓤} {𝓥}
  open TT-sorts sorts public
  field
    ctors : TT-ctors sorts
  open TT-ctors ctors public

Definition Riemann curvature tensor [B2D1]

The curvature RR of a Riemannian manifold (M,g)(M, g) is a tensor R∈Ω2(End(TM))R \in \Omega^2(End(TM))

R(X,Y)Z:=  ∇X∇YZ−∇Y∇XZ−∇[X,Y]Z=  [∇X,∇Y]Z−∇[X,Y]Z\begin{aligned} R(X, Y)Z :=&\; \nabla_X \nabla_Y Z - \nabla_Y \nabla_X Z - \nabla_{[X,Y]} Z \\ =&\; [\nabla_X, \nabla_Y] Z - \nabla_{[X,Y]} Z \end{aligned}

where X,Y,ZX, Y, Z are vector fields, ∇\nabla is the Levi-Civita connection of the metric gg (see Lectures on the Geometry of Manifolds Proposition 4.1.9.).

In local coordinates (x1,…,xn)(x^1, \dots, x^n) we have

Rijkm∂m=R(∂j,∂k)∂i R^m_{ijk} \partial_m = R(\partial_j, \partial_k) \partial_i

In terms of the Christoffel symbols we have

Rijkm=∂jΓikm−∂kΓijm+ΓnjmΓjkn−ΓnkmΓijn R^m_{ijk} = \partial_j \Gamma^m_{ik} - \partial_k \Gamma^m_{ij} + \Gamma^m_{nj}\Gamma^n_{jk} - \Gamma^m_{nk}\Gamma^n_{ij}

Lowering the indices we have a new tensor

Rijkl:=gimRjklm=g(R(∂k,∂l)∂j,∂i)=g(∂i,R(∂k,∂l)∂j) R_{ijkl} := g_{im}R^m_{jkl} = g(R(\partial_k, \partial_l) \partial_j, \partial_i) = g(\partial_i, R(\partial_k, \partial_l) \partial_j)

Theorem The Hairy Ball Theorem [DRE0]

用 constant vector field on plane 然後拉回 S2S^2 的定義方法很妙。

定理的證明是用 Flux 不變,但如果有處處非零的連續向量場,就可以讓 Flux 改變,矛盾。因此這樣的向量場不可能存在。

3-sphere S3S^3 (群 SU(2)SU(2)) 跟 RP3\mathbb{R}P^3 [JRT2]

用 S3S^3 quotient 掉 antipodal points 會得到 Real projective space RP3\mathbb{R}P^3。

Proposition S3S^3 is not simple [local-1]

Proof [local-0]

因為 {±1}\{\pm 1\} 是 S3S^3 的 normal subgroup:x×1×x−1x \times 1 \times x^{-1} 跟 x×−1×x−1x \times -1 \times x^{-1} for all x∈S3x \in S^3 都還是屬於 {±1}\{\pm 1\}。

而 {±1}\{\pm 1\} nontrivial,有 nontrivial normal subgroup 的群 not simple

RP3\mathbb{R}P^3 是群 SO(3)SO(3):The group of rotations of R3\mathbb{R}^3。SO(3)SO(3) is simple 所以跟 S3S^3 不是同一個群

S3S^3 作為一個群可以視為 2x2 複數矩陣的群,元素為

Q=(a+di−b−cib−cia−di),det⁡(Q)=1Q = \begin{pmatrix} a + di & -b - ci \\ b - ci & a - di \end{pmatrix} ,\quad \det(Q) = 1

這又稱為 The special unitary group SU(2)SU(2)。

Proposition S1S^1 不是 SU(2)SU(2) 的 normal subgroup [local-3]

Proof [local-2]

用對角矩陣箝入 S1→SU(2)S^1 \to SU(2)

eiθ↦(eiθ00e−iθ)e^{i\theta} \mapsto \begin{pmatrix} e^{i\theta} & 0 \\ 0 & e^{-i\theta} \end{pmatrix}

取

g:=(1−111)∈SU(2)h:=(i00−i)g := \begin{pmatrix} 1 & -1 \\ 1 & 1 \end{pmatrix} \in SU(2) \\ h := \begin{pmatrix} i & 0 \\ 0 & -i \end{pmatrix}

計算 ghg−1ghg^{-1} 得

(0ii0)\begin{pmatrix} 0 & i \\ i & 0 \end{pmatrix}

不屬於 S1S^1。因此 S1S^1 不是 normal subgroup

Definition Hopf bundle [5A3M]

Identify the unit odd dimensional sphere S2n−1S^{2n-1} with the submanifold

{(z1,…,zn)∈Cn∣∣z0∣2+⋯+∣zn∣2=1}\{ (z_1, \dots, z_n) \in \mathbb{C}^n \mid |z_0|^2 + \cdots + |z_n|^2 = 1 \}

an S1S^1-action on S2n−1S^{2n-1} given by

eiθ⋅(z1,…,zn)=(eiθz1,…,eiθzn)e^{i\theta} \cdot (z_1, \dots, z_n) = (e^{i\theta}z_1, \dots, e^{i\theta}z_n)

The complex projective space CPn−1\mathbb{C}P^{n-1} is isomorphic to S2n−1/U(1)S^{2n-1} / U(1), the group U(1)U(1) corresponds to S1S^1. This quotient map is a principal S1S^1 bundle called Hopf bundle.

  1. [eiθz]∼[z][e^{i\theta}z] \sim [z] by definition of CPn−1\mathbb{C}P^{n-1}
  2. Use Ui:={[z]∈CPn−1∣zi≠0}U_i := \{ [z] \in \mathbb{C}P^{n-1} \mid z_i \ne 0 \} (because ⋃i=0n−1Ui=CPn−1\bigcup_{i=0}^{n-1} U_i = \mathbb{C}P^{n-1}, these describe all points in the projective space). The map πi:π−1(Ui)→S1\pi_i : \pi^{-1}(U_i) \to S^1 defined by z↦zi∣zi∣z \mapsto \frac{z_i}{|z_i|} then πi(eiθ⋅z)=eiθz∣eiθz∣=eiθz∣z∣=eiθ⋅z∣z∣=eiθ⋅πi(z)\begin{aligned} \pi_i(e^{i\theta} \cdot z) &= \frac{e^{i\theta} z}{|e^{i\theta} z|} \\ &= \frac{e^{i\theta} z}{|z|} \\ &= e^{i\theta} \cdot \frac{z}{|z|} \\ &= e^{i\theta} \cdot \pi_i(z) \end{aligned}

SOGAT of untyped lambda calculus [ag-000V]

{-# OPTIONS --safe --without-K #-}
open import MLTT.Spartan hiding (id)
open import ag-0005

module ag-000V where

SOGAT of untyped lambda calculus.

record LC : 𝓤 ⁺  ̇ where
  field
    Λ : 𝓤 ̇
    lambda : (f : Λ → Λ) → Λ
    apply : Λ → Λ → Λ
    β : ∀ f x → apply (lambda f) x = f x
    η : ∀ f → lambda (λ x → apply f x) = f

  _$_ : Λ → Λ → Λ
  x $ y = apply x y
  infixl 30 _$_

  syntax lambda (λ x → t) = ƛ x ⇒ t

  zeroΛ : Λ
  zeroΛ = ƛ z ⇒ ƛ s ⇒ z

  succΛ : Λ → Λ
  succΛ n = ƛ z ⇒ ƛ s ⇒ (s $ n $ (n $ z $ s))

  id : Λ
  id = ƛ x ⇒ x

  recΛ : Λ → (Λ → Λ → Λ) → Λ → Λ
  recΛ zr su n = n $ zr $ (ƛ k ⇒ ƛ sk ⇒ su k sk)

  recΛβ-zero : ∀ {zr su} → recΛ zr su zeroΛ = zr
  recΛβ-zero {zr} {su} =
    (ap (_$ (ƛ k ⇒ ƛ sk ⇒ su k sk)) (β (λ z → ƛ s ⇒ z) zr))
    ∙ (β (λ _ → zr) (ƛ k ⇒ ƛ sk ⇒ su k sk))

  recΛβ-succ : ∀ {zr su n} → recΛ zr su (succΛ n) = su n (recΛ zr su n)
  recΛβ-succ {zr} {su} {n} =
    (ap (_$ (ƛ k ⇒ ƛ sk ⇒ su k sk)) (β (λ z → ƛ s ⇒ (s $ n $ (n $ z $ s))) zr))
    ∙ (β (λ s → s $ n $ (n $ zr $ s)) (ƛ k ⇒ ƛ sk ⇒ su k sk))
    ∙ (ap (_$ (n $ zr $ (ƛ k ⇒ ƛ sk ⇒ su k sk))) (β (λ k → ƛ sk ⇒ su k sk) n))
    ∙ (β (λ sk → su n sk) (n $ zr $ (ƛ k ⇒ ƛ sk ⇒ su k sk)))

  embed-nat : ℕ → Λ
  embed-nat 0 = zeroΛ
  embed-nat (succ x) = succΛ (embed-nat x)

Lambda calculus (Second-order algebraic theories) universe polymorphic extended.

代數幾何:視 base ring 的元素為函數 [WYCP]

在 manifold MM 上我們可以定義 C∞(M)C^\infty(M)。在代數幾何裡面我們想要抽象並仿造這個結構,所以若 x∈Spec⁡Ax \in \operatorname{Spec} A 為一點(亦同時是 prime ideal),residue field at point xx 定義為 the field of fractions of the quotient ring

κ(x):=Frac(A/x)\kappa(x) := \text{Frac}(A / x)

那麼,每個 f∈Af \in A 取 f(x)∈κ(x)f(x) \in \kappa(x) 將使 ff 可以被視為一個「函數」,不過在不同點 ff 的 codomain 都不同。構造即取 f↦[f]A/xf \mapsto [f]_{A / x} 再取 x↦x/1x \mapsto x/1。

Status of the smooth rectangular Peg problem [VEYQ]

https://www.math.columbia.edu/~ums/Peg%20problem%20-%20slides.pdf
  1. Emch (1913) solved the problem for smooth convex curves. (Proof uses configuration spaces and homology.)
  2. Schnirelman (1929) solved it for any smooth Jordan curve.

Theorem Vaughan (1977) [local-0]

Every continuous Jordan curve contains four points forming the vertices of some rectangle. This is what 3b1b did, see video here.

Theorem Greene-Lobb (2020) [local-1]

Given a smooth Jordan curve γ\gamma and a rectangle RR in the plane, then γ\gamma contain four points forming the vertices of a rectangle similar to R.

Theorem Barr's theorem [KGRZ]

If E\mathcal{E} is a Grothendieck topos, then there is a surjective geometric morphism

F→E\mathcal{F} \to \mathcal{E}

where F\mathcal{F} satisfies the axiom of choice.

presheaves exponential 同構的推導 [21ME]

Topos Theory 的 1.12

令 X,Y,Z∈C^X, Y, Z \in \widehat{C} 為 category CC 的 presheaves,那麼

hom(Z,YX)≅hom(Z×X,Y)\text{hom}(Z, Y^X) \cong \text{hom}(Z \times X, Y)

Proof [local-0]

hom(Z,YX)≅hom(colim(hα),YX)(Z 可以表示為 representables 的 colimit)≅lim⁡hom(hα,YX)(contravariant)≅lim⁡hom(hα×X,Y)(YX的定義)≅hom(colim(hα×X),Y)(contravariant)≅hom(colim(hα)×X,Y)((−)×X preserves colimits in Sets, hence in C^)≅hom(Z×X,Y)\begin{aligned} \text{hom}(Z, Y^X) &\cong \text{hom}(\text{colim}(h_\alpha), Y^X) \quad (Z \text{ 可以表示為 representables 的 colimit}) \\ &\cong \lim \text{hom}(h_\alpha, Y^X) \quad (\text{contravariant}) \\ &\cong \lim \text{hom}(h_\alpha \times X, Y) \quad (Y^X \text{的定義}) \\ &\cong \text{hom}(\text{colim}(h_\alpha \times X), Y) \quad (\text{contravariant}) \\ &\cong \text{hom}(\text{colim}(h_\alpha) \times X, Y) \quad ((-)\times X \text{ preserves colimits in } \text{Sets} \text{, hence in } \widehat{C}) \\ &\cong \text{hom}(Z \times X, Y) \end{aligned}
  1. ZZ 用 Presheaves are colimits of representables 改寫
  2. Contravariant 用到的是 Hom-functors preserve limits

Proposition Hom-functors preserve limits [math-TGEI]

This is a very useful property of hom-functor.

Let CC be a category, then its hom-functor can be wrote as

HomC:Cop×C→Sets\text{Hom}_C : C^{op} \times C \to Sets

If the limit lim←⁡Xi\varprojlim X_i exists in CC, then for all Y∈Ob(C)Y \in \text{Ob}(C) there is a natural isomorphism

HomC(Y,lim←⁡iXi)≅lim←⁡i(HomC(Y,Xi))\text{Hom}_C(Y, \varprojlim_i X_i) \cong \varprojlim_i (\text{Hom}_C(Y, X_i))

If the colimit lim→⁡iXi\varinjlim_i X_i exists in CC, then for all Y∈Ob(C)Y \in \text{Ob}(C) there is a natural isomorphism

HomC(lim→⁡iXi,Y)≅lim←⁡i(HomC(Xi,Y))\text{Hom}_C(\varinjlim_i X_i, Y) \cong \varprojlim_i (\text{Hom}_C(X_i, Y))

See nLab for more details.

Definition Holonomy [math-L2W1]

Let E→ME \to M be a vector bundle with a connection ∇\nabla. The holonomy of ∇\nabla along a closed path γ\gamma is the parallel transport along γ\gamma.

Definition Parallel transport [math-XU4I]

Let E→ME \to M be a vector bundle with a connection ∇\nabla. For any smooth path γ:[0,1]→M\gamma : [0,1] \to M we will define a linear isomorphism Tγ:Eγ(0)→Eγ(1)T_\gamma : E_{\gamma(0)} \to E_{\gamma(1)} called the parallel transport along γ\gamma.

The construction [local-0]

More precisely, we construct a family of linear isomorphisms:

Tt:Eγ(0)→Eγ(t)T_t : E_{\gamma(0)} \to E_{\gamma(t)}

for all t∈[0,1]t \in [0, 1]. Consider arbitrary t∈[0,1]t \in [0, 1], let u0∈Eγ(0)u_0 \in E_{\gamma(0)} be a vector, then define ut:=Tt(u0)u_t := T_t(u_0), we know ut∈Eγ(t)u_t \in E_{\gamma(t)}. What we are searching is a "constant" path, in the sense that derivative is 00, hence we want

∇ddtut=0,where ddt=γ˙\nabla_{\frac{d}{dt}} u_t = 0, \quad \text{where } \frac{d}{dt} = \dot{\gamma}

so this suggests a way of defining TtT_t: For any u0∈Eγ(0)u_0 \in E_{\gamma(0)} and any t∈[0,1]t \in [0,1], define Tt(u0)T_t(u_0) as the value at tt of the solution of the initial value problem:

{∇ddtu(t)=0u(0)=u0\begin{cases} \nabla_{\frac{d}{dt}} u(t) = 0 \\ u(0) = u_0 \end{cases}

And this is a system of linear ordinary differential equations in disguise.

Definition Covariant Derivative (Linear Connection) [math-HCIJ]

Let E→ME \to M be a vector bundle. A covariant derivative on EE is a K\mathbb{K}-linear map

∇:C∞(E)→C∞(T∗M⊗E)\nabla : C^\infty(E) \to C^\infty(T^*M \otimes E)

such that, for all f∈C∞(M)f \in C^\infty(M) and all u∈C∞(E)u \in C^\infty(E), we have

∇(fu)=df⊗u+f∇u\nabla(fu) = df \otimes u + f \nabla u

where C∞(E)C^\infty(E) denotes the space of smooth sections of EE over MM.

Remind that

Hom(T∗M,E)≃C∞(T∗M⊗E)\text{Hom}(T^*M, E) \simeq C^\infty(T^*M \otimes E)

Therefore, ∇u\nabla u has a more traditional view

∇u:Vect(M)→C∞(E)X↦∇Xu\begin{aligned} &\nabla u : \text{Vect}(M) \to C^\infty(E) \\ &X \mapsto \nabla_X u \end{aligned}

When a map is an equivalence? [RNNM]

For a given function f:X→Yf : X \to Y, the following are two correct definitions of f is an equivalence.

Defintion Voevodsky's [ag-000T]

ff is an equivalence if its fibers are contractible (or singletons): For every y:Yy : Y, the type

{-# OPTIONS --safe --without-K #-}
module ag-000T where

open import MLTT.Spartan hiding (fiber)
fiber : {X : 𝓤 ̇ } {Y : 𝓥 ̇ } → (X → Y) → Y → 𝓤 ⊔ 𝓥 ̇
fiber f y = Σ x ꞉ domain f , f x = y

has the property that there is a distinguished element σ0:fiber f y\sigma_0 : \text{fiber f } y such that σ=σ0\sigma = \sigma_0 for all σ:fiber f y\sigma : \text{fiber f } y.

is-equiv : {X : 𝓤 ̇ } {Y : 𝓥 ̇ } → (f : X → Y) → 𝓤 ⊔ 𝓥 ̇
is-equiv f = ∀ (y : codomain f) → Σ σ₀ ꞉ fiber f y , ∀ (σ : fiber f y) → σ = σ₀

Defintion Joyal's [ag-000U]

Of course, the second post in thread is more important, there is a wrong definition, and Escardo shows why it's wrong.

什麼是量子幾何 [FWA9]

Why (∑i=1ni)2=∑i=1ni3(\sum_{i=1}^n{i})^2 = \sum_{i=1}^n{i^3}, A Four Dimensional Proof [E963]

JIT: Write XOR Execute policy [UIC7]

所謂的 W^X (Write XOR Execute) policy 是指不要讓記憶體同時是 PROT_WRITE 跟 PROT_EXEC,所以正確的配置方式是(參見 mmap)

  1. 先設定成 PROT_READ | PROT_WRITE
  2. 等寫完指令再改成 PROT_READ | PROT_EXEC(像是用 mprotect https://man7.org/linux/man-pages/man2/mprotect.2.html)

然後才能真的執行這段程式。

Corollary About Boolean ring [math-HS0H]

Let AA be a Boolean ring (see nLab) and X=Spec⁡AX = \operatorname{Spec} A.

  1. Every prime ideal of AA is a maximal ideal. Details
  2. κ(x):=Frac(A/x)=F2\kappa(x) := \text{Frac}(A/x) = \mathbb{F}_2 for all x∈Xx \in X. Details
  3. AA has characteristic 2. Because for all x∈Ax \in A we have x+x=(x+x)∗(x+x)=x∗x+x∗x+x∗x+x∗x=x+x+x+xx + x = (x + x) * (x + x) = x*x + x*x + x*x + x*x = x+x+x+x deduces that 2x=x+x=02x = x + x = 0. Notice that, this also say x=−xx = -x for all x∈Ax \in A.
  4. For each φ:A→F2\varphi : A \to \mathbb{F}_2 we can define φ↦ker⁡φ\varphi \mapsto \operatorname{ker} \varphi these maps form a bijection between hom-set Hom(A,F2)\text{Hom}(A, \mathbb{F}_2) and Spec⁡A\operatorname{Spec} A. Details

Tool Unsure Calculator [VIPY]

Theorem The field of fractions is a torsion-free module [math-3E35]

Let RR be an integral domain, and K:=Frac(R)K := \text{Frac}(R) is the field of fractions of RR. Then KK is a torsion-free RR-module (see The Stacks project tag/0549).

Proof [local-0]

We want to show that the only torsion element of KK is 00. Every element of KK has the form as\frac{a}{s} where s≠0s \ne 0, now suppose as\frac{a}{s} is a torsion. Then there exists a r≠0∈Rr \ne 0 \in R such that

ras=ras=0∈Kr \frac{a}{s} = \frac{ra}{s} = 0 \in K

which leads

ra=0∈Rra = 0 \in R

in an integral domain, this leads r=0r = 0 or a=0a = 0, but r≠0r \ne 0 by definition, hence a=0a = 0. Which means as\frac{a}{s} is 0∈K0 \in K, be torsion is be zero in KK, KK is a torsion-free RR-module.

Theorem Premanifold 為 Hausdorff 的等價條件 [math-T4B3]

令 MM 為一個 premanifold(field 為 R\mathbb{R} 或是 C\mathbb{C})。則以下條件等價:

  1. MM 為 Hausdorff 空間
  2. 對於 MM 中任意相異兩點 x,y∈Mx, y \in M(x≠yx \ne y),存在開集 UU 使得 x,y∈Ux, y \in U,且在 OM(U)\mathcal{O}_M(U) 中,存在函數 f∈OM(U)f \in \mathcal{O}_M(U) 使得 f(x)≠f(y)f(x) \ne f(y)

Proof [local-0]

(2) ⇒ (1):設 x,y∈Mx, y \in M 為相異兩點。由條件 (2),存在開集 UU 使得 x,y∈Ux, y \in U,且存在 f∈OM(U)f \in \mathcal{O}_M(U) 使得 f(x)≠f(y)f(x) \ne f(y)。

令 d=∣f(y)−f(x)∣>0d = |f(y) - f(x)| > 0。因為 ff 為 smooth 函數,存在 xx 的開鄰域 Vx⊆UV_x \subseteq U 使所有 z∈Vxz \in V_x,有 ∣f(z)−f(x)∣<d2|f(z) - f(x)| < \frac{d}{2}。

同理,存在 yy 的開鄰域 Vy⊆UV_y \subseteq U 使得對所有 w∈Vyw \in V_y,有 ∣f(w)−f(y)∣<d2|f(w) - f(y)| < \frac{d}{2}。於是我們知道 Vx∩Vy=∅V_x \cap V_y = \emptyset,因為如果存在 p∈Vx∩Vyp \in V_x \cap V_y,則:

d=∣f(y)−f(x)∣≤∣f(y)−f(p)∣+∣f(p)−f(x)∣<d2+d2=dd = |f(y) - f(x)| \le |f(y) - f(p)| + |f(p) - f(x)| < \frac{d}{2} + \frac{d}{2} = d

為矛盾,也就是說不存在這種 pp。因此 MM 為 Hausdorff 空間。

(1) ⇒ (2):設 x,y∈Mx, y \in M 為相異兩點。因為 MM 為 Hausdorff 空間,存在不相交的開鄰域 U∋xU \ni x 和 V∋yV \ni y 使得 U∩V=∅U \cap V = \emptyset。

因為 MM 為 premanifold,存在 open cover (Uk)k∈K(U_k)_{k \in K} 使得每個 UkU_k 與某個 local ringed space 同構。因此存在 UiU_i 和 UjU_j 使得 x∈Uix \in U_i 且 y∈Ujy \in U_j。

考慮開集 Ui∩UU_i \cap U 和 Uj∩VU_j \cap V。因為 U∩V=∅U \cap V = \emptyset,我們有 (Ui∩U)∩(Uj∩V)=∅(U_i \cap U) \cap (U_j \cap V) = \emptyset。

取 xx 的開鄰域 Vx⊆Ui∩UV_x \subseteq U_i \cap U 及函數 f∈OM(Vx)f \in \mathcal{O}_M(V_x) 使得 f(x)=0f(x) = 0(此函數對應於 stalk OM,x\mathcal{O}_{M,x} 的 maximal ideal 中的元素)。同理,取 yy 的開鄰域 Vy⊆Uj∩VV_y \subseteq U_j \cap V 及函數 g∈OM(Vy)g \in \mathcal{O}_M(V_y) 使得 g(y)≠0g(y) \ne 0(對應於 stalk OM,y\mathcal{O}_{M,y} 中不在 maximal ideal 的元素)。

令 W=Vx∪VyW = V_x \cup V_y,則 WW 為開集且 x,y∈Wx, y \in W。因 VxV_x 與 VyV_y 不相交,可定義函數 h∈OM(W)h \in \mathcal{O}_M(W),在 VxV_x 上取 h:=fh := f,在 VyV_y 上取 h:=gh := g。於是 h(x)=f(x)=0h(x) = f(x) = 0 而 h(y)=g(y)≠0h(y) = g(y) \ne 0,WW 與 hh 滿足條件 (2)。

NOTE: Explicit Weakening [ag-000S]

在 Substitution Without Copy and Paste 結尾也有提過這篇,就來稍微看一下。

Explicit Weakening
{-# OPTIONS --rewriting --no-level-universe #-}
module ag-000S where

open import MLTT.Spartan hiding (Type; id)
{-# BUILTIN REWRITE _=_ #-}

cong₂ : ∀ {A B C : 𝓤 ̇ } (f : A → B → C) {x y u v} → x = y → u = v → f x u = f y v
cong₂ f refl refl = refl
data Type : 𝓤₀ ̇ where
  base : Type
  _⇒_ : Type → Type → Type
infixr 7 _⇒_

variable
  A B C : Type

data Con : 𝓤₀ ̇ where
  ∅ : Con
  _▷_ : Con → Type → Con
infixl 5 _▷_

variable
  Γ Δ Θ Ξ : Con

data _⊢_ : Con → Type → 𝓤₀ ̇ where
  • : Γ ▷ A ⊢ A
  _↑ : (M : Γ ⊢ B)
      ------------
      → Γ ▷ A ⊢ B
  ƛ_ : (N : Γ ▷ A ⊢ B) → Γ ⊢ A ⇒ B
  _·_ : (L : Γ ⊢ A ⇒ B) (M : Γ ⊢ A)
      -----------------------------
      → Γ ⊢ B
infix 5 ƛ_
infix 4 _⊢_
infixl 7 _·_

variable
  L M N P Q : Γ ⊢ A

data _⊨_ : Con → Con → 𝓤₀ ̇ where
  id : Δ ⊨ Δ
  _↑ : (σ : Γ ⊨ Δ) → Γ ▷ A ⊨ Δ
  _▷_ : (σ : Γ ⊨ Δ)
        (M : Γ ⊢ A)
        ------------
        → Γ ⊨ Δ ▷ A
infix 4  _⊨_
infix 8 _↑

variable
  σ τ υ : Γ ⊨ Δ

pattern △ = _ ▷ _

Instantiation

_[_] : (M : Δ ⊢ A) (σ : Γ ⊨ Δ) → Γ ⊢ A
M [ id ] = M
M [ σ ↑ ] = (M [ σ ]) ↑
• [ σ ▷ P ] = P
(M ↑) [ σ ▷ P ] = M [ σ ]
(ƛ M) [ σ @ △ ] = ƛ (M [ σ ↑ ▷ • ])
(L · M) [ σ @ △ ] = L [ σ ] · (M [ σ ])

_⨟_ : (σ : Θ ⊨ Δ) (τ : Γ ⊨ Θ) → Γ ⊨ Δ
σ ⨟ id = σ
σ ⨟ (τ ↑) = (σ ⨟ τ) ↑
id ⨟ τ @ △ = τ
(σ ↑) ⨟ (τ ▷ Q) = σ ⨟ τ
(σ ▷ P) ⨟ τ @ △ = (σ ⨟ τ) ▷ (P [ τ ])
infixl 5 _⨟_

[][] : (M : Δ ⊢ A)
       (σ : Θ ⊨ Δ)
       (τ : Γ ⊨ Θ)
       → M [ σ ] [ τ ] = M [ σ ⨟ τ ]
[][] M σ id = refl
[][] M σ (τ ↑) = ap _↑ ([][] M σ τ)
[][] M id (τ ▷ M₁) = refl
[][] M (σ ↑) (τ ▷ M₁) = [][] M σ τ
[][] • (σ ▷ P) τ@△ = refl
[][] (M ↑) (σ ▷ P) τ@△ = [][] M σ τ
[][] (ƛ N) σ@△ τ@△ = ap ƛ_ ([][] N (σ ↑ ▷ •) (τ ↑ ▷ •))
[][] (L · M) σ@△ τ@△ = cong₂ _·_ ([][] L σ τ) ([][] M σ τ)
{-# REWRITE [][] #-}

Left identity

left-id : (τ : Γ ⊨ Δ) → id ⨟ τ = τ
left-id id = refl
left-id (τ ↑) = ap _↑ (left-id τ)
left-id (τ ▷ Q) = refl
{-# REWRITE left-id #-}

Associative

assoc : (σ : Θ ⊨ Δ)
        (τ : Ξ ⊨ Θ)
        (υ : Γ ⊨ Ξ)
        → (σ ⨟ τ) ⨟ υ = σ ⨟ (τ ⨟ υ)
assoc σ τ id = refl
assoc σ τ (υ ↑) = ap _↑ (assoc σ τ υ)
assoc σ id (υ ▷ M) = refl
assoc σ (τ ↑) (υ ▷ M) = assoc σ τ υ
assoc id (τ ▷ M₁) (υ ▷ M) = refl
assoc (σ ↑) (τ ▷ M₁) (υ ▷ M) = assoc σ τ (υ ▷ M)
assoc (σ ▷ M₂) (τ ▷ M₁) (υ ▷ M) = cong₂ _▷_ (assoc σ (τ ▷ M₁) (υ ▷ M)) refl
{-# REWRITE assoc #-}

下面的案例是本來在 PLFA 中不好做出來,但用這套就很簡單的問題

_[_]₀ : (N : Γ ▷ A ⊢ B)
        (M : Γ ⊢ A)
        ------------
        → Γ ⊢ B
N [ M ]₀ = N [ id ▷ M ]

_[_]₁ : (N : Γ ▷ A ▷ B ⊢ C)
        (M : Γ ⊢ A)
        ------------
        → Γ ▷ B ⊢ C
N [ M ]₁ = N [ (id ▷ M) ↑ ▷ • ]

double-subst : N [ M ]₁ [ L ]₀ = N [ L ↑ ]₀ [ M ]₀
double-subst = refl
commute-subst : N [ M ]₀ [ L ]₀ = N [ L ]₁ [ M [ L ]₀ ]₀
commute-subst = refl

最後也有談到缺點是 identifying when terms are equivalent may become more difficult,但我沒有試這是什麼清況。

NOTE: Substitution Without Copy and Paste [tt-IHCF]

Substitution Without Copy and Paste

The copy-and-paste approach [ag-000M]

{-# OPTIONS --safe --without-K #-}
module ag-000M where

open import MLTT.Spartan

類型跟 context

data Ty : 𝓤₀ ̇ where
  base : Ty
  _⇒_ : Ty → Ty → Ty
infixl 50 _⇒_

data Con : 𝓤₀ ̇ where
  ◇ : Con
  _▷_ : Con → Ty → Con
infixl 40 _▷_
  1. 等一下用的變數
  2. de Bruijn variables
  3. terms
variable
  Γ Δ Ξ : Con
  A B C : Ty

data _∋_ : Con → Ty → 𝓤₀ ̇ where
  here : Γ ▷ A ∋ A
  there : Γ ∋ A → (B : Ty)
        ------------------
        → Γ ▷ B ∋ A
infixl 30 _∋_

data _⊢_ : Con → Ty → 𝓤₀ ̇ where
  -- embeds variables in λ-terms
  `_ : Γ ∋ A → Γ ⊢ A
  -- application t · u
  _·_ : Γ ⊢ A ⇒ B → Γ ⊢ A → Γ ⊢ B
  ƛ_ : Γ ▷ A ⊢ B → Γ ⊢ A ⇒ B
infixl 20 _⊢_
infixl 60 `_
infixl 50 _·_
infixl 40 ƛ_

substitution 定義成

data _⊩_ : Con → Con → 𝓤₀ ̇ where
  ε : Γ ⊩ ◇
  _,_ : Γ ⊩ Δ → Γ ⊢ A → Γ ⊩ Δ ▷ A

現在要定義 substitution 在 terms 跟 variables 上的作用:

_v[_] : Δ ∋ A → Γ ⊩ Δ → Γ ⊢ A
here v[ ts , t ] = t
there i B v[ ts , t ] = i v[ ts ]

data _⊩v_ : Con → Con → 𝓤₀ ̇ where
  ε : Γ ⊩v ◇
  _,_ : Γ ⊩v Δ → Γ ∋ A → Γ ⊩v Δ ▷ A

_v[_]v : Γ ∋ A → Δ ⊩v Γ → Δ ∋ A
here v[ is , i ]v = i
there i B v[ is , j ]v = i v[ is ]v

_⁺v_ : Γ ⊩v Δ → (A : Ty) → Γ ▷ A ⊩v Δ
ε ⁺v A = ε
(is , i) ⁺v A = (is ⁺v A) , there i A

_↑v_ : Γ ⊩v Δ → (A : Ty) → Γ ▷ A ⊩v Δ ▷ A
is ↑v A = (is ⁺v A) , here

_[_]v : Γ ⊢ A → Δ ⊩v Γ → Δ ⊢ A
(` i) [ is ]v = ` (i v[ is ]v)
(t · u) [ is ]v = (t [ is ]v) · (u [ is ]v)
(ƛ t) [ is ]v = ƛ (t [ is ↑v _ ]v)

idv : Γ ⊩v Γ
idv {Γ = ◇} = ε
idv {Γ = Γ ▷ A} = idv ↑v A

為了定義下面的 suc-tm,需要定義上面大量的類似結構 Γ ⊩v Δ

_⁺_ : Γ ⊩ Δ → (A : Ty) → Γ ▷ A ⊩ Δ
ε ⁺ A = ε
(ts , t) ⁺ A = (ts ⁺ A) , suc-tm t A
  where
  suc-tm : Γ ⊢ B → (A : Ty) → Γ ▷ A ⊢ B
  suc-tm t A = t [ idv ⁺v A ]v

_↑_ : Γ ⊩ Δ → (A : Ty) → Γ ▷ A ⊩ Δ ▷ A
ts ↑ A = ts ⁺ A , ` here

_[_] : Γ ⊢ A → Δ ⊩ Γ → Δ ⊢ A
(` i) [ ts ] = i v[ ts ]
(t · u) [ ts ] = (t [ ts ]) · (u [ ts ])
(ƛ t) [ ts ] = ƛ (t [ ts ↑ _ ])

所以為了避免這些重複,方法要改成:

Substituion without copy and paste 的提議 [ag-000N]

{-# OPTIONS --safe --without-K #-}
module ag-000N where

open import MLTT.Spartan hiding (_⊔_; id)
open import ag-000M using (Ty; _⇒_; Con; ◇; _▷_)

variable
  Γ Δ Ξ : Con
  A B C : Ty

引入 Sort 區分 variable 跟 term 的情況

mutual
  data Sort : 𝓤₀ ̇ where
    V : Sort
    T>V : (s : Sort) → IsV s → Sort
  data IsV : Sort → 𝓤₀ ̇ where
    isV : IsV V

pattern T = T>V V isV

variable
  q r s : Sort

這樣就可以把 variables 跟 terms 定義到一起,用 s 區分 Γ ⊢[ s ] A 是 variable 還是 term

data _⊢[_]_ : Con → Sort → Ty → 𝓤₀ ̇ where
  here : Γ ▷ A ⊢[ V ] A
  there : Γ ⊢[ V ] A → (B : Ty) → Γ ▷ B ⊢[ V ] A
  `_ : Γ ⊢[ V ] A → Γ ⊢[ T ] A
  _·_ : Γ ⊢[ T ] A ⇒ B → Γ ⊢[ T ] A → Γ ⊢[ T ] B
  ƛ_ : Γ ▷ A ⊢[ T ] B → Γ ⊢[ T ] A ⇒ B

variable
  x y z : Γ ⊢[ q ] A

substitution 現在定義成

data _⊩[_]_ : Con → Sort → Con → 𝓤₀ ̇ where
  ε : Γ ⊩[ q ] ◇
  _,_ : Γ ⊩[ q ] Δ → Γ ⊢[ q ] A → Γ ⊩[ q ] Δ ▷ A

variable
  xs ys zs : Δ ⊩[ q ] Γ

現在需要考慮 sort 之間的關係,這些 lemma 有助於簡化後面的證明

data _⊑_ : Sort → Sort → Set where
  rfl : s ⊑ s
  v⊑t : V ⊑ T

_⊔_ : Sort → Sort → Sort
V ⊔ r = r
T ⊔ r = T

一些輔助用的 REWRITE [ag-000O]

{-# OPTIONS --without-K --rewriting #-}
module ag-000O where

open import MLTT.Spartan hiding (_⊔_; id)

open import ag-000M using (Ty; _⇒_; Con; ◇; _▷_)
open import ag-000N

{-# BUILTIN REWRITE _=_ #-}

這邊的定義很繁瑣但只是單純攤開 V、T 就能證明,並不是很重要。重點在最後用 REWRITE 避免後續需要證明一些麻煩的情況

⊑t : s ⊑ T
⊑t {V} = v⊑t
⊑t {T} = rfl
v⊑ : V ⊑ s
v⊑ {V} = rfl
v⊑ {T} = v⊑t
⊑q⊔ : q ⊑ (q ⊔ r)
⊑q⊔ {V}{V} = rfl
⊑q⊔ {V}{T} = v⊑t
⊑q⊔ {T}{V} = rfl
⊑q⊔ {T}{T} = rfl
⊔⊔ : q ⊔ (r ⊔ s) = (q ⊔ r) ⊔ s
⊔⊔ {V}{V}{V} = refl
⊔⊔ {V}{V}{T} = refl
⊔⊔ {V}{T}{V} = refl
⊔⊔ {V}{T}{T} = refl
⊔⊔ {T}{V}{V} = refl
⊔⊔ {T}{V}{T} = refl
⊔⊔ {T}{T}{V} = refl
⊔⊔ {T}{T}{T} = refl
⊔v : q ⊔ V = q
⊔v {V} = refl
⊔v {T} = refl
⊔t : q ⊔ T = T
⊔t {V} = refl
⊔t {T} = refl
⊑⊔r : r ⊑ (q ⊔ r)
⊑⊔r {V}{V} = rfl
⊑⊔r {V}{T} = v⊑t
⊑⊔r {T}{V} = rfl
⊑⊔r {T}{T} = rfl

⊔-self : q ⊔ q = q
⊔-self {V} = refl
⊔-self {T} = refl

{-# REWRITE ⊔⊔ ⊔v ⊔t ⊔-self #-}

substitution 的組合 [ag-000P]

{-# OPTIONS --without-K --rewriting #-}
module ag-000P where

open import MLTT.Spartan hiding (_⊔_; id)

open import ag-000M using (Ty; _⇒_; Con; ◇; _▷_)
open import ag-000N
open import ag-000O

這裡的目的是定義 ⊑ relation 對 term 的影響,以及定義 substitution 的結合 ◦

tm⊑ : q ⊑ s → Γ ⊢[ q ] A → Γ ⊢[ s ] A
tm⊑ rfl x = x
tm⊑ v⊑t i = ` i

here[_] : (q : Sort) → Γ ▷ A ⊢[ q ] A
here[ V ] = here
here[ T ] = ` here

mutual
  _[_] : Γ ⊢[ q ] A → Δ ⊩[ r ] Γ → Δ ⊢[ q ⊔ r ] A
  here [ xs , x ] = x
  there i _ [ xs , x ] = i [ xs ]
  (` i) [ xs ] = tm⊑ ⊑t (i [ xs ])
  (t · u) [ xs ] = (t [ xs ]) · (u [ xs ])
  (ƛ t) [ xs ] = ƛ (t [ xs ↑ _ ])

  id-poly : (q : Sort) → Γ ⊩[ q ] Γ
  id-poly {Γ = ◇} q = ε
  id-poly {Γ = Γ ▷ A} q = id-poly q ↑ A
  id : Γ ⊩[ V ] Γ
  id = id-poly V
  {-# INLINE id #-}

  there[_] : (q : Sort) → Γ ⊢[ q ] B → (A : Ty) → Γ ▷ A ⊢[ q ] B
  there[ V ] i A = there i A
  there[ T ] t A = t [ id ⁺ A ]

  _⁺_ : Γ ⊩[ q ] Δ → (A : Ty) → Γ ▷ A ⊩[ q ] Δ
  ε ⁺ A = ε
  (ts , t) ⁺ A = (ts ⁺ A) , there[ _ ] t A

  _↑_ : Γ ⊩[ q ] Δ → (A : Ty) → Γ ▷ A ⊩[ q ] Δ ▷ A
  ts ↑ A = ts ⁺ A , here[ _ ]
infixl 70 _⁺_

_◦_ : Γ ⊩[ q ] Ξ → Δ ⊩[ r ] Γ → Δ ⊩[ q ⊔ r ] Ξ
ε ◦ ys = ε
(xs , x) ◦ ys = (xs ◦ ys) , x [ ys ]

Proposition The right identity law [ag-000Q]

{-# OPTIONS --without-K --rewriting #-}
module ag-000Q where

open import MLTT.Spartan hiding (_⊔_; id)

open import ag-000M using (Ty; _⇒_; Con; ◇; _▷_)
open import ag-000N
open import ag-000O
open import ag-000P
⁺-nat[]v : (i : Γ ⊢[ V ] A) → (xs : Δ ⊩[ q ] Γ) → i [ xs ⁺ B ] = there[ q ] (i [ xs ]) B
⁺-nat[]v here (xs , x) = refl
⁺-nat[]v (there j _) (xs , x) = ⁺-nat[]v j xs

[id] : x [ id ] = x
[id] {x = here} = refl
[id] {x = there i B} =
  (i [ id ⁺ B ]) =⟨ ⁺-nat[]v {q = V} i id ⟩
  there (i [ id ]) B =⟨ ap (λ - → there - B) [id] ⟩
  there i B ∎
[id] {x = ` i} = ap `_ [id]
[id] {x = t · u} =
  ((t [ id ]) · (u [ id ])) =⟨ ap (t [ id ] ·_) [id] ⟩
  ((t [ id ]) · u) =⟨ ap (_· u) [id] ⟩
  (t · u) ∎
[id] {x = ƛ t} = ap ƛ_ [id]

◦id : xs ◦ id = xs
◦id {xs = ε} = refl
◦id {xs = xs , x} =
  (xs ◦ id) , (x [ id ]) =⟨ ap ((xs ◦ id) ,_) [id] ⟩
  (xs ◦ id) , x          =⟨ ap (_, x) ◦id ⟩
  xs , x ∎

Proposition Left identity law 與 Associative law [ag-000R]

{-# OPTIONS --allow-unsolved-metas --without-K --rewriting #-}
module ag-000R where

open import MLTT.Spartan hiding (_⊔_; id)

open import ag-000M using (Ty; _⇒_; Con; ◇; _▷_)
open import ag-000N
open import ag-000O
open import ag-000P
open import ag-000Q

這兩個是 mutual 定義的,而且有一些 goals 我也看不出怎麼解了,暫時就先這樣 xd

tm[] : tm⊑ ⊑t (x [ xs ]) = (tm⊑ ⊑t x) [ xs ]
tm[] {x = here} = refl
tm[] {x = there x B} = refl
tm[] {x = ` x} = tm[] {x = x}
tm[] {x = x · x₁} = refl
tm[] {x = ƛ x} = refl

zero[] : {q : Sort} {r : Sort} {Γ : Con} {Δ : Con} {A : Ty} {xs : Δ ⊩[ r ] Γ} {x : Δ ⊢[ r ] A} → here[ q ] [ xs , x ] = tm⊑ (⊑⊔r {q = q}) x
zero[] {q = V} {r = V} = refl
zero[] {q = V} {r = T} = refl
zero[] {q = T} {r = V} = refl
zero[] {q = T} {r = T} = refl

tm⊑zero : (q⊑r : q ⊑ r) → here[ r ] = tm⊑ q⊑r here[ q ]
tm⊑zero rfl = refl
tm⊑zero v⊑t = refl

{-# TERMINATING #-}
mutual
  suc[] : (there[ s ] x _) [ ys , y ] = x [ ys ]
  suc[] {s = V} = refl
  suc[] {s = T} {x = x} {ys = ys} {y = y} =
    there[ T ] x _ [ ys , y ] =⟨ refl ⟩
    x [ id ⁺ _ ] [ ys , y ]   =⟨ [◦] {x = x} ⁻¹ ⟩
    x [ (id ⁺ _) ◦ (ys , y) ] =⟨ ap (x [_]) ⁺◦ ⟩
    x [ id ◦ ys ] =⟨ ap (x [_]) id◦ ⟩
    x [ ys ] ∎

  ⁺◦ : xs ⁺ A ◦ (ys , x) = xs ◦ ys
  ⁺◦ {xs = ε} = refl
  ⁺◦ {xs = ts , t} {A = A} {ys = ys} {x = x} =
    ((ts ⁺ A) ◦ (ys , x)) , (there[ _ ] t A [ ys , x ]) =⟨ ap (((ts ⁺ A) ◦ (ys , x)) ,_) (suc[] {x = t}) ⟩
    ((ts ⁺ A) ◦ (ys , x)) , (t [ ys ]) =⟨ ap (_, (t [ ys ])) ⁺◦ ⟩
    (ts ◦ ys) , (t [ ys ]) ∎

  ⁺−nat◦ : {xs : Δ ⊩[ q ] Γ} → {ys : Ξ ⊩[ r ] Δ} → {A : Ty} →
            xs ◦ (ys ⁺ A) = (xs ◦ ys) ⁺ A
  ⁺−nat◦ {xs = ε} = refl
  ⁺−nat◦ {q = q} {r = r} {xs = xs , x} {ys = ys} {A = A} =
    (xs ◦ (ys ⁺ A)) , (x [ ys ⁺ A ]) =⟨ ap ((xs ◦ (ys ⁺ A)) ,_) (⁺-nat[] {q = q} {B = A} {x = x} {xs = ys}) ⟩
    (xs ◦ (ys ⁺ A)) , there[ _ ] (x [ ys ]) A =⟨ ap (_, there[ _ ] (x [ ys ]) A) ⁺−nat◦ ⟩
    ((xs ◦ ys) ⁺ A) , there[ _ ] (x [ ys ]) A ∎

  ⁺-nat[] : {q r : Sort} → {A B : Ty} → {x : Γ ⊢[ q ] A} → {xs : Δ ⊩[ r ] Γ} → x [ xs ⁺ B ] = there[ q ⊔ r ] (x [ xs ]) B
  ⁺-nat[] {q = V} {x = i} {xs = xs} = ⁺-nat[]v i xs
  ⁺-nat[] {q = T} {B = B} {x = x} {xs = xs} =
    x [ xs ⁺ B ]        =⟨ ap (λ - → x [ - ⁺ B ]) (◦id {xs = xs} ⁻¹) ⟩
    x [ (xs ◦ id) ⁺ B ] =⟨ ap (x [_]) (⁺−nat◦ ⁻¹) ⟩
    x [ xs ◦ (id ⁺ B) ] =⟨ [◦] {x = x} ⟩
    x [ xs ] [ id ⁺ B ] =⟨ refl ⟩
    there[ T ] (x [ xs ]) B ∎

  ↑◦ : {r s : Sort} → {xs : Δ ⊩[ r ] Ξ} → {ys : Γ ⊩[ s ] Δ} → {A : Ty} → (xs ◦ ys) ↑ A = (xs ↑ A) ◦ (ys ↑ A)
  ↑◦ {r = r} {s = s} {xs = xs} {ys = ys} {A = A} =
    (xs ◦ ys) ↑ A                                  =⟨ refl ⟩
    (xs ◦ ys) ⁺ A , here[ r ⊔ s ]                  =⟨ ap (λ - → - , here[ _ ]) (⁺−nat◦ ⁻¹) ⟩
    xs ◦ (ys ⁺ A) , here[ r ⊔ s ]                  =⟨ ap (xs ◦ (ys ⁺ A) ,_) (tm⊑zero (⊑⊔r {r = s} {q = r})) ⟩
    xs ◦ (ys ⁺ A) , tm⊑ (⊑⊔r {q = r}) here[ s ]    =⟨ ap (xs ◦ (ys ⁺ A) ,_) (zero[] {q = r} {r = s} {A = A} {xs = ys ⁺ A} {x = here[ s ]} ⁻¹) ⟩
    xs ◦ (ys ⁺ A) , (here[ r ] [ ys ↑ A ])         =⟨ ap (_, (here[ r ] [ ys ↑ A ])) (⁺◦ {xs = xs} {A = A} {ys = ys ⁺ A} {x = here[ s ]}  ⁻¹) ⟩
    ((xs ⁺ A) ◦ (ys ⁺ A , here[ s ])) , (here[ r ] [ ys ↑ A ]) =⟨ refl ⟩
    (xs ↑ A) ◦ (ys ↑ A)∎

  [◦] : x [ xs ◦ ys ] = x [ xs ] [ ys ]
  [◦] {x = here} {xs = xs , x} = refl
  [◦] {x = there i B} {xs = xs , x} = [◦] {x = i}
  [◦] {x = ` x} {xs = xs} {ys = ys} =
    tm⊑ ⊑t (x [ xs ◦ ys ])   =⟨ ap (λ - → tm⊑ ⊑t -) ([◦] {x = x}) ⟩
    tm⊑ ⊑t (x [ xs ] [ ys ]) =⟨ tm[] {x = x [ xs ]} ⟩
    (tm⊑ ⊑t (x [ xs ]) [ ys ]) ∎
  [◦] {x = t · u} {xs = xs} {ys = ys} =
    (t [ xs ◦ ys ]) · (u [ xs ◦ ys ])   =⟨ ap (_· (u [ xs ◦ ys ])) ([◦] {x = t}) ⟩
    (t [ xs ] [ ys ]) · (u [ xs ◦ ys ]) =⟨ ap ((t [ xs ] [ ys ]) ·_) ([◦] {x = u}) ⟩
    ((t [ xs ]) [ ys ]) · ((u [ xs ]) [ ys ]) ∎
  [◦] {x = ƛ t} {xs = xs} {ys = ys} = ap ƛ_
    (t [ (xs ◦ ys) ↑ _ ]       =⟨ ap (t [_]) (↑◦ {xs = xs}) ⟩
     t [ (xs ↑ _) ◦ (ys ↑ _) ] =⟨ [◦] {x = t} ⟩
     (t [ xs ↑ _ ]) [ ys ↑ _ ] ∎)

  id◦' : Sort → id ◦ xs = xs
  id◦' {xs = ε} q = refl
  id◦' {xs = xs , x} q = ap (_, x)
    (((id ⁺ _) ◦ (xs , x)) =⟨ ⁺◦ ⟩
     id ◦ xs               =⟨ id◦ ⟩
     xs ∎)

  id◦ : id ◦ xs = xs
  id◦ = id◦' V
  {-# INLINE id◦ #-}

到這裡已經證明了 contexts 與 substitutions 真的是一個範疇,而且這個範疇有 terminal object。第五節是把這邊的工作放進去 CwF-simple(constant presheaves 可以讓 CwF 適用於 simply typed calculus)裡,那個我暫時沒什麼興趣。

AI Is Slowly Destroying Your Brain [45VG]

Lie 群的意義 [VQ6V]

Lie 群是同時是群跟流形的物件,但這有什麼意義呢?

最簡單的案例是平面旋轉群 SO(2)\text{SO}(2),這是由所有平面上的旋轉組成的群,如果把所有的軌跡都畫到平面上,那這會構成一個 S1S^1。而我們知道局部的看 S1S^1 可以視為一個直線(切線),這就使得局部的來說,可以用切線近似的討論,這條線被稱為 Lie algebra。

所以我們成功地把曲線問題變成線性問題,更重要的是,這個方法更廣泛來說還是有用,比如很多物理學研究的對稱性可以用某個 Lie 群研究。

另外很有趣的是,Complex number 除了可以用代數的方式定義(see Algebra: Chapter 0, III, Proposition 4.6.):

C≃R[x]/⟨x2+1⟩\mathbb{C} \simeq \mathbb{R}[x] / \langle x^2 + 1 \rangle

在 Naive Lie Theory 中提到我們也能用旋轉矩陣來定義。

Lawvere-Tierney topology [math-MRL4]

Let E\mathcal{E} be a topos. A Lawvere-Tierney topology in E\mathcal{E} is a morphism j:Ω→Ωj : \Omega \to \Omega such that the following diagrams are commutative:

figure tex16966
figure tex16967
figure tex16968

A topology jj in a topos E\mathcal{E} gives rise to a new topos Shj(E)\text{Sh}_j(E) defined over E\mathcal{E}.

Tool x86-64 Playground [software-9JPJ]

Definition Weil algebra [math-T4B2]

A Weil algebra WW is an algebra over the rational numbers Q\mathbb{Q}, equipped with a morphism

π:W→Q\pi : W \to \mathbb{Q}

such that WW is a local ring with maximal ideal:

I:=π−1(0)I := \pi^{-1}(0)

with II a nilpotent ideal, and such that WW is a finite dimensional Q\mathbb{Q}-vector space.

The notion of Weil algebra makes sense in any topos E\mathcal{E} with a natural numbers object NN.

Proposition nilpotent maps form a prime ideal [math-6W2V]

Definition Coprimary [local-0]

Let AA be a Noetherian ring. A nonzero finitely generated AA-module MM is coprimary if for all a∈Aa \in A, the multiplication map (reuse element aa to denote it)

a:M→Mx↦axa : M \to M \\ x \mapsto ax

is injective or nilpotent.

If MM is coprimary, then the set

P:={a∈A∣a is nilpotent}P := \{ a \in A \mid a \text{ is nilpotent} \}

forms a prime ideal in AA.

Proof [local-1]

To check PP is a prime ideal, we want to check that if a∉Pa \not\in P and b∉Pb \not\in P then ab∉Pab \not\in P.

Because MM is coprimary, so such a,ba, b are injective, and

(ab)(x)=a(b(x))(ab)(x) = a(b(x))

the composition of injective maps is injective, hence ab∉Pab \not\in P. □

具體的 Sheaf 以及如何得到 ringed 與 locally ringed space 的定義 [UXEP]

Sheaf 的定義是

Definition Sheaf [math-PPAW]

我們說一個 presheaf F:Open(X)op→SetsF : \text{Open}(X)^{op} \to \text{Sets} 是 sheaf 是指:對所有 open sets UU in XX 與所有 UU 的 open covering (Ui)i∈I(U_i)_{i\in I},以下兩個條件成立

  1. Let s1,s2∈F(U)s_1, s_2 \in F(U) with s1∣Ui=s2∣Ui{s_1}_{\mid U_i} = {s_2}_{\mid U_i} for all ii. Then s1=s2s_1 = s_2.
  2. Given si∈F(Ui)s_i \in F(U_i) for all ii such that si∣Ui∩Uj=sj∣Ui∩Uj{s_i}_{\mid U_i \cap U_j} = {s_j}_{\mid U_i \cap U_j} for all i,ji,j. Then there exists an s∈F(U)s \in F(U) such that s∣Ui=sis_{\mid U_i} = s_i (注意,根據條件一這個 ss 是唯一的)

對我個人比較有意義的案例是

Example MM 上的可微分函數 C∞(M)C^\infty(M) [local-0]

假設 XX 是一個 CrC^r-manifold(0≤r≤∞0 \le r \le \infty),我們通常用 CXr(U)C^r_X(U) 表示集合

{f:U→R∣f is Cr-differentiable}\{ f : U \to \mathbb{R} \mid f \text{ is } C^r\text{-differentiable} \}

,而 UU 是 XX 的一個開集。這時候 CXrC^r_X 是一個 sheaf of R\mathbb{R}-algebras on XX

  1. 這本身也是一個 Ring
  2. 在這個案例中,stalk 也就變成經典的 function germs(用重合定義的函數局部等價類)。

所以 ringed space 也就定義成了

Definition Ringed space [math-9M06]

Ringed space 是一個 pair (X,OX)(X, \mathcal{O}_X)

  1. 一個 topological space XX
  2. 一個 sheaf of (commutative) rings OX\mathcal{O}_X

注意到如果 RR 是一個 commutative ring,那 RR-algebra AA 也能視為一個 ring (with unit),所以這確實是 manifold (M,Cr)(M, C^r) 的推廣。

如果進一步要求 OX\mathcal{O}_X 的每個 stalk 都是 local ring,那就得到了 locally ringed space:

Definition Locally Ringed space [math-AYGI]

Locally ringed space 是 ringed space (X,OX)(X, \mathcal{O}_X) 加上條件:for all p∈Xp \in X

OX,p\mathcal{O}_{X, p}

是一個 local ring(i.e. 有 maximal ideal)

語法作為一種檢視方式 [32PV]

正如 Bicameral, Not Homoiconic 一文所述(推薦先看完 Bicameral 再看我這裡寫的東西),真正讓 LISP 脫穎而出的功能,是它 pipeline 特殊的雙層解析器:

  1. scan 出詞素(token)
  2. 用 reader 讀出「資料」,通常是一種 form,以 LISP 來說就是 s-expression。而且 reader 會順便讀取 macro 定義跟把 macro 展開
  3. 最後用 parser 解析成表面語言

程式語言的設計會影響實現,有些實現方式會非常多的靜態檢查,以至於在這些實現內部消除了絕大多數的語意錯誤,像是 dependent typed 的語言,這時候我們幾乎可以相信這些編譯器的內部表示,跟我們等下提到的客觀語法真的一樣。要注意這並不總是成立,也有很多語意錯誤會被延遲到執行時再處理(如 Python、Racket 的情況),所以在程式語言的實現中,總是假設並依賴一個理想的客觀語法,是由我們規定的語意生成的,我們通常用化簡語意或是指稱語意去研究它,而編譯器很大一部分工作就是保證自己遵循這個語意來實現語言。一套客觀語法可以有很多種檢視方式,比如「指定 a 的新值是整數 1」這個客觀語法可以寫成

  1. Racket (set-box! a 1)
  2. C a = 1;
  3. OCaml a := 1

更瘋狂一點的話,也不是不能寫成 JSON

{
  "assign": {
    "variable": "a",
    "expression": {
      "type": "int",
      "val": 1
    }
  }
}

為什麼表面語法有可能是錯的呢?比如 OCaml 的 parser 不會拒絕 a := 1 的寫法,即使 a 不是 int ref 類型。要到 type checker 的檢查階段,這段程式碼才會因為類型錯誤而被拒絕(這樣就消除了一個語意不正確的表面語句)。

所以一般開發者說的語法,其實可以說是「檢視語法」,當然這並不是說檢視不重要,正如 Concrete syntax matters, actually 說的,好的檢視方式本身就揭示了我們在談論什麼:我當然可以用 * 表示加法、用 + 表示乘法,然後問 3 + 2 * 5 是什麼,但如果有人算錯,我不應該太意外。

所以之所以要視之為檢視,是因為要讓我們可以去想像更好的表示方式,比如

  1. Adding interactive visual syntax to textual code
  2. Totally Live Programming and Proving in Hazel

「檢視」暗示了更豐富的運用,像在 proof assistant 的應用中,我們經常想要知道當前 context 可以看到的定義,以及打算證明的目標的類型;在除錯時我們想看到執行期的堆疊等等,都可以考慮為與跟生成客觀語法的語意匹配的檢視方式。

最後,釐清一些常見的誤解

  1. Bicameral 語法不一定要是 s-expression:Rhombus 使用 Shrubbery Notation
  2. 不是所有 LISPy 語言都用 list 表示其資料層,Racket 就用了 syntax object 抽象(Bicameral 一文也有說這件事)

MILKY☆SUBWAY [TDJD]

In Defense of Inefficiency [29QD]

Я - extremely composable embeddable programming language [software-000A]

Extremely composable embeddable programming language

可以先從這些截圖感受一下這什麼程式語言xd

Tool witr - Why is this running? [software-0009]

系統上執行的某個程式或服務 - 無論是 process、service 或綁定到連接埠的程式。都必然有其原因,但這些原因通常間接、不易察覺,或是跨越多個層級,例如監控程式、容器、服務或 shell。而 witr 的用途就是一次展示這些資訊。

Tool OCaml formatter online configurator [programming-0006]

看不懂 OCaml formatter 要怎麼設定?這個專案把排版選項、原始碼跟結果都展示出來,讓人直覺的做出選擇。

Definition Covering spaces in HoTT [ag-000L]

From Zero to QED [lean-0000]

Eliminator [ag-000K]

{-# OPTIONS --safe --without-K #-}
module ag-000K where

open import MLTT.Spartan
open import Naturals.Properties

Eliminator of ℕ

ℕ-elim : ∀ (P : ℕ → 𝓤 ̇) → P 0 → (∀ (n : ℕ) → P n → P (succ n)) → (∀ (n : ℕ) → P n)
ℕ-elim P P0 Ps zero = P0
ℕ-elim P P0 Ps (succ n) = Ps n (ℕ-elim P P0 Ps n)

Define with pattern matching

plus : ℕ → ℕ → ℕ
plus zero b = b
plus (succ a) b = succ (plus a b)

mul : ℕ → ℕ → ℕ
mul zero c = zero
mul (succ a) b = plus b (mul a b)

exp : ℕ → ℕ → ℕ
exp x zero = 1
exp x (succ k) = mul x (exp x k)

Now use the eliminator to define them

plus' : ℕ → ℕ → ℕ
plus' x = ℕ-elim (λ _ → ℕ → ℕ) (λ z → z) (λ x' plus-x' → λ y → succ (plus-x' y)) x

t5 : plus' 1 1 = 2
t5 = refl

p1 : (a b : ℕ) → plus a b = plus' a b
p1 zero b = refl
p1 (succ a) b =
  succ (plus a b)  =⟨ ap succ (p1 a b) ⟩
  succ (plus' a b) =⟨by-definition⟩
  succ (ℕ-elim (λ _ → ℕ → ℕ) (λ z → z) (λ x' plus-x' → λ y → succ (plus-x' y)) a b)
    =⟨by-definition⟩
  plus' (succ a) b ∎

mul' : ℕ → ℕ → ℕ
mul' x = ℕ-elim (λ _ → ℕ → ℕ) (λ z → zero) (λ x' mul-x' → λ y → plus' y (mul-x' y)) x

t7 : mul' 0 1 = 0
t7 = refl
t8 : mul' 1 1 = 1
t8 = refl
t9 : mul' 2 2 = 4
t9 = refl

p2 : (a b : ℕ) → mul a b = mul' a b
p2 zero b = refl
p2 (succ a) zero = p2 a 0
p2 (succ a) (succ b) =
  plus (succ b) (mul a (succ b))   =⟨ p1 (succ b) (mul a (succ b)) ⟩
  plus' (succ b) (mul a (succ b))  =⟨ ap (plus' (succ b)) (p2 a (succ b)) ⟩
  plus' (succ b) (mul' a (succ b)) =⟨by-definition⟩
  mul' (succ a) (succ b) ∎

exp' : ℕ → ℕ → ℕ
exp' x y = ℕ-elim (λ _ → ℕ → ℕ) (λ x → 1) (λ y' exp-y' → λ x → mul' x (exp-y' x)) y x

t10 : exp' 2 0 = 1
t10 = refl
t11 : exp' 2 10 = 1024
t11 = refl

p3 : (a b : ℕ) → exp a b = exp' a b
p3 a zero = refl
p3 zero (succ b) = refl
p3 (succ a) (succ b) =
  exp (succ a) (succ b)           =⟨by-definition⟩
  mul (succ a) (exp (succ a) b)   =⟨ p2 (succ a) (exp (succ a) b) ⟩
  mul' (succ a) (exp (succ a) b)  =⟨ ap (mul' (succ a)) (p3 (succ a) b) ⟩
  mul' (succ a) (exp' (succ a) b) =⟨by-definition⟩
  exp' (succ a) (succ b) ∎

Plus commutative yoga

C : commutative plus
C zero zero = refl
C zero (succ b) =
  succ b =⟨ ap succ (C 0 b) ⟩
  succ (plus b zero) ∎
C (succ a) zero =
  succ (plus a 0) =⟨ ap succ (C a 0) ⟩
  succ (plus 0 a) =⟨ refl ⟩
  plus 0 (succ a) ∎
C (succ a) (succ b) =
  succ (plus a (succ b)) =⟨ ap succ (C a (succ b)) ⟩
  succ (plus (succ b) a) =⟨ ap succ refl ⟩
  succ (succ (plus b a)) =⟨ ap (λ x → succ (succ x)) (C b a) ⟩
  succ (succ (plus a b)) =⟨ ap succ refl ⟩
  succ (plus (succ a) b) =⟨ ap succ (C (succ a) b) ⟩
  succ (plus b (succ a)) ∎

Remind

add1 : ℕ → ℕ
add1 = ℕ-elim (λ _ → ℕ) (succ zero) λ _ n → succ n

t1 : add1 0 = 1
t1 = refl

double' : ℕ → ℕ
double' = ℕ-elim (λ _ → ℕ) zero λ _ mn → succ (succ mn)

t2 : double' 0 = 0
t2 = refl
t3 : double' 1 = 2
t3 = refl
t4 : double' 2 = 4
t4 = refl

M-type (the type of non-well-founded, labelled trees) [ag-000J]

{-# OPTIONS --cubical --guardedness --two-level --no-level-universe #-}
module ag-000J where

open import Cubical.Foundations.Prelude
open import Cubical.Data.Sum
open import Cubical.Data.Nat

data 𝟘 : Type where
data 𝟙 : Type where
  ⋆ : 𝟙
data Maybe (X : Type) : Type where
  none : Maybe X
  some : X → Maybe X
record ℕ∞ : Type where
  coinductive
  field
    pred∞ : Maybe ℕ∞

M-type 是 non-well-formed, labelled trees 的型別,有可能有有限也可能有無限長的 path。 M 是 strictly positive coinductive types 的 universal type。

record M (S : Type) (P : S → Type) : Type where
  coinductive
  field
    shape : S
    pos : P shape → M S P

M S P 代表了 conatural number

module conatural-number where
  open ℕ∞
  open M

  S = 𝟙 ⊎ 𝟙

  P : S → Type
  P (inl _) = 𝟘
  P (inr _) = 𝟙

  N∞ = M S P

  inf : ℕ∞
  pred∞ inf = none
  inf' : ℕ∞
  pred∞ inf' = some inf

  i : N∞
  shape i = inl ⋆
  pos i = λ ()

  i' : N∞
  shape i' = inr ⋆
  pos i' = λ x → i

W-type (the type of well-founded, labelled trees) [ag-000I]

{-# OPTIONS --cubical --guardedness --two-level --no-level-universe #-}
module ag-000I where

open import Cubical.Foundations.Prelude
open import Cubical.Data.Sum
open import Cubical.Data.Nat

data 𝟘 : Type where
data 𝟙 : Type where
  ⋆ : 𝟙

W-type (due to Martin-Löf) 是 well-founded, labelled trees 的型別。每棵 W-type 的樹都可以有無限多分支,但 path 都是有限長。W 有兩個參數

  1. S : Type 表示 shape
  2. P : S → Type 表示有 (P s)-many positions

W 是 strictly positive inductive types 的 universal type。

data W (S : Type) (P : S → Type) : Type where
  sup-W : (s : S) → (P s → W S P) → W S P

Example: 自然數

module natural-number where
  S = 𝟙 ⊎ 𝟙

  P : S → Type
  P (inl _) = 𝟘 -- therefore, in this direction cannot go further
  P (inr _) = 𝟙 -- this direction has one continuation

  N = W S P

  z : N
  z = sup-W (inl ⋆) λ ()
  s : N → N
  s n = sup-W (inr ⋆) λ ⋆ → n

  α : ℕ → N
  α zero = z
  α (suc n) = s (α n)
  β : N → ℕ
  β (sup-W (inl ⋆) x) = zero
  β (sup-W (inr ⋆) f) = suc (β (f ⋆))

  main : (n : ℕ) → β (α n) ≡ n
  main zero =
    β (α zero) ≡⟨ refl ⟩
    β z ≡⟨ refl ⟩
    zero ∎
  main (suc n) = cong suc (main n)

  main⁻¹ : (n : N) → α (β n) ≡ n
  main⁻¹ (sup-W (inl ⋆) f) =
    α (β (sup-W (inl ⋆) f)) ≡⟨ refl ⟩
    z                       ≡⟨ refl ⟩
    sup-W (inl ⋆) (λ ())    ≡⟨ cong (sup-W (inl ⋆)) (sym (funExt λ ())) ⟩
    sup-W (inl ⋆) f ∎
  main⁻¹ (sup-W (inr ⋆) f) =
    α (β (sup-W (inr ⋆) f))           ≡⟨ refl ⟩
    α (suc (β (f ⋆)))                 ≡⟨ refl ⟩
    s (α (β (f ⋆)))                   ≡⟨ refl ⟩
    sup-W (inr ⋆) (λ _ → α (β (f ⋆))) ≡⟨ cong (sup-W (inr ⋆)) (funExt t) ⟩
    sup-W (inr ⋆) f ∎
    where
    t : (x : 𝟙) → α (β (f ⋆)) ≡ f x
    t ⋆ = main⁻¹ (f ⋆)

Simplex category 與 face maps [math-001I]

根據定義,每個 simplicial set SS 都是 simplex category Δ\Delta 的一個 presheaf

Definition Simplex Category [local-0]

  1. Ob: 每個 object 都是 [n]:={0,…,n}[n] := \{0, \dots, n\} 並帶有整數的 order 結構(其中 nn 是非負整數)
  2. Hom: 每個 morphism 都是嚴格遞增函數 Δ([m],[n]):={ϕ:[m]→[n]∣x>y  ⟹  ϕ(x)>ϕ(y)}\Delta([m], [n]) := \{ \phi : [m] \to [n] \mid x > y \implies \phi(x) > \phi(y) \}

這些 morphism 可以用一類特殊的 maps 組出來,叫做 face maps,舉例來說

δi:[n−1]→[n]x↦{x,x<ix+1,x≥i\delta_i : [n-1] \to [n] \\ x \mapsto \begin{align*}\begin{cases} x, \quad &x < i \\ x + 1, \quad &x \ge i \\ \end{cases}\end{align*}

這個定義乍一看實在沒辦法理解這在定義什麼,所以要實際看看幾個案例:從 [0][0] 到 [1][1] 可以畫成

從 [1][1] 到 [2][2] 可以畫成

事實上,如果畫成 simplex 的幾何表示 Simpn\text{Simp}_n 就更明顯了:

標準 nn-simplex Simpn\text{Simp}_n 可以定義成:

Simpn:={(x0,…,xn)∈[0,1]n∣∑ixi=1}\text{Simp}_n := \{ (x_0,\dots,x_n) \in [0,1]^n \mid \sum_i x_i = 1 \}

所以 face maps 就是在表示 [n−1][n-1] 表示 [n][n] 的哪一個邊界,線的邊界是兩個點,面的邊界是三條線。

沒有內接矩形的平面曲線 [math-001H]

在看過

之後的一點嘗試。

就我的認知,有限多的 singular points 無法破壞這裡的拓墣特性,所以討論非碎形曲線的時候,頂多討論能夠減少內接矩形到什麼程度。所以我真正有興趣的是局部構成沒有內接矩形時,如何重複這個構成還是保持特性。

然而一次跨出這步太超出我目前所知了,所以只能先考慮相關的變形問題:首先,開放的曲線可能沒有內接矩形,比如下圖由兩個有界直線構成(箭頭表示無限延伸方向)

  1. 如果選擇了頂點與其中一邊的點,那麼法向只能再跟此圖交於一點,無法構成矩形。另一邊因為對稱性所以一樣。
  2. 如果選擇一邊的兩點,那法向接觸到另一邊的長度不同,自然也不是矩形。
  3. 如果一邊各自選一點,因為這條邊往任意一邊移動都會改變長度,也沒辦法構成矩形。

但這張圖如果稍作修改,比如加一個直線拉回來變成三角形,就會再次有內接矩形。

另一種值得考慮的基本構造是圓,因為可以說圓的內接矩形有無限多個,但也可以說某種程度上只有一個內接矩形。所以如果考慮取半圓形,另一半則是想辦法破壞對稱性,比如我考慮過的其中一種形狀是

想法就是一直取一半直徑的半圓去填右半部。這個旋轉一下就可以弄成方程組,所以要驗證這個圖形可以嘗試看看方程組中出現矩形要怎麼驗證。

Formal Topology in UF [math-001G]

Reading https://github.com/ayberkt/formal-topology-in-UF and use TypeTopology to understand

Definition Poset [ag-000F]

{-# OPTIONS --safe --without-K #-}
module ag-000F where

open import MLTT.Spartan
open import UF.Sets
open import UF.SubtypeClassifier

Order is a binary relation ≤\le.

order-structure : 𝓤 ̇  → 𝓤 ⁺ ̇
order-structure {𝓤} A = A → A → Ω 𝓤

A poset AA is a pair (A,≤)(A, \le)

  1. x≤xx \le x for all x∈Ax \in A
  2. x≤yx \le y and y≤zy \le z implies x≤zx \le z for all x,y,z∈Ax,y,z \in A
  3. x≤yx \le y and y≤xy \le x implies x=yx = y for all x,y∈Ax,y \in A
poset-axioms : (A : 𝓤 ̇ ) → order-structure A → 𝓤 ̇
poset-axioms A _≤_ = is-set A
                    × ((x : A) → (x ≤ x) holds)
                    × ((x y z : A) → (x ≤ y) holds → (y ≤ z) holds → (x ≤ z) holds)
                    × ((x y : A) → (x ≤ y) holds → (y ≤ x) holds → x = y)

Poset-structure : 𝓤 ̇  → 𝓤 ⁺ ̇
Poset-structure A = Σ _≤_ ꞉ order-structure A , (poset-axioms A _≤_)

Poset : (𝓤 : Universe) → 𝓤 ⁺ ̇
Poset 𝓤 = Σ A ꞉ 𝓤 ̇ , Poset-structure A

We can add a helper to extract underlying set

⟨_⟩ : {S : 𝓤 ̇ → 𝓥 ̇ } → Σ S → 𝓤 ̇
⟨ X , s ⟩ = X

order-of : (P : Poset 𝓤) → ⟨ P ⟩ → ⟨ P ⟩ → Ω 𝓤
order-of (X , _≤_ , _) x y = x ≤ y

syntax order-of P x y = x ≤⟨ P ⟩ y

posets-are-sets : (P : Poset 𝓤) → is-set ⟨ P ⟩
posets-are-sets (X , _≤_ , i , rfl , trans , ir) = i

A hom from a poset to another, is a map that preserves the order

is-hom : (P : Poset 𝓤) (Q : Poset 𝓥) → (⟨ P ⟩ → ⟨ Q ⟩) → 𝓤 ⊔ 𝓥 ̇
is-hom P Q f = ∀ {x y} → (x ≤⟨ P ⟩ y) holds → (f x ≤⟨ Q ⟩ f y) holds

Identity map is a hom

id-is-hom : (P : Poset 𝓤) → is-hom P P id
id-is-hom P x≤y = x≤y

The composition of homs is a hom

∘-is-hom : (P : Poset 𝓤) (Q : Poset 𝓥) (R : Poset 𝓦)
            (f : ⟨ P ⟩ → ⟨ Q ⟩) (g : ⟨ Q ⟩ → ⟨ R ⟩)
          → is-hom P Q f → is-hom Q R g → is-hom P R (g ∘ f)
∘-is-hom P Q R f g f-is-hom g-is-hom x≤y = g-is-hom (f-is-hom x≤y)

Definition Frame [ag-000G]

{-# OPTIONS --safe --without-K #-}
module ag-000G where

open import MLTT.Spartan
open import UF.SubtypeClassifier
open import ag-000F

To build frame, we must be able to talk about arbitrary subsets of underlying set XX

Fam : 𝓤 ̇  → 𝓤 ⁺ ̇
Fam {𝓤} A = Σ I ꞉ 𝓤 ̇ , (I → A)

module JoinSyntax {A : 𝓤 ̇ } (join : Fam A → A) where
  join-of : {I : 𝓤 ̇ } → (I → A) → A
  join-of {I} f = join (I , f)

  syntax join-of (λ i → e) = ∨⟨ i ⟩ e

index : {X : 𝓤 ̇ } → Fam X → 𝓤 ̇
index (I , _) = I

_$_ : {X : 𝓤 ̇ } → (F : Fam X) → index F → X
_$_ (_ , f) = f
infixl 40 _$_

_∈_ : {X : 𝓤 ̇ } → X → Fam X → 𝓤 ̇
x ∈ (_ , f) = fiber f x

Beside poset axioms, frame axioms are

  1. There is a top element ⊤\top, every element x≤⊤x \le \top
  2. Binary meet x∧yx \land y is smaller than xx and yy, and it is a limit
  3. Each arbitrary subset UU has a join ∨U\lor U, such that each element of it smaller than the join
  4. Binary meets must distribute over arbitrary joins
frame-axioms : (X : 𝓤 ̇ ) → order-structure X → X → (X → X → X) → (Fam X → X) → 𝓤 ⁺ ̇
frame-axioms X _≤_ ⊤ _∧_ ∨ =
  ((x : X) → (x ≤ ⊤) holds)
  × ((x y : X) → ((x ∧ y) ≤ x) holds × ((x ∧ y) ≤ y) holds)
  × ((x y z : X) → (z ≤ x) holds → (z ≤ y) holds → (z ≤ (x ∧ y)) holds)
  × ((U : Fam X) → (x : X) → x ∈ U → (x ≤ ∨ U) holds)
  × ((U : Fam X) → (x : X) → ((y : X) → y ∈ U → (y ≤ x) holds) → (∨ U ≤ x) holds)
  × distrib
  where
  open JoinSyntax ∨
  distrib = ((U : Fam X) → (x : X) → x ∧ (∨ U) = ∨⟨ i ⟩ (x ∧ U $ i))

Frame-structure : 𝓤 ̇  → 𝓤 ⁺ ̇
Frame-structure X =
  Σ _≤_ ꞉ order-structure X ,
  Σ ⊤ ꞉ X ,
  Σ _∧_ ꞉ (X → X → X) ,
  Σ ∨ ꞉ (Fam X → X) ,
  (poset-axioms X _≤_) × (frame-axioms X _≤_ ⊤ _∧_ ∨)

Frame : (𝓤 : Universe) → 𝓤 ⁺ ̇
Frame 𝓤 = Σ X ꞉ 𝓤 ̇ , Frame-structure X

Properties of frames [ag-000H]

{-# OPTIONS --safe --without-K #-}
module ag-000H where

open import MLTT.Spartan
open import UF.SubtypeClassifier
open import ag-000F
open import ag-000G

In frames, meet is commutative, hence no difference between x∧yx \land y and y∧xy \land x

meet-is-comm : (F : Frame 𝓤) → (x y : ⟨ F ⟩) → 𝓤 ̇
meet-is-comm (X , _≤_ , ⊤ , _∧_ , _ ) x y = x ∧ y = y ∧ x

prove-meet-is-comm : (F : Frame 𝓤) → (x y : ⟨ F ⟩) → meet-is-comm F x y
prove-meet-is-comm (X , _≤_ , ⊤ , _∧_ , ∨ , (_ , _ , _ , split) , (_ , meet , lim , _ , _) ) x y = split (x ∧ y) (y ∧ x) I II
  where
  I : ((x ∧ y) ≤ (y ∧ x)) holds
  I = lim y x (x ∧ y) (meet x y .pr₂) (meet x y .pr₁)
  II : ((y ∧ x) ≤ (x ∧ y)) holds
  II = lim x y (y ∧ x) (meet y x .pr₂) (meet y x .pr₁)

Matrix representation of complex numbers [math-001F]

To see why

Rθ=[cos⁡θ−sin⁡θsin⁡θcos⁡θ]R_\theta = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix}

behave same as the complex numbers zθ=cos⁡θ+isin⁡θz_\theta = \cos\theta + i\sin\theta is to write RθR_\theta as a linear combination:

Rθ=cos⁡θ[1001]+sin⁡θ[0−110]R_\theta = \cos\theta \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} + \sin\theta \begin{bmatrix} 0 & -1 \\ 1 & 0 \end{bmatrix}

and hence we are wondering, what if we define

1=[1001]andi=[0−110]\bold{1} = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \quad \text{and} \quad \bold{i} = \begin{bmatrix} 0 & -1 \\ 1 & 0 \end{bmatrix}

and multiplication as matrix multiplication, addition as matrix addition? Are these behave same as complex numbers? Since 1\bold{1} is the identity matrix, we simply get followings

  1. 12=1\bold{1}^2 = \bold{1}
  2. 1i=i1=i\bold{1}\bold{i} = \bold{i}\bold{1} = \bold{i}

we would like to know if i2=−1\bold{i}^2 = -\bold{1}:

i2=[0−110][0−110]=[−100−1]=−[1001]=−1\bold{i}^2 = \begin{bmatrix} 0 & -1 \\ 1 & 0 \end{bmatrix} \begin{bmatrix} 0 & -1 \\ 1 & 0 \end{bmatrix} = \begin{bmatrix} -1 & 0 \\ 0 & -1 \end{bmatrix} = - \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} = -\bold{1}

as desired. Then we also know linear combinations based on 1\bold{1} and i\bold{i} maps to complex numbers bijectively:

[a−bba]=a1+bi≃a+bi\begin{bmatrix} a & -b \\ b & a \end{bmatrix} = a\bold{1} + b\bold{i} \simeq a + bi

so now we can see this indeed is a representation of complex numbers.

旋轉矩陣的 product 是給定角度的相加 [ag-000E]

{-# OPTIONS --without-K #-}
module ag-000E where

open import MLTT.Spartan hiding (_+_; _×_)
open import MLTT.Fin

因為不想引入太多其餘結構,把實數跟三角函數的一些性質直接公理化來用

module _ (ℝ : 𝓤₀ ̇) where
  variable
    a b : ℝ
  postulate
    cos : ℝ → ℝ
    sin : ℝ → ℝ
    -_  : ℝ → ℝ
    _+_ : ℝ → ℝ → ℝ
    _×_ : ℝ → ℝ → ℝ

    tri1 : cos (a + b) = cos a × cos b + - (sin a × sin b)
    tri2 : sin (a + b) = sin a × cos b + sin b × cos a

    ℝ-neg-1 : a × - b = - (a × b)
    ℝ-neg-add : - a + - b = - (a + b)
    ℝ-+-comm : a + b = b + a
    ℝ-×-comm : a × b = b × a
  infixl 60 -_
  infixl 40 _+_
  infixl 50 _×_
  ℝ-neg-2 : - a × b = - (a × b)
  ℝ-neg-2 {a}{b} =
    - a × b   =⟨ ℝ-×-comm ⟩
    b × - a   =⟨ ℝ-neg-1 ⟩
    - (b × a) =⟨ ap -_ ℝ-×-comm ⟩
    - (a × b) ∎

矩陣可以看成由兩個索引指向某其 Field KK 的元素的型別

  Matrix : (m n : ℕ) → (K : 𝓤 ̇) → 𝓤 ̇
  Matrix m n K = Fin m → Fin n → K

只定義 2×22 \times 2 的矩陣乘法

  _⊗_ : Matrix 2 2 ℝ → Matrix 2 2 ℝ → Matrix 2 2 ℝ
  _⊗_ m n 𝟎 𝟎 = m 𝟎 𝟎 × n 𝟎 𝟎 + m 𝟎 𝟏 × n 𝟏 𝟎
  _⊗_ m n 𝟎 𝟏 = m 𝟎 𝟎 × n 𝟎 𝟏 + m 𝟎 𝟏 × n 𝟏 𝟏
  _⊗_ m n 𝟏 𝟎 = m 𝟏 𝟎 × n 𝟎 𝟎 + m 𝟏 𝟏 × n 𝟏 𝟎
  _⊗_ m n 𝟏 𝟏 = m 𝟏 𝟎 × n 𝟎 𝟏 + m 𝟏 𝟏 × n 𝟏 𝟏
  infixl 30 _⊗_

旋轉矩陣它本人,這個用來表示 RθR_\theta,其中 θ∈ℝ\theta \in \mathbb{R} 是角度的值

  R : ℝ → Matrix 2 2 ℝ
  R θ 𝟎 𝟎 = cos θ
  R θ 𝟎 𝟏 = sin θ
  R θ 𝟏 𝟎 = - sin θ
  R θ 𝟏 𝟏 = cos θ

證明目標:RθRφ=Rθ+φR_\theta R_\varphi = R_{\theta + \varphi}

證明方式就是按 component 去證明等式成立。

  thm : {θ φ : ℝ} (i j : Fin 2) → (R θ ⊗ R φ) i j = R (θ + φ) i j
  thm {θ}{φ} 𝟎 𝟎 =
    (R θ ⊗ R φ) 𝟎 𝟎                   =⟨by-definition⟩
    cos θ × cos φ + sin θ × (- sin φ) =⟨ ap (cos θ × cos φ +_) ℝ-neg-1 ⟩
    cos θ × cos φ + - (sin θ × sin φ) =⟨ tri1 ⁻¹ ⟩
    cos (θ + φ)                       =⟨by-definition⟩
    R (θ + φ) 𝟎 𝟎 ∎
  thm {θ}{φ} 𝟎 𝟏 =
    (R θ ⊗ R φ) 𝟎 𝟏               =⟨by-definition⟩
    cos θ × sin φ + sin θ × cos φ =⟨ ℝ-+-comm ⟩
    sin θ × cos φ + cos θ × sin φ =⟨ ap (sin θ × cos φ +_) ℝ-×-comm ⟩
    sin θ × cos φ + sin φ × cos θ =⟨ tri2 ⁻¹ ⟩
    sin (θ + φ)                   =⟨by-definition⟩
    R (θ + φ) 𝟎 𝟏 ∎
  thm {θ}{φ} 𝟏 𝟎 =
    (R θ ⊗ R φ) 𝟏 𝟎                       =⟨by-definition⟩
    (- sin θ) × cos φ + cos θ × (- sin φ) =⟨ ap (_+ cos θ × - sin φ) ℝ-neg-2 ⟩
    - (sin θ × cos φ) + cos θ × (- sin φ) =⟨ ap (- (sin θ × cos φ) +_) ℝ-neg-1 ⟩
    - (sin θ × cos φ) + - (cos θ × sin φ) =⟨ ℝ-neg-add ⟩
    - (sin θ × cos φ + cos θ × sin φ)     =⟨ ap -_ (ap (sin θ × cos φ +_) ℝ-×-comm) ⟩
    - (sin θ × cos φ + sin φ × cos θ)     =⟨ ap -_ (tri2 ⁻¹) ⟩
    - sin (θ + φ)                         =⟨by-definition⟩
    R (θ + φ) 𝟏 𝟎 ∎
  thm {θ}{φ} 𝟏 𝟏 =
    (R θ ⊗ R φ) 𝟏 𝟏                   =⟨by-definition⟩
    - sin θ × sin φ + cos θ × cos φ   =⟨ ℝ-+-comm ⟩
    cos θ × cos φ + - sin θ × sin φ   =⟨ ap (cos θ × cos φ +_) ℝ-neg-2 ⟩
    cos θ × cos φ + - (sin θ × sin φ) =⟨ tri1 ⁻¹ ⟩
    R (θ + φ) 𝟏 𝟏 ∎

  addition : {θ φ : ℝ} (i j : Fin 2) → (R θ ⊗ R φ) i j = (R φ ⊗ R θ) i j
  addition {θ} {φ} i j =
    (R θ ⊗ R φ) i j =⟨ thm i j ⟩
    R (θ + φ) i j   =⟨ ap (λ x → R x i j) ℝ-+-comm ⟩
    R (φ + θ) i j   =⟨ thm i j ⁻¹ ⟩
    (R φ ⊗ R θ) i j ∎

Streams and finite observations [ag-000D]

From Topology via logic
{-# OPTIONS --safe --without-K --guardedness --no-exact-split #-}
module ag-000D where

open import MLTT.Spartan
open import MLTT.List

Stream can be defined as a coinductive record.

record Stream (A : 𝓤 ̇ ) : 𝓤 ̇ where
  coinductive
  constructor _∷_
  field
    head : A
    tail : Stream A

open Stream

For example a stream of all zero.

zeros : Stream 𝟚
head zeros = ₀
tail zeros = zeros

s ⊨starts o defines a relation that a stream can be realized by a finite observation.

_⊨starts_ : Stream 𝟚 → List 𝟚 → 𝓤₀ ̇
s ⊨starts [] = ₀ = ₀
s ⊨starts (x ∷ xs) = (x = head s) × (tail s ⊨starts xs)

For example, the first bit zeros produces is ₀.

first-bit : zeros ⊨starts [ ₀ ]
first-bit = refl , refl

Every stream can be realized by “no” observation.

realize-by-no-observation : (s : Stream 𝟚) → s ⊨starts []
realize-by-no-observation s = refl

We can define order relation for these finite observations.

_⊇_ : List 𝟚 → List 𝟚 → 𝓤₀ ̇
_ ⊇ [] = ₀ = ₀
[] ⊇ _ = 𝟘
(x ∷ l) ⊇ (x₁ ∷ l2) = (x = x₁) × (l ⊇ l2)

This order has antisymmetric

eq-condition : (l1 l2 : List 𝟚) → l1 ⊇ l2 → l2 ⊇ l1 → l1 = l2
eq-condition [] [] p q = refl
eq-condition (x ∷ l1) (y ∷ l2) (ph , pt) (qh , qt) =
  x ∷ l1 =⟨ ap (_∷ l1) ph ⟩
  y ∷ l1 =⟨ ap (y ∷_) (eq-condition l1 l2 pt qt) ⟩
  y ∷ l2 ∎

, in fact total, which means a boring order. The order induces refinement of observations: if a observation is subsequence of another observation that realise the stream, then the stream also be realized by this subsequence.

refine-observation : {s : Stream 𝟚} → (l l2 : List 𝟚) → s ⊨starts l → l ⊇ l2 → s ⊨starts l2
refine-observation l2 [] _ _ = refl
refine-observation (x ∷ l) (y ∷ l2) (x=head , tail) (x=y , rest) =
  (x=y ⁻¹ ∙ x=head) , refine-observation l l2 tail rest

Dependent equality in dependent type theory [ag-000C]

這是從 https://mathstodon.xyz/@MartinEscardo/114751426538568913 學到的技巧。

{-# OPTIONS --safe --without-K #-}
module ag-000C where

open import Agda.Primitive
  renaming (Set to Type; Setω to Typeω)
open import Agda.Builtin.Equality
open import Agda.Builtin.Nat

假設我們有

  1. a type X : Type
  2. a family of types A : X → Type indexed by X

那我們常常會遇到有

  1. x y : X
  2. a : A x
  3. b : A y
  4. p : x = y

= 是 MLTT 的 identity type,p 是一個 x = y 的證明,這時候如果我們問 a = b 是沒有答案的,因為根據 MLTT,a 跟 b 的類型壓根兒就不一樣,這導致問題連寫都寫不下來,那怎麼辦?

方法是定義高階等式(又稱為 dependent equality 或是 PathOver 或是 path transport),在該依賴項等價的情況下把問題變成新的等式來讓 dependent type 語言表達等式

用案例來說就是如果有個 equality 是「類型不同」的(出於依賴項的不透明性,比如這裡 vector length 輸入的 associative 不同)

先定義一些下面案例會用到的輔助程式:

cong : {X Y : Type} (f : X → Y) {x₀ x₁ : X} → x₀ ≡ x₁ → f x₀ ≡ f x₁
cong {X} {Y} f refl = refl

+-assoc : ∀ l m n → (l + m) + n ≡ l + (m + n)
+-assoc zero     m n = refl
+-assoc (suc l) m n = cong suc (+-assoc l m n)

具體案例 vector ++ 的 associativity

data Vec (A : Type) : Nat → Type where
  [] : Vec A 0
  _::_ : ∀{n} → A → Vec A n → Vec A (suc n)
infixl 40 _::_

_++_ : {Y : Type} {l m : Nat} → (xs : Vec Y l) → (ys : Vec Y m) → Vec Y (l + m)
[]        ++ ys = ys
(x :: xs) ++ ys = x :: (xs ++ ys)
infixl 30 _++_

基於 x₀ ≡ x₁ 定義一個更高階的 equality

higher-equality : {X : Type} (A : X → Type) {x₀ x₁ : X} → A x₀ → x₀ ≡ x₁ → A x₁ → Type
higher-equality A a₀ refl a₁ = a₀ ≡ a₁

但可以根據案例定義比較簡單的版本

_≡[_]_ : {X : Type} {x₀ x₁ : Nat} → Vec X x₀ → x₀ ≡ x₁ → Vec X x₁ → Type
a₀ ≡[ refl ] a₁ = a₀ ≡ a₁

命題 (xs ++ ys) ++ zs ≡ xs ++ (ys ++ zs) 無法寫下,因為(meta-level 的)型別不同。 所以需要用高階等式描述

cong-cons : {X : Type} {m n : Nat} {xs : Vec X m} {ys : Vec X n}
  (x : X) (p : m ≡ n)
  → xs ≡[ p ] ys → x :: xs ≡[ cong suc p ] x :: ys
cong-cons {X}{A} x refl refl = refl

++-assoc : {X : Type} (l m n : Nat)
  (xs : Vec X l) (ys : Vec X m) (zs : Vec X n)
  → (xs ++ ys) ++ zs ≡[ +-assoc l m n ] xs ++ (ys ++ zs)
++-assoc {X} zero     m n []       ys zs = refl
++-assoc {X} (suc l) m n (x :: xs) ys zs = I
  where
  I : x :: (xs ++ ys) ++ zs ≡[ cong suc (+-assoc l m n) ] x :: (xs ++ (ys ++ zs))
  I = cong-cons x (+-assoc l m n) (++-assoc l m n xs ys zs)

Second-Order Generalised Algebraic Theories: Signatures and First-Order Semantics [tt-000U]

NOTE about Second-Order Generalised Algebraic Theories: Signatures and First-Order Semantics

這篇文章主要在探討程式語法的表示方式,並展示如何結合代數方法跟 HOAS。作者說他們跟隨 Uemura 把語言定義成 second-order generalised algebraic theories (SOGATs),通過一系列案例揭示 non-substructural languages 可以自然的定義成 SOGATs

  1. SOGAT 的形式定義 (using the syntax of a particular SOGAT)
  2. 定義兩種 SOGAT signatures 到 GAT signatures (signatures for quotient inductive-inductive types) 的轉換,分別基於同時替換(parallel substitution)與單一替換(single substitution)

按代數抽象程度區分 [local-0]

從具體到抽象可以把語法表示看成

語法表示 能力
abstract syntax trees (AST) 把程式原文 parse 後直接儲存用的一系列資料結構
well-scoped syntax tree λx.x 跟 λy.y 在這類表示法裡面無法區分,也就是說綁定使用的具體名稱不再重要
intrinsic well-typed terms 這種表示把語法跟 typing relation 整合,所以 non well-typed 的程式甚至無法表達
well-typed, quotiented by the conversion relation (GAT) 加上更多 well-formness relation 的推廣代數理論,下面介紹
SOGAT GAT 推到 second-order,下面介紹

在 well-typed terms 上再加上 conversion relation 就變成廣義代數理論(generalised algebraic theory,簡稱 GAT),GAT 用來處理 dependently typed languages 時特別方便,因為 typing 依賴了 conversion relation。在 GAT 上只能定義保留了 conversion relation 的函數,因此連印出函數都無法定義,但 normalisation(正規化)、typechecking(型別檢查)跟 parametricity 這些函數保留 conversion 因此可定義。

對任何 GAT 來說,syntax 可以定義成 initial model,因此沒有區分語法跟語意的必要,某種意義上來說,一個程式語言就是一個 GAT。

HOAS 方法:按對 bindings/variables 的處理方式區分 [local-1]

HOAS 觀點關心 bindings 跟 variables 的處理方式,比如 De Bruijn indices 使名稱選擇與語意無關,但這也表示替換必須是語法的一部分,舉例來說 form of a category with families。

Logical frameworks 跟 higher-order abstract syntax (HOAS) 提供了另一種實現 bindings 跟 variables 的方式:使用 metatheory 的函數空間。 舉例來說,pure lambda calculus 的 lambda operation 的 type 是二階函數空間 (Tm → Tm) → Tm。這在理論上的解釋是 type-theoretic internal language of presheaves over the category of contexts and syntactic substitutions,在這個 topos 的 internal language 裡,lambda 的類型就長那樣。

Internal language 的觀點可以用來定義程式語言是什麼:有綁定的語言不是一個 GAT,而是一個二階的廣義代數理論(second-order generalised algebraic theory,簡稱 SOGAT),這種理論可以有二階操作(但不是任意高階)。

Untyped 或是 Simply typed 都有被定義成二階理論過,但 Uemura 是第一個用 SOGATs 定義有綁定的語言的人。這個理論真的很厲害,一個語言的 SOGAT 定義比 well-typed quotiented 定義還要抽象:SOGAT 連 contexts 跟 substitutions 都不用提到,這些會自動生成。但這不是一個 well-behaved 的代數理論,比如 second-order models 之間沒有有意義的 homomorphism。

為了描述 SOGAT 的一階模型、homomorphisms 或是 syntax 的 notion,作者把它轉成一個 GAT。這個過程中引入新的 sorts 給 contexts 跟 substitutions,然後把每個操作都用其 context index,second-order 的函數空間也由 context indexing 轉換成 first-order。因此得到一個有 some “correctness by construction” properties 的 GAT,比如每個操作都自動保留替換。這對複雜的理論來說,如果不是從 SOGAT 出發而是直接用其 GAT 表示,那這種屬性並不 trivial。

Cubical type theory 跟有 internal parametricity 的 type theory 都可以定義成 SOGATs,這些方法已經用來證明型別論的屬性。

Substructural (像是 linear or modal) type theories 無法用這篇論文說的方法用 SOGATs 定義,但有時候 presheaves over a substructural theory 提供的 substructural internal language 可以用來描述理論,像是 multi-modal type theory。

簡單的代數理論可以用 signatures 和方程式來表示,也可以 presentation independently 為 Lawvere theories。

GATs 的 syntactic signatures 可以用 preterms 跟 well-formedness relations 定義,也可以 presentation-independent 為 contextual categories 或 categories with families (CwFs) 或 clans。

GATs 的 theory of signatures (ToS) 方法落在 syntactic 跟 presentation-independent 方法中間:signatures 用某個 GAT 語法定義,這是一種設計來專用於定義簽名的類型理論。簽名跟我們在 Agda 裡寫下的 inductive datatype 定義一模一樣:A list (telescope) of the curried types of sorts and constructors。ToS 裡一個 signature 是一個理論的具體表示,但在 well-typed quotiented syntax 這層抽象上給出。這讓我們得到優雅的語意構造,又還是能用 signatures 工作。

SOGATs 同樣可以定義成 syntactically 或 presentation-independently(用 representable map categories 或是 CwFs with locally representable types)

這篇論文貢獻了 ToS 風格的 SOGATs 定義。SOGAT signatures 的理論本身也是 SOGAT,所以這個理論可以描述自己。

避免了循環論證,因為我們首先將 SOGAT 簽名定義為 GAT,從而引導 SOGAT 簽名理論,而 GAT 簽名理論(即 GAT 的語法)本身可以使用 Church 編碼進行引導。

Contributions [local-2]

The main takeaway of this paper is that structural languages are SOGATs.

We justify this claim through several examples. Our technical contributions are the following:

  • The theory of SOGAT signatures (ToS+), a domain-specific type theory in which every closed type is a SOGAT signature. As it is a structural type theory, it can be defined as a SOGAT itself. Signatures can be formalised in ToS+ without encoding overhead.
  • A translation from SOGAT signatures to GAT signatures based on a parallel substitution calculus. Thus, for every SOGAT, we obtain all of the semantics of GATs: a category of models with an initial object, (co)free models, notions of displayed models and sections, the fact that induction is equivalent to initiality, and so on. The GAT descriptions that we obtain are readable, do not contain occurrences of Yoneda as in usual presheaf function spaces. Correctness of the translation is showed by proving that internally to presheaves over a model of the GAT, a second-order model of the SOGAT is available.
  • We define an alternative translation producing a single substitution calculus.

作者開始展示如何把各種 logic 或程式語言定義成代數理論。這邊我寫下每個代數理論的 agda 版本

Schönfinkel's combinator calculus (Algebraic Theories) [ag-0003]

{-# OPTIONS --safe --without-K #-}
module ag-0003 where

open import MLTT.Spartan

Combinator calculus 可以看成一個代數理論,這時候它有

  1. 一個 sort of terms
  2. 一個 binary
  3. 兩個 nullary operations
  4. 兩個等式
record combinator-calculus : 𝓤₁ ̇ where
  field
    Tm : 𝓤₀ ̇

    _·_ : Tm → Tm → Tm

    K : Tm
    S : Tm

    Kβ : {u f : Tm} → K · u · f = u
    Sβ : {f g u : Tm} → S · f · g · u = f · u · (g · u)

  infixl 30 _·_
  1. 從這個符號可以明顯看出代數/模型的概念
  2. Combinator calculus 的 quotiented syntax 是初始模型,它總是存在。
  3. Notions of homomorphism, displayed/dependent model, induction, products and coproducts of models, free models, and so on, are derivable from the signature, as described in any book on universal algebra
  4. Algebraic Theory 的 initial algebra 叫做 quotient inductive type

其他 single-sorted algebraic theories 著名案例:

  1. 邏輯:經典(或直覺主義)命題邏輯,定義為布林代數(或海廷代數)理論
  2. 代數:monoids、群、環、lattices 等等

Generalised algebraic theories (GATs) [local-3]

Generalised algebraic theories (GATs) 的 sort 可以 indexed by 其他 sort。案例有 typed combinator calculus、propositional logic with Hilbert-style proof theory、theories of graphs、preorders、categories 等等

Typed combinator calculus (Generalised algebraic theories) [ag-0004]

{-# OPTIONS --safe --without-K #-}
module ag-0004 where

open import MLTT.Spartan
record typed-combinator-calculus : 𝓤₁ ̇ where
  field

給 types 的 sort

    Ty : 𝓤₀ ̇

每個 type 對應(index)一個 term 用的 sort

    Tm : Ty → 𝓤₀ ̇

    ι : Ty
    _⇒_ : Ty → Ty → Ty

    _·_ : {A B : Ty} → Tm (A ⇒ B) → Tm A → Tm B

    K : {A B : Ty} → Tm (A ⇒ B ⇒ A)
    S : {A B C : Ty} → Tm ((A ⇒ B ⇒ C) ⇒ (A ⇒ B) ⇒ A ⇒ C)

    Kβ : {A B : Ty} {u : Tm A} {f : Tm B} → K · u · f = u
    Sβ : {A B C : Ty}
      {f : Tm (A ⇒ B ⇒ C)}
      {g : Tm (A ⇒ B)}
      {u : Tm A}
      → S · f · g · u = f · u · (g · u)

  infixl 40 _·_
  infixr 30 _⇒_

上述 Algebraic Theory 的通用代數特徵可以推廣到 GAT。具體來說,每個 GAT 都具有由 quotient inductive-inductive type 給出的語法,我們有 free 模型和 cofree 模型。

Second-order algebraic theories (SOATs) [local-4]

如果一個語言有變數或是綁定,就被定義成一個二階理論。

Lambda calculus (Second-order algebraic theories) [ag-0005]

{-# OPTIONS --safe --without-K #-}
module ag-0005 where

open import MLTT.Spartan
record lambda-calculus : 𝓤₁ ̇ where
  field
    Tm : 𝓤₀ ̇

lam 的(metatheory)型別不是一階的(not strictly positive)

    lam : (Tm → Tm) → Tm
    _·_ : Tm → Tm → Tm

    β : {f : Tm → Tm} {u : Tm} → lam f · u = f u

  infixl 30 _·_

By the syntax of lambda calculus, we mean the syntax for the GAT of Definition 4. However, we still prefer to define lambda calculus as a SOGAT: it is a shorter definition, does not include boilerplate, and ensures that once translated to its first-order version, all operations respect substitution by construction.

此外,我們可以像邏輯框架一樣,使用二階表示來進行程式設計。這意味著,使用二階表示,我們可以定義 derivable operation 並證明 derivable 等式,而不是像證明 admissible 那樣需要歸納法。

舉例來說 Y combinator 是 derivable operation。可以證明它是 fixpoint combinator:

  Y : Tm
  Y = lam (λ f → (lam (λ x → f · (x · x))) · (lam (λ x → f · (x · x))))

  Y-is-fixed-point : {f : Tm} → Y · f = f · (Y · f)
  Y-is-fixed-point {f} =
    Y · f                                                                 =⟨by-definition⟩
    lam (λ f → (lam (λ x → f · (x · x))) · (lam (λ x → f · (x · x)))) · f =⟨ β ⟩
    (λ f → (lam (λ x → f · (x · x))) · (lam (λ x → f · (x · x)))) f       =⟨ refl ⟩
    (lam (λ x → f · (x · x))) · (lam (λ x → f · (x · x)))                 =⟨ β ⟩
    f · ((lam (λ x → f · (x · x))) · (lam (λ x → f · (x · x))))           =⟨ refl ⟩
    f · ((λ f → (lam (λ x → f · (x · x))) · (lam (λ x → f · (x · x)))) f) =⟨ ap (f ·_) (β ⁻¹) ⟩
    f · (Y · f) ∎

這種推理對任何 second-order model 都有效,而且任何 first-order model 都可以在 internal language of presheaves over first-order model 裡被升級成 second-order model。

但注意沒有可用的 SOAT models MM 和 NN 之間的同態概念。為了討論同態或語法,我們將 SOAT 轉換為一階 GAT:加上上下文、替換、索引 Tm 以及所有基於上下文的操作,然後 lam 就變成了一個以擴展上下文中的項作為輸入的一階函數。轉換出來的 GAT 就是

Lambda calculus (GAT) [ag-0006]

{-# OPTIONS --safe --without-K #-}
module ag-0006 where

open import MLTT.Spartan hiding (_∘_; id)

作者這邊開始解釋從二階理論得出一階理論(GAT)的標準過程

record first-order-lambda-calculus : 𝓤₁ ̇  where
  field
    Con : 𝓤₀ ̇
    Sub : Con → Con → 𝓤₀ ̇

有 terminal object 的 category

    _∘_ : {Δ Γ Θ : Con} → Sub Δ Γ → Sub Θ Δ → Sub Θ Γ
    assoc : {A B C D : Con} {γ : Sub C D} {δ : Sub B C} {θ : Sub A B}
      → (γ ∘ δ) ∘ θ = γ ∘ (δ ∘ θ)
    id : {Γ : Con} → Sub Γ Γ
    id-left : {A B : Con} {γ : Sub A B} → id ∘ γ = γ
    id-right : {A B : Con} {γ : Sub A B} → γ ∘ id = γ
    -- empty context: zero
    ◇ : Con
    ε : {Γ : Con} → Sub Γ ◇
    -- terminal
    ◇η : {Γ : Con} → (σ : Sub Γ ◇) → σ = ε

sort Tm 現在 indexed by Con 且有一個 instantiation operation,這個 operation 是 functorial ([◦], [id]).

    Tm : Con → 𝓤₀ ̇
    _[_] : {Γ Δ : Con} → Tm Γ → Sub Δ Γ → Tm Δ
    [id] : {Γ : Con} {t : Tm Γ} → t [ id ] = t
    [∘] : {Θ Γ Δ : Con} {t : Tm Γ} {γ : Sub Δ Γ} {δ : Sub Θ Δ} → t [ γ ∘ δ ] = t [ γ ] [ δ ]

context extension 讓 contexts 是 natural number algebra

    _▹ : Con → Con

substitutions 是一串 terms,由組成元件表達

    _,,_ : {Δ Γ : Con} → Sub Δ Γ → Tm Δ → Sub Δ (Γ ▹)

有了 contexts 跟 substitutions,變數就可以定義成 De Bruijn indices:

  1. 0 = q
  2. 1 = q[p]
  3. 2 = q[p] [p],以此類推
    p : {Γ : Con} → Sub (Γ ▹) Γ
    q : {Γ : Con} → Tm (Γ ▹)

應該滿足的等式規則

    ▹β₁ : {Δ Γ : Con} {γ : Sub Δ Γ} {t : Tm Δ}
      → p ∘ (γ ,, t) = γ
    ▹β₂ : {Δ Γ : Con} {γ : Sub Δ Γ} {t : Tm Δ}
      → q [ γ ,, t ] = t
    ▹η : {Δ Γ : Con} {σ : Sub Δ (Γ ▹)} → σ = (p ∘ σ ,, q [ σ ])

    lam : {Γ : Con} → Tm (Γ ▹) → Tm Γ
    lam[] : {Δ Γ : Con} {γ : Sub Δ Γ} {t : Tm (Γ ▹)} → (lam t)[ γ ] = lam (t [ γ ∘ p ,, q ])

    _·_ : {Γ : Con} → Tm Γ → Tm Γ → Tm Γ
    ·[] : {Δ Γ : Con} {γ : Sub Δ Γ} {t u : Tm Γ} → (t · u)[ γ ] = t [ γ ] · (u [ γ ])

    β : {Δ Γ : Con} {γ : Sub Δ Γ} {t : Tm (Γ ▹)} {u : Tm Γ}
      → lam t · u = t [ id ,, u ]

  infixl 40 _∘_
  infixl 30 _,,_
  infixl 40 _·_
  infixl 50 _[_]

Second-order generalised algebraic theories (SOGATs) [local-5]

SOGATs combine the two previous classes: sorts can be indexed over previous sorts and second-order operations are allowed.

Simply typed lambda calculus [ag-0007]

{-# OPTIONS --safe --without-K #-}
module ag-0007 where

open import MLTT.Spartan
open import UF.Equiv
record simply-typed-lambda-calculus : 𝓤₁ ̇  where
  field
    Ty : 𝓤₀ ̇
    _⇒_ : Ty → Ty → Ty

generalised 的部分是因為 index Tm by Ty

    Tm : Ty → 𝓤₀ ̇

綁定的部分

    lam : {A B : Ty} → (Tm A → Tm B) → Tm (A ⇒ B)
    _·_ : {A B : Ty} → Tm (A ⇒ B) → (Tm A → Tm B)

    stlc-cong : {A B : Ty} → Tm (A ⇒ B) ≃ (Tm A → Tm B)

一樣參照 first-order lambda calculus 的過程,加上 contexts、加上 substitutions,相應的 first-order 等式跟改寫,就會得到 simply-typed-lambda-calculus 的 GAT。

Minimal intuitionistic first-order logic (SOGAT) [ag-0008]

{-# OPTIONS --safe --without-K #-}
module ag-0008 where

open import MLTT.Spartan
open import UF.Subsingletons
record minimal-intuitionistic-first-order-logic : 𝓤₁ ̇  where
  field
    For : 𝓤₀ ̇
    Tm : 𝓤₀ ̇
    _⊃_ : For → For → For
    All : (Tm → For) → For
    Eq : Tm → Tm → For

    Pf : For → 𝓤₀ ̇
    Pf-is-prop : (A : For) → is-prop (Pf A)

    intro⊃ : {A B : For} → (Pf A → Pf B) → Pf (A ⊃ B)
    elim⊃ : {A B : For} → Pf (A ⊃ B) → (Pf A → Pf B)

    intro∀ : {A : Tm → For} → ((𝑡 : Tm) → Pf (A 𝑡)) → Pf (All A)
    elim∀ : {A : Tm → For} → Pf (All A) → ((𝑡 : Tm) → Pf (A 𝑡))

    introEq : {t : Tm} → Pf (Eq t t)
    elimEq : {t t' : Tm} → (A : Tm → For) → Pf (Eq t t') → Pf (A t) → Pf (A t')

一樣參照 first-order lambda calculus 的過程,加上 contexts、加上 substitutions,相應的 first-order 等式跟改寫。

Polymorphic lambda calculus (SOGAT) [ag-0009]

{-# OPTIONS --safe --without-K #-}
module ag-0009 where

open import MLTT.Spartan
record polymorphic-lambda-calculus : 𝓤₁ ̇  where
  field
    Ty : 𝓤₀ ̇
    Tm : Ty → 𝓤₀ ̇
    _⇒_ : Ty → Ty → Ty
    lam : {𝐴 𝐵 : Ty} → (Tm 𝐴 → Tm 𝐵) → Tm (𝐴 ⇒ 𝐵)
    _·_ : {𝐴 𝐵 : Ty} → Tm (𝐴 ⇒ 𝐵) → (Tm 𝐴 → Tm 𝐵)
    All : (Ty → Ty) → Ty
    Lam : {𝐴 : Ty → Ty} → ((𝑋 : Ty) → Tm (𝐴 𝑋)) → Tm (All 𝐴)
    _•_ : {𝐴 : Ty → Ty} → Tm (All 𝐴) → ((𝑋 : Ty) → Tm (𝐴 𝑋))

一樣參照 first-order lambda calculus 的過程,加上 contexts、加上 substitutions,相應的 first-order 等式跟改寫。

System Fω (SOGAT) [ag-000A]

{-# OPTIONS --safe --without-K #-}
module ag-000A where

open import MLTT.Spartan
record system-F-ω : 𝓤₁ ̇  where
  field
    □ : 𝓤₀ ̇
    Ty : □ → 𝓤₀ ̇

    _⇛_ : □ → □ → □
    LAM : {K L : □} → (Ty K → Ty L) → Ty (K ⇛ L)
    _●_ : {K L : □} → Ty (K ⇛ L) → (Ty K → Ty L)

    ∗ : □
    Tm : Ty ∗ → 𝓤₀ ̇

    All : {K : □} → (Ty K → Ty ∗) → Ty ∗
    Lam : {K : □}{A : Ty K → Ty ∗} → ((X : Ty K) → Tm (A X)) → Tm (All A)
    _•_ : {K : □}{A : Ty K → Ty ∗} → Tm (All A) → ((X : Ty K) → Tm (A X))

    _⇒_ : Ty ∗ → Ty ∗ → Ty ∗
    lam : {A B : Ty ∗} → (Tm A → Tm B) → Tm (A ⇒ B)
    _·_ : {A B : Ty ∗} → Tm (A ⇒ B) → (Tm A → Tm B)

System Fω 轉換後有

  1. 3 個 operations 綁定 Ty-variables
  2. 1 個 operation 綁定 term-variable

Minimal Martin-Löf type theory (SOGAT) [ag-000B]

{-# OPTIONS --safe --without-K #-}
module ag-000B where

open import MLTT.Spartan
open import MLTT.NaturalNumbers
variable
  𝑖 : ℕ

record minimal-martin-lof-type-theory : 𝓤₁ ̇  where
  field
    Ty : ℕ → 𝓤₀ ̇
    U : (𝑖 : ℕ) → Ty (succ 𝑖)
    Tm : Ty 𝑖 → 𝓤₀ ̇

    c : Ty 𝑖 → Tm (U 𝑖)
    El : Tm (U 𝑖) → Ty 𝑖

    PI : (A : Ty 𝑖) → (Tm A → Ty 𝑖) → Ty 𝑖
    Lift : Ty 𝑖 → Ty (succ 𝑖)

    lam : {𝐴 : Ty 𝑖}{𝐵 : Tm 𝐴 → Ty 𝑖} → ((𝑎 : Tm 𝐴) → Tm (𝐵 𝑎)) → Tm (PI 𝐴 𝐵)
    _·_ : {𝐴 : Ty 𝑖}{𝐵 : Tm 𝐴 → Ty 𝑖} → Tm (PI 𝐴 𝐵) → ((𝑎 : Tm 𝐴) → Tm (𝐵 𝑎))

    mk : {𝐴 : Ty 𝑖} → Tm 𝐴 → Tm (Lift 𝐴)
    un : {𝐴 : Ty 𝑖} → Tm (Lift 𝐴) → Tm 𝐴

這個理論的對應 GAT 得到一個具有族的範疇(CwF),更準確地說,是一個具有 N 個 families 的範疇,這些族配備了 familywise Π-types、宇宙以及族之間的一步向上提升。 這些類型是 Ty : Con → N → Set 和 Tm : (Γ : Con) → Ty Γ 𝑖 → Set,其中 𝑖 論證隱含在後者中。

後面幾節

  1. 第三節 Theories of signatures as SOGATs,開始把 signatures 理論也寫成 SOGAT 來討論
  2. 第四節 Naive semantics of SOGAT signatures,討論 for any SOGAT signature 的 a notion of first-order model.
  3. 第五節 Direct semantics of SOGAT signatures,用一個更小心版本的 presheaf model 定義 first-order models of SOGATs
  4. 第六節 GAT signature semantics of SOGAT signatures,把 SOGAT signatures 轉成 GAT signatures 的方法

Intrinsically typed term [ag-0002]

{-# OPTIONS --safe --without-K #-}
module ag-0002 where

open import MLTT.Spartan hiding (Type)
open import MLTT.List

Type 在 STLC 還只需要是一個簡單的 formation

data Type : 𝓤₀  ̇ where
  bool : Type
  _⇒_ : Type → Type → Type
infixr 50 _⇒_

variable
  S T : Type

Context 通常會自訂,比如 MLTT 需要兩種綁定時自訂就會更方便一些

Ctx = List Type
_▷_ : Ctx → Type → Ctx
Γ ▷ T = T ∷ Γ
infix 40 _▷_

variable Γ : Ctx

Intrinsically-scoped de Brujin indices

基本上變數都長這樣

data _∋_ : Ctx → Type → 𝓤₀  ̇ where
  here  : Γ ▷ T ∋ T
  there : Γ ∋ T → Γ ▷ S ∋ T
infix 20 _∋_

variable x : Γ ∋ T

Intrinsically-typed terms

確保 term 是類型良好的一種方式就是從一開始就跟 context 一起構造,讓 terms 必須是 well-typed

data _⊢_ : Ctx → Type → 𝓤₀  ̇ where
  true false : Γ ⊢ bool
  var : Γ ∋ T → Γ ⊢ T
  lam : Γ ▷ S ⊢ T → Γ ⊢ S ⇒ T
  _·_ : Γ ⊢ S ⇒ T → Γ ⊢ S → Γ ⊢ T
  if_then_else_ : Γ ⊢ bool → Γ ⊢ T → Γ ⊢ T → Γ ⊢ T
infix 30 _⊢_

Video Why You Can't Bring Checkerboards to Math Exams [math-001E]

A cool way to do multiply, divide and root!

Definition Diffeological space [math-001D]

A diffeological space is a pair (X,DX)(X, \mathcal{D}_X) consists of a given set XX and a diffeology DX\mathcal{D}_X consists of a collection of parameterizations p:U→Xp : U \to X satisfying the following conditions:

  1. All parameterizations with domain R0\mathbb{R}^0 belong to DX\mathcal{D}_X, namely all the points of XX
  2. If p:V→Xp : V \to X is a parameterization, and f:U→Vf : U \to V is a smooth map between cartesian spaces, then p∘fp \circ f belongs to DX\mathcal{D}_X
  3. If p:U→Xp : U \to X is a parameterization, an open cover (Ui)i∈I(U_i)_{i\in I} of UU that each restriction p∣Ui∈DXp \mid_{U_i} \in \mathcal{D}_X, then p∈DXp \in \mathcal{D}_X

If DX\mathcal{D}_X is a diffeology, then we call a parameterization pp that belongs to it a plot.

Lemma Presheaves are colimits of representables [math-001B]

The presheaf X∈A^X \in\widehat{A} is the colimit of the functor φX:=h∘πX\varphi_X := h \circ \pi_X,

πX:∫X→AπX(a,s):=a\pi_X : \int X \to A \\ \pi_X(a, s) := a

where hh is the yoneda embedding, ∫X\int X is the category of elements of XX. For morphism φX(u):=u\varphi_X(u) := u.

Proof [local-0]

We first show that XX is a cocone, for each object (a,s)∈∫X(a, s) \in \int X, there is a morphism

ha→sX h_a \xrightarrow{s} X
here abuse notation that s∈Xas \in X_a has a corresponding ha→Xh_a \to X in A^\widehat{A} because the Yoneda lemma.

and for each (a,s)→u(b,t)(a,s)\xrightarrow{u}(b,t), the following diagram commutes

figure tex16120

hence XX is a cocone. Given any other cocone YY, which means a collection of sections

fs:ha→Yf_s : h_a \to Y

where u∗(ft)=fsu^*(f_t) = f_s for each u:(a,s)→(b,t)u : (a,s) \to (b,t) by definition. The point is if we define a natural transformation

ηa:Xa→Yaηa(s):=fs\eta_a : X_a \to Y_a \\ \eta_a(s) := f_s

naturality follows because X(u)(t)=sX(u)(t) = s implies Y(u)(ft)=fsY(u)(f_t) = f_s. It is clear that η\eta is the unique natural transformation under φX\varphi_X, showing that XX is the colimit.

Presheaves, Yoneda embedding, and Yoneda lemma [math-001A]

Definition Presheaf [local-0]

Let AA be a category. A presheaf over AA is a functor of the form

X:Aop→SetX : A^{op} \to Set

For each object a∈Aa \in A, we will denote by

Xa:=X(a)∈SetX_a := X(a) \in Set

the evaluation of XX at aa. The set XaX_a will sometimes be called the fibre of the presheaf XX at aa, and the elements of XaX_a thus deserve the name of sections of XX over aa.

For morphism a→uba \xrightarrow{u} b, the induced map from Xb→XaX_b \to X_a denotes u∗:=X(u)u^* := X(u).

The category of presheaves over AA denotes A^\widehat{A}.

Definition Yoneda embedding [local-1]

Yoneda embedding is a functor

h:A→A^h(a):=HomA(−,a)\begin{aligned} &h &&: A \to \widehat{A} \\ &h(a) &&:= \text{Hom}_A(-,a) \end{aligned}

we denote ha:=h(a)h_a := h(a)

Lemma Yoneda [local-3]

For any presheaf XX over AA, there is a natural bijection of the form

θ:HomA^(ha,X)→∼Xaθ(α):=αa(1a)\begin{aligned} &\theta &&: \text{Hom}_{\widehat{A}}(h_a,X) \xrightarrow{\sim} X_a \\ &\theta(\alpha) &&:= \alpha_a(1_a) \end{aligned}

Proof [local-2]

We first define inverse map τ:Xa→HomA^(ha,X)\tau : X_a \to \text{Hom}_{\widehat{A}}(h_a,X), given a section ss of XX over aa, i.e. s∈Xas \in X_a, we have

τ(s)b:HomA(b,a)→Xbτ(s)b(f):=f∗(s)\begin{aligned} \tau(s)_b &: \text{Hom}_A(b,a) \to X_b \\ \tau(s)_b(f) &:= f^*(s) \end{aligned}

for each morphism b→fab \xrightarrow{f} a. This indeed defines a morphism ha→τ(s)Xh_a \xrightarrow{\tau(s)} X in A^\widehat{A}.

Now check θ\theta and τ\tau indeed are inverse of each other. First: given s∈Xas \in X_a, we have

θ(τ(s))=τ(s)a(1a)=1a∗(s)=X(1a)(s)=s\theta(\tau(s)) = \tau(s)_a(1_a) = 1_a^*(s) = X(1_a)(s) = s

Another direction: given α:ha→X\alpha : h_a \to X, we have

τ(θ(α))b(f)=τ(αa(1a))b(f)=f∗(αa(1a))by definition of τ=X(f)(αa(1a))=αb(HomA(f,a)(1a))by naturality=αb(1a∘f)=αb(f)\begin{aligned} \tau(\theta(\alpha))_b(f) &= \tau(\alpha_a(1_a))_b(f) \\ &= f^*(\alpha_a(1_a)) \quad \text{by definition of } \tau \\ &= X(f)(\alpha_a(1_a)) \\ &= \alpha_b(\text{Hom}_A(f, a)(1_a)) \quad \text{by naturality} \\ &= \alpha_b(1_a \circ f) \\ &= \alpha_b(f) \end{aligned}

for each f:b→af : b \to a. Naturality is obvious, hence they form a natural bijection.

隱式編程:coherence 與 stability 屬性 [tt-000T]

這篇是 COCHIS: Stable and coherent implicits 的筆記

隱式編程機制是指,使用型別指導的推導能力,在使用者不提供完整資訊的情況下給出程式語意的技術。比如 Haskell 的 type class、Rust 的 trait 等。合成的過程叫做 resolution。

Haskell 的 type class 的一個重要特徵是給定的類型只會有一個 instance 符合。coherence 在這個意義下指的是,給出的程式語意是唯一的,也就是說對某段合法程式碼,不會合成出超過一個語意。

比如説 Haskell 會拒絕 show (read "3") == "3" 這段程式碼,因為根據 type class resolution 有很多種可能性(show : α -> String 跟 read : String -> α)

  1. 選了 α := Float 那結果是 False,因為 show (read "3") == "3.0"
  2. 選了 α := Int 那結果是 True
  3. 選了 α := Char 那結果是 True

所以這種會導致有多種語意出現的程式就需要被拒絕。

Haskell 的 overlapping instances 技術是對上述問題的一種推廣(使我們可以接受更多程式),比如說

class Trans α where trans :: α → α
instance Trans α where trans x = x
instance Trans Int where trans x = x + 1

對於程式 trans 3 應該要決定出什麼結果?Overlapping 的決定是,因為 α := Int 比沒有決定更特定,因此選 instance Trans Int。然而,也有 overlapping 策略也無法決定的情況,比如下面比較刻意的

class C α β where
  m :: α → β → Bool
instance C Bool α where
  mx y = x
instance C α Bool where
  mx y = y

對程式 m True False 兩個 instances 都一樣特定,沒辦法決定,因此這段程式碼也必須被拒絕。

Stability 是跟 coherence 高度相關的屬性。不正式的說,stable 是指 type variables 的實例化與否不影響 resolution 的結果。但 overlapping 技術會影響這個結果,比如

bad :: α → α
bad x = trans x

就是一個 unstable 的定義。如果寫成 Trans α => α → α 就不一樣了,這表示 α 交由呼叫 bad 的地方決定,但這裡則是必須在定義處馬上決定,如果 Haskell 接受這段定義,那可能會選擇第一個 instance Trans,導致 bad 3 是 3 而 trans 3 是 4。雖然 bad x := trans x 是定義等價。

也可以參考 https://blog.ezyang.com/2014/07/type-classes-confluence-coherence-global-uniqueness/ 的案例跟論點。

Definition 流形上的微分式 [math-0019]

設 (xi)(x^i) 為 differentiable manifold MnM^n 的局部座標,可以把微分式定義為 ∂1,… .∂n\partial_1, \dots. \partial_n 的對偶基底,記為 dx1,…,dxndx^1, \dots, dx^n。亦即

dxi(∂i)=δjidx^i (\partial_i) = \delta^i_j

一階微分式的整體記為 Ω(M)\Omega(M)。

任何給定的微分式 ω\omega 可以寫成向量形式 ω=aidxi\omega = a_i dx^i

對一個 f∈C∞(M)f \in C^\infty(M),什麼是 dfdf?用向量微積分的觀點,是函數 ff 的一階變化量

df(X)=DXf:=lim⁡t→0f(p+tX)−f(p)tdf(X) = D_X f := \lim_{t\to0} \frac{f(p + tX) - f(p)}{t}

因此其類型是 df:TpM→Rdf : T_pM \to \R 的線性函數,通過空間對偶可知這就是 Tp∗MT_p^*M 的元素。

性質一 [local-0]

df=∂f∂xidxidf = \frac{\partial f}{\partial x^i} dx^i

證明如下:設 df=bjdxjdf = b_j dx^j

df(∂i)=bjdxj(∂i)=bjδij=bidf(\partial_i) = b_j dx^j(\partial_i) = b_j \delta^j_i = b_i

又有

df(∂i)=D∂if=∂f∂xidf(\partial_i) = D_{\partial_i} f = \frac{\partial f}{\partial x^i}

因此

df=∂f∂xidxidf = \frac{\partial f}{\partial x^i} dx^i
然而要注意到,並不是每個 ω∈Ω(M)\omega \in \Omega(M) 都可以表示成某個 ff 的微分 dfdf。

性質二 [local-1]

而且,對於每個具體的 ii,xix^i 顯然是一種 C∞(M)C^\infty(M) 的特例,因此也可以定義

dxi(X):=DXxidx^i(X) := D_X x^i

驗證

DXxi=DXj∂jxi=XjD∂jxi=Xj∂xi∂xj=Xi\begin{aligned} D_X x^i &= D_{X^j \partial_j} x^i \\ &= X^j D_{\partial_j} x^i \\ &= X^j \frac{\partial x^i}{\partial x^j} \\ &= X^i \end{aligned}

可見如此定義的 dxidx^i 跟取對偶基底的結果相同。

Definition 切向量場沿曲線平行 (parallel) [math-0018]

令 γ(t)\gamma(t) 為一 C∞C^\infty-affine manifold (Mn,∇)(M^n, \nabla) 上一 C∞C^\infty-曲線。ZZ 為 γ\gamma 上有意義的切向量場(i.e. 對所有 tt,可以對 tt 可微的指定一個 Z∈Tγ(t)MZ\in T_{\gamma(t)} M)

∇dγdtZ=0\nabla_{\frac{d\gamma}{dt}}Z=0

稱 ZZ 沿 γ\gamma 為平行。

若適當的局部座標為 (xi)(x^i),則

γ(t)=(xi(t))Z=Zi∂i\gamma(t) = (x^i(t)) \\ Z=Z^i\partial_i

令 X=dγdtX = \frac{d\gamma}{dt} (即速度向量),則

dγdtf=df∘γdt=df(xi(t))dt=∂f∂xidxidt=dxidt∂if\frac{d\gamma}{dt} f = \frac{d f\circ\gamma}{dt} = \frac{d f(x^i(t))}{dt} = \frac{\partial f}{\partial x^i} \frac{d x^i}{dt} = \frac{d x^i}{dt} \partial_i f

因此

X=dxidt∂iX = \frac{d x^i}{dt} \partial_i

因此

∇dγdtZ=∇X(Zj∂j)=dxidt∇∂i(Zj∂j)=dxidt((∂iZj)∂j+Zj∇∂i∂j)by Leibniz=dxidt((∂iZj)∂j+ZkΓikj∂j)by Christoffel=dxidt((∂iZj)+ZkΓikj)∂j=(dxidt(∂iZj)+dxidtZkΓikj)∂j=(ddtZj+dxidtZkΓikj)∂j=(dZjdt+dxidtΓikjZk)∂j\begin{aligned} \nabla_{\frac{d\gamma}{dt}}Z &= \nabla_{X} (Z^j \partial_j) = \frac{d x^i}{dt} \nabla_{\partial_i}(Z^j \partial_j) \\ &= \frac{d x^i}{dt} ((\partial_i Z^j) \partial_j + Z^j \nabla_{\partial_i}\partial_j) \quad \text{by Leibniz} \\ &= \frac{d x^i}{dt} ((\partial_i Z^j) \partial_j + Z^k \Gamma^j_{ik} \partial_j) \quad \text{by Christoffel} \\ &= \frac{d x^i}{dt} ((\partial_i Z^j) + Z^k \Gamma^j_{ik}) \partial_j \\ &= (\frac{d x^i}{dt}(\partial_i Z^j) + \frac{d x^i}{dt}Z^k \Gamma^j_{ik}) \partial_j \\ &= (\frac{d}{dt}Z^j + \frac{d x^i}{dt}Z^k \Gamma^j_{ik}) \partial_j \\ &= (\frac{d Z^j}{dt} + \frac{d x^i}{dt}\Gamma^j_{ik} Z^k) \partial_j \end{aligned}

ZZ 沿 γ\gamma 平行的充要條件為滿足一階線性方程組

dZjdt+dxidtΓikjZk,∀j=1,…,n\frac{d Z^j}{dt} + \frac{d x^i}{dt}\Gamma^j_{ik} Z^k, \forall j = 1,\dots,n

測地線方程組推導 [math-0017]

令 γ(t)\gamma(t) 為一 C∞C^\infty-affine manifold (Mn,∇)(M^n, \nabla) 上一 C∞C^\infty-曲線,我們定義當

∇dγdtdγdt=0\nabla_{\frac{d\gamma}{dt}} \frac{d\gamma}{dt}=0

對所有 tt 成立時,γ\gamma 為一測地線。只要參考切向量場沿著某一曲線如何被視為平行定義的推廣就可以直觀的看出測地線的幾何意義。

藉由座標 γ(t)=(xi(t))\gamma(t) = (x^i(t)),可將 γ\gamma 表達為

dγdt=dxidt∂∂xi\frac{d\gamma}{dt} = \frac{d x^i}{dt} \frac{\partial}{\partial x^i}

故推導當 γ\gamma 為一測地線時,有方程式

0=∇dxidt∂idxjdt∂xj=dxidt∇∂idxjdt∂jby linear=dxidt((∂idxjdt)∂j+dxjdt∇∂i∂j)by Leibniz=dxidt(∂idxjdt)∂j+dxidtdxjdt∇∂i∂j=dxidtdxjdt∇∂i∂j+dxidt(∂idxjdt)∂j=dxidtdxjdt∇∂i∂j+ddt(dxjdt)∂jby chain rule=dxidtdxjdt∇∂i∂j+d2xjdt2∂j=dxidtdxjdt∇∂i∂j+d2xkdt2∂k=dxidtdxjdtΓijk∂k+d2xkdt2∂kby ∇∂i∂j=Γijk∂k=(dxidtdxjdtΓijk+d2xkdt2)∂k\begin{aligned} 0 &= \nabla_{\frac{d x^i}{dt} \partial_i}{\frac{d x^j}{dt} \partial x_j} \\ &= \frac{d x^i}{dt} \textcolor{red}{\nabla_{\partial_i}{\frac{d x^j}{dt} \partial_j}} \quad\quad\quad \text{by linear} \\ &= \frac{d x^i}{dt} (\textcolor{red}{(\partial_i \frac{d x^j}{dt}) \partial_j + \frac{d x^j}{dt} \nabla_{\partial_i}{\partial_j}}) \quad \text{by Leibniz} \\ &= \frac{d x^i}{dt}(\partial_i \frac{d x^j}{dt}) \partial_j + \textcolor{blue}{\frac{d x^i}{dt}\frac{d x^j}{dt} \nabla_{\partial_i}{\partial_j}} \\ &= \textcolor{blue}{\frac{d x^i}{dt}\frac{d x^j}{dt} \nabla_{\partial_i}{\partial_j}} + \textcolor{green}{\frac{d x^i}{dt}}(\textcolor{green}{\partial_i} \frac{d x^j}{dt}) \partial_j \\ &= \frac{d x^i}{dt}\frac{d x^j}{dt} \nabla_{\partial_i}{\partial_j} + \textcolor{green}{\frac{d}{dt}}(\frac{d x^j}{dt}) \partial_j \quad \text{by chain rule} \\ &= \frac{d x^i}{dt}\frac{d x^j}{dt} \nabla_{\partial_i}{\partial_j} + \frac{d^2 x^{\textcolor{red}{j}}}{dt^2} \partial_{\textcolor{red}{j}} \\ &= \frac{d x^i}{dt}\frac{d x^j}{dt} \nabla_{\partial_i}{\partial_j} + \frac{d^2 x^k}{dt^2} \partial_k \\ &= \frac{d x^i}{dt}\frac{d x^j}{dt} \Gamma^k_{ij}\textcolor{red}{\partial_k} + \frac{d^2 x^k}{dt^2} \textcolor{red}{\partial_k} \quad \text{by } \nabla_{\partial_i}\partial_j = \Gamma^k_{ij}\partial_k \\ &= (\frac{d x^i}{dt}\frac{d x^j}{dt} \Gamma^k_{ij} + \frac{d^2 x^k}{dt^2}) \textcolor{red}{\partial_k} \end{aligned}

因此測地線方程組就是指

d2xkdt2+dxidtdxjdtΓijk=0,∀k=1,…,n\frac{d^2 x^k}{dt^2} + \frac{d x^i}{dt}\frac{d x^j}{dt} \Gamma^k_{ij} = 0, \quad \forall k=1,\dots,n

The Basel problem with trigonometric Fourier series [math-0016]

An idea is define f(x)=x2f(x) = x^2 on [−π,π][-\pi, \pi]. Its trigonometric Fourier series was:

a02+∑n=1∞(ancos⁡(nx)+bnsin⁡(nx))\frac{a_0}{2} + \sum_{n=1}^{\infty}(a_n \cos(nx)+b_n \sin(nx))

which is periodic and converges to f(x)f(x) in [−π,π][-\pi,\pi].

Observing that f(x)f(x) is even, hence

bn=1π∫−ππf(x)sin⁡(nx) dx=0b_n = \frac{1}{\pi} \int_{-\pi}^{\pi} f(x)\sin(nx)\,dx = 0

for all n=1,2,3,…n = 1,2,3,\dots. Now compute a0a_0

a0=1π∫−ππx2 dx=2π∫0πx2 dx=2π[x33]0π=2ππ33=2π23\begin{aligned} a_0 &= \frac{1}{\pi} \int_{-\pi}^{\pi} x^2\,dx = \frac{2}{\pi}\int_{0}^{\pi} x^2\,dx \\ &= \frac{2}{\pi} \left[\frac{x^3}{3}\right]_0^\pi \\ &= \frac{2}{\pi} \frac{\pi^3}{3} = \frac{2\pi^2}{3} \end{aligned}

and each ana_n is

an=1π∫−ππx2cos⁡(nx) dx=2π∫0πx2cos⁡(nx) dx\begin{aligned} a_n &= \frac{1}{\pi} \int_{-\pi}^{\pi} x^2\cos(nx)\,dx \\ &= \frac{2}{\pi} \textcolor{red}{\int_{0}^{\pi} x^2\cos(nx)\,dx} \end{aligned}

Now let's focus on integral by part

∫x2cos⁡(nx) dx=x2(∫cos⁡(nx) dx)−∫2x(∫cos⁡(nx) dx) dx=x2sin⁡(nx)n−2∫xsin⁡(nx)n dx\begin{aligned} \textcolor{red}{\int x^2\cos(nx)\,dx} &= x^2(\int \cos(nx)\,dx) - \int 2x (\int \cos(nx)\,dx)\,dx \\ &= x^2 \frac{\sin(nx)}{n} - 2 \textcolor{blue}{\int x \frac{\sin(nx)}{n}\,dx} \end{aligned}

and again

∫xsin⁡(nx)n dx=x∫sin⁡(nx)n dx−∫1(∫sin⁡(nx)n dx) dx=x−cos⁡(nx)n2−∫−cos⁡(nx)n2 dx=x−cos⁡(nx)n2−−sin⁡(nx)n3\begin{aligned} \textcolor{blue}{\int x \frac{\sin(nx)}{n}\,dx} &= x \int\frac{\sin(nx)}{n}\,dx - \int 1 (\int\frac{\sin(nx)}{n}\,dx)\,dx \\ &= x \frac{-\cos(nx)}{n^2} - \int \frac{-\cos(nx)}{n^2}\,dx \\ &= x \frac{-\cos(nx)}{n^2} - \frac{-\sin(nx)}{n^3} \end{aligned}

It seems complicated, but in fact we have sin⁡(nπ)=0\sin(n\pi) = 0, hence we can ignore them in this definite integral

an=2π[2xcos⁡(nx)n2]0π=2π2πcos⁡(nπ)n2=4cos⁡(nπ)n2=4(−1)nn2=(−1)n4n2\begin{aligned} a_n &= \frac{2}{\pi} \left[ \frac{2 x \cos(nx)}{n^2} \right]_0^\pi \\ &= \frac{2}{\pi} \frac{2 \pi \cos(n \pi)}{n^2} \\ &= \frac{4 \cos(n \pi)}{n^2} \\ &= \frac{4 (-1)^n}{n^2} = (-1)^n \frac{4}{n^2} \end{aligned}

Therefore, if we compute f(π)f(\pi) can get

f(π)=π2=π23+∑n=1∞((−1)n4n2cos⁡(nπ))=π23+∑n=1∞((−1)n(−1)n4n2)=π23+∑n=1∞((−1)2n4n2)=π23+∑n=1∞(4n2)=π23+4∑n=1∞(1n2)\begin{aligned} f(\pi) &= \pi^2 \\ &= \frac{\pi^2}{3} + \sum_{n=1}^\infty ((-1)^n \frac{4}{n^2} \cos(n\pi)) \\ &= \frac{\pi^2}{3} + \sum_{n=1}^\infty ((-1)^n (-1)^n \frac{4}{n^2}) \\ &= \frac{\pi^2}{3} + \sum_{n=1}^\infty ((-1)^{2n} \frac{4}{n^2}) \\ &= \frac{\pi^2}{3} + \sum_{n=1}^\infty (\frac{4}{n^2}) \\ &= \frac{\pi^2}{3} + 4 \sum_{n=1}^\infty (\frac{1}{n^2}) \end{aligned}

Hence

2π23=4∑n=1∞(1n2)π26=∑n=1∞(1n2)\frac{2\pi^2}{3} = 4 \sum_{n=1}^\infty (\frac{1}{n^2}) \\ \frac{\pi^2}{6} = \sum_{n=1}^\infty (\frac{1}{n^2})

Definition Impredicative [tt-000V]

參考 https://github.com/AndrasKovacs/elaboration-zoo/tree/master/06-first-class-poly

In type theory [local-0]

A universe is impredicative if function types whose codomains are in the universe are always in the universe, regardless of their domain types.

foo:(a:Uk)→…\text{foo} : (a : U_k) \to \ldots

如果 foo:Uk\text{foo} : U_k 可以通過檢查,這個 Universe UkU_k 就是 impredicative 的,有 impredicative universe 存在的類型理論就叫做有 impredicativity。像 Rocq 或是 Lean 都有特殊的 Prop universe 有這樣的特性。

In Elaboration algorithm [local-1]

An elaboration algorithm is impredicative if it is able to solve metavariables to implicit function types.

RP1\R P^1 is diffeomorphic to S1S^1 [math-0015]

Construction

  1. Ua=S1−(0,1)U_a = S^1 - (0,1) and φa(u,v)=u1−v\varphi_a(u,v) = \frac{u}{1-v}
  2. Ub=S1−(0,−1)U_b = S^1 - (0,-1) and φb(u,v)=u1+v\varphi_b(u,v) = \frac{u}{1+v}

and RP1\R P^1 use

  1. U1={[x:y]∣x≠0}U_1 = \{[x:y] \mid x\ne0\} and φ1([x:y])=yx\varphi_1([x:y]) = \frac{y}{x}
  2. U2={[x:y]∣y≠0}U_2 = \{[x:y] \mid y\ne0\} and φ1([x:y])=xy\varphi_1([x:y]) = \frac{x}{y}

The diffeomorphism ψ:RP1→S1\psi : \R P^1 \to S^1 defined as

ψ(p=[x:y])={φa−1∘φ1 if p∈U1φb−1∘φ2 if p∈U2\psi(p=[x:y]) = \begin{cases} \varphi_a^{-1} \circ \varphi_1 \text{ if } p\in U_1 \\ \varphi_b^{-1} \circ \varphi_2 \text{ if } p\in U_2 \end{cases}

Given [x:y][x:y] we have a ratio k=y/xk = y/x, we want to recover a point (u,v)(u,v) on S1S^1, how to get this inverse map? The idea is

k=u1−v  ⟹  k(1−v)=u  ⟹  k2(1−v)2=u2  ⟹  k2(1−v)2+v2=1  ⟹  k2(1−2v+v2)+v2=1  ⟹  (k2+1)v2−2k2v+k2=1  ⟹  (k2+1)v2−2k2v+(k2−1)=0k = \frac{u}{1-v} \implies k(1-v)=u \\ \implies k^2(1-v)^2=u^2 \\ \implies k^2(1-v)^2 + v^2=1 \\ \implies k^2(1-2v+v^2) + v^2=1 \\ \implies (k^2+1) v^2 - 2k^2v + k^2=1 \\ \implies (k^2+1) v^2 - 2k^2v + (k^2-1)=0

Now we can use quadratic formula to solve vv (and remind that v≠1v \ne 1):

v=2k2±4k4−4(k2+1)(k2−1)2(k2+1)=2k2±2k4−(k2+1)(k2−1)2(k2+1)=k2±k4−(k2+1)(k2−1)k2+1=k2±k4−(k4−1)k2+1=k2±1k2+1v = \frac{ 2k^2 \pm \sqrt{4k^4 - 4(k^2+1)(k^2-1)} }{2(k^2+1)} = \frac{2k^2\pm2\sqrt{k^4-(k^2+1)(k^2-1)}}{2(k^2+1)} \\ = \frac{k^2\pm\sqrt{k^4-(k^2+1)(k^2-1)}}{k^2+1} \\ = \frac{k^2\pm\sqrt{k^4-(k^4-1)}}{k^2+1} = \frac{k^2\pm1}{k^2+1}

However, v≠1v \ne 1 hence

v=k2−1k2+1v = \frac{k^2-1}{k^2+1}

By this we can see

u=2kk2+1u = \frac{2k}{k^2+1}

Therefore, φa−1\varphi_a^{-1} is

φa−1(k)=(2kk2+1k2−1k2+1)\varphi_a^{-1}(k) = \begin{pmatrix} \frac{2k}{k^2+1}\\ \frac{k^2-1}{k^2+1} \end{pmatrix}

The similiar reasoning can show

φb−1(k)=(2kk2+11−k2k2+1)\varphi_b^{-1}(k) = \begin{pmatrix} \frac{2k}{k^2+1}\\ \frac{1-k^2}{k^2+1} \end{pmatrix}

Hence, for U1∩U2U_1 \cap U_2 (i.e. x≠0∧y≠0x \ne 0 \land y \ne 0) we have

φa−1∘φ1=φb−1∘φ2\varphi_a^{-1} \circ \varphi_1 = \varphi_b^{-1} \circ \varphi_2

By component, first check uu:

2y/xy2/x2+1=2y/x(x2+y2)/x2=2yx2(x2+y2)x=2xyx2+y2and2x/yx2/y2+1=2x/y(x2+y2)/y2=2xy2(x2+y2)y=2xyx2+y2\frac{2 y/x}{y^2/x^2 + 1} = \frac{2 y/x}{(x^2+y^2)/x^2} = \frac{2 y x^2}{(x^2+y^2)x} = \frac{2 xy}{x^2+y^2} \\ \text{and} \\ \frac{2 x/y}{x^2/y^2 + 1} = \frac{2 x/y}{(x^2+y^2)/y^2} = \frac{2 xy^2}{(x^2+y^2)y} = \frac{2 xy}{x^2+y^2}

Then check vv:

(y/x)2−1(y/x)2+1=y2−x2y2+x2and1−(x/y)2(x/y)2+1=y2−x2x2+y2\frac{(y/x)^2-1}{(y/x)^2+1} = \frac{y^2-x^2}{y^2+x^2} \\ \text{and} \\ \frac{1-(x/y)^2}{(x/y)^2+1} = \frac{y^2-x^2}{x^2+y^2}

So ψ\psi is indeed well defined, and smooth on it domain, the inverse defined as

ψ−1(p=(u,v))={φ1−1∘φa if p∈Uaφ2−1∘φb if p∈Ub\psi^{-1}(p=(u,v)) = \begin{cases} \varphi_1^{-1} \circ \varphi_a \text{ if } p\in U_a \\ \varphi_2^{-1} \circ \varphi_b \text{ if } p\in U_b \end{cases}

where φ1−1(a)=[1:a]\varphi_1^{-1}(a) = [1 : a] and φ2−1(b)=[b:1]\varphi_2^{-1}(b) = [b : 1] because the equivalence. These maps are smooth on u,vu,v and agree each other (inverse the ratio because the position) when meet hence well defined. Hence ψ\psi is a diffeomorphism.

Proposition U3U_3 is open [math-4M36]

Let U3⊂RP2U_3 \subset \mathbb{R}P^2 the set of those lines that intersect P3:={(x1,x2,x3)∣x3=1}P_3 := \{(x_1,x_2,x_3) \mid x_3 = 1\}.

Proof [local-0]

By definition, U3⊂RP2U_3 \subset \mathbb{R}P^2 is open if and only if its preimage in S2S^2 is open (its preimage under the map p:S2→RP2p : S^2 \to \mathbb{R}P^2).

V3:=p−1(U3)={(x1,x2,x3)∈S2∣x3≠0} V_3 := p^{-1}(U_3)= \{ (x_1,x_2,x_3)\in S^2 \mid x_3 \ne 0 \}

Hence, we want to prove V3V_3 is open in S2S^2. Because V3=S2−{(x1,x2,x3)∈R3∣x3≠0}V_3 = S^2 - \{(x_1,x_2,x_3) \in \mathbb{R}^3 \mid x_3 \ne 0\}, and S2S^2 inherits the topology of R3\mathbb{R}^3, so if we can show an open set W⊂R3W \subset \mathbb{R}^3 such that W∩S2=V3W \cap S^2 = V_3, then V3V_3 is an open set. Then we can see if we define W:=R3−{(x1,x2,x3)∈R3∣x3≠0}W := \mathbb{R}^3 - \{(x_1,x_2,x_3) \in \mathbb{R}^3 \mid x_3 \ne 0\}, it's open and W∩S2=V3W \cap S^2 = V_3, so V3V_3 is open in S2S^2 and U3U_3 is open in RP2\mathbb{R}P^2.

Definition Real Projective nn-space as quotient of SnS^n [math-UGKQ]

Another famous view is viewing RPn\mathbb{R}P^n as the quotient of the sphere SnS^n, because it’s obvious that each element (a line) of projective nn-space intersects SnS^n exactly two points, and the two points are antipodal points!

Use lal_a to represent an element of RPn\mathbb{R}P^n that intersects SnS^n at aa.

Therefore, if we make a quotient relation:

a∼b  ⟺  la=lb  ⟺  a=±ba \sim b \iff l_a = l_b \iff a = \pm b

Then we can see that RPn≃Sn/∼\mathbb{R}P^n \simeq S^n/\sim, this homeomorphism can be used to transfer the CrC^r-structure on SnS^n to RPn\mathbb{R}P^n.

Definition Jacobian matrix [math-0014]

Let f:U⊂Rn→Rmf : U \subset \R^n \to \R^m be a map, hence we can view each mm component is a function Rn→R\R^n \to \R:

f(x1,x2,…,xn)=(f1(x1,…,xn)f2(x1,…,xn)⋮fm(x1,…,xn))f(x^1, x^2, \dots, x^n) = \begin{pmatrix}f_1\left(x^1,\ldots,x^{n}\right)\\ f_2\left(x^1,\ldots,x^{n}\right)\\ \vdots\\ f_{m}\left(x^1,\ldots,x^{n}\right) \end{pmatrix}

with respect to standard bases, and a∈Rna \in \R^n, Df∣aDf\left|_{a}\right. is given by the m×nm \times n matrix of partial derivatives (the Jacobian matrix) in the following sense

Df∣av=(∂f1∂x1(a)∂f1∂x2(a)⋯∂f1∂xn(a)∂f2∂x1(a)∂f2∂x2(a)⋯∂f2∂xn(a)⋮⋮⋱⋮∂fm∂x1(a)∂fm∂x2(a)⋯∂fm∂xn(a))⏞n()}m(v1v2⋮vn)Df\left|_{a}\right.v=\overbrace{\begin{pmatrix}\frac{\partial f_1}{\partial x^1}\left(a\right) & \frac{\partial f_1}{\partial x^2}\left(a\right) & \cdots & \frac{\partial f_1}{\partial x^{n}}\left(a\right)\\ \frac{\partial f_2}{\partial x^1}\left(a\right) & \frac{\partial f_2}{\partial x^2}\left(a\right) & \cdots & \frac{\partial f_2}{\partial x^{n}}\left(a\right)\\ \vdots & \vdots & \ddots & \vdots\\ \frac{\partial f_{m}}{\partial x^1}\left(a\right) & \frac{\partial f_m}{\partial x^2}\left(a\right) & \cdots & \frac{\partial f_m}{\partial x^{n}}\left(a\right)\end{pmatrix}}^{n}\left.\vphantom{ \begin{pmatrix} \\ \\ \\ \\ \end{pmatrix} }\right\rbrace m\begin{pmatrix}v^1\\ v^2\\ \vdots\\ v^{n}\end{pmatrix}

Or using the index notation, so ω=Df(a)v\omega=Df\left(a\right)v can be expressed as:

ωi=∑j∂fi∂xj(a)vj\omega^{i}=\sum_{j}\frac{\partial f_{i}}{\partial x^{j}}\left(a\right)v_{}^{j}

Type system 的 Soundness 與 Completeness [tt-000S]

  1. 我們說型別系統 sound 的時候,意思是如果一隻程式的型別不正確,系統就不會接受這隻程式。這蘊含了如果程式被系統接受 (type-checked),那就一定是沒有類型錯誤的程式。

  2. 我們說型別系統 complete 的時候,意思是如果一隻程式的型別正確,就一定會被系統接受。

我們通常更偏好滿足 soundness,因為有型別錯誤卻被接受的程式,因為比起有幾個需要改寫幾隻程式的麻煩,unsound 往往能造成更大的問題。

Definition Predicative [tt-000R]

Definition Injectivity [tt-000Q]

Counterexamples in Type Systems

如果我們說一個型別建構子 FF 是 Injective,那麼意思是如果 F[A]=F[B]F[A] = F[B] 則 A=BA = B。

一個程式語言的各個參數化型別不必然都具有這個特性。

代數幾何:非常基本的部分 [math-XGSJ]

代數幾何的核心物件是:多個多項式等式構成的系統

  1. 有 nn 個變數,記為 xnx_n
  2. 有 kk 個多項式

幾何上我們就是研究 Cn\mathbb{C}^n 中解集的軌跡。代數上我們就是研究

A=C[x]/⟨f1,…,fk⟩A = \mathbb{C}[x]/\langle f_1, \dots, f_k \rangle

這個 algebra。事實上任何有限生成 ring 都可以表示成這個形式:AA finitely generated 表示存在一個 surjective map C[X]→A\mathbb{C}[X] \to A,然後 Hilbert Basis theorem 說明這個 map 的 kernel 可以用有限個元素生成。

⟨f1,…,fk⟩\langle f_1, \dots, f_k \rangle 這個理想是由 linear combinations ∑igifi=g1f1+⋯+gkfk\sum_i g_i f_i = g_1f_1 + \cdots + g_kf_k 的形式組成的,其中 gi∈C[x]g_i \in \mathbb{C}[x] 是多項式

Definition maximal ideal [math-0013]

A maximal ideal AA of a commutative ring RR is a proper ideal of RR such that, whenever BB is an ideal of RR and A⊂B⊂RA \subset B \subset R, then B=AB = A or B=RB = R.

An equivalent condition is R/AR / A is a field if and only if AA is maximal.

Definition prime ideal [math-0012]

Let AA be a ring and II be an ideal, the followings are equivalent conditions to say that II is prime

  1. II is prime if ab∈Iab \in I than a∈Ia \in I or b∈Ib \in I for all a,b∈Aa,b \in A
  2. II is prime if A/IA / I is an integral domain

Proof [local-2]

Backward [local-0]

Let A/IA / I be an integral domain, that's say if x,y∈A/Ix, y \in A / I and xy=0xy = 0, then x=0x = 0 or y=0y = 0. Let (a+I)(b+I)(a + I)(b + I) be the zero element of II (i.e. (0∈A)+I(0 \in A) + I), then ab+I=Iab + I = I. Hence a+I=Ia + I = I or b+I=Ib + I = I, implies a∈Ia \in I or b∈Ib \in I.

Forward [local-1]

Let II be a prime ideal, let

(a+I)(b+I)=0+I=I(a+I)(b+I)=0+I = I

then ab∈Iab \in I and therefore, a∈Ia \in I or b∈Ib \in I. Hence a+Ia + I or b+Ib + I is the zero coset in A/IA / I.

Algorithm 君主選舉 [cs-000I]

前提

  1. 每個節點入場的時候都分配到一個代數(generation),這個數字是唯一的
  2. 第一個啟動節點直接當選

當原始的領導者掛了(一段時間無回應),注意到這點的節點就開始問比自己老的所有節點是不是還活著

  1. 收到 alive 回應,或是得到其他更高優先順序的候選節點資訊。
  2. 從中選出最老(代數數字最小)的節點告知它當選了,當選節點會廣播自己當選的消息。

問題 [local-0]

  1. 注意到領導者無回應而發起投票的節點可以超過一個
  2. 兩個發起投票的節點有連線的節點當然可能不同

比如 5 6 都注意到 1 死亡,發起投票。3 4 跟 5 有連線於是選出 2;2 3 跟 6 有連線於是選出 3。這時候 2 3 就都覺得自己是領導者了,而且 5 對 6 的通知還是更不正確的結果。

當然補上當選節點廣播之後,較年輕的當選者會自己去除這個屬性也是可以,但這中間會有一小段時間可能發生(以資料庫而言)雙重寫入而遺失資料。

而且要注意到實際上當然可以比這麻煩的多,比如通訊密集時,更容易讓 leader 過載;同時 90% 的節點都發現這點並發起投票,那麼消除腦分裂前的混亂就會特別嚴重。

Internal language 之用 [math-0011]

這是 An informal introduction to topos theory 的閱讀筆記,Leinster 在這裡說 generalized elements 可以說是 Category 的 internal language。而 set theoretic 裡面使用 element 的論證多半都能改用這樣的語言進行,甚至,不使用 LEM 與 AC 的構造式證明,可以在任意 topos 中使用。

除了在 Generalized element 已經討論過的 product (x,y)(x, y),topos 還有 exponentials YXY^X,equalizer 也可以記為

{x∈X∣fx=gx}\{ x \in X \mid f x = g x \}

表示 X⇉YX \rightrightarrows Y。

這樣就無需使用大量的 diagram,而是採用數學家已經熟悉的集合式的論證即可。

Definition Generalized element [math-0010]

Let E\mathcal{E} be a category, and let AA be an object of E\mathcal{E}. A generalized element of AA is simply a map in E\mathcal{E} with codomain AA.

A generalized element x:S→Ax : S \to A is shape SS or SS-element of AA.

When S=1S = 1 (the terminal) then SS-elements are called global elements.

Global elements can be very boring, for example in the category of groups.

The language of generalized elements is the internal language of the category. For example, let E\mathcal{E} be a category with finite products. An SS-element of X×YX \times Y consists of two component x:S→X,y:S→Yx : S \to X, y : S \to Y and is denoted by (x,y)(x,y), hence extended the notation of set-theoretic Cartesian product of global elements.

Definition Immersion, embedding, and submanifold [math-000Z]

Let M,NM, N be differentiable manifolds (dimensions are mm and nn respectively). A differentiable map φ:M→N\varphi : M \to N is said to be an immersion if

dφp:TpM→Tφ(p)Nd \varphi_p : T_pM \to T_{\varphi(p)} N

is injective for all p∈Mp \in M.

If in addition, φ\varphi is a homeomorphism onto φ(M)⊂N\varphi(M) \subset N, where φ(M)\varphi(M) has the subspace topology induced from NN, then φ\varphi is an embedding.

If M⊂NM \subset N and the inclusion M⊂NM \subset N is an embedding, then MM is a submanifold of NN.

Proposition Right adjoint fully faithful <=> counit is isomorphism [math-000Y]

Suppose F⊣GF \dashv G is an adjunction, and G:B→AG : B \to A is fully faithful, then counit ε:FG→1B\varepsilon : FG \to 1_B is an isomorphism

Proof [local-2]

Forward direction [local-0]

To prove counit εB:FG(B)→B\varepsilon_B : FG(B) \to B is an isomorphism, we need to find an inverse ε−1\varepsilon^{-1} and show pre and post composition of them are identity. Let ε−1:=G−1η\varepsilon^{-1} := G^{-1}\eta, then we have two targets

  1. ε−1≫ε=idX\varepsilon^{-1} \gg \varepsilon = id_X

    Apply GG to get

    GG−1η=Gε−1≫Gε=idG(X)\boxed{G G^{-1} \eta = G \varepsilon^{-1}} \gg G \varepsilon = id_{G(X)}

    hence the target is η≫Gε=idG(X)\eta \gg G \varepsilon = id_{G(X)}, right triangle fills the target.

  2. ε≫ε−1=idFG(X)\varepsilon \gg \varepsilon^{-1} = id_{FG(X)}

    Use counit naturality on ε−1\varepsilon^{-1} to get

    Fη≫εFG(B)=εB≫ε−1=G−1ηF \eta \gg \varepsilon_{FG(B)} = \varepsilon_B \gg \boxed{\varepsilon^{-1} = G^{-1}\eta}

    Therefore, we have target Fη≫εFG(B)=idFG(X)F \eta \gg \varepsilon_{FG(B)} = id_{FG(X)}, left triangle fills the target.

Backward direction [local-1]

For GG is faithful, we want to know if Gf=GgGf = Gg then f=gf = g. We first obtain two equations via naturality of counit:

FGf≫εY=εX≫fFGg≫εY=εX≫g\begin{align*}FGf \gg \varepsilon_Y = \varepsilon_X \gg f \\ FGg \gg \varepsilon_Y = \varepsilon_X \gg g\end{align*}

Replace GfGf with GgGg then we have εX≫f=εX≫g\varepsilon_X \gg f = \varepsilon_X \gg g, counit is an isomorphism and hence left-cancellable, f=gf = g.

For GG is full, we want to show every ff there is a aa such that Ga=fG a = f. Let a=εX−1≫φ−1fa = \varepsilon_X^{-1} \gg \varphi^{-1} f (where φ\varphi is the hom-set equivalence of adjunction), this is same as asking

G(εX−1)=ηGXG(\varepsilon_X^{-1}) = \eta_{GX}

because isomorphism property, we have

G(εX−1)= G(εX−1≫εX)= G(εX−1)≫G(εX)= ηGX≫G(εX)\begin{align*}&G(\varepsilon_X^{-1}) \\ =\ &G(\varepsilon_X^{-1} \gg \varepsilon_X) \\ =\ &G(\varepsilon_X^{-1}) \gg G(\varepsilon_X) \\ =\ &\eta_{GX} \gg G(\varepsilon_X)\end{align*}

now we use isomorphism to cancel right, so G(εX−1)=ηGXG(\varepsilon_X^{-1}) = \eta_{GX}.

Counterexample pp no need to be identity when p≫f=fp \gg f = f [math-000X]

The counterexample in the category of sets is

p:2→2p=notf:2→1f(b)=⋆\begin{align*} &p : 2 \to 2 \\ &p = not \\ &f : 2 \to 1 \\ &f(b) = \star \end{align*}

We have f(p(x))=f(x)f(p(x)) = f(x) for all x:2x : 2, but pp is not identity. Where 1,21, 2 represent the set with 11 and 22 elements, respectively.

tr-notes transclude 的發展 [tr-0007]

tr 最開始我的想法是讓每一張卡片自己都輸出一個 HTML 網頁,然後就想到「哎糟糕,被嵌入 (transclude 概念) 的網頁會有重複的共用元素」就放棄了,當時認為所以必須像 forester 那樣用 XML 才行

好久之後我再次考慮(2025/05)實現一個 forester fork 時才想到,只要每張卡生成一個 a.index.html 一個 a.embed.html 就可以避免重複元素了

順著這個想法我用 iframe 嵌入來實現功能,直到我實在解不開 JS 的工作空間問題,這逼我思考其他方案。結果過了幾天我想到其實根本不用這麼麻煩xd,transclude 直接讀 embed 的內容就好了(並且 escape 排版確保不破壞 pre tag 等對排版敏感的內容)

現在剩下的問題就是其實 index 其實也沒必要再用 racket 生成一次,而是應該把 header, footer 等內容插入,讀取自己的 embed 檔案,但目前耦合比較多(依靠 generate-index? 判斷是否生成這些區塊),需要重新思考怎麼編排這些程式

魔物獵人荒野 充能斧 操作筆記 [game-0000]

基本操作 [local-0]

  • △: 劍 牽制斬
  • △ + O: 劍 突進斬
  • O 長按: 劍 蓄力上撈斬
  • R2 + △: 劍 變形斬
  • R2 + O: 劍 充能

強化瓶系統 [local-1]

最有效率的集氣連技是: O 長按 → △

但魔物太靈活時這樣可能會一直落空,不一定要堅持這樣打

充能模式 [local-5]

1. 充能盾牌(紅盾) [local-2]

架盾操作:
  1. R2 + O 之後保持 O 不放開
  2. △ + O 三次接 R2
    • 突進斬
    • 盾突刺
    • 高解
    • 屬性強化迴旋斬

2. 充能劍(紅劍) [local-3]

操作流程:
  • R2 + O 後按住 △ 進行蓄力
  • 放開後打出「劍:高壓屬性斬」

3. 充能斧(紅斧) [local-4]

觸發條件有三種(任何一個達成就會觸發紅斧模式):
  1. L2 瞄準用 R1 集中攻擊打到傷口(必須命中才會觸發)
  2. 精準防禦之後按 △
  3. 騎乘打出處決後觸發

出紅斧是為了能長按攻擊鍵 △ 或是 O 時,斧會持續輸出而不是只有一次輸出

Proposition Christoffel 等於 0 iff g 是常數(平直空間) [math-GDOS]

Christoffel 定義為

Γijk=12(∂∂xigjk+∂∂xjgki−∂∂xkgij)\Gamma_{ijk} = \frac{1}{2}( \frac{\partial}{\partial x^i}g_{jk} + \frac{\partial}{\partial x^j}g_{ki} - \frac{\partial}{\partial x^k}g_{ij} )

Proof [local-0]

(<=) gg 是常數表示微分為 00,因此 Christoffel Γijk=0\Gamma_{ijk} = 0

(=>) 因為

Γijk+Γjki=12(∂∂xigjk+∂∂xjgki−∂∂xkgij)+12(∂∂xjgki+∂∂xkgij−∂∂xigjk)=∂∂xjgki\begin{aligned} \Gamma_{ijk} + \Gamma_{jki} & = \frac{1}{2}( \frac{\partial}{\partial x^i}g_{jk} + \frac{\partial}{\partial x^j}g_{ki} - \frac{\partial}{\partial x^k}g_{ij} ) + \frac{1}{2}( \frac{\partial}{\partial x^j}g_{ki} + \frac{\partial}{\partial x^k}g_{ij} - \frac{\partial}{\partial x^i}g_{jk} ) \\ & = \frac{\partial}{\partial x^j}g_{ki} \end{aligned}

對兩邊取積分可知 gki=Cg_{ki} = C

Naturality cannot be given by a family of isomorphisms [math-000S]

This is came from when I'm formalizing lemma 1.3.11 of Basic Category Theory, I miss a precondition (HH below must be a natural transformation in the lemma) and try to prove an impossible thing.

Let F,G:C→DF, G : \mathcal{C} \to \mathcal{D} be functors, and a family

H:(X:C)↦FX≅GXH : (X : C) \mapsto F X \cong G X

Does HH must be natural?

Counterexample [math-000T]

The result is HH can be not natural.

This counterexample is given by Zhixuan Yang:

Let C\mathcal{C} be the two-object one-arrow category, and D\mathcal{D} be SetSet, and

F,G:0→1↦2→id2F, G : 0 \to 1 \mapsto 2 \xrightarrow{id} 2

where 22 is the two elements set. For 00 we choice H(0)=idH(0) = id and H(1)=notH(1) = \text{not}, then HH is not natural.

Definition exterior algebra [math-000R]

The exterior algebra of vector space VV is defined as a Z\mathbb{Z}-graded algebra:

Λ∙V:=⨁r≥0ΛrV\Lambda^\bullet V := \bigoplus_{r \ge 0} \Lambda^r V

Definition Homotopy extension property (HEP) [math-000O]

A map i:A→Xi : A \to X of spaces has the homotopy extension property for a space YY if

  1. for each homotopy H:A×I→YH : A \times I \to Y
  2. and for each map f:X→Yf : X \to Y with f(i(a))=H(a,0)f(i(a)) = H(a, 0) for all a∈Aa \in A

there is a homotopy H′:X×I→YH' : X \times I \to Y such that

H′(i(a),t)=H(a,t)H′(x,0)=f(x)\begin{align*} &H'(i(a), t) &= &H(a, t) \\ &H'(x, 0) &= &f(x) \end{align*}

for all a∈Aa \in A, x∈Xx \in X and t∈It \in I. The idea can be expressed in the following commutative diagram:

figure tex15697

The homotopy H′H' is called the extension of HH with initial condition ff.

Definition Natural Transformation [math-000N]

Let C\mathcal{C} and D\mathcal{D} be categories, let F,G:C→DF, G : \mathcal{C} \to \mathcal{D} be functors. A natural transformation α:F⇒G\alpha : F \Rightarrow G is a function consists of

  1. For each X∈CX \in \mathcal{C}, there is a morphism αX:F(X)→G(X)\alpha_X : F(X) \to G(X) in D\mathcal{D}, called the XX-component of α\alpha
  2. For every morphism f:X→Yf : X \to Y in C\mathcal{C}, there is a commute diagram
    figure tex15274

常青筆記的困難 [note-0001]

Sterling 的 https://www.forester-notes.org/QHXX/index.xml 精確的描述了常青筆記可能遭遇的困難,關鍵在於,常青筆記對於不停變化的目標,如數學、電腦程式框架等存在,本體論的目標並不統一。用數學為例,我們傳統上接受 ZFC 作為「集合論」的本體,但 topos theory 的發展給出另一套定義 ETCS https://en.wikipedia.org/wiki/Elementary_Theory_of_the_Category_of_Sets!ETCS 說我們覺得集合論是「由 sets 與 functions 構成的 well-pointed topos,有自然數 object 與 Epics split」。

這個定義並沒有循環定義(但使用了短語簡化說法),因為 sets 跟 functions 的公理可以直接給出,ETCS 並沒有比 ZFC 不穩固。

事實上我們甚至知道 ETCS 跟 ZFC 的差異,ETCS + replacement(https://en.wikipedia.org/wiki/Axiom_schema_of_replacement)等價於 ZFC 的推理能力。ZFC 中的某部份等價於 ETCS(參考 Sheaves in Geometry and Logic: A First Introduction to Topos Theory VI. 10)

重點是,既然沒辦法保證討論主題的永久不變,那就應該紀錄當下對主題的洞見,因而在未來仍可從思想中復原出結構。

Definition Pfaffian [math-000P]

Let AA be a skew-symmetric endomorphism of a vector space VV (hence AA can also be view as a tensor: A∈Λ2VA \in \Lambda^2 V) and N=dim⁡VN = \dim{V} is even, the Pfaffian of AA is the number Pf A\text{Pf}\ A defined as the constant factor in the tensor equality:

(Pf A)e1∧⋯∧eN=1(N/2)!A∧⋯∧A⏟N/2 times(\text{Pf}\ {A}) e_1 \wedge \dots \wedge e_N = \frac{1}{(N/2)!} \underbrace{A \wedge \dots \wedge A}_{N/2\ times}

where {e1,…,eN}\{ e_1,\dots,e_N \} is an orthonormal basis of VV.

The sign of Pfaffian depends on the orientation of the orthonormal basis.

An Agda Framework for Synthetic Mathematics [math-000K]

Theorem Borsuk–Ulam [math-000L]

If f:Sn→Rnf : S^n \to \R^n is continuous then there exists a point x∈Snx \in S^n such that f(x)=f(−x)f(x) = f(-x).

Lemma [math-000M]

If f:Sn→Rnf : S^n \to \R^n is continuous and antipode-preserving, then there exists a point x∈Snx \in S^n such that f(x)=0f(x) = 0.

Proof [local-0]

Use standard stereographic projection, we can see NN and SS charts gives exactly the same coordinate system at equator (i.e. where its embedding coordinate (x1,…,xn+1)(x_1, \dots, x_{n+1}) with xn+1=0x_{n+1} = 0). This also tells the equator is a Sn−1S^{n-1} in Rn\R^n because x12+⋯+xn2=1x_1^2 + \dots + x_n^2 = 1.

By continuous and antipode-preserving, ff preserves such an equator (we denote EE) to Sn−1S^{n-1} (with any deformation that still an antipode shape) and f(E)f(E) must bound a set contains 0∈Rn0 \in \R^n.

By continuous, both of two open sets of SnS^n, complement of EE, needs to be mapped to cover the subset of Rn\R^n which bounded by f(E)f(E), so there exists a point x∈Snx \in S^n such that f(x)=0f(x) = 0.

Proof [local-0]

Define g(x)=f(x)−f(−x)g(x) = f(x) - f(-x), gg is continuous.

By

g(x)=f(x)−f(−x)=−(f(x)−f(−x))=−g(−x)g(x) = f(x) - f(-x) = -(f(x) - f(-x)) = -g(-x)

gg is antipode-preserving.

By the lemma, there is a point x∈Snx \in S^n such that g(x)=0g(x) = 0, so f(x)−f(−x)=0f(x) - f(-x) = 0 then f(x)=f(−x)f(x) = f(-x).

Determinant of Skew-Symmetric Matrices [math-000V]

This problem arose from studying the book Lectures on the Geometry of Manifolds: Suppose VV is a real vector space, and ω:V×V→R\omega : V \times V \to \mathbb{R} is a symplectic duality, then VV has even dimension.

I can make some concrete computation on dimension 2 and 3 and roughly understand the reason, but I have no general proof.

After a month, I found a solution:

Proof Using the properties of matrix column operations [math-000W]

Since the multiplication factor of a matrix column can be extracted as a basis, flip the column 1 (i.e. the whole column multiply −1-1) we have

det⁡(A)=−1⋅det⁡(Aflip1)\det(A) = -1 \cdot \det(A_{\text{flip1}})

Following this pattern, flipping column 2 gives us:

det⁡(A)=(−1)⋅(−1)⋅det⁡(Aflip1,flip2)\det(A) = (-1) \cdot (-1) \cdot \det(A_{\text{flip1,flip2}})

Let AA be an n×nn \times n skew-symmetric matrix. After flipping all nn columns, we obtain −A-A, therefore

det⁡(A)=(−1)n⋅det⁡(−A)\det(A) = (-1)^n \cdot \det(-A)

By definition, skew-symmetric means −A=AT-A = A^T, so

det⁡(A)=(−1)n⋅det⁡(AT)\det(A) = (-1)^n \cdot \det(A^T)

When nn is odd, this gives us

det⁡(A)=−det⁡(AT)=−det⁡(A)\det(A) = -\det(A^T) = -\det(A)

Therefore det⁡(A)\det(A) must be 0.

After formalize this statement https://github.com/dannypsnl/blackboard/commit/2c0de90a98c24ae57bd30bc47ed8c3b6a75f2664, I found this need the field is charateristic 0, sure R\mathbb{R} indeed satisfies that, this point to me is that Lean can help me refine my ideas.

If AA represents a duality, then det⁡(A)≠0\det(A) \neq 0. Therefore nn cannot be odd—it must be even.

What I Wish I Knew When Learning HoTT [tt-000P]

Dependent Pattern Matching [ag-0001]

Lecture Domain Theory [dt-0000]

Programming in pcas [math-WE2N]

Categorical Realizability

Everything here works over a pca A\mathcal{A}.

Definition term [local-0]

Fix a countably infinite set of variables, inductively define the set of terms over a pca A\mathcal{A}:

  1. a variable is a term,
  2. an element of A\mathcal{A} is a term,
  3. given two terms ss and tt, we may form a new term s ts\ t.

Definition defined terms [local-1]

A closed term is defined if, when we interpret s ts\ t as ss applied to tt in A\mathcal{A}, all these applications are defined.

Extends to open term tt then is if all possible substitutions of all variables in tt by elements of A\mathcal{A}, the obtained closed term is defined.

Definition "λ\lambda-abstraction" in pca [local-2]

For a variable xx and a term tt, we can define a new term ⟨x⟩. t\langle x \rangle.\ t by recursion on terms:

  • ⟨x⟩. x≐I=S K K\langle x \rangle.\ x \doteq I = S\ K\ K,
  • ⟨x⟩. y≐K y\langle x \rangle.\ y \doteq K\ y if yy is a variable different from xx,
  • ⟨x⟩. a≐K a\langle x \rangle.\ a \doteq K\ a for a∈Aa \in \mathcal{A},
  • ⟨x⟩. (t1 t2)≐S(⟨x⟩. t1)(⟨x⟩. t2)\langle x \rangle.\ (t_1\ t_2) \doteq S(\langle x \rangle.\ t_1)(\langle x \rangle.\ t_2).

Notation [local-3]

⟨xy⟩. t\langle xy \rangle.\ t writes for ⟨x⟩. (⟨y⟩. t)\langle x \rangle.\ (\langle y \rangle.\ t)

Example [local-4]

Now, we can work on it, e.g.

true≐⟨xy⟩. xfalse≐⟨xy⟩. yif≐⟨x⟩. x\bold{true} \doteq \langle xy \rangle.\ x \\ \bold{false} \doteq \langle xy \rangle.\ y \\ \bold{if} \doteq \langle x \rangle.\ x

so

if true a b=aandif false a b=b\bold{if}\ \bold{true}\ a\ b = a \quad\text{and}\quad \bold{if}\ \bold{false}\ a\ b = b

Pair and projections are

pair≐⟨xyz⟩. zxyfst≐⟨w⟩. w truesnd≐⟨w⟩. w false\bold{pair} \doteq \langle xyz \rangle.\ zxy \\ \bold{fst} \doteq \langle w \rangle.\ w\ \bold{true} \\ \bold{snd} \doteq \langle w \rangle.\ w\ \bold{false}

Definition The category of assemblies over a pca [math-I7R9]

Categorical Realizability

First, we define map between assemblies.

Definition assembly map [local-0]

An assembly map from an assembly XX to an assembly YY is a function f:∣X∣→∣Y∣f : |X| \to |Y| that is tracked by some element.

Definition Track [math-GM4F]

For assemblies XX and YY, we say that an element t∈At \in \mathcal{A} tracks a function f:∣X∣→∣Y∣f : |X| \to |Y| if for all x∈∣X∣x \in |X| and a∈Aa \in \mathcal{A}, if a⊩Xxa \Vdash_X x, then t at\ a is defined and t a⊩Yf(x)t\ a \Vdash_Y f(x).

Then, we check assemblies and assembly maps form a category.

Proposition assemblies and assembly maps form a category [local-2]

Proof [local-1]

If f:X→Yf : X \to Y and g:Y→Zg : Y \to Z are assembly maps, then g∘f:∣X∣→∣Z∣g \circ f : |X| \to |Z| is tracked. Let tft_f and tgt_g track ff and gg respectively. We claim that ⟨x⟩. tg(tf(x))\langle x \rangle.\ t_g(t_f(x)) tracks g∘fg \circ f, the closed term ⟨x⟩. tg(tf(x))\langle x \rangle.\ t_g(t_f(x)) is defined by construction, and if a⊩Xxa \Vdash_X x then

(⟨x⟩. tg(tf(x))) a=tg(tf(a))⊩Zg(f(x))(\langle x \rangle.\ t_g(t_f(x)))\ a = t_g(t_f(a)) \Vdash_Z g(f(x))

by choice of tft_f and tgt_g. Then we need identity, for each assembly XX, II tracks any identity on ∣X∣|X|, so assemblies and assembly maps form a category.

Notation AsmA\text{Asm}_{\mathcal{A}} [local-3]

We denote AsmA\text{Asm}_{\mathcal{A}} for the category of assemblies over a pca A\mathcal{A}.

Example [local-4]

The trivial pca has Asm{⋆}=Set\text{Asm}_{\{ \star \}} = \text{Set}.

Proposition terminal object [local-5]

The terminal object 11 in AsmA\text{Asm}_{\mathcal{A}} is given by

∣1∣≐{⋆}anda⊩1⋆ for all a∈A|1| \doteq \{ \star \} \quad\text{and}\quad a\Vdash_1 \star\ \text{for all}\ a \in \mathcal{A}

Proposition products [local-6]

The product X×YX \times Y of two assemblies is given by

∣X×Y∣≐∣X∣×∣Y∣andpair a b⊩X×Y(x,y) for all a⊩Xx and b⊩Yy|X \times Y| \doteq |X| \times |Y| \quad\text{and}\quad \bold{pair}\ a\ b \Vdash_{X \times Y} (x, y) \ \text{for all}\ a \Vdash_X x \ \text{and}\ b \Vdash_Y y

Proposition exponentials [local-8]

The exponential YXY^X of two assemblies is given by

∣YX∣≐the set of assembly maps from X to Yandt⊩YXf if t tracks f|Y^X| \doteq \text{the set of assembly maps from}\ X\ \text{to}\ Y \quad\text{and}\quad t \Vdash_{Y^X} f\ \text{if}\ t\ \text{tracks}\ f

Proof [local-7]

The evaluation morphism ev:YX×X→Yev : Y^X \times X \to Y is given by (f,x)↦f(x)(f,x) \mapsto f(x) is tracked by ⟨x⟩. fst u(snd u)\langle x \rangle.\ \bold{fst}\ u(\bold{snd}\ u). Every g:Z×X→Yg : Z \times X \to Y induces a unique assembly map gˉ:Z→YX\bar{g} : Z \to Y^X making the commute diagram:

figure tex16543

Since there is a unique assignment gˉ(z)≐(x↦g(z,x))\bar{g}(z) \doteq (x \mapsto g(z, x)) and the assignment is tracked by ⟨u⟩. (⟨v⟩. tg(pair u v))\langle u \rangle.\ (\langle v \rangle.\ t_g(\bold{pair}\ u\ v)) when tgt_g tracks gg.

Proposition equalizers [local-9]

The equalizer EE of two assembly maps f,g:X→Yf,g : X \to Y is given by

∣E∣≐{x∈∣X∣∣f(x)=g(x)}anda⊩Ex if a⊩Xx|E| \doteq \{ x \in |X| \mid f(x) = g(x) \} \quad\text{and}\quad a \Vdash_E x\ \text{if}\ a \Vdash_X x

Proposition initial object [local-10]

The initial object 00 is given by ∣0∣≐∅|0| \doteq \varnothing with empty realizability relation (no element so empty realizability is fine).

Proposition coproducts [local-11]

The coproduct X+YX + Y is defined by

∣X+Y∣≐∣X∣+∣Y∣andleft a⊩X+Yinl(x) for a⊩Xxright b⊩X+Yinr(y) for b⊩Yy\begin{aligned} |X + Y| \doteq |X| + |Y| \quad\text{and}\quad \bold{left}\ &a \Vdash_{X+Y} \text{inl}(x)\ \text{for}\ a \Vdash_X x \\ \bold{right}\ &b \Vdash_{X+Y} \text{inr}(y)\ \text{for}\ b \Vdash_Y y \end{aligned}

where

left≐pair false and right≐pair true\bold{left} \doteq \bold{pair}\ \bold{false} \ \text{and}\ \bold{right} \doteq \bold{pair}\ \bold{true}

Proposition coequalizers [local-12]

The coequalizer CC of assembly maps f,g:X→Yf,g : X \to Y is given by

∣C∣≐∣Y∣/∼anda⊩C[y] if a⊩Yy′ for some y′∼y|C| \doteq |Y|/\sim \quad\text{and}\quad a \Vdash_C [y] \ \text{if}\ a \Vdash_Y y' \ \text{for some}\ y' \sim y

where ∼\sim is the least equivalence relation on ∣Y∣|Y| generated by f(x)∼g(x)f(x) \sim g(x) for all x∈∣X∣x \in |X|.

Course CS208 Logic & Algorithms [MSP-cs208]

Tool agda 的開發工具 [agda-0001]

我使用的編輯器工具是 Agda Mode on VS Code,也可以用 emacs 之類的。常用操作有

  • ctrl+c, ctrl+l 會編譯檢查檔案,假設程式中有 ?,會被替換成所謂的 hole {! !},其實就是待寫的程式

  • ctrl+c, ctrl+, 可以窺看 hole 的目標類型,與當前 context 有哪些 term 可用

  • ctrl+c, ctrl+r 會把 hole 中你打的程式碼往前提取,當然前提是類型是正確的

  • ctrl+c, ctrl+m 會把 hole 中你打的程式碼直接當成結果,一樣類型要是正確的

  • 一般來說一個 agda 定義如下

    hello : A → B
    hello a = {! !}

    ctrl+c, ctrl+c 會問你要把哪個變數用構造子分開,回答 a,假設有 a1 與 a2 兩個構造子,程式就會變成

    hello : A → B
    hello a1 = {! !}
    hello a2 = {! !}
使用 Linux 的使用者可以更改預設的 copy/cut 指令以免衝突。

已完成的軟體 [software-0007]

已完成的軟體這種概念,是指一個軟體的功能已經沒有大幅度更動的必要,可以長期使用在產品上,而軟體本身只會進行必要的安全與移植性更新。我在 https://josem.co/the-beauty-of-finished-software/ 讀到這個想法。對應到筆記軟體上,我不希望軟體一直更新,尤其是當我一打開工具需要寫筆記時,上面的更新按鈕非常的讓人煩躁。同時,這個想法也是一種解放我們原先對軟體想像的開端,比起軟體如何如何,更重要的是真的去做,外部連結裡面也談到冰與火之歌正是用這樣的軟體寫出。

git send-email setup with Protonmail [software-0006]

In the original setup I already explain the configuration, to do the same with Protonmail will need to install Proton Mail Bridge(https://proton.me/mail/bridge), then with configuration as below.

[sendemail]
  smtpEncryption = STARTTLS
  smtpServer = 127.0.0.1
  smtpUser = <your id>@protonmail.com
  smtpServerPort = 1025
  smtpPass = <your password>

Definition point-surjective [math-000A]

A morphism A→ϕBA \xrightarrow{\phi} B is point-surjective iff for every point 1→qB1 \xrightarrow{q} B, there exists a point 1→pA1 \xrightarrow{p} A that lifts qq (satisfy ϕ∘p=q\phi \circ p = q).

git send-email 的設定 [software-0004]

I use gmail, and hence, I need to get a Google app password. After having the password, one has to setup ~/.gitconfig with content:

[sendemail]
  smtpEncryption = tls
  smtpServer = smtp.gmail.com
  smtpUser = <your id>@gmail.com
  smtpServerPort = 587
  smtpPass = <your password>

Then you are able to use git send-email command:

git switch -c branch-patch
git format-patch main
git send-email 0001-***********.patch

prompt will ask some questions, an important one is which mailing list is your target? After command success, your patch are sent.

For certain git repository you're working on, can config local repository via git config --edit, and add below to omit email list in command line.

[sendemail]
  to = <target email list>

Mastodon 私訊相比於一般通訊軟體 e.g. LINE, Telegram [software-0003]

好處 [local-0]

  1. 可以有效分類特定話題,例如一個串是講約去哪裡吃飯、另一個串講專業內容
  2. 可以用僅限提及的人,限制可見性,所以可以形成一定程度的群組概念

壞處 [local-1]

  1. 兩方站點的站長都能看到內容
  2. 客戶端不支援把一群提及名單固定成群組,這或許是一個可行的客戶端新功能

壞處的可能解法:公佈自己的 public key 讓對方加密訊息再傳,配上專用客戶軟體或許可以做的更方便

let Racket GC manage your FFI object [software-0005]

All you need are deallocator and allocator from ffi/unsafe/alloc.

(require ffi/unsafe
         ffi/unsafe/define
         ffi/unsafe/alloc)

(define-ffi-definer define-xxx
  (ffi-lib "" '(#f)))

(define-xxx free-yyy (_fun _YyyRef -> _void)
  #:c-id yyy_delete
  #:wrap (deallocator))
(define-xxx make-yyy (_fun -> _YyyRef)
  #:c-id yyy_new
  #:wrap (allocator free-yyy))

Tool ngrok [software-0002]

Sometimes we didn't have public ip, but temporary wants to test website, ngrok can help in this situation.

# expose localhost:8080 by HTTP
$ ngrok http 8080
# expose localhost:8080 by TCP
$ ngrok tcp 8080

XDP [software-0001]

XDP is eXpress Data Path, it's a technology about putting a BPF code virtual machine on the NIC(network interface controller) driver before kernel network stack so that we can filter the packet before kernel, it would make processing speed greater.

We can do following things on the packet:

  1. XDP_PASS: allow the packet to pass through
  2. XDP_DROP: drop the packet
  3. XDP_TX: bounce the packet back on the same interface
  4. XDP_REDIRECT: redirects the packet to another interface

Here is an example of counting how many IPv4/6 packets be dropped.

package main

import (
    "fmt"
    "os"
    "os/signal"

    bpf "github.com/iovisor/gobpf/bcc"
)

// bcc is from iovisor/bcc this project
/*
#cgo CFLAGS: -I/usr/include/bcc/compat
#cgo LDFLAGS: -lbcc
#include 
#include 
void perf_reader_free(void *ptr);
*/
import "C"

const source string = `
#define KBUILD_MODNAME "foo"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
BPF_TABLE("array", int, long, dropcnt, 256);
static inline int parse_ipv4(void *data, u64 nh_off, void *data_end) {
    struct iphdr *iph = data + nh_off;
    if ((void*)&iph[1] > data_end)
        return 0;
    return iph->protocol;
}
static inline int parse_ipv6(void *data, u64 nh_off, void *data_end) {
    struct ipv6hdr *ip6h = data + nh_off;
    if ((void*)&ip6h[1] > data_end)
        return 0;
    return ip6h->nexthdr;
}
int xdp_prog1(struct xdp_md *ctx) {
    void* data_end = (void*)(long)ctx->data_end;
    void* data = (void*)(long)ctx->data;
    struct ethhdr *eth = data;

    uint64_t nh_off = sizeof(*eth);
    if (data + nh_off  > data_end)
        return XDP_DROP;
    uint16_t h_proto = eth->h_proto;
    if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
        struct vlan_hdr *vhdr;
        vhdr = data + nh_off;
        nh_off += sizeof(struct vlan_hdr);
        if (data + nh_off > data_end)
            return XDP_DROP;
            h_proto = vhdr->h_vlan_encapsulated_proto;
    }
    if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
        struct vlan_hdr *vhdr;
        vhdr = data + nh_off;
        nh_off += sizeof(struct vlan_hdr);
        if (data + nh_off > data_end)
            return XDP_DROP;
            h_proto = vhdr->h_vlan_encapsulated_proto;
    }
    int index;
    if (h_proto == htons(ETH_P_IP))
        index = parse_ipv4(data, nh_off, data_end);
    else if (h_proto == htons(ETH_P_IPV6))
        index = parse_ipv6(data, nh_off, data_end);
    else
        index = 0;
    long *value;
    value = dropcnt.lookup(&index);
    if (value) lock_xadd(value, 1);
    return XDP_DROP;
}
`

func usage() {
    fmt.Printf("Usage: %v \n", os.Args[0])
    fmt.Printf("e.g.: %v eth0\n", os.Args[0])
    os.Exit(1)
}

func main() {
    if len(os.Args) != 2 {
        usage()
    }
    module := bpf.NewModule(source, []string{
        "-w",
    })
    defer module.Close()

    fn, err := module.Load("xdp_prog1", C.BPF_PROG_TYPE_XDP, 1, 65536)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Failed to load xdp prog: %v\n", err)
        os.Exit(1)
    }

    device := os.Args[1]
    if err := module.AttachXDP(device, fn); err != nil {
        fmt.Fprintf(os.Stderr, "Failed to attach xdp prog: %v\n", err)
        os.Exit(1)
    }

    defer func() {
        if err := module.RemoveXDP(device); err != nil {
            fmt.Fprintf(os.Stderr, "Failed to remove XDP from %s: %v\n", device, err)
        }
    }()

    fmt.Println("Dropping packets, hit CTRL+C to stop")
    sig := make(chan os.Signal, 1)
    signal.Notify(sig, os.Interrupt, os.Kill)

    dropcnt := bpf.NewTable(module.TableId("dropcnt"), module)

    <-sig

    fmt.Println("\n{IP protocol-number}: {total dropped pkts}")
    for it := dropcnt.Iter(); it.Next(); {
        key := bpf.GetHostByteOrder().Uint32(it.Key())
        value := bpf.GetHostByteOrder().Uint64(it.Leaf())

        if value > 0 {
            fmt.Printf("%v: %v pkts\n", key, value)
        }
    }
}

Algorithm Mark sweep GC [cs-0008]

Mark-Sweep is a classic GC algorithm, it's combined with two parts, mark and sweep.

mark(root):
  if not marked?(root):
    mark(root)
  for obj in knowns(root):
    mark(obj)
sweep(heap):
  for obj in heap:
    if marked?(obj):
      unmark(obj)
    else:
      release(obj)

If we run collection (mark-sweep), then since each object is reachable from root, so no one would be released.

figure tex11886

After do some executions, obj1 don't need obj3 anymore, so it became:

figure tex11887

Now when we run collection, obj3 is unreachable from root, so it won't be marked! When running to sweep, it will be dropped.