规则有一些很好的答案,但无法全部解决

时间:2017-11-13 12:19:00

标签: list matrix prolog infinite-loop failure-slice

这些是我的规则,我的问题在于:

get_row([H|_],1,H):-!.
get_row([_|T],I,X) :-
    I1 is I-1,
    get_row(T,I1,X).

get_column([],_,[]).
get_column([H|T], I, [R|X]):-
   get_row(H, I, R), 
   get_column(T,I,X).

good_by_coulmns(Solution) :-
      length(Solution, Length),
      forall((between(1, Length, X),
              get_column(Solution, X, Y)),
              all_distinct(Y)).

createRow(Solution, Domain, Row) :- 
      maplist(member, Row, Domain),
      all_distinct(Row), 
      good_by_coulmns(Solution).
      %, write(Solution), nl.

tryToSolve(Domains, Solution) :-
      maplist(createRow(Solution),
              Domains, Solution),
      length(Solution, L), 
      length(Domains, L),
      good_by_coulmns(Solution).

问题是,最后一条规则产生了大约20个好的答案,但之后它会进入无限循环。第一条规则中有一个调试写入。

它写出这些行(总是改变数字),同时无限循环:

[[1, 2, 3, 4], [3, 1, 4, 2], [4, 3, 2, 1], [2, 4, 1, 3], _8544, _8550, _8556, _8562]
[[1, 2, 3, 4], [3, 4, 1, 2], _8532, _8538, _8544, _8550, _8556, _8562]

解决方案,我们等待是一个4x4矩阵。在第一行中,如果我们删除前4个元素,这是一个很好的解决方案。

以_开头的变量数总是在增加,而矩阵的第一行([1,2,3,4])永远不会改变。

你有什么想法,这里出了什么问题?

实际查询:

tryToSolve([[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]], [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]], [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]], [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]], L).

1 个答案:

答案 0 :(得分:3)

要确定问题,我将使用。在此,我将 false 目标插入您的计划中。通过插入这些目标,我将减少程序执行所需的推断数量。如果该数字仍然是无穷大,则可见部分包含错误 1

?- D = [1,2,3,4], D4 = [D,D,D,D], tryToSolve([D4,D4,D4,D4], L), false.

good_by_coulmns(Solution) :-
   length(Solution, Length), false,
   forall((between(1, Length, X),get_column(Solution, X, Y)), all_distinct(Y)).

createRow(Solution, Domain, Row) :-
   maplist(member, Row, Domain),
   all_distinct(Row),         % false, % terminates here
   good_by_coulmns(Solution), false.

tryToSolve(Domains, Solution) :-
   maplist(createRow(Solution), Domains, Solution), false,
   length(Solution, L),
   length(Domains, L),
   good_by_coulmns(Solution).

这个片段已经循环了。因此,可见部分必定存在错误。注意变量Solution!它应该是一个固定长度的列表,在length(Solution, Length)首次出现之后,Length终止。

建议:首先放置目标length(Domains, L), length(Solution, L)

对您的计划的一些评论:forall/2是一个非常有问题的结构。不惜一切代价避免它。很好的是,片段不包含它 - 这会使诊断更加复杂。

此外,首先尝试从较短的问题开始 - 这简化了终止的观察。

我如何设置 false 目标?嗯,这是一种直觉和反复试验。严格地说, false 目标的任何 1 位置都可以,这会产生一个仍然循环的片段。在考虑所有可能性时,即~2 失败切片,那些最小的失效切片是最有趣的。有关更多信息,请参阅

1 实际上,精确的前提条件有点复杂。粗略地说,获得的片段必须在一定程度上是纯的。