1. 程式人生 > >4.4.3 邏輯程式設計是數學的邏輯嗎

4.4.3 邏輯程式設計是數學的邏輯嗎

4.4.3 邏輯程式設計是數學的邏輯嗎
在查詢語言中被使用的組合的方法首先可能與數學邏輯的與或非操作相同,查詢語言的規則的應用
在事實上是由推理的方法來完成的。查詢語言與數學邏輯的標識性並不是真正的有效的,因為查詢
語言提供了一個控制結構來程式化的解釋邏輯語句。我們能夠常常利用這種控制結構。例如,為了
找到所有的程式設計師的監督者,我們能寫一個查詢,以如下的兩種等價的形式:

(and  (job  ?x   (computer programmer))
      (supervisor   ?x   ?y))

或者是

(and (supervisor   ?x   ?y)
        (job  ?x   (computer programmer)))

如果一個公司有比程式設計師更多的監督者,(普通的例子)那麼使用上面的第一個寫法比第二個的寫法更好。
因為資料庫能被掃描生成的結果是由第一個子句生成的。

邏輯語言的作用是提供給程式設計師把一個計算的問題分解成兩個獨立的問題的技術。
這兩個問題是什麼能被計算,這應該如何計算?通過選擇數學邏輯的語句的子集,
就能完成這個任務了。數學邏輯有足夠的能力來描述什麼可能被計算,然而卻沒有
足夠的能力有一個可控制性的程式化的解釋。這裡的目的是說,一方面,在一種邏輯
程式設計的語言中規範的程式應該是一個易被影響的能被一個計算機執行的程式。根據語言
的解釋的順序,控制(即如何計算)能被影響。我們應該能夠安排子句的順序,子目標的順序,
為了計算被完成在一種順序中,並且是有影響的且有效率的。同時,我們應該能夠把
計算的結果(計算什麼)視覺化,作為邏輯的規則的一簡單的成果。

我們的查詢語言能夠被認為是數學邏輯的一個程式化的可解釋的子集。一個斷言表示一個簡單的事實。
一個規則 表示了內容是規則結論要滿足的規則內容體的條件。一個規則有一個自然的程式化的解釋。
為了建立規則的結論內部,建立規則的內容體。規則因此指定了計算。然而,因為規則也能被認為是
數學邏輯的語言,我們能通過一個邏輯程式來完成任何的推理。邏輯程式通過使用數學邏輯
得到斷言的相同的結果。

* 無限的迴圈
邏輯程式的程式化解釋的一個結果是為了解釋特定的問題,組裝了一個無希望的低效率的程式
的情況可能會發生。在做推導時當系統陷入了無限的迴圈時,低效率的極端的例子就發生了。
作一個簡單的例子,假定我們為了著名的婚姻安裝了一個數據庫,包括

(assert!   (married Minnie  Mickey))

如果我們現在問

(married  Mickey  ?who)

我們將沒有得到響應,因為系統不知道,如果A和B是夫妻,那麼B和A是夫妻。
所以我們加上了如下的規則

(assert!   (rule   (married  ?x  ?y)  (married ?y ?x)))

並且再一次查詢

(married  Mickey  ?who)

不幸的是,這將驅動系統進入了無限的迴圈,如下:

.系統發現married規則是可應用的,也就是規則的結論 (married ?x ?y)成功地統一了查詢模式
(married  Mickey  ?who),生成了一個幀,它的?x 綁定了 Mickey 和 ?y 綁定了 ?who。所以
直譯器繼續解釋規則的內容體(married ?y  ?x),在效果上看,是處理查詢(married ?who  Mickey)
.  在資料庫中一個答案直接作為記錄出現了:(married  Minnie  Mickey)
.  married規則是可應用的,所以直譯器再一次解釋規則的內容體,這一次等價為(married  Mickey  ?who)

系統現在處於無限迴圈之中。的確,在系統進行無限迴圈之前,系統是否將發現簡單的答案
(married  Minnie  Mickey),依賴於系統檢查資料庫中項的順序這樣的實現細節。互關聯的規則的集合能夠
導致更難參與的迴圈,迴圈的情況依賴於在一個與操作中的子句的順序(見練習4.64)或者是系統處理查詢的
順序的低層次的細節。

* not 帶來的問題
在查詢系統中的另一個問題涉及到not.給定一個4.4.1部分中的資料庫,考慮如下的兩個查詢:

(and  (supervisor   ?x  ?y) 
         (not  (job ?x   (computer programmer))))

(and  (not  (job ?x   (computer programmer)))
         (supervisor   ?x  ?y))

這兩個查詢沒有生成相同的結果。第一個查詢開始於在資料庫中
找到所有的匹配(supervisor   ?x  ?y)的記錄。並且然後過濾結果幀,並且移除
滿足(job ?x   (computer programmer))的條件。第二個查詢開始於過濾
滿足(job ?x   (computer programmer)),因為幀是空的,它檢查資料庫是否有模式滿足
(job ?x   (computer programmer)),因為這是入口,非子句過濾了空的幀,返回了一個空的流。
因此,整個流返回空。

困難在於非的實現真的是在變數的值的過濾器。如果一個非的子句被處理,一個幀中的
一些變數保留著未繫結。系統生成了非期望的結果。相似的問題發生在lisp-value的使用,
如果它的實際引數未繫結,Lisp的斷言不能工作。見練習4.77

查詢語言的非不同於數學邏輯的非,這也有更多的嚴肅的方式。在邏輯上,我們解釋了
語句 “not P”意味著P不是真的。在查詢系統中,然而,“not p”意味著P不在資料庫中知識。
例如,給出一個個人員工的資料庫, 系統推導著非語句的排序,例如 苯不是一個排球迷,
戶外沒有雨,2+2不等於4。換句話說,邏輯程式語言的非反映因此叫,所有的相關的資訊
已經包括在資料庫中。

練習4.64
羅斯從資料庫中誤刪除了規則 Outranked-by(4.4.1部分)。當他意識到這時,他快速
重新安裝了它。不幸的是,他在規則中做了一點修改,並且內容如下:

(rule  (outranked-by  ?staff-person   ?boss) 
         (or  (supervisor   ?staff-person  ?boss) 
                (and  (outranked-by   ?middle-manager  ?boss)
                         (supervisor   ?staff-person  ?middle-manager))))

羅斯向系統中輸入了這個資訊後,威特發現誰比苯位高,他發出了查詢

(outranked-by  (Bitdiddle Ben)  ?who)

回答了之後,系統進入了無限的迴圈。解釋為什麼。

練習4.65
Cy,當他在公司時,他期待著有一天,給一個查詢,找到的所有的間接的領導。
(使用4.4.1部分中的規則 wheel)

(wheel   ?who)

令他吃驚的是,系統返回:
;;;Query results:
(wheel  (Warbucks Oliver))
(wheel  (Bitdiddle Ben))
(wheel  (Warbucks Oliver))
(wheel  (Warbucks Oliver))
(wheel  (Warbucks Oliver))

為什麼 Warbucks 被列出了四次?

練習4.66
苯已經泛化了查詢系統,為了提供關於公司的統計資訊。
例如,為了找到所有的程式設計師的總工資數,查詢如下:

(sum  ?amount 
            (and  (job  ?x  (computer programmer))
                     (salary  ?x  ?amount)))

總之,苯的新的系統允許如下的表示式的形式:

(accumulation-function  <variable>  <query pattern>)

accumulation-function能像sum,average,maximum一樣。
苯的理由是實現這應該是很容易的事。他將簡單地把查詢模式餵給qeval.
這產生了一個幀的流。他然後把這個流給了一個對映函式,把流中的每個幀中
抽取了特定的變數的值,再把值的結果流餵給了accumulation函式。正如苯完成的實現,
並且將測試。Cy用練習4.65的wheel查詢結果來解謎。當Cy顯出了苯的系統的響應,
苯說“不,我們簡單的累計的函式失效了。”

苯已經意識到了什麼?為了解決這種情況,列出他能使用的方法

練習4.67
在查詢系統中,為了安裝一個迴圈檢測器,用它來避免在練習4.64中出現的簡單的迴圈情況,
給出一個方式。通用的思想是系統應該維護推導的當前鏈條的一些歷史資訊,當它正在工作時,
不應該開始處理一個新的查詢。描述一下什麼樣的資訊(模式和幀)應該包括在這個歷史中,
應該如何做檢查。(當你學習了在4.4.4部分中的查詢系統的實現細節後,你可能要修改系統來
包括你的迴圈檢測器)

練習4.68
定義一個規則來實現練習2.18中的反向操作,它返回一個列表,包括與給定的列有一樣的元素,
且與原列表的排列順序相反。(提示:使用append-to-form)你的規則能回答(reverse (1 2 3)  ?x)
和 (reverse   ?x  (1 2 3)) 嗎?

練習4.69
開始於你在練習4.63中寫的資料庫內容與規則,寫一個規則 新增"太"到祖孫關係中。
這應該能讓系統推匯出irad是Adam的重孫,或者Jabal和Jubal是Adam的重重重重重孫。
(提示:表示關於Irad的事實,例如 ((great  grandson)   Adam Irad)) .寫規則確定
一個列表的結尾處是否是孫子。使用這個來表達一個規則 允許人來推導關係 
((great  .  ?rel)   ?x  ?y),   ?rel 是一個列表以孫子結尾 ) .  以查詢檢查 你的規則,例如
((great  grandson)   ?g  ?ggs) 和 (?relationship  Adam Irad)。