Prolog如何在不使用内置函数的情况下计算事实的数量
考虑到许多事实,有没有一种方法可以不使用内置函数来计算它们呢?我已经用下面的代码尝试过这样做,但没有成功。我希望有人能帮助我。 例如,以下事实:Prolog如何在不使用内置函数的情况下计算事实的数量,prolog,Prolog,考虑到许多事实,有没有一种方法可以不使用内置函数来计算它们呢?我已经用下面的代码尝试过这样做,但没有成功。我希望有人能帮助我。 例如,以下事实: stops(jubilee,bondstreet,1). stops(jubilee,waterloo,2). stops(jubilee,bakerstreet,3). 到目前为止,守则的内容是: findStops(X) :- stops(X,_, N), N1 is N+1, stopsX,_,N1). 我想这样做,N1是jubilee线如何
stops(jubilee,bondstreet,1).
stops(jubilee,waterloo,2).
stops(jubilee,bakerstreet,3).
到目前为止,守则的内容是:
findStops(X) :- stops(X,_, N), N1 is N+1, stopsX,_,N1).
我想这样做,N1是jubilee线如何停止的计数器。一个简单的解决方案是计算第一个参数中包含原子
jubilee
的停止/3
事实的数量。假设stops/3
谓词的所有子句都有一个绑定的第一个参数,您可以编写:
?- findall(1, stops(jubilee,_,_), List), length(List, Count).
在这个查询中,findall/3
是标准的Prolog谓词,length/2
是事实上的标准谓词,通常作为内置谓词或库谓词提供
您能否将此查询转换为一个谓词,该谓词将站作为参数(而不是硬编码的站作为
jubilee
),并返回该站的计数?这个问题并不完全清楚,因为还没有定义“内置”谓词所允许的内容。如果不使用某种预定义的谓词,就无法解决这样的问题
这里还有一些其他的想法
使用assertz
和retract
:
count_stops(Count) :-
assertz(num_stops(0)),
count_stops_aux(Count).
count_stops_aux(_) :-
stops(_, _, _),
retract(num_stops(C)),
C1 is C + 1,
assertz(num_stops(C1)),
fail.
count_stops_aux(Count) :-
retract(num_stops(Count)).
您也可以使用SWI Prolog的b_setval/2
和b_getval/2
执行类似的操作
下面是一个递归解决方案,它使用一个列表来检查我们是否已经统计了一个特定的事实:
count_stops(Count) :-
count_stops_aux([], 0, Count).
count_stops_aux(L, Count, Total) :-
stops(A, B, C),
\+ member(stops(A,B,C), L),
C is Count + 1,
count_stops_aux([stops(A,B,C)|L], C, Total), !.
count_stops_aux(_, Total, Total).
或者类似地,但也使用length/2
:
count_stops(Count) :-
count_stops_aux([], Facts),
length(Facts, Count).
count_stops_aux(L, Facts) :-
stops(A, B, C),
\+ member(stops(A,B,C), L),
count_stops_aux([stops(A,B,C)|L], Facts), !.
count_stops_aux(Facts, Facts).
第一种解决方案将计算冗余事实(如果相同事实存在不止一次),并且
assertz
和retract
是缓慢的操作。第二个和第三个解决方案不会计算多余的事实,但实际上只是保罗解决方案的笨拙、冗长版本,以避免使用findall
。这就是为什么Prolog有诸如findall/3
和bagof/3
之类的谓词提示:列出您检索的结果,以防止两次收到相同的事实。@WillemVanOnsem有方法递归添加结果吗?您编写N1 is N+1
,因此您使用的是内置的(is)/2
。