【问题标题】:How can labeling/2 generate solutions starting from the midpoint of a domain?labeling/2 如何从域的中点生成解决方案?
【发布时间】:2019-10-10 01:33:58
【问题描述】:

有一个包含自变量的列表,其域为 1..N,我们如何使用 labeling/2 使其从中间开始生成解决方案?

我尝试的标志是[bisect],[enum],[max],[min],[ff],但无论我选择哪个,我都无法使其工作。

我的代码是:

:-use_module(library(clpfd)).

combos(EMPLOYEES,POSTS,LIST):-
   LIMIT is POSTS-EMPLOYEES+1,
   length(LIST,EMPLOYEES),
   LIST ins 1..LIMIT,
   sum(LIST,#=,POSTS),
   labeling([bisect],LIST).

设置查询后,例如:

?-combos(2,10,LIST).

我希望它返回:

L = [5,5];
L = [4,6];
L = [6,4] ...

代替:

L = [1,9];
L = [2,8];
L = [3,7] ...

【问题讨论】:

  • 投反对票,因为 TimzyPatzy 在发布答案后更改了问题,导致答案无效。 TimzyPatzy 应该接受已发布的答案并发布不同的问题。
  • 我同意@false,这是一个完全不同的问题!正如您所说,您不仅对原始问题更加“具体”。您完全改变它!即使是您原始问题中的示例也与您添加的更具体的内容相矛盾!

标签: prolog clpfd labeling


【解决方案1】:

给你!

combos(2,S,L) :- b2(S,L).
combos(C,S,[A|L]) :-
    C > 2,
    b2(S,[A,B]),
    D is C-1,
    combos(D,B,L).

b2(S,L) :- B is S-1, bisector(B,L).

bisector(Y,[A,B]) :-
    odd(Y),
    M is div(1+Y,2),
    Z is M-1,
    range(D,0,Z),
    bisec1(D,M,A,B).
bisector(Y,[A,B]) :-
    even(Y),
    M is 1+Y,
    Z is Y/2-1,
    range(D,0,Z),
    bisec2(D,M,A,B).

bisec1(0,M,M,M).
bisec1(D,M,A,B) :- D > 0, A is M + D, A > 0, B is M - D, B > 0.
bisec1(D,M,A,B) :- D > 0, A is M - D, A > 0, B is M + D, B > 0.

bisec2(D,M,A,B) :- A is (M+2*D+1)/2, A > 0, B is (M-2*D-1)/2, B > 0.
bisec2(D,M,A,B) :- A is (M-2*D-1)/2, A > 0, B is (M+2*D+1)/2, B > 0.

even(X) :- 0 is mod(X, 2).
odd(X) :- 1 is mod(X, 2).

range(M,M,_).
range(X,M,N) :- P is M + 1, P =< N, range(X,P,N).

【讨论】:

  • 对不起,我的问题不够清楚。通过中点,我的意思是返回解决方案,使每个变量与列表中的其他变量具有大致相同的值。所以像这样的问题:?-combos(4,16,LIST) 应该返回:LIST = [4,4,4,4],然后 LIST = [4,4,3,5],依此类推。
【解决方案2】:

根据经验,每当您尝试扩展 clpfd 的功能时,请尽量重用。看来您首先需要到中心的距离总和尽可能小的解决方案。

combos2(EMPLOYEES,POSTS,LIST):-
   LIMIT is POSTS-EMPLOYEES+1,
   length(LIST,EMPLOYEES),
   LIST ins 1..LIMIT,
   sum(LIST,#=,POSTS),
   Mid is (LIMIT+1) div 2,           %%
   maplist(dist(Mid), LIST, DISTS),  %%    
   sum(DISTS,#=,Totaldist),          %%
   labeling([],[Totaldist|LIST]).

dist(Mid, E, D) :-
    D #= abs(Mid-E).

?- combos2(2,10,L).
   L = [5,5]
;  L = [4,6]
;  L = [6,4]
;  L = [3,7]
;  L = [7,3]
;  ...

【讨论】:

  • 具体来说,我想将 POSTS 尽可能均匀地分配给 EMPLOYEES,因此,例如,查询:?-combos(5,21,L) 应该作为第一个解决方案返回:L = [4,4,4,4,5]。
  • 好的,但是您正在更改您的要求。将dist/2 替换为:dist(Mid, E, D) :- D #= (Mid-E)^2.
  • 然后检查这个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-28
  • 1970-01-01
  • 1970-01-01
  • 2019-10-16
相关资源
最近更新 更多