Prolog 使用具体化约束使3个数字连续

Prolog 使用具体化约束使3个数字连续,prolog,constraints,clpfd,sicstus-prolog,Prolog,Constraints,Clpfd,Sicstus Prolog,以下是我的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使L5和L4相邻。如果我想让三个数字彼此相邻,例如L3、L4和L5,我如何使用具体化约束来实现这一点 例如

以下是我的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
使
L5
L4
相邻。如果我想让三个数字彼此相邻,例如
L3
L4
L5
,我如何使用具体化约束来实现这一点


例如,
L3=4
L5=5
L4=6
L4=7
L5=8
L3=9
这实现了您在评论中给出的连续性。对于
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).

TL;DR:评论时间过长:有专门限制的播放时间


这个答案是跟进的;SICStus Prolog的最新版本提供了专门的clpfd约束
maximum/2
minimum/2
,作为
minu of/2
max of/2
的替代方案

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

:- (). :-使用_模块()。 工作台(如何,N,Ub):- \+\+((Xs,N), (Xs,1,Ub), (Xs), Max-MinN-1, (How=0 ;How=min_of,max_of(max,Xs),min_of(min,Xs) ;How=最小值、最大值(Max,Xs)、最小值(Min,Xs) ), ([enum],Xs))。 。。。我们运行以下测试:

  • 要估计最小/最大约束的最坏情况开销:

    ?- 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. ?-(How,[0,v1,v2]),(bench_(How,10,10),)。 How=0,T_ms=5910 ; How=v1,T_-ms=19560 ; How=v2,T_-ms=7190。
  • 要测量在更典型的情况下传播最小/最大约束的运行时成本,请执行以下操作:

    ?- 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. ?-(6,8,N),NN#=N+N,呼叫时间(工作台时间(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。 ?-介于(6,8,N)之间,NN#=N+N,呼叫时间(台架(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。
  • 在这两个“用例”中,专门的约束提供了令人印象深刻的加速


    脚注1:使用SICStus Prolog版本4.3.2(64位)。
    脚注2:回答顺序经过后处理以改善外观。

    带“continuoused”,你是指例如
    (L2#=L1+1#/\L3#=L2+1)#/(L2#=L1-1#/\L3#=L2-1)
    ?同样,这种关系应该适用于L的所有3个相邻成员,还是仅适用于某些/任何成员? ?- 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.