【问题标题】:Prolog generator stuck infinitely trying THE SAME OBJECT over and over?Prolog 生成器卡住了一遍又一遍地尝试相同的对象?
【发布时间】:2020-05-27 18:52:51
【问题描述】:

我真的被 Prolog 中的一个问题困住了。我正在尝试制作一个生成器“gen_lists_of_pairs(V, L)”,它给定一个自然数列表 V,生成包含两个元素列表的所有可能列表,这样它们的元素是唯一的,并且每个元素都采用 [ A, B] 其中 A 和 B 是 V 和 A

这是我的代码:

ascending([_]).
ascending([A, B|L]) :- A < B, ascending([B|L]).

gen_list_of_pairs(_, []).

gen_list_of_pairs(V, [[X,Y]|L]) :-
    gen_list_of_pairs(V, L),
    member(X, V),
    member(Y, V),
    ascending([X, Y]),
    not((member([X, Y], L))).

这是调用“gen_list_of_pairs([1], X)”时的调试跟踪:

Call:gen_list_of_pairs([1], _7086)
 Exit:gen_list_of_pairs([1], [])
X = []
 Redo:gen_list_of_pairs([1], _7086)
 Call:gen_list_of_pairs([1], _7902)
 Exit:gen_list_of_pairs([1], [])
 Call:lists:member(_7906, [1])
 Exit:lists:member(1, [1])
 Call:lists:member(_7912, [1])
 Exit:lists:member(1, [1])
 Call:ascending([1, 1])
 Call:1<1
 Fail:1<1
 Fail:ascending([1, 1])
 Redo:gen_list_of_pairs([1], _7902)
 Call:gen_list_of_pairs([1], _7920)
 Exit:gen_list_of_pairs([1], [])
 Call:lists:member(_7924, [1])
 Exit:lists:member(1, [1])
 Call:lists:member(_7930, [1])
 Exit:lists:member(1, [1])
 Call:ascending([1, 1])
 Call:1<1
 Fail:1<1
 Fail:ascending([1, 1])
 Redo:gen_list_of_pairs([1], _7920)
 ...

如您所见,在输出“X = []”后,prolog 陷入无​​限循环,一遍又一遍地尝试配对 [1,1],尽管据我所知,它应该尝试其他方法或在尝试失败后停止查询......我无法弄清楚这一点并且越来越沮丧。任何帮助将不胜感激...

【问题讨论】:

  • 值得注意的是,对于较大的列表,它会正确生成所有对象,但是最后会继续尝试一遍又一遍地生成相同的对象,而不是完成查询并返回 false..

标签: list prolog


【解决方案1】:

那里的递归太多了。特别是当你在“左边”递归时

gen_list_of_pairs(V, [[X,Y]|L]) :-
    gen_list_of_pairs(V, L), ...

如果第二个参数未实例化,则无论之后发生什么,这都会变成无穷大:

gen_list_of_pairs(V, [[X,Y]|L]) :-
    gen_list_of_pairs(V, L),false.

然后:

?- gen_list_of_pairs([1,2,3],X).
ERROR: Stack limit (1.0Gb) exceeded

...因为没有停止标准。我们只是将[X,Y] 添加到一个不断加长的列表中。

最好重新开始。

事实上,附加到“解决方案包”的任务由bagof/3setof/3 负责。

我们只需要从V生成新的对,可回溯:

gimme_another_pair(V,[X,Y]) :-
   member(X,V),
   member(Y,V),
   X < Y.

然后

?- gimme_another_pair([1,2,3],P).
P = [1, 2] ;
P = [1, 3] ;
P = [2, 3] ;
false.

所以:

gen_list_of_pairs(V, Result) :- setof(P,gimme_another_pair(V,P),Result).

所以:

?- gen_list_of_pairs([1,2,3],X).
X = [[1, 2], [1, 3], [2, 3]].

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 2016-12-20
    • 2017-02-15
    • 2019-08-29
    相关资源
    最近更新 更多