1

カットが(私が信じている)本来のことをしていないため、Prologに問題があります:

% line-column handlers
checkVallEle(_, _, 6, _):- write('FAIL'), !, fail.
checkVallEle(TABULEIRO, VALUE, LINE, COLUMN):- COLUMN>5, NL is LINE+1, checkVallEle(TABULEIRO, VALUE, NL, 0).

% if this fails, it goes to the next
checkVallEle(TABULEIRO, VALUE, LINE, COLUMN):-
       (checkHorizontal(TABULEIRO, VALUE, LINE, COLUMN, 0), write('HORIZONTAL ');
        checkVertical(TABULEIRO, VALUE, LINE, COLUMN, 0), write('VERTICAL');
        checkDiagonalRight(TABULEIRO, VALUE, LINE, COLUMN, 0), write('DIAGONALRIGHT');
        checkDiagonalLeft(TABULEIRO, VALUE, LINE, COLUMN, 0), write('DIAGONALLEFT')),
        write('WIN').

% goes to the next if above fails
checkVallEle(TABULEIRO, VALUE, LINE, COLUMN):-
        NC is COLUMN+1,
        checkVallEle(TABULEIRO, VALUE, LINE, NC).

私がやりたいことは、コードが最初のステートメントに到達した場合、つまり、行が 6 の場合、それ以上の可能性をチェックせずに (範囲外になったため) 失敗することです。しかし、最初のステートメントに到達すると、以下のステートメントに進み続け、カット記号を無視します。その理由はわかりません。最初の行に達したときにステートメントが失敗するようにしたいだけです。

私も体験させて頂きました…

run(6):-write('done'), !, fail.
run(X):-X1 is X+1, run(X1).

そして、これは私がトレースから得たものです:

| ?- run(0).
        1      1 Call: run(0) ? 
        2      2 Call: _1079 is 0+1 ? 
        2      2 Exit: 1 is 0+1 ? 
        3      2 Call: run(1) ? 
        4      3 Call: _3009 is 1+1 ? 
        4      3 Exit: 2 is 1+1 ? 
        5      3 Call: run(2) ? 
        6      4 Call: _4939 is 2+1 ? 
        6      4 Exit: 3 is 2+1 ? 
        7      4 Call: run(3) ? 
        8      5 Call: _6869 is 3+1 ? 
        8      5 Exit: 4 is 3+1 ? 
        9      5 Call: run(4) ? 
       10      6 Call: _8799 is 4+1 ? 
       10      6 Exit: 5 is 4+1 ? 
       11      6 Call: run(5) ? 
       12      7 Call: _10729 is 5+1 ? 
       12      7 Exit: 6 is 5+1 ? 
       13      7 Call: run(6) ? 
       14      8 Call: write(done) ? 
done
       14      8 Exit: write(done) ? 
       13      7 Fail: run(6) ? 
       11      6 Fail: run(5) ? 
        9      5 Fail: run(4) ? 
        7      4 Fail: run(3) ? 
        5      3 Fail: run(2) ? 
        3      2 Fail: run(1) ? 
        1      1 Fail: run(0) ? 
no

書き込み後の失敗は何ですか? それはまだ以前の回答に戻っていますか?この動作が、最初のコードでカットが失敗する理由ですか? 教えてください。

4

1 に答える 1

0

を評価している最後のステップを考えてみましょうrun(5):-run(6).run(6)失敗はrun(5)失敗を意味し、もちろんrun(4)失敗を意味します。

あなたの元の問題に関しては、それはカットを無視していません。カットはバックトラックを完全に停止するわけではなく、ソリューションのバックトラックを停止するだけですcheckVallEle(_,_,6,_)- これが失敗すると、 でさらにソリューションのバックトラックを開始しLINE=5ます。

本当の問題は、残りのルールが十分に制約されていないことです。で 2 番目のケースCOLUMN=6が試行されると、3 番目のケースが試行されますCOLUMN=6- それを止めるものは何もありません。より多くのカットを投げることでこれを回避できますが、それはあまり良いアプローチではありません.

より良いアプローチは、すべての制約を明示することです。他のすべてのルールの最初にcheckVallEle(_,_,6,_)言う限り、カットインの必要はありません. LINE<6そしてCOLUMN<6、すべてのルール (もちろん 2 番目を除く) で言うと、予期しないバックトラッキングの問題が解決するはずです。

于 2013-11-07T05:20:29.547 に答える