Prolog performance and recursion type

后端 未结 4 938
盖世英雄少女心
盖世英雄少女心 2021-01-04 14:34

I was playing with permutation in a couple of programs and stumbled upon this little experiment:

Permutation method 1:

permute([], []).
         


        
4条回答
  •  谎友^
    谎友^ (楼主)
    2021-01-04 14:48

    Really nice question.

    Waiting for someone to post a time/space analysis, the only caveat I can offer is that method 1 & 2 don't terminate when first argument is free, while method 3 does.

    Anyway, method 1 seems really much more efficient than the builtin. Good to know.

    edit: and given that the library implementation merely adjust instantiation of arguments and calls method 1, I'm going to discuss on SWI-Prolog mailing list your method 2 as alternative (or, you prefer to do it yourself, let me know).

    more edit: I forgot previously to point out that permutation/3 (let's say, method 2), gives lexicographically ordered solutions, while method 1 doesn't. I think that could be a strong preferential requirement, but should be expressed as an option, given the performance gain that method 1 allows.

    ?- time(call_nth(permute1([0,1,2,3,4,5,6,7,8,9],P),1000000)).
    % 3,112,758 inferences, 3,160 CPU in 3,162 seconds (100% CPU, 984974 Lips)
    P = [1, 4, 8, 3, 7, 6, 5, 9, 2|...] .
    
    ?- time(call_nth(permute2([0,1,2,3,4,5,6,7,8,9],P),1000000)).
    % 10,154,843 inferences, 9,779 CPU in 9,806 seconds (100% CPU, 1038398 Lips)
    P = [2, 7, 8, 3, 9, 1, 5, 4, 6|...] .
    

    YAP gives still more gain!

    ?- time(call_nth(permute1([0,1,2,3,4,5,6,7,8,9],P),1000000)).
    % 0.716 CPU in 0.719 seconds ( 99% CPU)
    P = [1,4,8,3,7,6,5,9,2,0]
    
    ?- time(call_nth(permute2([0,1,2,3,4,5,6,7,8,9],P),1000000)).
    % 8.357 CPU in 8.368 seconds ( 99% CPU)
    P = [2,7,8,3,9,1,5,4,6,0]
    

    edit: I've posted a comment on SWI-Prolog doc page about this theme.

提交回复
热议问题