在Prolog中计算事实

时间:2015-12-04 18:07:03

标签: prolog

我使用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。

2 个答案:

答案 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