--- title: 【數學理論】 11. 不完備、不一致、非保守、無法判定,數學信仰崩塌的盡頭 — 圖靈機停機問題(Turing Machine Halting Problem) tags: - 【數學理論】 url: https://hackmd.io/Zu9VEt8ESZ2goTBTo4LWIg lastSync: 2025-05-25T08:46:08.764Z hackmd: url: https://hackmd.io/Zu9VEt8ESZ2goTBTo4LWIg title: 【數學理論】 11. 不完備、不一致、非保守、無法判定,數學信仰崩塌的盡頭 — 圖靈機停機問題(Turing Machine Halting Problem) lastSync: 2025-05-25T08:52:38.292Z --- 不完備、不一致、非保守、無法判定,數學信仰崩塌的盡頭 === <font size=4><font color=gray>圖靈機停機問題(Turing Machine Halting Problem)</font><br></font><br> --- <!-- 20250910 --> 在[**上一篇**](https://hackmd.io/@lewisjjj800/rkcL9IxMgx)我們介紹了**哥德爾不完備定理**,回顧一下: >[!Important] **哥德爾第一不完備定理 (Gödel's First Incompleteness Theorems)** >任何**一致**的形式系統,只要蘊涵**皮亞諾公理**,就可以在其中構造在系統中不能被證明的真命題,因此通過推理演繹不能得到所有真命題,即:一致的**該形式系統是不完備的**。 >[!Important] **哥德爾第二不完備定理 (Gödel's Second Incompleteness Theorems)** >任何一致的形式系統,只要蘊涵皮亞諾公理,它就不能用於證明其本身的**一致性**。 <br> 這一篇我們就要來看看**希爾伯特綱領**中的**保守性**以及**可判定性**。 <br> **保守性**比較簡單,我們先來看**保守性**的證明。 --- <br> ## 非保守性的證明 首先,我們先來回顧一下 **希爾伯特綱領**中的**保守性**概念是什麼。 >[!Note] **保守性 (Conservation)** > 如果某個形式系統 $P'$ 是在 $P$ 上擴展出來的,而且 $P'$ 在某個語言中不會證出 $P$ 所無法證明的語句(例如對算術語句),那麼我們就說 $P'$ 對 $P$ 是**保守的**。 <br> 我們使用前一篇提到的 $T$ 以及 $\text{Con}(T)$: - $T$ 是**蘊含皮亞諾公理的形式系統** - $\text{Con}(T)$ 是「$T$ 是一致的」這件事的形式化語句 <br> 現在,我們來考慮一個**擴展系統**: $$ T + \text{Con}(T) $$ <br> 這代表: - **原系統**:$T$ - **擴展系統**:$T$ 加上一條新公理:「$T$ 是一致的」(也就是 $\text{Con}(T)$) <br> 看起來似乎沒什麼大不了,我們只是加了一句人類理性認為應該「是真的」話。 <br> 但,問題來了。 <br> 根據**哥德爾第二不完備定理**我們可以知道: $$ T\space無法證明自身是一致的。 $$ <br> 此時,當我們在 $T$ 加上一條新公理:「$T$ 是一致的」 <br> 就代表我們現在確定在 **擴展系統** $(T + \text{Con}(T))$ 中 $T$ 就是一致的。也就是: $$ T + \text{Con}(T) \vdash \text{Con}(T) $$ <br> 但是**哥德爾第二不完備定理**說:我們無法從 $T$ 證明 「$T$ 必是一致的」。也就是: $$ T \not\vdash \text{Con}(T) $$ <br> 所以**擴展系統**推導出了**原系統**無法證明的語句。 <br> 因此對於**蘊含皮亞諾公理的形式系統** $T$ ,若該形式系統通過加入公理(如 $\text{Con}(T)$)來證明 $T$ 的一致性,則該系統通常不是 $T$ 的保守擴展,因為它能證明 $T$ 無法證明的陳述(如 $\text{Con}(T)$)。 <br> 因此,**蘊含皮亞諾公理的形式系統**存在某些擴展是非保守的,如剛剛舉例的:「**擴展系統**推導出了**原系統**無法證明的語句」。 --- 真是完大蛋了,目前希爾伯特綱領中的四條性質中的三個已經被我們證實了:**不完備、不一致、非保守**,那最後一個**可判定性**呢? <br> **可判定性**就要利用 **圖靈機(Turing Machine)** 了。 --- <br> ## **圖靈機(Turing Machine)** 要介紹一下什麼是**圖靈機(Turing Machine)**,就要先介紹**圖靈(Turing)**。 <img src="https://raw.githubusercontent.com/lewisjjj800soic/HackMD-images-backup/main/Mathematic-Theorems/11/01.png" alt="圖片描述" style="display: block; margin: 0 auto;" width="400"> > <font size=1><font color=gray>photo credit by: https://images.app.goo.gl/piHGsU3Mgk6bXe7v5</font></font> 放錯了,不是這個圖靈,下面這個才是。 <img src="https://raw.githubusercontent.com/lewisjjj800soic/HackMD-images-backup/main/Mathematic-Theorems/11/02.png" alt="圖片描述" style="display: block; margin: 0 auto;" width="400"> > <font size=1><font color=gray>photo credit by: https://www.computerhistory.org/timeline/1949/</font></font> 艾倫·圖靈(Alan Turing)是英國電腦科學家、數學家、邏輯學家、密碼分析學家和理論生物學家,被譽為電腦科學與人工智慧之父。 <br> 他於1936年提出一種將人的計算行為抽象化的數理邏輯機,也就是**圖靈機(Turing Machine)**。 >[!Note] **圖靈機(Turing Machine)** > >圖靈機是一個理論上的「最簡形式電腦模型」,它由以下幾個部分組成: > >| 組件 | 功能 | >|------------|--------------------------------------| >| 無限長的紙帶(Tape) | 儲存資料與結果(類似記憶體) | >| 讀寫頭(Head) | 可以讀取與寫入 tape 上的符號,並左右移動 | >| 狀態機(State Register) | 記錄目前的內部狀態 | >| 遷移函數(Transition Function) | 根據當前狀態與符號,決定接下來的行為(寫入、移動、改變狀態) | <br> 而圖靈證明了:**任何可被電腦執行的演算法,圖靈機都能模擬。這就稱為「圖靈完備(Turing Completeness)」**。 >[!Note] **圖靈完備(Turing Completeness)** >如果一個計算系統被稱為圖靈完備(Turing Completeness),代表它能夠模擬通用圖靈機(Universal Turing Machine)的行為,從而計算任何可計算的函數(在給定無限記憶體和無限時間的情況下)。換句話說,圖靈完備的系統可以解決所有「可計算問題」(computable problems),只要這些問題在理論上能夠被圖靈機解決。 > >而如果一個計算系統(例如程式)要成為圖靈完備,通常需要具備以下能力: > >- 條件分支:能夠根據條件執行不同的操作(例如 `if-else` 語句)。 >- 重複或循環:能夠執行無限次的重複操作(例如 `while` 迴圈或遞迴)。 >- 記憶體操作:能夠讀取和寫入任意數量的資料(理論上需要無限記憶體,實際中受硬體限制)。 >- 狀態轉換:能夠在不同的狀態之間切換,模擬圖靈機的有限狀態控制器。 這些能力確保系統可以模擬圖靈機的紙帶、讀寫頭和狀態轉換規則。 <br> 而大多數現代程式語言(如 Python、C、Java、JavaScript)都是圖靈完備的,因為它們支援條件分支、迴圈和記憶體操作。此外,Minecraft的紅石電路同樣也是圖靈完備的,因為我們可以利用紅石電路達到邏輯閘、遞歸等效果。 <br> 下面就是我畫的一個**圖靈機**展示圖: <img src="https://raw.githubusercontent.com/lewisjjj800soic/HackMD-images-backup/main/Mathematic-Theorems/11/03.jpg" alt="圖片描述" style="display: block; margin: 0 auto;" width="600"> <br> <br> 可以看到有一個**無限長的紙帶**。 還有一個**讀寫頭**,**讀寫頭可以在表帶上左右移動**,並且可以**讀取當前格子上的數字以及寫入一個數字**。 右上角是**狀態機**,代表**這台圖靈機所有可能的狀態**。 左上角則是**遷移函數**,他會**根據讀寫頭上的字母以及讀寫頭讀取到的數字來改變**。 <br> 舉個例子: <img src="https://raw.githubusercontent.com/lewisjjj800soic/HackMD-images-backup/main/Mathematic-Theorems/11/04.jpg" alt="圖片描述" style="display: block; margin: 0 auto;" width="600"> 上圖我們可以看到,當前的狀態是 **「D,0」**。 <br> 那麼根據狀態 **「D,0」**,左上角的遷移函數會決定 **狀態是「D,0」** 時的下一步要怎麼走。如下圖: <br> <img src="https://raw.githubusercontent.com/lewisjjj800soic/HackMD-images-backup/main/Mathematic-Theorems/11/05.jpg" alt="圖片描述" style="display: block; margin: 0 auto;" width="600"> <br> <br> 根據**遷移函數**我們知道當 **狀態是「D,0」** 時,讀寫頭要變成 **「A」**,並且寫下一個 **「1」**。如下圖: <img src="https://raw.githubusercontent.com/lewisjjj800soic/HackMD-images-backup/main/Mathematic-Theorems/11/06.jpg" alt="圖片描述" style="display: block; margin: 0 auto;" width="600"> <br> <br> 並且**讀寫頭**要往**右邊**移動一格。如下圖: <img src="https://raw.githubusercontent.com/lewisjjj800soic/HackMD-images-backup/main/Mathematic-Theorems/11/07.jpg" alt="圖片描述" style="display: block; margin: 0 auto;" width="600"> >這邊我讓**紙帶往左**代表**讀寫頭向右**,為得就是 **讀寫頭** 保持不動。 <br> <br> 那這樣我們可以看到,現在有一個新的狀態是 **「A,1」**,如下圖。 <img src="https://raw.githubusercontent.com/lewisjjj800soic/HackMD-images-backup/main/Mathematic-Theorems/11/08.jpg" alt="圖片描述" style="display: block; margin: 0 auto;" width="600"> <br> <br> 就這樣,圖靈機可以持續根據**狀態**以及**讀寫頭**來繼續跑下去。 <br> 下面稍微展示一下: <img src="https://raw.githubusercontent.com/lewisjjj800soic/HackMD-images-backup/main/Mathematic-Theorems/11/09.gif" alt="圖片描述" style="display: block; margin: 0 auto;" width="600"> <br> <br> 你可能發現了上圖最後出現了 <font color=red> **停機** </font>,而我們根據右上角的狀態機可以看到,這八個格子裡的左上角對應了狀態機上的字母 **A、B、C、D**,唯獨有一個獨立出來的符號 **H** 。 <br> 而這個 **H** 代表的是 <font color=red> **停機 (Halt)** </font>,也就是讓這台圖靈機停下來的意思。 <br> 那除了 **停機** 這個特別的情況以外,還會有一個情況叫作 **死循環**。 <img src="https://raw.githubusercontent.com/lewisjjj800soic/HackMD-images-backup/main/Mathematic-Theorems/11/10.gif" alt="圖片描述" style="display: block; margin: 0 auto;" width="600"> <br> <br> 上圖可以看到,這台圖靈機只會在 **「D,0」** 以及 **「A,0」** 兩個狀態之間循環,好像進入死胡同一樣,這種情況就被稱作 **死循環 (Loop)**。 <br> 那問題來了:我們有辦法光看**一個圖靈機的所有狀態**,就能判斷這台圖靈機最後是否會**停機**或是進入**死循環**嗎? <br> 這個問題看起來好像不難對不對?接下來我們來考慮一個例子。 --- <br> ## 蘭頓的螞蟻 **蘭頓的螞蟻(Langton's ant)** 由克里斯托夫·蘭頓 (Christopher Langton) 在1986年提出,它由全白的方格畫布和一隻「螞蟻」構成,是一個二維圖靈機。 >[!Note] **蘭頓的螞蟻(Langton's ant)** >有一個全白的方格畫布,在其中一格正方形有一隻「螞蟻」。它的頭部朝向上下左右其中一個方向,螞蟻可以在畫布上的方格中填上黑色或白色。而這隻螞蟻只有兩個狀態: >- 若螞蟻在**白格**,右轉90度,將該格填上**黑色**,變成**黑格**,**向前移一步**。 >- 若螞蟻在**黑格**,左轉90度,將該格填上**白色**,變成**白格**,**向前移一步**。 <br> 很簡單對吧?現在假如畫布只有 $100 \times 100$ 的大小,而只要螞蟻最後觸碰到邊界,那螞蟻就**暫停**。那請你猜猜看,這個只有兩個狀態的螞蟻,最後會: - 碰到邊界?(**停機**) - 按照一條封閉的路徑循環?(**死循環**) >有興趣的可以暫停一下猜猜看。 <br> 我們可以利用 `python` 來撰寫這個程式,然後可視化,程式如下: :::spoiler 點擊以查看程式碼 ```python= import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation # Langton's Ant parameters grid_size = 100 steps = 12000 dirs = [(0, -1), (1, 0), (0, 1), (-1, 0)] direction_symbols = ['↑', '→', '↓', '←'] # 初始化格子與螞蟻位置 grid = np.zeros((grid_size, grid_size), dtype=int) x, y = grid_size // 2, grid_size // 2 d = 0 frames = [] positions = [] # 顏色對應:白、黑 color_map = { 0: [1.0, 1.0, 1.0], 1: [0, 0, 0], } # 模擬 Langton's Ant 移動 for step in range(steps): # 若螞蟻走到邊界,停止模擬 if x == 0 or x == grid_size - 1 or y == 0 or y == grid_size - 1: print(f"這隻螞蟻在走到第 {step} 步時停了下來, 停在 ({x}, {y}) 這個位置上") break rgb_grid = np.zeros((grid_size, grid_size, 3)) for val in [0, 1]: mask = grid == val rgb_grid[mask] = color_map[val] frames.append(rgb_grid.copy()) positions.append((x, y, d, step)) if grid[y, x] == 0: d = (d + 1) % 4 grid[y, x] = 1 else: d = (d - 1) % 4 grid[y, x] = 0 dx, dy = dirs[d] x += dx y += dy # 設定動畫圖形 fig, ax = plt.subplots() im = ax.imshow(frames[0], interpolation='none') ant_marker, = ax.plot([], [], 'ro') direction_text = ax.text(0, 0, '', color='black', fontsize=12, ha='center', va='center') step_text = ax.text(0.98, 0.02, '', color='blue', fontsize=10, ha='right', va='bottom', transform=ax.transAxes) # 關閉坐標軸數字 ax.set_xticks([]) ax.set_yticks([]) def update(i): grid_frame = frames[i] x, y, d, step = positions[i] im.set_array(grid_frame) ant_marker.set_data([x], [y]) direction_text.set_position((x, y)) direction_text.set_text(direction_symbols[d]) step_text.set_text(f"Step: {step}") return [im, ant_marker, direction_text, step_text] ani = animation.FuncAnimation(fig, update, frames=len(frames), interval=30, blit=True) # 儲存成 GIF 與 MP4 ani.save("langtons_ant.gif", writer='pillow') ani.save("langtons_ant.mp4", writer='ffmpeg') ``` ::: <br> 接下來我們來看看透過程式,將**蘭頓的螞蟻**可視化後的結果: <div style="padding:75% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/1084988902?h=d8aab216ec&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media" style="position:absolute;top:0;left:0;width:100%;height:100%;" title="langtons_ant (1)"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script> <br> <br> 執行完程式後,會輸出以下字串: ``` 這隻螞蟻在走到第 11655 步時停了下來, 停在 (0, 73) 這個位置上 ``` <br> 你猜到了嗎?這個只有兩個狀態的螞蟻,會在畫布上畫出一個極其複雜的圖案,然後需要花大約 **11000步** 才會以**104步為周期**,進入一條無限重複的「**高速公路**」,朝一個固定的方向移動,最後一共走了 **11655步** 碰到邊界才停了下來。 --- <br> ## 停機問題(Halting Problem) 藉由剛剛的例子,我們發現,就算只有兩個很簡單的**狀態**,也很難光看**狀態**來判斷一個具有規則作動的圖靈機,最後會不會**停機**,還是進入**死循環**。 <br> 但是,**是否有一個程式或是演算法,可以判定這台圖靈機能否會停機?** <br> 這,就是圖靈機的**停機問題(Halting Problem)** >[!Note] **停機問題(Halting Problem)** > **給定一台圖靈機 `M` 和輸入 `x`,是否存在一個演算法 `H(M, x)` 可以告訴我們:`M` 在輸入 `x` 時是否會最終停機?** <br> 你可能會想:**判斷停不停機可以幹嘛?** <br> 那如果我說:**判斷一台圖靈機是否會停機的這個演算法,可以解決這個世界上許多數學難題呢?** <br> 舉個例子,我們考慮**哥德巴赫猜想(Goldbach's conjecture)** >[!Note] **哥德巴赫猜想(Goldbach's conjecture)** >**哥德巴赫猜想**是數論中存在最久的未解問題之一。這個猜想最早出現在1742年普魯士數學家克里斯蒂安·哥德巴赫與瑞士數學家萊昂哈德·歐拉的通信中。用現代的數學語言,哥德巴赫猜想可以陳述為: >- **任一大於2的偶數,是否都可表示成兩個質數之和?** <br> 假如我們用程式來模擬 **哥德巴赫猜想** : >[!Tip] **我們設計一個程式:`G_C`** >讓這個程式 **`G_C`** 從 $n = 4$ 開始,檢查**每個偶數是否能表示為兩個質數的和**。若找到**某個偶數無法表示為兩個質數的和(反例),則「停機」**。 > 前面有說**程式語言**是**圖靈完備**的,代表程式語言可以模擬圖靈機,所以這邊用**程式來模擬**等於**用圖靈機來模擬**。 <br> 那假如我們可以找到**一套演算法**來判斷 「**程式`M`** 以及給定的輸入 $n = 4$」是否會**停機**。 <br> 那就代表我們可以解決**哥德巴赫猜想**。 <br> 當然還有,**黎曼猜想(Riemann Hypothesis)**。 >[!Note] **黎曼猜想(Riemann Hypothesis)** > 黎曼 $\zeta$ 函數:$\zeta(s)$ 的所有非平凡零點(複數零點)是否都具有實部 $Re(s)=\frac{1}{2}$? <br> 那我們設計一個程式:**`R_H`** 來模擬 **黎曼猜想** : >[!Tip] **我們設計一個程式:`R_H`** >讓這個程式 **`R_H`** 檢驗 $\zeta(s)$ 的零點,檢查是否存在非平凡零點的實部 $Re(s)=\frac{1}{2}$。遍歷可能的複數 $s$ 若找到反例則 **「停機」**。 <br> 當然還有很多難題,例如:**質數間隙問題(Twin Prime Conjecture)、$P = NP$ 問題、柯拉茲猜想(Collatz Conjecture)**,這些難題具有以下特點: - **可計算性**:這些難題的驗證過程(檢查解或反例)是可計算的,可以用圖靈機或程式模擬。 - **停機條件**:程式設計為在找到解(例如反例或證明)時停機,表示問題解決。 - **不確定性**:若猜想為真,程式可能永不停止,類似於停機問題中的不可預測性。 <br> 因此,假如你真的找到一套演算法可以判斷一台圖靈機是否可**停機**,代表你**有辦法解決大部分數學界的難題**,如果你真的有辦法,那我想號稱 **數學界的諾貝爾獎的菲爾茲獎(Fields Medal)** 絕對非你莫屬,甚至**菲爾茲**本人都要**親自從棺材裡爬起來替你頒獎**。 <br> 但是,真的有這麼簡單嗎? --- ## 不可判定性的證明 現在,我們**假設存在一個停機判定器 `H(M, x)`**: - `H(M, x)` 是一個函數,`H(M, x)` 輸入為程式 `M` ,而 `M` 的輸入為 `x`。也就是 `H(M(x))` - `H(M, x)` 會根據以下結果回傳 `True` 或是 `False`: - 如果 `M(x)` 最終會**停機**,回傳 `True` - 如果 `M(x)` 永遠不會停(**死循環**),回傳 `False` <br> 接下來,我們定義一個反常行為的程式 `D`,它接受一個程式 `M` 為輸入,且判斷 `H(M, M)` 回傳的結果,並執行行為如下: ```python def D(M): if H(M, M) == True: while True: pass # 進入"死循環" else: return "停機" ``` <br> 用中文說就是: 讓 `M` 輸入自己,也就是 `M(M)`,那如果: - 如果 `H(M, M)` 判斷 `M(M)` 會**停機**,那 `D(M)` 就進入**死循環**。 - 如果 `H(M, M)` 判斷 `M(M)` 會進入**死循環**,那 `D(M)` 就馬上**停機**。 <br> 你可能會想說:**哪有程式可以輸入自己的?** <br> 事實上可以哦!以下舉個例子: ```python= def process_self(code): """處理程式自身的原始碼,例如計算長度或檢查內容""" print(f"程式原始碼長度:{len(code)} 字元") # 模擬簡單分析,例如檢查是否有特定關鍵字 if "process_self" in code: print("找到函數 'process_self',模擬處理自身") else: print("未找到預期內容") # 模擬停機:完成處理後停止 return True def main(): """主程式:讀取自身原始碼並作為輸入""" try: # 讀取當前程式的原始碼 with open(__file__, 'r', encoding='utf-8') as file: code = file.read() print("程式正在輸入自己(讀取原始碼)...") # 將原始碼作為輸入傳給 process_self result = process_self(code) if result: print("程式成功處理自身並停機") except Exception as e: print(f"錯誤:{e}") if __name__ == "__main__": main() ``` <br> 上面這個程式的處理邏輯是這樣: 1. 程式讀取自身檔案。 2. 將原始碼作為輸入,傳遞給內部函數處理。 3. 輸出處理結果並停止。 <br> 我們把程式儲存為 `self_input.py`,運行後就會輸出: ```python 程式正在輸入自己(讀取原始碼)... 程式原始碼長度:674 字元 找到函數 'process_self',模擬處理自身 程式成功處理自身並停機 ``` <br> 所以輸入自己是可以的。 <br> 接下來,問個問題:`D(D)` **會停機嗎?** <br> >[!Caution] `D(D)` **會停機嗎?** >如果 `H(D, D) == True`: >- 代表 `D(D)` 會**停機** → 根據定義,`D(D)` 應該進入**死循環**,<font color=red>**矛盾**!</font> > >如果 `H(D, D) == False`: >- 代表 `D(D)` 進入**死循環** → 根據定義,`D(D)` 應該**停機**,<font color=red>**矛盾**!</font> <br> 因為上面兩種情況都會導致邏輯崩潰,所以 **停機判定器 `H(M, x)`** 根本不可能存在。 <br> 也就是說,**不存在任何一種演算法可以判定一台圖靈機是否可以停機!** <br> 因此,**可判定性不成立**。 --- <br> ## 自我指涉 (Self-reference) 聰明的你可能發現了,無論是 **哥德爾不完備定理** 還是本篇介紹到的 **圖靈機停機問題**,都有一個共通點,就是我們都可以找到一個方法讓**他們都讓自己引用自己,引發矛盾**。 <br> 這種**自己引用自己**的情況就叫:**自我指涉 (Self-reference)** <br> 例如我們在[**這一篇**](https://hackmd.io/@lewisjjj800/rkXv5Ixzel#%E7%BE%85%E7%B4%A0%E6%82%96%E8%AB%96%EF%BC%88Russell%E2%80%99s-Paradox%EF%BC%89)提到的**理髮師悖論(Barber Paradox)**: >[!Important]**理髮師悖論(Barber Paradox)** > 在某個村莊裡,有一位理髮師,他為**所有不自己刮鬍子的人刮鬍子。那這位理髮師該不該幫自己刮鬍子?** > - 如果他幫自己刮鬍子,那**他就不屬於「不自己刮鬍子」的人,他就不該幫自己刮鬍子。** >- 如果他不幫自己刮鬍子,那**他就符合「不自己刮鬍子」的條件,他應該幫自己刮鬍子。** > >理髮師幫自己刮鬍子也對,不刮也對,這就導致了矛盾。 <br> 還有**說謊者悖論(Liar paradox)**: >[!Important]**說謊者悖論(Liar paradox)** >有一個人說:「**我正在說謊。**」 > - 如果實際上他**真的在說謊**,那麼他所說的就是**真的**,但如果他所說的就是**真的**,那麼**他就是在說謊**。 > - 如果實際上他**沒有在說謊**,那麼他所說的就是**假的**,但如果他所說的就是**假的**,那麼**他沒有在說謊**。 <br> 這些悖論之所以是悖論,因為他們都涉及了**自我指涉**,他們都**直接或是間接來引用自己**,從而引發**矛盾**。 <br> 而日常生活中充滿了**自我指涉**,例如下面這句話: ><font color=black>「我是不是太常懷疑我是不是太常懷疑自己了?」</font> <br> 你在懷疑自己是不是很常懷疑自己時,那你就已經開始懷疑自己了。 <br> 還有著名的**德羅斯特效應(Droste effect)**,我們看下面這張圖: <img src="https://raw.githubusercontent.com/lewisjjj800soic/HackMD-images-backup/main/Mathematic-Theorems/11/11.gif" alt="圖片描述" style="display: block; margin: 0 auto;" width="300"> > <font size=1><font color=gray>photo credit by: 由 Designer: Jan MissetUploader: Alf van Beem - 自己的作品, 公有領域, https://commons.wikimedia.org/w/index.php?curid=30739029</font></font> <br> 上面這張圖是荷蘭著名廠牌德羅斯特(Droste)可可粉的包裝盒,包裝盒上的圖案是一位護士拿著一個放著杯子及紙盒的托盤,而托盤上的紙盒就是**德羅斯特可可粉的包裝盒**。這是一種**自我遞歸**的表現。 <br> 或者是假如你是一台機器人,然後你內部有一串代碼: ```python= if self.cleaning_state == "confused": self.debug(self.status) ``` <br> 也就是:**當我不知道自己在幹嘛的時候,我就會開始檢查我自己在幹嘛。** <br> --- ## 結論 我們會發現,生活周遭中有很多**自我指涉**的例子,有時候甚至會變成一個**笑點**來娛樂我們。 <br> 然而,數學發展了幾千年的歷史,好不容易有人想要將數學來**公理化**,希望: 1. 數學的真命題都可以被證明。 2. 數學是沒有矛盾的。 3. 衍生出的新理論證明,也可以從舊理論證明出來。 4. 數學問題是可以被判定真偽的。 <br> 但卻因為一個**笑點**毀了。這就好像是上帝給我們開了一個玩笑。 <br> 但是,縱使如此,熱愛數學的我們依舊熱愛數學。 <br> 因為朋友跟戀人會背叛你,但是數學不會。因為數學不會就是不會。 <br> --- ## 後記 過去的日子裡我撰寫了許多談論**數學理論**的專欄,大多都是從我的經驗出發,接著開始講述一個個我熱愛的**數學理論**。 <br> 而**哥德爾不完備定理**正是我想要開始撰寫這個專欄的契機,因為**哥德爾不完備定理**真的是我見過最有趣又富含哲理的數學了。因此在最一開始要撰寫這個專欄時,我就在想這個以**數學理論**為名的系列,最後要以**哥德爾不完備定理**做為結尾。 <br> 現在,寫完了長達三篇的**哥德爾不完備定理**介紹,很難想像我真的一步步寫到這裡。 <br> 當然未來我還是會繼續寫下去,會開啟其他系列,繼續富足我的研究之路。 <br> 那就請看到這邊的你,繼續期待下一篇吧! <br> 我是Lewis,我們[**下一篇**](https://hackmd.io/@lewisjjj800/rky7sneLex)專欄見!