上記の例のカットには、次の効果があります。
理想的には、見つかった最初の回答に対して発生する可能性のある検索をコミットします。solve_task_a/6
これによりリソースが解放され、さらなる回答を見つけることができるため、スペースの消費が改善されます。
範囲の問題
ただし、同時に、へのさらなる回答が隠さagent_current_position/2
れている可能性もあります。もちろん、この目標に対してこれ以上の答えを出すことはあまり意味がありませんが、たまたましばらくスリープ状態になり、最悪の場合、アクティブになるだけでまだ発見されていないエラーである可能性があります。
このため、切り取りではなく書き込みが望ましいでしょう。
...,
once( solve_task_a( ... ) ),
...
これにより、範囲が正確に表現したいものに限定されます。
堅牢性の問題
しかし、これが唯一の考えられる問題の原因ではありません。この変数が表示されますCost
。呼び出し時にインスタンス化されますsolve_task(Task, Cost)
か? ここで多くの推測を行うことができました。しかし、少なくともこの変数は、Prolog がコミットする答えに影響を与える可能性があります。したがってsolve_task(Task, 99)
、 とsolve_task(Task, Cost), Cost = 99
は異なる答えを生み出す可能性があります。実際、後者は失敗することさえあります。このような問題を抱えている述語は、不動性に欠けると言われています。
このような状況で安定性が簡単に失われることを説明するために、(既に改善された) プログラムの次の (実行可能な) スケッチを検討してください。
solve_task(タスク、コスト):-
% agent_current_position(oscar,P),
once(solve_task_a(Task,[b(0,0,P)],[],R,Cost,_NewPos)),
真実。
solve_task_a(_, _, _, _, 20, _)。
solve_task_a(_, _, _, _, 30, _)。
今
?- solve_task(a, Cost).
Cost = 20.
?- solve_task(a, 30).
true.
?- solve_task(a, Cost), Cost = 30.
false.
variableをきれいにテストすることで、この問題を解決する簡単な方法があります。ただし、(コメントで示したように) コストを決定したい場合は、次のようにする必要があります。Cost
Cost >= 0
Cost
solve_task(タスク、コスト):-
% agent_current_position(oscar,P),
once(solve_task_a(Task,[b(0,0,P)],[],R,CostX,_NewPos)),
CostX = コスト
真実。
Cost
このようにして、 が の結果に影響を与えないことを確信できます(うーん - と の間にsolve_task_a/6
エイリアシングがない場合- しかし、今のところそれを仮定しましょう)。出力の統合は commit の後ろに置かれるとも言います。Cost
Task
solve_task(Task, Cost)
多くの人は、特定のコストで使用することは決してないので、そのような特別な注意は必要ないと言うでしょう. それは事実かもしれませんが、あなたはそれを覚えていますか?そして、ソース コードが (動的チェックなしで) それを覚えていると確信していますか? そのような暗黙の仮定は、あなたの精神的能力が過度に負担されている場合、ある程度簡単に蓄積されます.
常に簡単な方法があるとは限りません。しかし、多くの場合、論理的純粋性を維持することは可能ですlogical-purity。その場合、そのような仮定を覚えておく必要はありません。
いずれにせよ、当面は Prolog のこれらの部分には立ち入らないことをお勧めします。むしろ、後継演算、clpfd 、および論理純粋性を維持する他のクリーンで単調なプログラムに固執してください。学ぶことがたくさんあります!