2016-11-27 45 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. 

;-)