2017-02-09 41 views
3

我有一組規則和相同的斷言事實的集合撤消只有一個規則,而不是相同的謂詞的事實在序言

p(1). 
p(2). 
g(1,1). 
h(3,2). 
p(X):- g(X,Y). 
p(X):- h(X,Y). 

我願做一個retractall般的斷言和刪除只有規則而不是事實。所以像這樣的東西:

retractRules(p(X)). 

在Prolog中如何做到這一點?

+2

你會得到一個「不連續的謂詞」因爲對'p條款的定義與此代碼警告/ 1'被的定義分離不同的謂詞。這就意味着「p(X)」條款根本不能被識別。 – lurker

回答

1

您不能使用標準retract/1謂詞來收回事實。諸如retract((p(_) :- Body))之類的呼叫收回事實並將Body例示爲true

假設你正在使用SWI-Prolog的,一個非便攜解決方案是使用clause/3去規則的引用,然後刪除該條款用erase/1這些引用。假設p/1是一個動態的謂詞:

?- forall((clause(p(_), Body, Ref), Ref \== true), erase(Ref)). 

你當然可以收回所有條款,然後斷言回的只有事實,但聽起來矯枉過正:

?- forall((retract(p(X) :- Body), Body == true), assertz(p(X)). 
+2

在GNU Prolog和SWI Prolog中使用的解決方案是使用'clause/2':'retractRules(R): - clause(R,B),B \ == true,retract(:-(R,B)), fail.' – lurker

2

我刪除了我以前的答案因我的邏輯缺陷只依靠retract/1

大廈使用clause/3的保羅·莫拉的想法,這裏是一個使用ISO謂詞clause/2的解決方案,使其成爲一個小更便攜:

retractRules(R) :- 
    clause(R, B), 
    B \== true, 
    retract(:-(R, B)), 
    fail. 
retractRules(_). 

這裏的假設是,你的規則是擺在首位動態創建,並使用適當的指令(:- dynamic)聲明爲動態謂詞。例如,在什麼地方,你就會有這樣的事情:

assertz(:-(p(X), g(X,Y))).