1

2 つの変数Aとに対して次の条件がありBます。

[A,B] #:: 1..10,
(A #= 3) or (B #= 3),
((A #> 3 or B #>3) ->
     % expression 1
;
     % expression 2
)
%cntd

A問題は 2 行目にあり、ソルバーはとの値を認識していませんB。2 行目の変数の値を指定せずに、条件のどの分岐を続行するかを決定する方法は?

合理的な行動は、ソルバーが変数の可能な値をトラバースするときに、変数の値に基づいてこの分岐を決定することです。しかし、変数の値を知る前に、これらの式のいずれかを通過することがわかりました。それを防ぐ解決策は何ですか?

4

2 に答える 2

-1

何が問題ですか? 重要な注意点は->、if-else に (矢印) を使用することです。式がある場合S -> T ; USが評価され、変数が含まれている場合、コードに副作用が生じる可能性があります。より明確にするために、いくつかの例を実行してみてください。

?-[A,B] #:: 1..10,
(A #= 3) or (B #= 3),
((A #> 3 or B #>3) ->
    write("expression 1")
;
    write("expression 2")
).

Aandの値はB決定されないため、条件は常に true であり、 の値がexpression 1出力されます。また、結果は次のとおりです。

A = A{1 .. 10}
B = B{1 .. 10}
There are 6 delayed goals.
Yes (0.00s cpu)

ご覧のとおり、and の境界はA将来Bの式に保留されているため変更されません。

次に、別の例を試してください。

?- [A,B] #:: 1..10,
(A #= 3) or (B #= 3),
((A #> 3 or B #>3) ->
    write("expression 1")
;
    write("expression 2")
),
A = 3. % this line is added

の値Aが決定さA #> 3れるので真ではありませんが、どうBですか?それは 3 に等しいか、3 より大きいですか? 先ほど言ったように、条件部分が実行されます! したがって、最後の制約Bは ですB #> 3。の実行に加えてwrite("expression 1")、結果は次のとおりです。

A = 3
B = B{4 .. 10}
Yes (0.00s cpu)

最後の例は次のとおりです。

?- [A,B] #:: 1..10,
(A #= 3) or (B #= 3),
((A #> 3 or B #>3) ->
    write("expression 1")
;
    write("expression 2")
),
A = 3,
B = 3. % this line is added

また、この例expression 1では が出力され、結果は次のようになります。

No (0.00s cpu)

これは、矢印の頭と常にexpression 1実行されるためです。

1 つの解決策;は、次のような演算子を使用することです。

[A,B] #:: 1..10, 
(
    (A = 3, B = 3, write('expression 21'))
    ; 
    (A = 3, B #> 3, write('expression 11'))
    ; 
    (A #> 3, B #> 3, write('expression 12'))
    ; 
    (A #> 3, B = 3, write('expression 13'))
), 
A = 3,
B = 5.

上記のコードの結果は次のとおりです。

A = 3
B = 5
Yes (0.00s cpu, solution 1, maybe more)

そしてそれは印刷します:

expression 21 expression 11

これは最初のブランチがダウンしたことを意味しますが、失敗して自動的にバックトレースされ、次のケースに進みます! 次のケースが適用されると、すべてが成功します。

于 2019-05-15T10:52:00.733 に答える