使用确定的约束使3个数字连续

时间:2015-05-07 21:38:05

标签: prolog constraints clpfd

这是我的SWI-Prolog计划的概要:

:- use_module(library(clpfd)).

consec1(L) :-
   L=[L1,L2,L3,L4,L5,L6,L7,L8,L9],
   L ins 1..9,
   ...,
   abs(L5-L4)#=1,
   all_different(L),
   labeling([],L)

abs(L5-L4)#=1使L5L4彼此相邻。如果我想让三个数字彼此相邻,例如L3L4L5,我如何使用具体约束来执行此操作?

E.g。 L3=4L5=5L4=6L4=7L5=8L3=9

2 个答案:

答案 0 :(得分:3)

这实现了你在评论中给出的连续性。对于N值列表,我们需要足够的空间来使所有值都适合,并且所有值都需要不同。

consecutive([]).  % debatable case
consecutive(Xs) :-
   Xs = [_|_],
   length(Xs, N),
   all_different(Xs),
   max_of(Max, Xs),
   min_of(Min, Xs),
   Max-Min #= N-1.

max_of(Max, [Max]).
max_of(Max0, [E|Es]) :-
   Max0 #= max(E,Max1),
   max_of(Max1, Es).

min_of(Min, [Min]).
min_of(Min0, [E|Es]) :-
   Min0 #= min(E, Min1),
   min_of(Min1, Es).

答案 1 :(得分:2)

TL; DR:评论时间过长:具有专门 约束的播放时间

这个答案随后为this previous answer;最新版本的SICStus Prolog提供专门的clpfd约束maximum/2minimum/2作为min_of/2max_of/2的替代。

使用以下代码进行基准测试 1,2 ...

:- use_module(library(clpfd)).
:- use_module(library(between)).

bench_(How, N, Ub) :-
   \+ \+ ( length(Xs, N),
           domain(Xs, 1, Ub),
           all_different(Xs),
           Max-Min #= N-1,
           (  How = 0
           ;  How = min_of , max_of( Max, Xs), min_of( Min, Xs)
           ;  How = minimum, maximum(Max, Xs), minimum(Min, Xs)
           ),
           labeling([enum], Xs) ).

...我们运行以下测试:

  1. 估算最小/最大约束的最坏情况开销:

    ?- member(How, [0,v1,v2]), call_time(bench_(How,10,10), T_ms).
       How = 0 , T_ms =  5910
    ;  How = v1, T_ms = 19560
    ;  How = v2, T_ms =  7190.
    
  2. 在更典型的情况下测量传播最小/最大约束的运行时成本:

    ?- between(6, 8, N), NN #= N+N, call_time(bench_(v1,N,NN),T_ms).
       N = 6, NN = 12, T_ms =   50 
    ;  N = 7, NN = 14, T_ms =  300
    ;  N = 8, NN = 16, T_ms = 2790.
    
    ?- between(6, 8, N), NN #= N+N, call_time(bench_(v2,N,NN),T_ms).
       N = 6, NN = 12, T_ms =   20
    ;  N = 7, NN = 14, T_ms =  100
    ;  N = 8, NN = 16, T_ms =  830.
    
  3. 在两个“用例”中,专门的约束条件给出了令人印象深刻的加速。

    脚注1:使用SICStus Prolog版本4.3.2(64位) 脚注2:对答案序列进行后处理以改善外观。 功能