【问题标题】:Prolog Cut Not WorkingProlog 剪辑不起作用
【发布时间】:2013-11-07 03:49:04
【问题描述】:

我对 Prolog 有疑问,因为 cut 没有做(我相信)它应该做的事情:

% 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

写入后的那些失败是什么?它仍然回溯到以前的答案吗?这种行为是我的第一个代码中 cut 失败的原因吗?请赐教。

【问题讨论】:

    标签: debugging prolog


    【解决方案1】:

    考虑最后一步,您正在评估run(5):-run(6).。 run(6) 失败,表示run(5) 失败,当然也表示run(4) 失败,以此类推。

    至于您最初的问题,它并没有忽略剪辑。剪切不会完全停止回溯,它只会停止回溯以获取 checkVallEle(_,_,6,_) 的解决方案 - 一旦失败,它将开始回溯以获取更多 LINE=5 的解决方案。

    真正的问题是您的其余规则约束不足。一旦它用COLUMN=6 尝试了第二种情况,它将用COLUMN=6 尝试第三种情况——没有什么可以阻止它。您可以通过对其进行更多削减来解决此问题,但这不是一个很好的方法。

    更好的方法是明确所有约束。只要您在所有其他规则的开头说LINE<6,就不需要删减checkVallEle(_,_,6,_)。如果你在每条规则中都说COLUMN<6(当然第二条除外),它应该可以解决你的意外回溯问题。

    【讨论】:

    • 啊,递归失败了所有遗留下来的东西,我现在得到了失败的火车,但我确实希望它失败,毕竟这并不能解释为什么我的第一个代码的剪切不起作用
    • @user2295607 抱歉,看来我完全错过了重点……更新了我的答案。
    • 谢谢,我现在明白这个问题并妥善解决了:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-26
    • 2014-08-02
    • 2012-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多