【问题标题】:Some good answers by the rule, but cannot get them all规则中的一些好的答案,但不能全部获得
【发布时间】:2017-11-13 12:18:59
【问题描述】:

这些是我的规则,我的问题出在哪里:

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).

【问题讨论】:

  • @nullpointer:这种琐碎的编辑没有任何帮助,甚至没有纠正拼写错误
  • 我添加了一个基本查询,并添加了规则。请看上面。它正在实现一个谜题求解器,此时类似于基本数独。
  • clpfd 是你所需要的...
  • 我不知道那个库,你能告诉我,我怎么能在这里使用它?
  • 您已经在使用library(clpfd)!这就是all_distinct/1 的来源。

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


【解决方案1】:

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

?- D = [1,2,3,4], D4 = [D,D,D,D], tryToSolve([D4,D4,D4,D4], L), false。 good_by_coulmns(解决方案):- 长度(解决方案,长度),falseforall((between(1, Length, X),get_column(Solution, X, Y)), all_distinct(Y))。 createRow(解决方案,域,行):- maplist(成员,行,域), all_distinct(Row), % false, % 在这里终止 good_by_coulmns(解决方案),错误。 tryToSolve(域,解决方案):- maplist(createRow(Solution), Domains, Solution), false, 长度(解决方案,L)长度(域,L)good_by_coulmns(解决方案)

这个片段已经循环了。因此,可见部分肯定有错误。注意变量Solution!让length(Solution, Length)终止应该是一个固定长度的列表,毕竟Length是第一次出现在这里。

建议:将目标length(Domains, L), length(Solution, L)放在首位。

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

另外,尝试先从较短的问题开始 - 这可以简化对终止的观察。

我如何设置这些 false 目标?嗯,这有点直觉和反复试验。严格来说,false 目标的任何1 位置都是可以的,这会导致片段仍在循环。在考虑所有可能性时,即 ~2lines 故障切片,最小的那些是最有趣的。更多信息,请参阅


1 实际上,精确的前提条件要复杂一些。粗略地说,得到的片段一定是纯的。

【讨论】:

  • 谢谢!这是一个很好的调试技巧!现在它似乎找到了几乎所有的解决方案,但现在我在最后一个解决方案中遇到了内存不足的错误。我希望通过给它更多的限制它会消失。
  • 我得到了 576 个解决方案。在 SICStus 和 SWI 中。
  • 也许你可以帮我改进一下:stackoverflow.com/questions/47272417/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多