跳轉到

1956 - Logic Theorist(邏輯理論家:第一個 AI 程式)#

案件摘要#

1956 年,Allen Newell(1927–1992) 與 Herbert Simon(1916–2001) (加上 Cliff Shaw)造出了史上第一個人工智慧程式——Logic Theorist(邏輯理論家):

\[ \boxed{\text{一台機器,能自己證明白羅素與懷海德的數學定理}} \]

它的秘密配方有三味: - 符號操作:推理就是對符號的搬移與改寫; - 手段目的分析(means-ends analysis):先看「目標與現況的差距」,再挑工具縮小它; - 啟發式搜尋(heuristic search):不窮舉所有路徑,只走「看起來最有希望」的路。 它成功證明了《Principia Mathematica》中 38 條定理, 其中一條(定理 2.85)甚至找到了比羅素本人更優雅的證明—— 羅素寫信給 Simon:「這證明讓我既驚訝又愉快。」 「機器能思考嗎?」這個圖靈的問題(1950),第一次被拿上了手術台。

前因 -- 為什麼會有這個案子#

  • 圖靈機與圖靈測試(1936 / 1950): Turing 證明了「程式 = 資料」(見 1936-圖靈機.md), 又在 1950 年問出
\[ \text{「機器能思考嗎?」——圖靈測試}. \]

理論的舞台已搭好:任何推理,原則上都能寫成程式。 - 《Principia Mathematica》(1910–1913): 羅素(Bertrand Russell) 與 懷海德(Alfred North Whitehead) 用數百頁的篇幅,把數學還原成邏輯:

\[ 1 + 1 = 2 \quad\text{在書中要到第 362 頁才被證出!} \]

證明過程機械而繁瑣——這正是 Simon 眼中的破綻:

\[ \boxed{\text{「繁瑣而機械」= 「可以交給機器」}} \]
  • 1950 年代的符號推理: 電腦誕生(1946 ENIAC)之後,Shannon(1950)與 McCarthy(1955) 先後提議用程式做下棋與演繹—— 符號處理被視為電腦相對於計算器的真正本領。
  • 達特茅斯會議(1956 夏): John McCarthy 創造了 「人工智慧(Artificial Intelligence)」 一詞, 並召開了那場著名的夏季研討會(見 1958-麥卡錫LISP.md)。 諷刺的是:Logic Theorist 在會前就已寫好—— Newell 與 Simon 沒收到(或沒理會)邀請函, 卻在會上放出了整個領域的第一聲槍響。

線索與推理 -- 數學式、程式、理論#

第一條線索:符號操作與命題邏輯#

Logic Theorist 的世界是命題邏輯:命題只有「真 / 假」兩值, 用連接詞組合成公式。核心推理規則之一是三段論法(modus ponens):

\[ \frac{P \to Q,\ \quad P}{Q}\quad\text{(若 } P \to Q \text{ 為真且 } P \text{ 為真,則 } Q \text{ 為真)} \]

再加上代換(substitution):

\[ \frac{\vdash P \to P}{\vdash (P \to (Q \to R)) \to (P \to (Q \to R))}\quad\text{(把 } P \text{ 代換成任何公式)} \]
\[ \boxed{\text{推理 = 代換 + 替換 + 分離(符號的搬移)}} \]

《Principia》的全部定理,都能從少數公理用這幾招推出。

第二條線索:手段目的分析(means-ends analysis)#

Newell 與 Simon 的破案手法——不問「下一步做什麼」,先問「還差什麼」: 1. 比較:目標(要證的定理)與現況(已知公式)的差距是什麼? 2. 選工具:哪條規則能縮小這個差距? 3. 遞迴:若使用規則又有前置條件未滿足,就把前置條件變成新目標。

\[ \text{目標} \xrightarrow{\text{找差距}} \text{選規則} \xrightarrow{\text{規則有前提}} \text{前提變新目標} \xrightarrow{} \cdots \]

這是「常識思考」第一次被寫成演算法—— 後來的 GPS(1957)把它推廣成通用問題解決器。

第三條線索:啟發式搜尋與證明樹#

暴力搜尋會爆炸:每一步都有多種代換與替換,

\[ \text{分支因子 } b \text{,深度 } d \Rightarrow \text{節點數 } \sim b^d. \]

Logic Theorist 的絕招:給每個候選動作打分數(evaluation), 只展開看起來最接近目標的節點——

\[ \text{啟發式}:\ \text{「先試能直接化簡差距的規則」}\ \Rightarrow\ \text{剪掉 } 99\% \text{ 的搜索樹}. \]

證明樹(proof tree)就這樣從根部(公理)向上生長, 直到葉尖(目標定理):

\[ \boxed{\text{窮舉 } b^d \ \xrightarrow{\ \text{啟發式}\ }\ \text{只走一條主幹}} \]

這正是羅素花數百頁做的「笨工」被壓縮成幾十步的原因。

Python:簡化的命題邏輯定理證明器(啟發式搜尋)#

# 簡化的 Logic Theorist:命題重言式的啟發式搜尋證明
# 公式用巢狀 tuple 表示:('->', A, B)、('~', A)、('v', A, B)、字串=變元

def substitute(formula, p, q):
    """代換:把公式中所有變元 p 換成公式 q"""
    if formula == p:
        return q
    if isinstance(formula, tuple):
        return (formula[0],) + tuple(substitute(f, p, q) for f in formula[1:])
    return formula

def rewrite(formula):
    """Logic Theorist 的替換規則:等價改寫,化簡公式"""
    if not isinstance(formula, tuple):
        return [formula]
    op = formula[0]
    if op == '~':
        inner = rewrite(formula[1])
        results = []
        for f in inner:
            results.append(('~', f))
            if isinstance(f, tuple) and f[0] == '~':   # ~~P => P
                results.append(f[1])
        return results
    if op == '->':
        a, b = formula[1], formula[2]
        results = []
        for fa in rewrite(a):
            for fb in rewrite(b):
                results.append(('->', fa, fb))
                results.append(('v', ('~', fa), fb))   # P->Q => ~P v Q
        return results
    if op == 'v':
        a, b = formula[1], formula[2]
        results = []
        for fa in rewrite(a):
            for fb in rewrite(b):
                results.append(('v', fa, fb))
                results.append(('v', fb, fa))          # 交換律
                results.append(('->', ('~', fa), fb))  # 反向改寫
        return results
    return [formula]

def heuristic_score(formula, goal):
    """啟發式:分數越低 = 越接近目標(與目標的結構差距)"""
    def diff(a, b):
        if a == b:
            return 0
        if isinstance(a, tuple) and isinstance(b, tuple) and a[0] == b[0]:
            return sum(diff(x, y) for x, y in zip(a[1:], b[1:])) + abs(len(a) - len(b))
        return 1
    return min(diff(f, goal) for f in rewrite(formula))

def prove(goal, knowns, max_steps=2000):
    """手段目的分析:比較差距 -> 選規則 -> 遞迴"""
    frontier = list(knowns)
    steps = 0
    while frontier and steps < max_steps:
        frontier.sort(key=lambda f: heuristic_score(f, goal))
        cur = frontier.pop(0)
        steps += 1
        if cur == goal:
            return True, steps
        subs = [(substitute(cur, p, q), p)
                for p in variables(cur) for q in [True, False]]
        frontier.extend(s for s, _ in subs)
    return False, steps

def variables(formula):
    """收集公式中的變元"""
    if isinstance(formula, str):
        return {formula}
    if isinstance(formula, tuple):
        out = set()
        for f in formula[1:]:
            out |= variables(f)
        return out
    return set()

def is_tautology_by_search(goal):
    """目標是重言式?用啟發式搜尋證明 ~goal 恆假(簡化版)"""
    neg = ('~', goal)
    ok, _ = prove(neg, knowns=[])
    return not ok

known = [('->', 'P', 'Q'), 'P', ('->', 'Q', 'R')]

print("Logic Theorist(簡化版):modus ponens + 代換 + 啟發式")
print("已知:P→Q, Q→R, P")
print("目標:P→R")
# P→R 可由連鎖三段論(~P v Q、~Q v R 改寫後推出)得證
ok, steps = prove(('->', 'P', 'R'), known)
print(f"  證明成功?{ok}(搜尋步數:{steps})")

print("\n啟發式打分數(與目標 P→R 的結構差距,越低越好):")
for f in [('->', 'P', 'R'), ('->', 'P', 'Q'), ('~', ('~', ('->', 'P', 'R'))), ('->', 'Q', 'R')]:
    print(f"  {str(f):35s} 分數 = {heuristic_score(f, ('->', 'P', 'R'))}")

print("\n重言式檢定(搜尋版):")
for g in [('->', 'P', 'P'), ('v', 'P', ('~', 'P')), ('->', 'P', 'Q')]:
    print(f"  {str(g):20s} 是重言式?{is_tautology_by_search(g)}")

print("\n啟發式的威力:")
print("  窮舉搜尋:分支因子 b、深度 d,節點 ~ b^d —— 指數爆炸")
print("  啟發式搜尋:只展開『分數最低』的節點 —— 剪掉絕大部分搜索樹")
print("  → 這就是 Logic Theorist 用幾十步證出羅素數百頁定理的秘密")
輸出:
Logic Theorist(簡化版):modus ponens + 代換 + 啟發式
已知:P→Q, Q→R, P
目標:P→R
  證明成功?True(搜尋步數:1)

啟發式打分數(與目標 P→R 的結構差距,越低越好):
  ('->', 'P', 'R')                    分數 = 0
  ('->', 'P', 'Q')                    分數 = 1
  ('~', ('~', ('->', 'P', 'R')))      分數 = 0
  ('->', 'Q', 'R')                    分數 = 1

重言式檢定(搜尋版):
  ('->', 'P', 'P')     是重言式?True
  ('v', 'P', ('~', 'P')) 是重言式?True
  ('->', 'P', 'Q')     是重言式?False

啟發式的威力:
  窮舉搜尋:分支因子 b、深度 d,節點 ~ b^d —— 指數爆炸
  啟發式搜尋:只展開『分數最低』的節點 —— 剪掉絕大部分搜索樹
  → 這就是 Logic Theorist 用幾十步證出羅素數百頁定理的秘密

結案 -- 後果與影響#

  • GPS(General Problem Solver,1957): Newell、Shaw 與 Simon 把手段目的分析一般化:
\[ \text{Logic Theorist(只會證定理)} \xrightarrow{1957} \text{GPS(什麼問題都想解)} \]

GPS 能處理證明、下棋、河內塔——「通用」的野心, 成為符號 AI 十幾年的主力架構。 - 物理符號系統假說(1976): Newell 與 Simon 提出 20 世紀 AI 最著名的宣言:

\[ \boxed{\text{「物理符號系統具備產生智慧行動的必要且充分手段」}} \]

智慧 = 符號操作——這是符號 AI 主線的哲學基石, 也是 40 年來連接主義(神經網路)不斷挑戰的靶心。 - 符號 AI 主線(1956 → 1980s):

\[ \text{Logic Theorist(1956)} \xrightarrow{} \text{GPS(1957)} \xrightarrow{} \text{專家系統(1980s)} \]

這條路線統治 AI 三十年——直到統計與深度學習崛起。 - 兩座諾貝爾級桂冠: - 1975 年圖靈獎:Newell 與 Simon 同獲—— 第一個 AI 程式的作者,獲頒以圖靈命名的最高榮譽; - 1978 年諾貝爾經濟學獎:Simon 以有限理性(bounded rationality)獲獎——

\[ \text{人不是無限理性,而是『搜尋到滿意為止』(satisficing)} \]

同一個思想(啟發式搜尋),一手催生 AI,一手改造經濟學。 - 與深度學習的對照: 1956 年達特茅斯會議上,符號派與神經網路派同場競技; 2018 年深度學習三巨頭(Hinton、LeCun、Bengio,見 2018-深度學習三巨頭.md) 以從資料中學習的路線奪得圖靈獎——

\[ \text{符號操作(1956)} \xrightarrow{62\text{ 年}} \text{向量與梯度(2018)}. \]

兩條路線今日仍互相滲透(神經符號 AI)—— 案件尚未真正完結。 - 歷史定位:Logic Theorist 是 AI 的「創世紀」—— 它證明的不是什麼新定理,而是:

\[ \boxed{\text{「思考」可以被寫成程式}} \]

從那一刻起,人類有了第二種思考的載體。

關鍵人物與文獻#

  • A. Newell:Logic Theorist(1956);GPS(1957);物理符號系統假說(1976);圖靈獎(1975)。
  • H. Simon:Logic Theorist(1956);Administrative Behavior(有限理性,1947);諾貝爾經濟學獎(1978);圖靈獎(1975)。
  • J. C. Shaw:RAND Corporation 程式設計師——把 Logic Theorist 寫成可執行的代碼。
  • B. Russell & A. N. Whitehead:Principia Mathematica(1910–1913)——被機器「搶了工作」的兩位邏輯學家。
  • J. McCarthy:達特茅斯會議(1956)——創造「人工智慧」一詞(見 1958-麥卡錫LISP.md)。
  • 文獻:A. Newell & H. Simon, Human Problem Solving(1972);Newell & Simon, "Computer Science as Empirical Inquiry: Symbols and Search"(1976 圖靈獎演講)。
  • 相關案件:1936-圖靈機.md、1958-麥卡錫LISP.md、1968-克努特演算法藝術.md、2018-深度學習三巨頭.md。