自動回溯是Prolog中頗有表明性的一個特徵。可是回溯可能會致使低效。有時Prolog會浪費時間在一些沒有結果的可能性搜索上。若是在回溯行爲方面有一些控制機制的話,會是一件比較有意義的事情,可是直到如今爲止咱們看到只有兩種至關初級的方式能夠用於這個目的:交換規則順序,和交換目標順序。其實有另一種方式:存在一個內置的謂詞:!(英文感嘆號),稱爲中斷,能夠提供一種更爲直接地控制Prolog搜尋解決方案的方式。學習
到底中斷是什麼,它是如何起做用的?它實際上是一個特殊的原子,咱們能夠在子句中使用它。看例子:code
p(X) :- b(X), c(X), !, d(X), e(X).
上面的例子就是一個完美的Prolog規則。中斷是這樣起做用的:首先,它是一個永遠成功的目標;其次,更爲重要的是,它有一個反作用。假設有其餘一些目標會使用這個子句(咱們稱之爲父目標,好比例子中的p(X)),在進行搜索時,中斷會使得規則左邊的目標沒法回溯,而只能回溯規則右邊的目標。讓咱們經過例子來學習。blog
首先思考沒有中斷的代碼:原理
p(X) :- a(X). p(X) :- b(X), c(X), d(X), e(X). p(X) :- f(X). a(1). b(1). b(2). c(1). c(2). d(2). e(2). f(3).
若是查詢p(X),咱們會獲得以下的答案:搜索
?- p(X). X = 1; X = 2; X = 3; false
下面是對應的搜索樹,注意其中必須回溯的地方,當進入第二個子句,決定知足第一個目標b(1),回溯後被替換爲b(2)。程序
如今假設咱們在第二個子句中加入中斷:im
p(X) :- b(X), c(X), !, d(X), e(X).
若是如今查詢p(X),會獲得以下的答案:d3
X = 1; false
這裏發生了什麼?讓咱們思考一下。查詢
若是觀察以下的搜索樹,你會發現一些樹枝被刪除:當目標d(1)不能在進行,可是須要回溯尋找新的選擇時,搜索已經被中止:db
有一個須要強調的要點:中斷會提交全部的選擇,這些選擇是爲了知足父目標而將包含中斷的子句合一時作出的,而且是從中斷左端進行合一的那些選擇。好比,在以下規則的模式中:
q :- p1, ..., pn, !, r1, ..., rm
當咱們到達中斷的時候,Prolog會提交爲了知足q的而且包含中斷的子句的全部選擇,而且這些選擇是運算p1, ..., pm得出的。然而,在r1, ..., rm內,咱們可以進行回溯,而且知足目標q以前的其餘選擇咱們也能夠進行回溯。經過看下面的例子來明確這些原理。
首先思考沒有中斷的程序:
s(X, Y) :- q(X, Y). s(0, 0). q(X, Y) :- i(X), j(Y). i(1). i(2). j(1). j(2). j(3).
以下是查詢和結果:
?- s(X, Y). X = 1 Y = 1; X = 1 Y = 2; X = 1 Y = 3; X = 2 Y = 1; X = 2 Y = 2; X = 2 Y = 3; X = 0 Y = 0; false
下面是對應的搜索樹:
假設咱們在q/2子句中加入中斷:
q(X, Y) :- i(X), !, j(Y).
如今程序的行爲以下:
?- s(X, Y). X = 1 Y = 1; X = 1 Y = 2; X = 1 Y = 3; X = 0 Y = 0; false
讓咱們看看爲何:
以下式對應的搜索樹: