假设f(X)
是动态事实,可以assert
和retract
编辑,并假设X
始终为数字。现在,假设执行最多的查询是关于找到最小的f(X)
。在SWI-Prolog中我可以写:
min_f(R) :- aggregate(min(X), f(X), R).
但是,显然,这个总是导致Prolog对所有事实进行线性搜索。现在,假设会有大量(例如1,000,000)这样的事实。由于我知道,我经常会执行min_f/1
:
f/1
上强加一个订单,这样引擎可以找到 O(1)中的最小值吗? assert
包含所有事实的最小堆,然后偷看头部;可以将事实存储在min-heap 中隐式吗?我对Prolog方言没有任何限制,所以任何替代的Prolog实现都可以。
答案 0 :(得分:1)
可以快速传递最小值或最大值的数据结构的替代方法是使用模式定向制表。在模式定向制表中,可以指定所需的聚合函数:
f(5).
f(4).
f(6).
:- table min_f(min).
min_f(X) :- f(X).
最小值仅计算一次,这是一个示例查询。在SWI-Prolog中有效,自1.4.0版以来,在Jekejeke Prolog中也适用:
?- min_f(X).
X = 4.
理论上,它由制表实现决定,它如何计算最小值。当前,还在进行增量制表的开发,这将使f / 1动态化,然后跟踪更改。
答案 1 :(得分:0)
:- dynamic(f/1).
min_f(X) :-
f(X),
!.
assert_f(X) :-
min_f(Min),
Min<X,
assertz(f(X)),
!.
assert_f(X) :-
asserta(f(X)).
使用assert_f / 1而不是assert / 1。 f / 1的第一个解决方案总是最小值,但不要假设f / 1的解决方案从低到高列出。