Prolog, find minimum in a list

前端 未结 13 1957
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-07 01:25

in short: How to find min value in a list? (thanks for the advise kaarel)

long story:

I have created a weighted graph in amzi prolog and given 2 nodes, I am

13条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-07 01:49

    SWI-Prolog offers library(aggregate). Generalized and performance wise.

    :- [library(aggregate)].
    min(L, M) :- aggregate(min(E), member(E, L), M).
    

    edit

    A recent addition was library(solution_sequences). Now we can write

    min(L,M) :- order_by([asc(M)], member(M,L)), !.
    max(L,M) :- order_by([desc(M)], member(M,L)), !.
    

    Now, ready for a surprise :) ?

    ?- test_performance([clpfd_max,slow_max,member_max,rel_max,agg_max]).
    clpfd_max:99999996
    % 1,500,000 inferences, 0.607 CPU in 0.607 seconds (100% CPU, 2470519 Lips)
    slow_max:99999996
    % 9,500,376 inferences, 2.564 CPU in 2.564 seconds (100% CPU, 3705655 Lips)
    member_max:99999996
    % 1,500,009 inferences, 1.004 CPU in 1.004 seconds (100% CPU, 1494329 Lips)
    rel_max:99999996
    % 1,000,054 inferences, 2.649 CPU in 2.648 seconds (100% CPU, 377588 Lips)
    agg_max:99999996
    % 2,500,028 inferences, 1.461 CPU in 1.462 seconds (100% CPU, 1710732 Lips)
    true 
    
    with these definitions:
    
    ```erlang
    :- use_module(library(clpfd)).
    
    clpfd_max([L|Ls], Max) :- foldl([X,Y,M]>>(M #= max(X, Y)), Ls, L, Max).
    
    slow_max(L, Max) :-
       select(Max, L, Rest), \+ (member(E, Rest), E @> Max).
    
    member_max([H|T],M) :-
        member_max(T,N), ( \+ H@ M=H ; M=N ).
    member_max([M],M).
    
    rel_max(L,M) :-
        order_by([desc(M)], member(M,L)), !.
    
    agg_max(L,M) :-
        aggregate(max(E), member(E,L), M).
    
    test_performance(Ps) :-
        test_performance(Ps,500 000,_).
    test_performance(Ps,N_Ints,Result) :-
        list_of_random(N_Ints,1,100 000 000,Seq),
        maplist({Seq}/[P,N]>>time((call(P,Seq,N),write(P:N))),Ps,Ns),
        assertion(sort(Ns,[Result])).
    
    list_of_random(N_Ints,L,U,RandomInts) :-
        length(RandomInts,N_Ints),
        maplist({L,U}/[Int]>>random_between(L,U,Int),RandomInts).
    
    

    clpfd_max wins hands down, and to my surprise, slow_max/2 turns out to be not too bad...

提交回复
热议问题