Prolog教程 5 組合查詢

2021-09-06 09:32:25 字數 4023 閱讀 2629

常用內部謂詞

write/1

此謂詞被呼叫時永遠是成功的,並且它可以把它的引數作為字串輸出到螢幕上。當回溯時,它永遠是失敗,所以回溯是不會把已經寫到螢幕上的字元又給刪除的。

nl/0

此謂詞沒有引數,和write一樣,從call埠呼叫時總是成功的,從redo埠回溯時總是失敗的,它的作用是在螢幕上輸出乙個回車符。

tab/1

此謂詞的引數是乙個整數,它的作用是輸出n個空格,n為它的引數。其控制流程與上面兩個相同。

我們可以把簡單的查詢連線起來,組成一些較複雜的查詢。例如,如果我們想知道廚房裡能吃的東西,就可以向prolog進行如下的詢問。

?- location(x, kitchen), edible(x).

簡單的查詢只有乙個目標,而混合查詢可以把這些目標連線起來,從而進行較為複雜的查詢。上面的連線符號』,'是並且的意思。

上面的式子用語言來描述就是「尋找滿足條件的x,條件是:x在廚房裡,並且x能吃。」如果某個變數在詢問中多次出現,則此變數在所有出現的位置都必須繫結為相同的值。所以上面的查詢只有找到某乙個x的值,使得兩個目標都成立時,才算查詢成功。

每次查詢所使用的變數都是區域性的變數,它只在本查詢中有意義,所以當我們進行了如下的查詢後,

查詢結果中沒有broccoli(椰菜),因為我們沒有把它定義為可吃的東西。此後,還可以用x進行其他的查詢。

?- room(x).

x = kitchen ;

x = office ;

x = hall ;

…;no

除了使用邏輯的方法理解混合查詢外,還可以通過分析程式的執行步驟來理解。用程式的語言來說就是「首先找到一樣位於廚房的東西,然後判斷它能否食用,如果不能,就到廚房裡找下一樣東西,再判斷能否食用。一直如此重複,直到找到答案或把廚房的東西全部查完為止。」

請參照下圖來理解。

呼叫查詢後,程式將按照下面的步驟執行,請參照上圖來理解。

搜尋第乙個目標,如果成功轉到2,如果失敗則回答』no』,查詢結束。

搜尋第二個目標,如果成功轉到3,如果失敗轉到1。

把繫結的變數的值輸出。使用者輸入』;'後轉到2。

上面的例子中只有乙個變數,下面我們再來看乙個有兩個變數的例子。

?- door(kitchen, r), location(t,r).

r = office

t = desk ;

r = office

t = computer ;

r = cellar

t = 『washing machine』 ;

no上面的查詢用邏輯的語言來解釋就是:「找房間r,使得從廚房到房間r有門相連,並且把房間r中的物品t(這裡是房間r的所有物品)也找出來。」

下面是此查詢的單步執行過程。

goal: door(kitchen, r), location(t,r)

1 call door(kitchen, r)

1 exit (2) door(kitchen, office)

2 call location(t, office)

2 exit (1) location(desk, office)

r = office

t = desk ;

2 redo location(t, office)

2 exit (8) location(computer, office)

r = office

t = computer ;

2 redo location(t, office)

2 fail location(t, office)

1 redo door(kitchen, r)

1 exit (4) door(kitchen, cellar)

2 call location(t, cellar)

2 exit (4) location(『washing machine』, cellar)

r = cellar

t = 『washing machine』 ;

2 redo location(t, cellar)

2 fail location(t, cellar)

1 redo door(kitchen, r)

1 fail door(kitchen, r)

no內部謂詞

講了這麼多了,我們還只是用到了prolog的一些語法,完全沒有使用prolog提供的一些內部的函式,我把這些內部函式稱為內部謂詞。和其他的程式語言一樣,prolog也提供了一些基本的輸入輸出函式,下面我們要編寫乙個較複雜的查詢,它能夠找到所有廚房裡能夠吃的東西,並把它們列出來。而不是像以前那樣需要人工輸入』;』。

要想完成上面的任務,我們首先必須了解內部謂詞的概念。內部謂詞是指已經在prolog中事先定義好的謂詞。在記憶體中的動態資料庫中是沒有內部謂詞的子句的。當直譯器遇到了內部謂詞的目標,它就直接呼叫事先編好的程式。

內部謂詞一般所完成的工作都是與邏輯程式無關的,例如輸入輸出的謂詞。所以我們可以把這些謂詞叫做非邏輯謂詞。

但是這些謂詞也可以作為prolog的目標,所以它們也必須擁有和邏輯謂詞相同的四個埠:call、fail、redo和exit。

下面介紹幾個常用的輸出謂詞。

write/1

此謂詞被呼叫時永遠是成功的,並且它可以把它的引數作為字串輸出到螢幕上。當回溯時,它永遠是失敗,所以回溯是不會把已經寫到螢幕上的字元又給刪除的。

nl/0

此謂詞沒有引數,和write一樣,從call埠呼叫時總是成功的,從redo埠回溯時總是失敗的,它的作用是在螢幕上輸出乙個回車符。

tab/1

此謂詞的引數是乙個整數,它的作用是輸出n個空格,n為它的引數。其控制流程與上面兩個相同。

下圖是一般情況下的prolog目標的內部流程控制示意圖。我們將使用此圖和內部謂詞的流程控制圖相比較。

上圖中左上角的菱形方塊表示從call埠進入目標時所進行的處理。它從某謂詞的第乙個子句開始搜尋,如果匹配成功就到exit埠,如果沒有找到任何乙個子句與目標匹配就轉到fail埠。

i/o謂詞的流程控制和上述的不同,它不會改變流程的方向,如果流程從它的左邊進入,就會從它的右邊流出;而如果從它的右邊進入,則會從它的左邊流出。請參考下圖理解。

i/o謂詞不會改變變數的值,但是它們可以把變數的值輸出。

還有乙個專門引起回溯的內部謂詞fail/0,從它的名字不難看出,它的呼叫永遠是失敗的。如果fail/0從左邊得到控制權,則它立即把控制權再傳回到左邊。它不會從右邊得到控制,因為沒法通過fail/0把控制權傳到右側。它的內部流程控制如下:

以前我們是靠使用』;'來進入目標的redo埠的,並且變數的值的輸出是靠直譯器完成的。現在有了上面幾個內部謂詞,我們就可以靠i/o謂詞來顯示變數的值,靠fail謂詞來引起自動的回溯。

下面是此查詢語句及其執行結果。

下面是此查詢的流程圖。

下面是此查詢的單步除錯過程。

3 exit nl

4 call fail

4 fail fail

3 redo nl

3 fail nl

2 redo write(broccoli)

2 fail write(broccoli)

1 redo location(x, kitchen)

1 exit (7) location(crackers, kitchen)

2 call write(crackers) crackers

2 exit write(crackers)

3 call nl

3 exit nl

4 call fail

4 fail fail

3 redo nl

3 fail nl

2 redo write(crackers)

2 fail write(crackers)

1 redo location(x, kitchen)

1 fail location(x, kitchen)

no下面請你分析一下,

?- door(kitchen, r), write®, nl, location(t,r), tab(3), write(t), nl, fail.

的輸出的結果是什麼呢?

PyQt5教程 19 組合框

qcombobox 是乙個允許使用者從列表選項中選擇一項的控制項。usr bin python3 coding utf 8 pyqt5 教程 這個例子展示了如何使用qcombobox部件。部落格 import sys class example qwidget def init self super...

13 組合查詢 SQL

利用union操作符將多條select語句組合成乙個結果集。主要有兩種情況需要使用組合查詢 union規則 包含或取消重複的行 union從查詢結果集中自動去除了重複的行 換句話說,它的行為與一條select語句中使用多個where子句條件一樣。使用union時,重複的行會被自動取消。這是union...

Prolog教程 4 簡單查詢

goal 查詢目標 unification 匹配工作三個必要哦條件1.目標謂詞一致 2.謂詞引數數量一致 3.所有引數相同 查詢繼續 查詢4個埠 1.call 開始查詢 2.exit 成功查詢到結果,並繫結到變數 3.redo 從上次成功查詢處之後繼續查絢,先釋放變數 4.fail 查詢失敗退出 現...