Prolog pathloop失败

时间:2015-05-20 13:59:27

标签: graph prolog

我有这个程序:

pathloop

除了Path基本运行之外,一切都运行但是递归必须显示一个列表?- can_call(asd, dsa, Route),其中包含从A到B的路径。但是当我运行程序并输入{{1}时}, 它失败了(返回false。)。我必须在pathloop上改变什么?我试过了 ?- pathloop(1, 5, [], Path).并显示10-20个结果,然后显示false

2 个答案:

答案 0 :(得分:1)

  

我尝试了?- pathloop(1,5,[],Path).,它显示了10-20个结果,然后是false

让我们详细看看答案并突出显示任何虚假部分......

?- pathloop(1,5,[],Path).
  Path = [1,4,5]                                       % ok
; Path = [1,4,5,8,5]
; Path = [1,4,5,8,9,12,15,10,7,6,3,5]
; Path = [1,4,5,3,5]
; Path = [1,4,5,3,6,7,10,15,12,9,8,5]
; Path = [1,4,8,5]                                     % ok
; Path = [1,4,8,9,12,15,10,7,6,3,5]                    % ok
; Path = [1,4,8,5,3,5]
; Path = [1,2,1,4,5]
; Path = [1,2,1,4,5,8,5]
; Path = [1,2,1,4,5,8,9,12,15,10,7,6,3,5]
; Path = [1,2,1,4,5,3,5]
; Path = [1,2,1,4,5,3,6,7,10,15,12,9,8,5]
; Path = [1,2,1,4,8,5]
; Path = [1,2,1,4,8,9,12,15,10,7,6,3,5]
; Path = [1,2,1,4,8,5,3,5]
; false.

当前状态: 20个答案中的17个无效!

要解决此问题,我们使用 path/4

?- path(connect,Path,1,5).
  Path = [1,4,5]
; Path = [1,4,8,9,12,15,10,7,6,3,5]
; Path = [1,4,8,5]
; false.

确定!接下来,我们调整can_call/3的定义以使用path/4代替pathloop/4

can_call(PersonA, PersonB, Route) :-
    telephone(_-Area1-_, name(PersonA, _)),
    telephone(_-Area2-_, name(PersonB, _)),
    path(connect,Route,Area1,Area2).
  

但是当我运行[...] ?- can_call(asd,dsa,Route).时,它会失败(返回false。)

让我们使用新版can_call/3重新运行查询以上!

?- can_call(asd,dsa,Route).
  Route = [6,7,10,15,12]
; Route = [6,3, 5, 8, 9,12]
; Route = [6,3, 5, 4, 8, 9,12]
; false.

有效!

答案 1 :(得分:0)

问题在于,当您在pathloop/4中拨打can_call/3时,您会将未接地的变量_传递给Visited。换句话说,您提供了一个未经实例化的列表。现在,如果您执行成员检查member(a,X)X这样未实例化,它会说," 是的!这是可能的,只需制作X=[a|_] "。

因此,为了解决此问题,请将can_call/3重写为:

can_call(PersonA, PersonB, Route) :-
    telephone(_-Area1-_, name(PersonA, _)),
    telephone(_-Area2-_, name(PersonB, _)),
    pathloop(Area1, Area2,[Area1], Route).

从那时起,您只访问过Area1。

其他建议

我认为将基本案例定义为到达目的地更有意义:

pathloop(End,End, _,[End]) :-
    !.

" 剪切" (!)禁用以下事实:一旦到达目的地,您将继续搜索循环。例如,如果您想要从4连接到5。它不会提出类似4 -> 5 -> 8 -> 4 -> 5的路由,因此在到达后会循环。

接下来,归纳案例会搜索Next(我不会将其称为Middle,因为它不是中间的节点,而是位于开头旁边的节点。

pathloop(Start, End, Visited,[Start|Path]) :-
    connect(Start, Middle),
    \+ member(Middle, Visited),
    pathloop(Middle, End,[Middle|Visited],Path).

最好不要使用统一X=[A|B],如果这些已经可以在头部进行。它允许更快的执行,特别是如果你以相反的方向调用谓词。