用Python實現命題邏輯歸結推理系統--人工智能

  • 考察 命題邏輯歸結推理
  • 求點贊,給作者一點分享的鼓勵
  • 代碼沒寫GUI,因爲不喜歡這玩意,直接在終端中進行人機交互。使用代碼之前,請根據自身情況對字符編碼、文件路徑進行修改
  • 代碼沒有使用什麼算法進行優化,姑且這樣吧

歸結演繹推理

推理方式:

歸結演繹推理 定理:

謂詞公式化爲子句集

常出現的名詞:

  • 原子謂詞公式:一個不能再分解的命題
  • 文字:原子謂詞公式及其否定
    • 正文字:P
    • 負文字:~P
    • 正文字、負文字互補
  • 子句:任何文字的析取式。(任何文字本身也是子句)
  • 空子句(NIL):不包含任何文字的子句
    • 空子句是永假的,不可滿足的
  • 子句集:由子句構成的集合

用一個例子來說明一下謂詞公式化爲子句集的過程

[例]

  • 第一步:消去謂詞公式中的“\rightarrow” 和 “\Leftrightarrow” 符號

    • 公式:
    • [例]
  • 第二步:把否定符號 “~” 移到緊靠謂詞的位置上

    • 公式:
    • [例]
  • 第三步:變量標準化

    • 公式:
    • [例]
  • 第四步:消去存在量詞

    • 若存在量詞不出現在全稱量詞的轄域內(很簡單,用一個個體表示即可)
    • 若存在量詞出現在一個或多個全稱量詞的轄域內(存在量詞 y 的Skolem函數爲 y = f(x1, x2, …, xn),需要用Skolem函數代替每個存在量詞量化的變量的過程)
    • Skolem函數表示約束,但不關係約束是什麼
    • [例]
  • 第五步:化爲前束形

    • 前束形 = (前綴){母式}
    • 前綴:全稱量詞
    • 母式:不含量詞的謂詞公式
    • [例] 已經是前束形
  • 第六步:化爲Skolem標準化

    • 子句的合取式,稱爲Skolem標準形的母式
    • 公式:
    • [例]
  • 第七步:略去全稱量詞

    • [例]
  • 第八步:消去合取詞

    • [例]
  • 第九步:子句變量標準化

    • 即不同的子句用不同的變元
    • [例]

魯濱遜歸結原理(消解原理)

子句集中子句之間是合取關係,只要有一個子句不可滿足,則子句集就不可滿足

基本思想:

  • 檢查子句集S中是否包含空子句
  • 若包含,則S不可滿足
  • 若不包含,在S中選擇合適的子句進行歸結
  • 若歸結出空子句,就說明S是不可滿足的

1. 命題邏輯中的歸結原理(基子句的歸結)

  • C12 是 C1 和 C2歸結式
  • C1、C2 是 C12親本子句

歸結式:從親本子句中去掉一對互補文字後,剩餘的兩個部分的析取範式

2. 謂詞邏輯中的歸結原理(含有變量的子句的歸結)

證明過程較爲複雜,簡單來說:函數名相同,雖然變量名不同,可直接看作互補文字

歸結反演

  1. 將已知前提表示爲謂詞公式F
  2. 將待證明的結論表示爲謂詞公式Q,並否定得到~Q
  3. 把謂詞公式集{F, ~Q} 化爲子句集
  4. 應用歸結原理對子句集S中的子句進行歸結,並把每次歸結得到的歸結式都併入到S中,如此反覆,若出現了空子句,則停止歸結,此時證明了Q爲真

已知命題公式集 s,求證 r

第一步,將每個命題化爲子句形式:

第二步,用文本文件保存的形式爲:
p
~p ∨ ~q ∨ r
~u ∨ q
~t ∨ q
t
~ r

第三步,歸結:

這就是一階命題邏輯語言中一個簡單的歸結證明

題目及代碼

設給定的已知條件爲公式集F,要從F求證的命題爲G,進行命題演算的歸結步驟爲:

  1. 將公式集F中的所有命題改寫成子句。
  2. 將命題~G改寫成一個子句或多個子句。
  3. 將 1、2 所得到的子句合併成子句集S,放到一個文本文件中。(以上爲手工完成)

編寫程序完成以下功能:

  1. 讀入以上文本文件
  2. 以適當的形式保存爲子句集。
  3. 在出現一個矛盾或無任何進展(得不到新子句)之前執行:
    • 從子句集中選一對親本子句(兩個子句分別包含某個文字的正文字,另外一個包含負文字)
    • 將親本子句對歸結成一個歸結式;
    • 若歸結式爲非空子句,將其加入子句集;若歸結式爲空子句,則歸結結束。

子句集S存入文本文件

p
~p ∨ ~q ∨ r  
~u ∨ q   
~t ∨ q
t
~r
S = [] # 以列表形式存儲子句集S


"""
讀取子句集文件中子句,並存放在S列表中
    - 每個子句也是以列表形式存儲
    - 以析取式分割
    - 例如:~p ∨ ~q ∨ r 存儲形式爲 ['~p', '~q', 'r']
"""
def readClauseSet(filePath):
    global S
    for line in open(filePath, mode = 'r', encoding = 'utf-8'):
        line = line.replace(' ', '').strip()
        line = line.split('∨')
        S.append(line)


"""
- 爲正文字,則返回其負文字
- 爲負文字,則返回其正文字
"""
def opposite(clause):
    if '~' in clause:
        return clause.replace('~', '')
    else:
        return '~' + clause


"""
歸結
"""
def resolution():
    global S
    end = False
    while True:
        if end: break
        father = S.pop()
        for i in father[:]:
            if end: break
            for mother in S[:]:
                if end: break
                j = list(filter(lambda x: x == opposite(i), mother))
                if j == []:
                    continue
                else:
                    print('\n親本子句:' + ' ∨ '.join(father) + ' 和 ' + ' ∨ '.join(mother))
                    father.remove(i)
                    mother.remove(j[0])
                    if(father == [] and mother == []):
                        print('歸結式:NIL')
                        end = True
                    elif father == []:
                        print('歸結式:' + ' ∨ '.join(mother))
                    elif mother == []:
                        print('歸結式:' + ' ∨ '.join(mother))
                    else:
                        print('歸結式:' + ' ∨ '.join(father) + ' ∨ ' + ' ∨ '.join(mother))
                   

def ui():
    print('----')
    print('--------命題邏輯歸結推理系統--------')
    print('----')


def main():
    filePath = r'命題邏輯歸結推理系統/S.txt'
    readClauseSet(filePath)
    ui()
    resolution()


if __name__ == '__main__':
    main()

很遺憾,我寫的代碼暫時只能實現命題邏輯歸結推理系統,

對於謂詞邏輯歸結推理,以後有時間再完善代碼


推薦文章


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章