简体   繁体   中英

Imposing an order to facts in Prolog

Suppose that f(X) is a dynamic fact that can be assert ed and retract ed, and suppose that X is always number. Now, suppose that the most executed query is about finding the f(X) such that is minimum. In SWI-Prolog I may write:

min_f(R) :- aggregate(min(X), f(X), R).

But, apparently, this always causes Prolog to perform a linear search on all facts. Now, suppose that there will be a large number (eg 1,000,000) of such facts. Since I know before hand that I will often execute min_f/1 :

  • can I impose an ordering on f/1 , so that the engine can find the minimum in O(1) ?
  • I may explicitly assert a min-heap containing all the facts, and then peek at the head; could the facts be stored in a min-heap implicitly ?

I have no restriction on the Prolog dialect, so any alternative Prolog implementation would be fine.

An alternative to data structures that can quickly deliver a minimum or maximum, would be to use mode directed tabling. In mode directed tabling one can specify desired aggregate functions:

f(5).
f(4).
f(6).

:- table min_f(min).
min_f(X) :- f(X).

The minimum will be only computed once, here is an example query. Works in SWI-Prolog and since release 1.4.0 also in Jekejeke Prolog:

?- min_f(X).
X = 4.

Theoretically it is left to the tabling implementation, how it calculates min. There are currently also developments going on, incremental tabling, which would allow making f/1 dynamic and then track changes.

:- 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)).

Use assert_f/1 instead of assert/1. First solution to f/1 will allways be the minimun value, but don't assume that solutions to f/1 are listed low to high.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM