2015-05-07 12 views
5

Ecco un profilo del mio programma di SWI-Prolog:Usa reificata vincoli di fare 3 numeri consecutivi

:- 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 rende L5 e L4 uno accanto all'altro. Se volessi fare tre numeri uno accanto all'altro, ad es. L3, L4 e L5, come potrei usare i vincoli reificati per fare questo?

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

+0

Con "consecutivo", intendi ad es. '(L2 # = L1 + 1 #/\ L3 # = L2 + 1) # \/(L2 # = L1-1 #/\ L3 # = L2-1)'? – repeat

+0

Inoltre, questa relazione dovrebbe rimanere valida per tutti e 3 i membri adiacenti di L --- o solo per alcuni/altri? – repeat

risposta

3

Questo implementa consecutiva nel senso che hai dato nei commenti. Per un elenco dei valori N, abbiamo bisogno di spazio sufficiente per inserire tutti i valori in mezzo e tutti i valori devono essere diversi.

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

Questo funziona - grazie mille! – mmgro27

2

TL; DR: troppo lungo per un commento: play-tempo con specializzate vincoli


Questa risposta fa seguito this previous answer; le versioni recenti di SICStus Prolog offrono vincoli clpfd specializzati maximum/2 e minimum/2 come alternative a min_of/2 e max_of/2.

utilizzando il seguente codice per l'analisi comparativa 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)). 

... corriamo i seguenti test:

  1. Per stimare caso peggiore sovraccarico di min/vincolo massimo:

     
    ?- 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. Per misurare il tempo di esecuzione costi di moltiplicazione min/max vincoli nei casi più tipici:

     
    ?- 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. 
    

In entrambi i "casi d'uso", i vincoli specializzati danno impressionante aumento di velocità.


nota 1: Utilizzando SICStus Prolog versione 4.3.2 (64-bit).
Nota 2: Le sequenze di risposta sono state post-elaborate per migliorare l'aspetto.

Problemi correlati