はSWI-Prologのキューとスレッドを使用するソリューションです。それは古い既存のAPIを使用し、Tarau's Enginesに沿って何かをします。私は、スレッドの作成がテンプレートと目標をコピーすると仮定します。そして、私は、キューの送信が再び各ソリューションのコピーを行うと仮定します。
古典的なfindallと比較すると、1つのテンプレートと目標のコピーに余剰がありますが、それ以外の場合は、それぞれの解決策を古典的なfindallとしてコピーします。要点のソースhere。しかし、コレクションを行うthreadall2を修正することによって、すべての種類の集約を実装することもできます。
% threadall(+Term, +Goal, -List)
threadall(T, G, L) :-
message_queue_create(J, [max_size(1)]),
thread_create(threadall3(T, G, J), _, [detached(true)]),
thread_get_message(J, A),
threadall2(J, A, L),
message_queue_destroy(J).
% threadall3(+Term, +Goal, +Queue)
threadall3(T, G, J) :-
G, thread_send_message(J, the(T)), fail.
threadall3(_, _, J) :-
thread_send_message(J, no).
% threadall2(+Queue, +Term, -List)
threadall2(J, the(T), [T|L]) :- !,
thread_get_message(J, A),
threadall2(J, A, L).
threadall2(_, no, []).
ここでは実行例を示します。私は正しく帳簿をやりました。スレッドはdetach(true)で作成されたので、スレッドが終了するときにハンドルは必要ありません。メッセージキューは明示的に破棄されます。
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.23)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
?- threadall(X, between(0, 5, X), L).
L = [0, 1, 2, 3, 4, 5].
?- threadall(X-Y, (between(0, 2, X),
threadall(Z, between(0, 2, Z), Y)), L).
L = [0-[0, 1, 2], 1-[0, 1, 2], 2-[0, 1, 2]].
私たちのコードのみが通常の幸せなパスを実装しています:私たちはthe/1
とno/0
メッセージを実装ここではいくつかの例では、我々が期待どおりに動作することがわかり、SWI-Prologで実行されています。さらに、setup_call_cleanup/3
を使用しないので、割り込み付きのソリューションを使用することも安全ではありません。また、最後の議論は不動ではありません。これは、読者がこれらの追加の要件と対応する代替パスを実装するための練習として残されています。
[SWI-Prolog:findallなしですべてのソリューションを収集する]の複製が可能です(http://stackoverflow.com/questions/22492633/swi-prolog-gathering-all-solutions-without-findall) –
マルチ - スレッドと再帰? –