为什么这个Prolog谓词有效?

为什么这个Prolog谓词有效?,prolog,Prolog,我有以下代码: 请记住,虽然此代码用于列表,但这些列表表示集合,因此[1,1,2,2,3,3]和[1,2,3]应该是等价的 %contains(L1, L2), returns true if L1 contains L2 contains(_, []). contains(L1, [Head|Tail]) :- member(Head, L1), contains(L1, Tail). %equals(L1, L2), returns true if L1 is equal to L2 equ

我有以下代码: 请记住,虽然此代码用于列表,但这些列表表示集合,因此[1,1,2,2,3,3]和[1,2,3]应该是等价的

%contains(L1, L2), returns true if L1 contains L2
contains(_, []).
contains(L1, [Head|Tail]) :- member(Head, L1), contains(L1, Tail).
%equals(L1, L2), returns true if L1 is equal to L2
equals([X|L1],[X|L2]) :- equals(L1, L2).
equals(L1, L2) :- contains(L1, L2), contains(L2, L1).
其思想是equals([1,2,3],[1,2,1,3])应该返回true。然而,根据上述定义,我预计会发生以下情况:

  • equals([1,2,3],[1,2,1,3])匹配第一条规则,并调用equals([2,3],[2,1,3])
  • equals([2,3],[2,1,3]])匹配第二条规则并调用contains([2,3],[2,1,3]), 包含([2,1,3],[2,3])
  • 包含([2,3],[2,1,3])失败,并等于返回No
  • 但它仍然有效。其他混淆它的尝试也是如此。谁能给我解释一下吗


    (Prolog实现:SWI Prolog版本2.7.12)

    Prolog使用一种称为“回溯”的技术

    看看第一步,你的第一步

    Prolog有两条规则可以在这里使用,如果它使用您在解释中选择的规则,它将始终失败。但一旦失败,Prolog将回溯并尝试替代规则:

    等于([1,2,3],[1,2,1,3]):-包含([1,2,3],[1,2,1,3]),包含([1,2,1,3],[1,2,3])

    通过在找到错误答案后反复回溯,Prolog最终找到了正确的解决方案,因此它知道答案是正确的

    如果尝试了所有可能的方法应用规则,但没有找到正确的答案,那么答案肯定是错误的


    这是Prolog的一个非常基本的部分。我很惊讶你竟然没有理解它就走到了这一步。

    Prolog使用了一种称为“回溯”的技术

    看看第一步,你的第一步

    Prolog有两条规则可以在这里使用,如果它使用您在解释中选择的规则,它将始终失败。但一旦失败,Prolog将回溯并尝试替代规则:

    等于([1,2,3],[1,2,1,3]):-包含([1,2,3],[1,2,1,3]),包含([1,2,1,3],[1,2,3])

    通过在找到错误答案后反复回溯,Prolog最终找到了正确的解决方案,因此它知道答案是正确的

    如果尝试了所有可能的方法应用规则,但没有找到正确的答案,那么答案肯定是错误的


    这是Prolog的一个非常基本的部分。我很惊讶您竟然没有理解它就走到了这一步。

    您的代码非常奇怪,但是我建议您使用跟踪谓词进行测试。以下是一个例子:

    4 ?- trace([equals,contains]).
    %         equals/2: [call, redo, exit, fail]
    %         contains/2: [call, redo, exit, fail]
    true.
    
    [debug] 5 ?- equals([1,2,3],[1,2,1,3]).
     T Call: (7) equals([1, 2, 3], [1, 2, 1, 3])
     T Call: (8) equals([2, 3], [2, 1, 3])
     T Call: (9) equals([3], [1, 3])
     T Call: (10) contains([3], [1, 3])
     T Fail: (10) contains([3], [1, 3])
     T Fail: (9) equals([3], [1, 3])
     T Redo: (8) equals([2, 3], [2, 1, 3])
     T Call: (9) contains([2, 3], [2, 1, 3])
     T Call: (10) contains([2, 3], [1, 3])
     T Fail: (10) contains([2, 3], [1, 3])
     T Fail: (9) contains([2, 3], [2, 1, 3])
     T Fail: (8) equals([2, 3], [2, 1, 3])
     T Redo: (7) equals([1, 2, 3], [1, 2, 1, 3])
     T Call: (8) contains([1, 2, 3], [1, 2, 1, 3])
     T Call: (9) contains([1, 2, 3], [2, 1, 3])
     T Call: (10) contains([1, 2, 3], [1, 3])
     T Call: (11) contains([1, 2, 3], [3])
     T Call: (12) contains([1, 2, 3], [])
     T Exit: (12) contains([1, 2, 3], [])
     T Exit: (11) contains([1, 2, 3], [3])
     T Exit: (10) contains([1, 2, 3], [1, 3])
     T Exit: (9) contains([1, 2, 3], [2, 1, 3])
     T Exit: (8) contains([1, 2, 3], [1, 2, 1, 3])
     T Call: (8) contains([1, 2, 1, 3], [1, 2, 3])
     T Call: (9) contains([1, 2, 1, 3], [2, 3])
     T Call: (10) contains([1, 2, 1, 3], [3])
     T Call: (11) contains([1, 2, 1, 3], [])
     T Exit: (11) contains([1, 2, 1, 3], [])
     T Exit: (10) contains([1, 2, 1, 3], [3])
     T Exit: (9) contains([1, 2, 1, 3], [2, 3])
     T Exit: (8) contains([1, 2, 1, 3], [1, 2, 3])
     T Exit: (7) equals([1, 2, 3], [1, 2, 1, 3])
    true 
    

    您的代码非常奇怪,但是我建议您使用跟踪谓词进行测试。以下是一个例子:

    4 ?- trace([equals,contains]).
    %         equals/2: [call, redo, exit, fail]
    %         contains/2: [call, redo, exit, fail]
    true.
    
    [debug] 5 ?- equals([1,2,3],[1,2,1,3]).
     T Call: (7) equals([1, 2, 3], [1, 2, 1, 3])
     T Call: (8) equals([2, 3], [2, 1, 3])
     T Call: (9) equals([3], [1, 3])
     T Call: (10) contains([3], [1, 3])
     T Fail: (10) contains([3], [1, 3])
     T Fail: (9) equals([3], [1, 3])
     T Redo: (8) equals([2, 3], [2, 1, 3])
     T Call: (9) contains([2, 3], [2, 1, 3])
     T Call: (10) contains([2, 3], [1, 3])
     T Fail: (10) contains([2, 3], [1, 3])
     T Fail: (9) contains([2, 3], [2, 1, 3])
     T Fail: (8) equals([2, 3], [2, 1, 3])
     T Redo: (7) equals([1, 2, 3], [1, 2, 1, 3])
     T Call: (8) contains([1, 2, 3], [1, 2, 1, 3])
     T Call: (9) contains([1, 2, 3], [2, 1, 3])
     T Call: (10) contains([1, 2, 3], [1, 3])
     T Call: (11) contains([1, 2, 3], [3])
     T Call: (12) contains([1, 2, 3], [])
     T Exit: (12) contains([1, 2, 3], [])
     T Exit: (11) contains([1, 2, 3], [3])
     T Exit: (10) contains([1, 2, 3], [1, 3])
     T Exit: (9) contains([1, 2, 3], [2, 1, 3])
     T Exit: (8) contains([1, 2, 3], [1, 2, 1, 3])
     T Call: (8) contains([1, 2, 1, 3], [1, 2, 3])
     T Call: (9) contains([1, 2, 1, 3], [2, 3])
     T Call: (10) contains([1, 2, 1, 3], [3])
     T Call: (11) contains([1, 2, 1, 3], [])
     T Exit: (11) contains([1, 2, 1, 3], [])
     T Exit: (10) contains([1, 2, 1, 3], [3])
     T Exit: (9) contains([1, 2, 1, 3], [2, 3])
     T Exit: (8) contains([1, 2, 1, 3], [1, 2, 3])
     T Exit: (7) equals([1, 2, 3], [1, 2, 1, 3])
    true 
    

    事实上,这是我做过的第一个Prolog程序(或者更准确地说,是家庭作业),所以我并没有走多远。我完全是个初学者。无论如何,谢谢你给我解释。事实上,这是我做过的第一个Prolog程序(或者更准确地说是家庭作业),所以我并没有走多远。我完全是个初学者。不管怎样,谢谢你给我解释。