【问题标题】:Prolog domain restrictionProlog 域限制
【发布时间】:2013-12-13 13:53:09
【问题描述】:

如何告诉 Prolog/CLPFD 只使用特定数量的域作为最后一个资源?

例如: 域从 0...8。我希望 Prolog 只有在没有其他选项的情况下才使用 0 。我使用了“向下”选项进行标记,但分配了太多的 0。

上下文:Hoo-Doo 游戏 -> 生成 8x8 棋盘解决方案,其中任何列、行或对角线的数字都从 1-8 不重复(数独之类)。必须使用两个透明的部分(用 0 表示,可以是任何地方)才能完成解决方案。

代码如下:

...

setDomain(H,BoardSize), 
maplist(all_distinct,H), 
IndexI is BoardSize - 1, 
IndexJ is BoardSize - 2,
checkDiagonalsLR(H,IndexI,IndexJ,BoardSize), %calls the all_distinct
IndexJ2 is BoardSize - 1,
checkDiagonalsRL(H,1,IndexJ2,BoardSize), %calls the all_distinct
transpose(H,Columns), maplist(all_distinct,Columns), 
useLabeling(Columns,BoardSize), printBoard(Columns).

useLabeling([],N).
useLabeling([H|T],N) :- labeling([down],H), useLabeling(T,N).

【问题讨论】:

  • 请将您的代码添加到问题中。

标签: prolog sudoku clpfd


【解决方案1】:

一种方法是使用布尔变量 Bs 和具体化的约束,使 B_i 为 1 而 V_i 为零:

(V_i #= 0) #<==> B_i

B_i 变量的总和就是您的解决方案中出现的 N 的数量:

sum(Bs, #=, N)

然后,您可以使用labeling/2,使N 最小化:

labeling([min(N)], Vs)

这在 SICStus 和 SWI 中有效(稍作调整)。

【讨论】:

  • 这怎么能在我的代码中工作?我正在使用 SICStus。我是 Prolog 的新手,对此感到抱歉
  • 由于您需要正好 2 个零,因此无需最小化。你可以有一个像sum(Bs,#=,2) 这样的总和约束,并保持原样。
  • 其实并不完全是 2 个零。如果没有其他选项可用以完成登机,它应该只使用 0,因此可以有 0,1 或 2 个零(最多 2 个)。发生这种情况是因为板子的大小是可变的,我只是以 8x8 为例(它有一个 2-0 的解决方案)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-18
  • 2018-04-24
  • 2013-05-14
相关资源
最近更新 更多