我使用SWI-Prolog在Prolog文件(.pl)中拥有基础知识。
reserve(bus(2389),place(4),datetravel([12,2,1999]),
info([88032454321,robert,downe])).
reserve(bus(2389),place(33),datetravel([12,2,1999]),
info([88032454321,alberto,perez])).
reserve(bus(2389),place(16),datetravel([12,2,1999]),
info([88032454321,angel,clark])).
reserve(bus(4566),place(17),datetravel([22,3,2005]),
info([88032454321,don,self])).
reserve(bus(2389),place(22),datetravel([12,2,1999]),
info([88032454321,singmud,dante])).
我实施了一条规则,你给了我几个参数来计算符合这些限制的事件数量,但是对我来说不行,我可以吗?
规则
test(N,D,M,Y,P):-
reserve(bus(N),place(4),datetravel([D,M,Y]),
info([88032454321,robert,downe])),
test(N,D,M,Y,P+1).
问题
?- test(2389,12,2,1999,P).
鉴于我的问题,规则应该返回数字4。
答案 0 :(得分:1)
看看图书馆(aggregate)。
它非常强大且值得研究。
:- use_module(library(aggregate)). % optional, this library is autoloaded
test(N,D,M,Y,P):-
aggregate_all(count, reserve(bus(N),place(4),datetravel([D,M,Y]),info([88032454321,robert,downe])), P).
test / 5只是查询的占位符...实际上,您的数据模型不容易界面。由于Prolog数据模型是 relational ,您应该尝试应用类似于设计SQL数据库的技术。
答案 1 :(得分:1)
这是一个如何计算事实的例子,假设有一个唯一的密钥。这个例子只有一个简单的事实,foo/1
有一个参数,这是唯一的密钥。我这里有一个简单的框架。我将把它留作练习,让它适合你的情况,这非常简单。
另外,考虑到你想从更基本的原则编写代码,我也会留下member/2
作为练习。
foo(a).
foo(b).
foo(c).
count(Thing, N) :-
count(Thing, [], 0, N).
count(Thing, Seen, Acc, N) :-
call(Thing, X),
( member(X, Seen)
-> fail
; !,
Acc1 is Acc + 1,
count(Thing, [X|Seen], Acc1, N)
).
count(_, _, N, N).
以下是它的调用方式。如果您愿意,可以在count/2,4
中对您的事实仿函数进行硬编码。在这里,您只需将call(Thing, X)
替换为foo(X)
,并完全删除Thing
参数。但在这种情况下,我决定将仿函数作为一个论点:
| ?- count(foo, N).
N = 3
yes
| ?-
实际上,如果您愿意,count
可以提供整个评估事实列表。您只需将其作为额外的累加器参数包含在内。它已经收集在Seen
。