6

次の障害駆動ループを使用して、セミコロンを使用せずにすべてをリストしました。

happiness(fred,5).
happiness(john,3).
happiness(grace,2).

someGoal(X) :-
        happiness(X,Y), write(Y), tab(4), fail.

クエリモードでは、期待どおりにこれを取得します

?- someGoal(_).
5    3    2 

これらの数値を画面に書き込むのではなく、リストに挿入するにはどうすればよいですか? someGoalバックトラッキングは暗黙のように見えるため、これを処理できませんでした。

4

2 に答える 2

6

おっしゃるとおり、後戻りするのは Prolog が代替を処理する方法です。

「内部的に」バックトラッキングを使用してすべての選択肢を収集するfindall /3 を使用します。

someGoal(X, Values) :-
    findall(Value, happiness(X, Value), Values).

次に?- someGoal(_, Values).、値 = [5, 3, 2] をインスタンス化します。

于 2012-10-24T20:54:13.330 に答える
5

失敗によるループでは、遅かれ早かれ何らかの問題が発生する特定の部分が開いたまま未指定のままになることがよくあります。特に、変数の正確な定量化は簡単に未解決のままです。多くの場合、このようなループはまとめて回避できます。あなたの例では、なぜあなたが議論をしているのか、私にははっきりしませんsomeGoal/1。少なくともあなたはそれを使用しません。したがって、いくつかの疑問が生じます。

  1. 一致する値がない場合、何を期待しますか? 元のプログラムは何も出力せず、失敗します。

  2. 冗長なエントリがある場合、何を期待しますか? 何回も印刷したいですか?

  3. 値の正確な順序を主張しますか、それとも別の順序を想像できますか?

  4. 値を見ることに興味があるのはなぜですか?ほとんどの場合、それらを具体的な名前に関連付けて表示するか、合計や平均などの集計が必要です。

これらに対する答えがわからないので、いくつかの解決策を提示できます。私はあなたの例を1つの追加の(冗長な)事実で取り上げます:

幸福(フレッド、5)。
幸福(ジョン、3)。
幸福(ジョン、3)。
幸福(恵み、2)。

?-セット (PH、幸福 (P、H)、PHs)。
PH = [フレッド-5、グレース-2、ジョン-3]。

?- setof(H,P^happiness(P,H), PHs)。
PH = [2, 3, 5]。

?- bagof(H,P^happiness(P,H), PHs)。
PH = [5, 3, 3, 2]。
于 2012-10-25T14:50:24.473 に答える