aggregate/3 in swi-prolog

前端 未结 4 661
滥情空心
滥情空心 2021-01-11 16:05

I need to count all X, that some_predicate(X) and there really a lot of such X. What is the best way to do that?

First clue is

4条回答
  •  梦毁少年i
    2021-01-11 16:56

    In SWI-Prolog there is a much more efficient version, that also avoid locking the global store. So simply using nb_setval and nb_getval you gain at least 3 times the performance (more on multithreading). Just little time ago another question was on counting solutions. Being the base of aggregation it's an obvious stop point while learning Prolog. To evaluate the efficiency gain we get using these monothread semantically equivalent calls:

    count_solutions(Goal, N) :-
    assert(count_solutions_store(0)),
    repeat,
    (   call(Goal),
        retract(count_solutions_store(SoFar)),
        Updated is SoFar + 1,
        assert(count_solutions_store(Updated)),
        fail
    ;   retract(count_solutions_store(N))
    ), !.
    :- dynamic count_solutions_store/1.
    
    % no declaration required here
    count_solutions_nb(Goal, N) :-
        nb_setval(count_solutions_store, 0),
        repeat,
        (   call(Goal),
            nb_getval(count_solutions_store, SoFar),
            Updated is SoFar + 1,
            nb_setval(count_solutions_store, Updated),
            fail
        ;   nb_getval(count_solutions_store, N)
        ), !.
    
    parent(jane,dick).
    parent(michael,dick).
    parent(michael,asd).
    
    numberofchildren(Parent, N) :-
        count_solutions_nb(parent(Parent, _), N).
    
    many_solutions :-
        between(1, 500000, _).
    
    time_iso :-
        time(count_solutions(many_solutions, N)),
        write(N), nl.
    
    time_swi :-
        time(count_solutions_nb(many_solutions, N)),
        writeln(N).
    

    On my system, i get

    ?- [count_sol].
    % count_sol compiled 0,00 sec, 244 bytes
    true.
    
    ?- time_iso.
    tim% 1,000,006 inferences, 2,805 CPU in 2,805 seconds (100% CPU, 356510 Lips)
    500000
    true.
    
    ?- time_swi.
    % 2,000,010 inferences, 0,768 CPU in 0,768 seconds (100% CPU, 2603693 Lips)
    500000
    true.
    

提交回复
热议问题