2016-11-27 24 views
0

我之前已經動態定義了一些事實,如下所示。如何在Prolog中動態聲明新數據

% declare dynamic facts 
:- dynamic title/2. 
:- dynamic author/2. 
:- dynamic publisher/2. 
:- dynamic price/2. 
:- dynamic call_number/2. 
:- dynamic edition/2. 
:- dynamic data_disk/2. 

,並斷言這些事實每次程序運行

:- assert(title(book1, 'Elementary Statistics')). 
:- assert(title(book2, 'Statistics for Engineers')). 
:- assert(title(book3, 'Statistics for Engineers and Scientists')). 
:- assert(title(book4, 'IT in Language Learning')). 

:- assert(author(book1, 'Patricia Wilson')). 
:- assert(author(book2, 'James Mori')). 
:- assert(author(book3, 'James Mori')). 
:- assert(author(book4, 'O Ivan')). 

:- assert(publisher(book1, 'Addison Wesley')). 
:- assert(publisher(book2, 'World Scientific')). 
:- assert(publisher(book3, 'World Scientific')). 
:- assert(publisher(book4, 'Universal Press')). 

:- assert(price(book1, 75)). 
:- assert(price(book2, 125)). 
:- assert(price(book3, 125)). 
:- assert(price(book4, 5)). 

:- assert(call_number(book1, 'QA373')). 
:- assert(call_number(book2, 'QA673')). 
:- assert(call_number(book3, 'QA674')). 
:- assert(call_number(book4, 'QA007')). 

:- assert(edition(book1, 1)). 
:- assert(edition(book2, 3)). 
:- assert(edition(book3, 2)). 
:- assert(edition(book4, 1)). 

:- assert(data_disk(book1, 'No')). 
:- assert(data_disk(book2, 'Yes')). 
:- assert(data_disk(book3, 'Yes')). 
:- assert(data_disk(book4, 'No')). 

正如你所看到的事實是按照一定的順序

book1 
book2 
book3 
book4 

我怎樣才能獲得最後的X,其中X是bookX,並增加1,以便插入的新書總是(X + 1)?

回答

0

我在最近的星巴克清理了我的腦海,想出了最簡單的答案。

add_book :- 
    aggregate_all(count, title(_,_), Count), 
    NewCount is Count + 1, 
    atom_concat('book', NewCount, NewBook). 

的aggregate_all功能將計算題斷言,在我的知識基礎是可用的和一些計算將執行的數量。

雖然我願意提供更好的建議,但如果您有更好的方法,請回復。

1

你找到一個解決方案(即,算上現有的事實,並添加  1),它的工作原理,但有一個主要的缺點:它使得添加一個新的事實成正比的數量已經認定事實的運行時間。這意味着聲稱一系列事實需要時間與  N成比例。

理想地,我們希望有一種情況,斷言一個事實是在  풪(1),並且斷言Ñ  事實因此處於  풪(Ñ)。

實現此目的的一種方法是重新考慮您的 書籍的初始表示形式。

例如,假設您出示您的書如 這個(略去了一些數據):

 
book([title('Elementary Statistics'), 
     author('Patricia Wilson'), 
     price(75)]). 
book([title('Statistics for Engineers'), 
     author('James Mori'), 
     publisher('World Scientific')]). 

注意,這表示可以讓我們省去了僅在一些 書籍目前場。其他表示也是有意義的。

我們可以很容易地獲取findall/3所有這些事實:

 
?- findall(Book, book(Book), Books). 

這是線性在這些事實的數量。

此外,我們定義assert_book_/3如下:

 
assert_book_(Book, N0, N) :- 
     memberchk(title(Title), Book), 
     memberchk(author(Author), Book), 
     assertz(title(N0,Title)), 
     assertz(author(N0,Author)), 
     N #= N0 + 1. 

例如起見,我專注於冠軍作者。我保留這個作爲 練習。

這個謂詞的參數是:

  • 被斷言,表示爲屬性
  • 的列表當前索引N0
  • 下一個索引N1,這簡直就是一個大於比  N0

現在主要的問題:這些參數是在一個合適的順序來謂語超過 書一個列表,使用   foldl/4

 
?- findall(Book, book(Book), Books), 
    foldl(assert_book_, Books, 1, _). 

運行此查詢後,我們有:

 
?- title(N, T). 
N = 1, 
T = 'Elementary Statistics' ; 
N = 2, 
T = 'Statistics for Engineers'. 

而類似的f在數據庫author/2行爲:

 
?- author(N, T). 
N = 1, 
T = 'Patricia Wilson' ; 
N = 2, 
T = 'James Mori'. 

因此,我們使用foldl/4隱含跟蹤運行指標,我們 需要,取得具有所需運行時間 的解決方案。


注意,也有你的任務是明智開裂解決方案:

 
assert_title(Book, Title) :- 
     atom_concat(book, N0, Book), 
     atom_number(N0, N), 
     assertz(title(N, Title)). 

這顯然不是你要找的,但將努力爲您展示的例子,如果你使用的例如:

 
:- assert_title(book1, 'Elementary Statistics'). 
:- assert_title(book2, 'Statistics for Engineers'). 

現在,我們再次有:

 
?- title(N, Title). 
N = 1, 
Title = 'Elementary Statistics' ; 
N = 2, 
Title = 'Statistics for Engineers'. 

這裏的笑話是,你實際上已經進入了運行指數已經,並且我們可以使用atom_concat/3獲得它:

 
?- atom_concat(book, N0, book1), 
    atom_number(N0, N). 
N0 = '1', 
N = 1. 

;-)