如何在递归调用规则时停止回溯

时间:2016-05-31 06:17:56

标签: prolog

所以我有一个应该很容易解决的问题,到这一步,我知道我正在研究的这个程序的流程。

之前有代码,但我在这里粘贴的这段代码用这个来调用:

pairs_nodes_arcs(C, C, SalidaCreacionEnum, EnumArcos).

它应该做什么:通过第二个参数直到它为空,找到它是否满足每个条件,如果满足,给出已形成的输出列表(EnumArcos应该保持答案)因为条件作为回答" (我打算发送" up"通过回溯到代码的其余部分,因为它是真正问题的答案之一)。

现在,如果失败,它应该(并且确实)删除第三个参数的头部,这是一个列表列表,并且"重新启动"第二个参数(我也成功地做了这个,因为我总是持有第一个参数的副本,它与原来的第二个参数相同)。

正如我所说的那样,应该在答案列表的第4个参数中返回。它确实如此,当我使用跟踪时,我会在那里看到正确的答案(最后!!)但是它会丢失,因为当它回溯时,答案列表会变空,我最终会返回空白。

我刚刚在这里阅读http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse9基本查询是必需的。但我无法弄清楚(严格来说,我的代码不会陷入无限循环,即使它是由于运气不好,也不是问题)。问题是,当回溯时,我没有回答。

pairs_nodes_arcs(_, _, [],_).
pairs_nodes_arcs(_, [], _,_).
pairs_nodes_arcs([], _, _, _).
pairs_nodes_arcs([A-B | T],[C-D | Tail0], [H|NODES], LISTARCS) :-
    member(enum(NODE_ID_C, C), H),
    member(enum(NODE_ID_D, D), H),
    REMAINDER is abs(NODE_ID_C-NODE_ID_D),
    arcs_are_repeated([A-B  | T], [C-D | Tail0], [H|NODES], REMAINDER,LISTARCS).

arcs_are_repeated([A-B | T], [_ | Tail0], [H|NODES], REMAINDER, ListArcsInput):-
    %maplist(dif(enum(REMAINDER,_)), ListArcsInput),
    myMapList(enum(REMAINDER,_),ListArcsInput),
    pairs_nodes_arcs([A-B | T], Tail0, [H|NODES], [enum(REMAINDER, A-B) | ListArcsInput], ).

arcs_are_repeated([A-B | T], [_], [H|NODES],_,_):-
    pairs_nodes_arcs([A-B | T], [A-B | T], NODES, []).


myMapList(_, []).
myMapList(enum(NUM1,_), [enum(NUM2,_)|InputList]):-
    dif(NUM1,NUM2),
    myMapList(enum(NUM1,_), InputList).

我也有跟踪,我只粘贴我感觉像我的特定部分"松开答案(我手动分开第四个参数以强调它,它是同一个括号的所有部分):

pairs_nodes_arcs([a-b, b-c], [], [[enum(1, c), enum(3, b), enum(2, a)], [enum(2, c), enum(1, b), enum(3, a)], [enum(2, c), enum(3, b), enum(1, a)], [enum(3, c), enum(1, b), enum(2, a)], [enum(3, c), enum(2, b), enum(1, a)]], 


[enum(2, a-b), enum(1, a-b)])


 Exit:pairs_nodes_arcs([a-b, b-c], [], [[enum(1, c), enum(3, b), enum(2, a)], [enum(2, c), enum(1, b), enum(3, a)], [enum(2, c), enum(3, b), enum(1, a)], [enum(3, c), enum(1, b), enum(2, a)], [enum(3, c), enum(2, b), enum(1, a)]], [enum(2, a-b), enum(1, a-b)])
 Exit:arcs_are_repeated([a-b, b-c], [b-c], [[enum(1, c), enum(3, b), enum(2, a)], [enum(2, c), enum(1, b), enum(3, a)], [enum(2, c), enum(3, b), enum(1, a)], [enum(3, c), enum(1, b), enum(2, a)], [enum(3, c), enum(2, b), enum(1, a)]], 2, 


[enum(1, a-b)])


 Exit:pairs_nodes_arcs([a-b, b-c], [b-c], [[enum(1, c), enum(3, b), enum(2, a)], [enum(2, c), enum(1, b), enum(3, a)], [enum(2, c), enum(3, b), enum(1, a)], [enum(3, c), enum(1, b), enum(2, a)], [enum(3, c), enum(2, b), enum(1, a)]], 


[enum(1, a-b)])

edit1 好的,所以我到目前为止修复此问题的方法似乎是传递一个我操作的空列表,以及我一直为自己保留的变量。然后,当SUCCEED的基本情况成功时,我统一作为变量的解决方案的操作列表。我在代码中至少做了3次,需要1次。不是百分之百,这是一个很好的方式,但我最终得到了一些论点,但是...我的意思是这种方法似乎存在问题,但它至少是一个问题。< / p>

1 个答案:

答案 0 :(得分:3)

你回答关于回溯(回复发生在失败),但关于成功:你期待您的程序使用特定绑定成功,但

要进行调试,请以声明的方式思考:写下应该成功的目标,但失败

在您的示例中,查询:

?- arcs_are_repeated([a-b, b-c], [b-c], [[enum(1, c), enum(3, b), enum(2,a)],
    [enum(2, c), enum(1, b), enum(3, a)], [enum(2, c), enum(3, b), enum(1, a)],
    [enum(3, c), enum(1, b), enum(2, a)], [enum(3, c), enum(2, b), enum(1, a)]], 
    2, [enum(1, a-b)]).

可能就是这样一个例子。

然后,以仍然失败的方式使目标更加通用。例如,以下内容是否仍然失败:

?- arcs_are_repeated([a-b, b-c], [b-c], [[enum(1, c), enum(3, b), enum(2,a)],
    [enum(2, c), enum(1, b), enum(3, a)], [enum(2, c), enum(3, b), enum(1, a)], _], 2, _).

如果是这样,进一步概括。例如,怎么样:

?- arcs_are_repeated([a-b, b-c], _, _, _, _).

如果失败,你已经缩小了一个尚未考虑的案例,无论论证是什么。

这是你以声明的方式调试的方式:想想 应该成功但是失败了,并考虑 应该失败但是成功。在前一种情况下,您的程序太具体,而在后一种情况下,过于笼统。在你的情况下,它太具体了,所以你要么:

  • 添加条款或
  • 删除现有条款中的约束

使程序更通用。