ちょっと待って!続行する前に、まず述語にかかる時間を測定してください。
?- length(J,I), I>10, append(J,[2],L),maplist(=(1),J), time(largest(L,N)).
% 12,282 推論、0.006 秒で 0.006 CPU (99% CPU、1977389 リップ)
J = [1, 1, 1, 1, 1, 1, 1, 1, 1|...],
私=11、
L = [1, 1, 1, 1, 1, 1, 1, 1, 1|...],
N = 2;
% 4 つの推論、0.000 秒で 0.000 CPU (84% CPU、98697 リップ)
% 24,570 推論、0.011 秒で 0.011 CPU (99% CPU、2191568 リップ)
J = [1, 1, 1, 1, 1, 1, 1, 1, 1|...],
私=12、
L = [1, 1, 1, 1, 1, 1, 1, 1, 1|...],
N = 2;
% 4 つの推論、0.000 秒で 0.000 CPU (84% CPU、98556 リップ)
% 49,146 推論、0.021 秒で 0.021 CPU (100% CPU、2365986 リップ)
J = [1, 1, 1, 1, 1, 1, 1, 1, 1|...],
私=13、
L = [1, 1, 1, 1, 1, 1, 1, 1, 1|...],
N = 2 ...
長さが 1 増加するたびに、推論の数は明らかに 2 倍になります。これが、プロローグが非常に非効率的であるという悪い評判を得る方法であり、プロセッサ速度のすべての進歩を台無しにします.
では、あなたのプログラムでは何が起こっているのでしょうか? 詳細に入る必要はありませんが、プログラムの小さな断片 ( failure-slice ) について考えてみましょう。この結果のプログラムは目的に対して完全に機能不全ですが、プログラム内の推論数の下限を示します。
maximum([X],X) :- false .
maximum([X|Xs],X) :- maximum(Xs,Y), false , X>=Y .
maximum([X|Xs],N) :- maximum(Xs,N), false , N>X .
リスト内の各要素について、2 つの等しく適用可能な選択肢があります。N
要素のリストがあるので、2^N
選択肢があります。
可能な書き換えは次のとおりです。
largest([X],X).
largest([X|Xs],R) :-
largest(Xs,Y),
( X>=Y, R = X
; Y > X, R = N
).
if-then-else を使用すると、さらにうまくいくことができます...
largest([X],X).
largest([X|Xs],R) :-
largest(Xs,Y),
( X>=Y -> R = X
; Y > X, R = N
).
またmax/2
largest([X],X).
largest([X|Xs],R) :-
largest(Xs,Y),
R is max(X,Y).
このプログラムは、リストの長さに比例したスペースを必要とします。そして、末尾再帰バージョンを使用することで、これを定数に減らすことができます。しかし、少なくともこのバージョンは線形時間で実行されます。
そして、実行したい実際の最適化については、以下をお読みください
SWI-Prolog: Sum-List