2016-12-15 11 views
4

Я пытаюсь ограничить два списка, начиная с N последовательных элементов (E), используя CLP (FD). Вот пример: пусть L1 и L2 два списка размера 6, элементы принадлежат к области [0, 1], E = 1, и N = 3, то предикат constraint(+L1, +L2, +N) обеспечат следующие возможные решения:Ограничьте два списка, чтобы начать с N последовательных элементов в общей сложности с помощью CLP (FD)

L1 = [1, 1, 1, 0, _, _], L2 = [0, _, _, _, _, _]; 
L1 = [1, 1, 0, _, _, _], L2 = [1, 0, _, _, _, _]; 
L1 = [1, 0, _, _, _, _], L2 = [1, 1, 0, _, _, _]; 
L1 = [0, _, _, _, _, _], L2 = [1, 1, 1, 0, _, _]. 

Для списков размера 3, следующее было бы приемлемо:

L1 = [1, 1, 1], L2 = [0, _, _]; 
L1 = [1, 1, 0], L2 = [1, 0, _]; 
L1 = [1, 0, _], L2 = [1, 1, 0]; 
L1 = [0, _, _], L2 = [1, 1, 1]. 

в конце концов я хочу обобщить это на произвольное число списков и области, но это самый маленький эквивалент проблема, которую я мог думать.


Вот мой (неудачная) попытка до сих пор:

:- use_module(library(clpfd)). 

constseq([], _, 0). 
constseq([L|_], A, 0) :- L #\= A. 
constseq([A|Ls], A, N) :- N1 #= N - 1, constseq(Ls, A, N1). 

constraint(L1, L2, N) :- 
    SL1 + SL2 #= N, 
    constseq(L1, 1, SL1), 
    constseq(L2, 1, SL2). 

main(L1, L2) :- 
    length(L1, 6), 
    length(L2, 6), 
    constraint(L1, L2, 3). 

Хотя это работает, обратите внимание, что я генерации решений через возвратов, а не пользуясь CLP (FD) в сделайте грязную работу. Я пытаюсь понять, как это сделать, и я уже смотрю на предикаты, такие как chain/2, и монстры вроде automaton/3, но во мне что-то говорит, что должно быть более простое решение для этого ...

+2

Удалите формат '/ 2' и сделайте это доступным через ** аргументы **. Например, 'main (L1, L2): - ...'. Вы не можете проверить вывод, который появляется только на терминале, по крайней мере, не так легко, как аргумент. – mat

ответ

3

Вдохновленный на SICStus example из exactly/3, вот моя последняя попытка:

constseq_(_, [], _, 0). 
constseq_(X, [Y|L], F, N) :- 
    X #= Y #/\ F #<=> B, 
    N #= M+B, 
    constseq_(X, L, B, M). 

constseq(L, E, N) :- 
    constseq_(E, L, 1, N). 
+0

Хороший шаг в правильном направлении, но в настоящее время слишком общий. Вы можете комбинировать переопределение ограничений с помощью 'automaton/8'! – mat

+0

'automaton/8' кажется еще более пугающим, что' automaton/3'. Каковы были бы преимущества использования этого решения? Где это происходит? Каким образом вы считаете это слишком общим? –

+0

Как насчет списков формы '[1,1,1,0,1,1]'? В любом случае, вы используете слишком сложный пример в моем представлении. Подумайте о том, чтобы задать вопрос для * единственного * списка и правильно описать его. Затем вернемся сюда, чтобы обсудить версию, где описаны * два * списка. – mat

0

Я бы написать это следующим образом (с использованием ECLiPSe с library(ic)):

:- lib(ic). 
:- lib(ic_global). 

constraint(Xs, Ys, N) :- 
    Xs #:: 0..1, 
    Ys #:: 0..1, 
    sum(Xs) + sum(Ys) #= N, 
    ordered(>=, Xs), 
    ordered(>=, Ys). 

который ГИ ves требуемые решения:

?- length(Xs,6), length(Ys,6), constraint(Xs,Ys,3), labeling(Xs), labeling(Ys). 
Xs = [0, 0, 0, 0, 0, 0] 
Ys = [1, 1, 1, 0, 0, 0] 
Yes (0.00s cpu, solution 1, maybe more) ? ; 
Xs = [1, 0, 0, 0, 0, 0] 
Ys = [1, 1, 0, 0, 0, 0] 
Yes (0.00s cpu, solution 2, maybe more) ? ; 
Xs = [1, 1, 0, 0, 0, 0] 
Ys = [1, 0, 0, 0, 0, 0] 
Yes (0.00s cpu, solution 3, maybe more) ? ; 
Xs = [1, 1, 1, 0, 0, 0] 
Ys = [0, 0, 0, 0, 0, 0] 
Yes (0.00s cpu, solution 4) 
+0

Очень элегантный, но он пропускает решения, такие как Xs = [0, 1, 1, 1, 1, 1] и Ys = [1, 1, 1, 0, 1, 1]. Вот почему я использовал '_' в спецификации. –

+0

Вы правы, я неправильно понял! – jschimpf

 Смежные вопросы

  • Нет связанных вопросов^_^