2.1 歐幾里得《幾何原本》(約西元前 300 年)#
學習動機#
想像你是一位亞歷山大港博物館(Museum of Alexandria)的學者。在你之前,埃及人用繩結測量尼羅河氾濫後的土地,巴比倫人用表格計算面積,希臘人證明過一個又一個漂亮的定理——但每一代學者都得重新學起,因為沒有一本書把這些知識組織成一個從頭推起的系統。歐幾里得(Euclid,約公元前 300 年)的《幾何原本》(Elements,希臘語 Στοιχεῖα)改變了這一切:它從少數幾條不證自明的出發點(公設與公理)開始,以嚴謹的演繹推出 465 個命題,涵蓋平面幾何、數論、比例論與立體幾何。
《幾何原本》不只是數學教科書,它是公理化方法的第一個偉大典範。兩千多年後,牛頓在《自然哲學的數學原理》中模仿它的公理化體系;斯賓諾莎用幾何方式寫《倫理學》;二十世紀的 Hilbert 重建幾何公理系統,而計算機科學家再把它自動化成定理證明器。今天我們用 SymPy 做的每一步「從定義推出結果」的計算,都是這個傳統的迴響。讀完本節,你將能:
- 說出《幾何原本》的組織架構(13 卷、23 個定義、5 條公設、5 條公理);
- 理解第 I 卷 23 個定義如何為全書鋪路;
- 認識五大公設,尤其是後來審判非歐幾何的第五公設;
- 了解公理化方法如何塑造牛頓物理學與現代數學;
- 用 SymPy 把「定義」與「公設」寫成可執行程式碼。
1. 歐幾里得其人與其書#
關於歐幾里得本人,我們所知極少。普羅克洛斯(Proclus,公元 5 世紀)的《幾何學發展綱要》記載他活躍於托勒密一世(Ptolemy I)時代的亞歷山大。最有名的軼事有兩則:
- 國王托勒密問他學幾何有沒有捷徑,他答:「幾何學中沒有王者之路(οὐκ ἔστω βασιλικὴ ὁδὸς ἐπὶ γεωμετρίαν)」,意思是學習必須按部就班。
- 一個學生問學幾何有什麼用,歐幾里得叫僕人給他三枚硬幣,「因為他想從學習中撈取實利」。
《幾何原本》13 卷的內容分配:
| 卷 | 內容 |
|---|---|
| I–VI | 平面幾何:三角形、圓、比例論、相似形 |
| VII–IX | 數論:輾轉相除法、質數無窮多、完全數 |
| X | 不可公度量(無理數的幾何理論) |
| XI–XIII | 立體幾何;最後以正多面體的構造與分類收尾 |
在抄寫與印刷時代,它是僅次於聖經的流傳最廣書籍,印刷術問世後至 1900 年至少出了一千多個版本。英格蘭維多利亞時代的中小學直到 20 世紀初仍以它為課本(Bertrand Russell 幼年曾背誦《原本》)。
為什麼它被稱為「元素」? 希臘文 stoikheia 意為「字母」或「基本構件」——正如字母拼出單詞,公理與定義拼出全部幾何。
2. 23 個定義(第 I 卷開頭)#
《幾何原本》第 I 卷以 23 個定義開場。前八個最關鍵,原文與現代詮釋如下(Heath 譯本):
- 點(σημεῖον):點是沒有部分的部分——「點不可再分割」。
- 線:線是没有寬度的長度。
- 線的兩端是點。
- 直線:直線是其上各點平齊地放置的線。
- 面:面只有長度與寬度。
- 面的邊緣是線。
- 平面:平面是與其上直線平齊放置的面。
- 平面角:平面上兩條相交直線彼此的傾斜。
(第 9–12 個定義區分銳角、鈍角;第 13–17 個定義圓:圓是曲線、圓心、半徑、直徑、半圓。第 19–22 個定義直線形——三角形、四邊形等。第 23 個定義平行線。)
用比畢達哥拉斯晚兩百年的希臘眼光看,這些定義有一個奇怪的特點:它們不是完備的——例如「沒有寬度」的定義無法唯一描述點與線的本質,希臘人依然使用了這些概念。這個缺陷要到 Hilbert(1899)的《幾何基礎》才被察覺並修正:Hilbert 提出公理化系統中,未定義名詞(point、line、plane)不需要「定義」,只需要滿足公理即可。這句話後來被布爾巴基學派傳播為名言:
「我們必須能夠隨時說『桌子、椅子、啤酒杯』代替『點、直線、平面』。」
用 SymPy 表達幾何的「定義」再自然不過——幾何模組中的類別就是定義的化身:
from sympy import Point, Line, Circle
# 定義 1:點是沒有部分的部分——在程式裡,它只是一對座標
A = Point(0, 0)
# 定義 2、4:線是由兩點生成的(沒有寬度的長度)
l = Line(A, Point(1, 1))
print(l) # 預期輸出:Line2D(Point2D(0, 0), Point2D(1, 1))
# 定義 15:圓由圓心與半徑決定
c = Circle(A, 1)
print(c) # 預期輸出:Circle(Point2D(0, 0), 1)
# 定義 16:直徑 = 兩倍半徑
d = 2 * c.radius
print(d) # 預期輸出:2
注意:SymPy 的 Point 類預設 2 維,需要 3 綠時用 Point3D。你取用的 Circle 物件不必忠實再現希臘定義,但每一個屬性——.radius、.center——都對應一條《幾何原本》定義。
3. 五條公設(postulates)#
定義排列整齊之後,歐幾里得列出五條公設(αἰτήματα,aitēmata)——「要求」的斷言,即可執行幾何操作的許可:
- 由任一點到任一點(可)作直線。(畫直線)
- 有限直線可以任意延長。(延長線段)
- 以任意點為中心、任意距離為半徑可以作圓。(畫圓)
- 一切直角彼此相等。
- 同平面上一條直線與兩直線相交,若某一側的兩內角之和小於兩個直角,則這兩直線充分延長後,在那側相交。
前四條是最小操作集合:連兩點、延長、畫圓、比直角。第五條斷言過長,被中世紀編輯者稱為「醜婦」(claustra,鐵砧上的刺),甚至有傳說認為它其實是一條定理,歐幾里得不該把它放進公設。但它與前四條確實有不同的「口味」:它講的是一個無限過程的結果(延長到哪裡才會相交),而前四條都是有限操作。這個不協調是最後滋生非歐幾何的種子(第 6 章的主題)。
要強調的是:公設 1–3 都是構造性的——刻寫的「以尺規作圖」為限,這是歐幾里得的一切幾何構造都只用無刻度直尺與圓規的原因。第 I 卷就用它們完成了等邊三角形構造(命題 I.1)與畢氏定理(命題 I.47)。
SymPy 的幾何模組恰好就是這五條公設的程式化:
from sympy import Point, Ray, Circle, Rational, Segment
import sympy
# 公設 1:任兩點可連直線
p1 = Point(0, 0)
p2 = Point(sympy.sqrt(2), 1)
segment = Segment(p1, p2) # 兩點間的線段
print(segment.length) # 預期輸出:sqrt(3)(精確的無理數,不是小數)
# 公設 2:線段可任意延長 → 用 Ray(射線)向一方向無限延長
ray = Ray(p1, p2)
print(ray.direction) # 預期輸出:Point2D(sqrt(2), 1)(從原點指向 p2 的方向)
# 公設 3:以任點為圓心、任距離為半徑作圓
circle = Circle(p2, Rational(3, 2))
print(circle.equation()) # 預期輸出:(x - sqrt(2))**2 + (y - 1)**2 - 9/4
# 公設 4:所有直角相等 → 90° 是同一個物件
from sympy import pi
right_angle = pi / 2
print(sympy.simplify(right_angle * 2)) # 預期輸出:pi
看到輸出中的 sqrt(3)、9/2 是精確的有理數與根式而非浮點數——這正是歐幾里得精神的程式版:所有結論都不用近似值,只用公理系統內可證明為相等的表達式。
4. 五條公理(common notions)#
在公設之後,歐幾里得又列出五條公理(κοιναὶ ἔννοιαι,常識/koinai ennoiai),中文常譯為「共同觀念」:
- 等於同一量彼此相等。
- 等量加等量,其和相等(等式的加法性質)。
- 等量減等量,其差相等(減法性質)。
- 彼此重合的東西彼此相等(全等概念)。
- 全體大於部分(阿基米德性質的雛形)。
公設與公理的差別在於範圍:公設是幾何專有的操作許可,公理則是所有科學通用的推理規則。注意第 5 條「整體大於部分」現代數學裡並不成立——無窮集合可以與自己的真子集一一對應(如自然數與偶數),這是 19 世紀 Cantor 集合論帶來的震撼。歐幾里得的公理系統既偉大又不完美,這正是數學思想史迷人的地方。
5. 從公設到定理:命題 I.1 的範式#
《幾何原本》的每一個命題(proposition)都遵循同一個五段式結構,這是本節要帶走的「程式碼模板」:
- protasis(條陳): 描述要證什麼或作什麼。例如:「在一已知有限直線上作一等邊三角形」。
- ekthesis: 圖形設定——標記給定元素。
- diorismos: 目標重述——「要求做到的是……」。
- kataskeuē: 構造——根據公設 1–3 畫出輔助線與圓。
- apodeixis: 證明——根據定義、公設、公理與先前命題推理。
- horismos / porisma: 結論(Q.E.F. 作圖完:quod erat faciendum;或 Q.E.D. 證畢:quod erat demonstrandum)。
命題 I.1(在有限直線上作等邊三角形)是最佳示範。原文大意:
在有限直線 \(AB\) 上作等邊三角形。以 \(A\) 為心、 \(AB\) 為半徑作圓,再以 \(B\) 為心、 \(BA\) 為半徑作圓;兩圓交於 \(C\) 。連 \(CA\) 、 \(CB\) 。因 \(AC = AB\) (半徑), \(BC = AB\) (半徑),所以 \(AC = BC\) (公理 1、2)。故三角形 \(ABC\) 三邊相等。Q.E.F.
在 SymPy 中,整個構造只需要三條指令:兩個 Circle(公設 3)與一次 intersection:
from sympy import Point, Circle
import sympy
A = Point(0, 0)
B = Point(1, 0)
# 以 A 為心、AB 為半徑的圓 == 公設 3
c1 = Circle(A, B.distance(A))
# 以 B 為心、BA 為半徑的圓 == 公設 3
c2 = Circle(B, B.distance(A))
# 兩圓交點 == 構造 C(歐幾里得默認了它存在,這是日後 Hilbert 補上的漏洞)
intersections = c1.intersection(c2)
C = intersections[1] # 取上方的交點
print(C) # 預期輸出:Point2D(1/2, sqrt(3)/2)
# apodeixis:三邊相等
d_AB = A.distance(B)
d_AC = A.distance(C)
d_BC = B.distance(C)
print(sympy.simplify(d_AB)) # 預期輸出:1
print(sympy.simplify(d_AC)) # 預期輸出:1
print(sympy.simplify(d_BC)) # 預期輸出:1
print(d_AC == d_AB, d_BC == d_AB) # 預期輸出:True True
輸出 (1/2, sqrt(3)/2) 正是等邊三角形高 \(\sqrt{3}/2\) 的座標——如果你還懷疑這與 30–60–90 三角形有關,到 2.3 節的畢氏定理我們就會證明 \(1^2 = (1/2)^2 + (\sqrt{3}/2)^2\) 。
關鍵觀察:歐幾里得說兩圓「相交於 \(C\) 」,但他的公設不足以保證圓的連續性。這個漏洞直到 Hilbert(1899)與 Tarski(二十世紀的幾何公理系統)才被補上。如今,這個「缺失的公理」可以在 SymPy 的 Circle.intersection 裡自動完成——電腦代數系統幫兩千年的漏洞打了補丁。
6. 影響兩千年的公理化典範#
6.1 牛頓《自然哲學的數學原理》(1687)#
牛頓在 1687 年出版 Philosophiæ Naturalis Principia Mathematica 時刻意模仿《幾何原本》:先列「定義」(質量、動量、力)與「公理,或運動定律」(Newton 三定律),接著以「命題、定理、系、引理」的格式推演出行星運動、潮汐、彗星軌道。第 1 卷的第一條命題就完全沿用了 Euclid「構造—證明—結論」的 protasis 格式。牛頓著名的表述「Hypotheses non fingo(我不構造假說)」背後,就是 Euclid 式的信念:物理學應像幾何一樣,從最少的第一原理演繹出一切。
一個世紀後,Bottazzini 等史家指出,19 世紀的《Principia》註釋本(如 Laplace 的機械剖析)全都以 Euclid 為藍本《Newton's Principia: the mathematical principles of natural philosophy》——公理化不只是數學的內部規範,也是自然科學的寫作模板。
6.2 斯賓諾莎《倫理學》(1677)#
哲學家斯賓諾莎(Baruch Spinoza)用幾何方式(more geometrico)撰寫《倫理學》(Ethica Ordine Geometrico Demonstrata,「以幾何次序證明的倫理學」):定義、公理、命題、證明、附釋,一節不缺。他相信倫理學可以像幾何那樣演繹地建立。這體現了《幾何原本》在啟蒙運動的巨大威望。
6.3 非歐幾何與 Hilbert 重建#
兩千年來,數學家一直在折騰第五公設(第 6 章的主題):1697 年 Saccheri 的《歐幾里得無懈可擊》、1831 年前後 Gauss、Bolyai、Lobachevsky 各自獨立發現非歐幾何。這證明公理系統不是「唯一真理」,而是結構假設:換掉第五公設,換出一個同樣自洽的幾何。1899 年,Hilbert 的《幾何基礎》(Grundlagen der Geometrie)完成現代公理化:
- 明確列出未定義名詞(點、線、面、介於、全等);
- 將公理分成 結合(incidence)、次序(order)、全等、平行、連續五組,共 20 條;
- 補上 Euclid 缺漏的所有漏洞(兩圓相交、介於關係等)。
6.4 計算機定理證明:從公理到程式#
到 20 世紀,公理化方法延伸進電腦科學——定理證明從人類手工活動變成機器可執行的程式。計算機科學家推出形式化證明系統:
| 系統 | 年代 | 內容 |
|---|---|---|
| Automath(de Bruijn) | 1967–8 | 第一批機器檢驗全球數學證明 |
| Mizar | 1973– | 波蘭的證明資料庫,內含《幾何原本》全卷形式化 |
| Coq / Lean / Isabelle | 1990s– | 現代定理證明器;Lean 的 mathlib 完整形式化了 Hilbert 公理幾何 |
在 Lean 的 mathlib 中,你真的可以用 EuclideanGeometry 命名空間寫出歐幾里得命題。2014 年,Flyspeck project 宣布 Kepler 猜想的電腦輔助證明完成,使用了 Isabelle/HOL 驗證數萬行證明、花費約 20 個 CPU 年。2017 年起 Lean 的 mathlib 把「畢氏定理、幾何原本命題」與整本數學逐條寫成程式碼。SymPy 不是定理證明器,而是計算式的表意工具:它用代數化計算輔助你觀察幾何命題都成立,但不執行「邏輯完整性檢查」。本書選 SymPy 是因為它輕量、與 Python 完全融合、還能直接畫圖。
6.5 成語「Euclidean algorithm」#
《幾何原本》第 VII–IX 卷講數論。命題 VII.2 是輾轉相除法求最大公因數,至今仍叫 Euclidean algorithm。命題 IX.20 證明質數有無窮多——現代資訊安全(RSA 加密)的數論基石正是第 VII–IX 卷的歐氏遠產。SymPy 內建 gcd、primerange,直接呼應兩千年前的第 VII 卷:
import sympy
# 《幾何原本》VII.2:輾轉相除法求 gcd
print(sympy.gcd(1729, 25)) # 預期輸出:7
print(sympy.gcd(1071, 462)) # 預期輸出:21(Old Babylonian 標準範例)
# 《幾何原本》IX.20:質數有無窮多(電腦只給有限片段)
print(list(sympy.primerange(2, 30))) # 預期輸出:[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
7. 公理系統的現代規範#
用今天的語言,一個「像樣」的公理系統要滿足:
- 一致性(consistency):不能同時證出 \(P\) 與 \(\neg P\) 。
- 獨立性(independence):任一公設不能由其他公設推出。第五公設的獨立性到 1868 年 Beltrami 才證明。
- 完備性(completeness):系統內部每個命題都可判定。Gödel(1931)證明足夠強的算術系統不可能同時完備又一致——公理化方法的極限。
這三個概念不是古典概念,而是 19 世紀末數學基礎危機後的產物。歐幾里得本人從不問「這個系統完不完備?」他問的是「這個命題能不能從我的出發點推出?」這種實用主義的推理性,正是 SymPy 體現的精神。
用下面的表整理歐幾里得公理系統與現代對應:
| 《幾何原本》 | Hilbert (1899) | SymPy 幾何模組 |
|---|---|---|
| 23 個定義 | 未定義名詞 + 派生定義 | Point, Line, Circle 等 class 與 docstring |
| 5 公設 + 5 公理 | 20 條公理 | 物件的 method(Circle, Line, intersection 等行為由 Python 類別語義規定) |
| 465 個命題 | Hilbert 全書命題 | 各章的 SymPy 驗證腳本 |
8. 歷史回顧與一點延伸#
《幾何原本》最驚人的品質是自足:它假定讀者沒有數學知識,只帶走語言與邏輯。這種「零起點推起一門學科」的理想,影響到的書籍包括:
- Copernicus《天體運行論》(1543):模仿 Euclid 章節格式。
- Galileo《兩門新科學》(1638):幾何式推理。
- Spinoza《倫理學》(1677):more geometrico。
- Newton《Principia》(1687):公理 + 命題式物理學。
- 《美國獨立宣言》(1776):"We hold these truths to be self-evident(自明)..."——Jefferson 把自然權利寫成公設。
並非所有都順利:中世紀晚期,《幾何原本》的譯本與註釋多是節本(業餘編者的摘要),直到 1800 年代才有較忠實的版本;而 20 世紀,激進的「新數學」運動(1960s)把 Hilbert 式公理幾何塞進中小學課本,結果因過於抽象而失敗。今天我們用 SymPy 走的是第三條路:公理思想留在心中,計算交給機器,歷史作為背景音樂。
9. SymPy 動手做:重溯第 I 卷的開頭與收尾#
第 I 卷以命題 I.47(畢氏定理)收尾;第 I 卷前 4 個命題搭好兩件工具:
- I.1:在已知線段上作等邊三角形(上文已程式化)。
- I.2:在已知點,放一條與已知線段相等的線段。
- I.3:從兩條不等線段中,在長者上截出與短者相等的一段。
- I.4:邊角邊三角形全等(SAS)——歐幾里得用「疊合」(公理 4)證明。
其中 I.4(SAS 全等)是幾何的「原子操作」;SymPy 沒有內建 SAS,但可以驗證。以下小程式驗證 I.4 的關鍵思想——若兩三角形兩邊一夾角相等,則第三邊相等:
import sympy
from sympy import Point, pi
from sympy.geometry import Segment
# 三角形 T1:規格 (r, θ) — 兩腰為 r,夾角為 θ
def triangle(r1, r2, theta):
A = Point(0, 0)
B = Point(r1, 0)
C = Point(r2 * sympy.cos(theta), r2 * sympy.sin(theta))
return A, B, C
theta = sympy.pi / 3 # 夾角 60°
r1, r2 = sympy.Integer(3), sympy.Integer(4)
# 兩個三角形,同參數 → 公理系統上「全等」
A1, B1, C1 = triangle(r1, r2, theta)
A2, B2, C2 = triangle(r1, r2, theta)
# 驗證三對應邊相等(I.4 的結果)
print(sympy.simplify(Segment(A1, B1).length - Segment(A2, B2).length)) # 0
print(sympy.simplify(Segment(A1, C1).length - Segment(A2, C2).length)) # 0
third_1 = sympy.simplify(Segment(B1, C1).length)
third_2 = sympy.simplify(Segment(B2, C2).length)
print(third_1, third_2, third_1 == third_2)
# 預期輸出:sqrt(13) sqrt(13) True
# 夾角確為 pi/3(用兩條直線的夾角)
from sympy.geometry import Line
print(Line(A1, B1).angle_between(Line(A1, C1))) # 預期輸出:pi/3
(SymPy 以 Line.angle_between 計算夾角;兩條線段的夾角可視為其所屬直線的夾角。)
另一個小練習是驗證命題 I.5:「等腰三角形的底角相等」。這條俗名 pons asinorum「驢之橋」——中世紀學生過不了它,就像過不了獨木橋:
import sympy
from sympy import Point, Polygon
from sympy import sqrt
# 等腰三角形:AB = AC
A = Point(0, 3)
B = Point(-2, 0)
C = Point(2, 0)
tri = Polygon(A, B, C)
l_ac = A.distance(C)
l_ab = A.distance(B)
print(sympy.simplify(l_ab), sympy.simplify(l_ac), l_ab == l_ac)
# 預期輸出:sqrt(13) sqrt(13) True
# 兩底角是否相等:用向量內積計算餘弦
def cos_angle(P, V, Q):
"""在 V 點的角,向量與向量 P-V、Q-V 的夾角餘弦"""
from sympy import Matrix
u = Matrix([P.x - V.x, P.y - V.y])
w = Matrix([Q.x - V.x, Q.y - V.y])
return (u.dot(w) / (u.norm() * w.norm())).simplify()
c1 = cos_angle(A, B, C) # 在 B 的角
c2 = cos_angle(A, C, B) # 在 C 的角
print(sympy.simplify(c1), sympy.simplify(c2), sympy.simplify(c1 - c2) == 0)
# 預期輸出:2*sqrt(13)/13 2*sqrt(13)/13 True
10. 小結#
- 歐幾里得《幾何原本》(約前 300 年)以 23 個定義、5 公設、5 公理為基礎,演繹出 465 個命題,是公理化方法的第一個典範。
- 五大公設前四條是有限構造(直尺、圓規),第五條(平行公設)性質迥異,埋下非歐幾何伏筆。
- 《幾何原本》直接塑造了 Newton《Principia》、Spinoza《倫理學》與《獨立宣言》的寫作方式,至今影響形式驗證與定理證明器(Lean、Coq)。
- SymPy 的幾何類是這些「定義」的程式化身;本書每一章「前因後果 → 推導 → SymPy 驗證」的章法,都繼承了 Euclid 的命題結構。
習題#
-
定義抄本:用 SymPy 的
Circle、Line、Point寫一個函式diameter(c),傳回圓 \(c\) 的直徑長(定義 17),並以Circle(Point(0,0), 3)測試,預期輸出6。 -
公設 3 的實戰:給定 \(A=(0,0)\) 、 \(B=(4,0)\) ,用
Circle與intersection重做命題 I.1 的等邊三角形構造,並用Polygon.area計算三角形面積,預期輸出精確值 \(4\sqrt{3}\) 。順便驗證:等邊三角形面積公式 \(\frac{\sqrt{3}}{4}s^2\) 在 \(s = 4\) 時同樣得到 \(4\sqrt{3}\) 。 -
pons asinorum:把第 9 節的
cos_angle改寫成通用的「在點 \(V\) 的角」函式,並驗證等邊三角形每個角都是 \(\pi/3\) (即餘弦 \(= 1/2\) )。 -
第五公設的計算檢查:取直線 \(l: y = 0\) 與點 \(P = (0, 1)\) 。過 \(P\) 作斜率 \(m\) 的直線 \(l_m\) 。用 SymPy 計算 \(l_m\) 與 \(x\) 軸共線方向角與兩線交點,說明「只要 \(m \neq 0\) , \(l_m\) 與 \(l\) 在延長後必相交」——這正是第五公設刻畫的現象。
-
歷史對照:查閱 Heath 譯本公理 5「整體大於部分」,寫一段 100–200 字的短文,解釋為什麼它在 Cantor 集合論中失效(例如 \(\mathbb{N}\) 與偶數集),並討論這對歐幾里得公理系統的「一致性」意味著什麼。