2013-12-13 60 views
1

如何才能告訴Prolog/CLPFD只使用一定數量的域作爲最後一個資源?Prolog域限制

E.g. :從0 ... 8的域。我希望Prolog只有在沒有其他選項時才使用0。我使用'down'選項進行標記,但分配了太多的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). 
+0

請將您的代碼添加到問題中。 –

+0

剛剛添加的代碼 – user2884323

回答

3

一種方法是使用布爾變量Bs和具體化的約束條件,以便B_i是1 IFF V_i爲零:在B_i

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

總和那麼變量是您的解決方案中發生的零的數字N

sum(Bs, #=, N)

然後,您可以以這樣的方式使用labeling/2N最小:

labeling([min(N)], Vs)

這工作(有小的調整),例如在SICStus和SWI。

+0

這怎麼能在我的代碼中工作?我正在使用SICStus。我是Prolog的新手,對此感到抱歉 – user2884323

+0

由於您需要完全2個零,因此不需要最小化。你可以像sum(Bs,#=,2)'那樣有一個總和約束,並保持標籤原樣。 – jschimpf

+0

實際上並不完全是2個零。如果沒有其他選項可用於完成登錄,則應該只使用0,因此可以有0,1或2個零(最多2個)。發生這種情況是因爲電路板的大小是可變的,我只是以8x8爲例(它有一個2零解決方案) – user2884323