2014-12-12 3 views
4

Я разрабатываю программу в PROLOG (с ограничениями), которая должна выводить комбинацию из 6 номеров в пределах определенных ограничений.Создание комбинаций чисел в списке пролог

В списке должно быть номера от 1 до 4 и, следовательно, повторить 2 других номера. Это не возможно не иметь число от 1 до 4.

Possible examples:  Wrong examples: 
1,2,3,4,1,1   1,2,3,2,3,3 //Missing #4 
1,3,2,1,4,4   4,3,2,4,2,3 //Missing #1 
1,2,3,3,2,4 
4,1,3,2,1,4 

Для того, чтобы это сделать, я создал некоторые ограничения, такие как следующие:

Numbers = [A1, A2, A3, A4, A5, A6] 
nCr(6,4) = 15 restrictions 
A1 =\= A2 =\= A3 =\= A4 OR 
A1 =\= A2 =\= A3 =\= A5 OR 
Etc. 

Вот код, который я до сих пор:

make 

pred(Numbers) :- 

     Numbers = [A1, A2, A3, A4, A5, A6], 
     domain(Numbers, 1, 4), 

     %restrictions 
     all_different([A1,A2,A6,A3]) #\/ %A1 =/= A2 =/= A6 =/= A3 
     all_different([A1,A2,A6,A4]) #\/ %A1 =/= A2 =/= A6 =/= A4 
     all_different([A1,A2,A6,A5]) #\/ %A1 =/= A2 =/= A6 =/= A5 
      all_different([A1,A2,A3,A4]) #\/ %A1 =/= A2 =/= A3 =/= A4 
      all_different([A1,A2,A3,A5]) #\/ %A1 =/= A2 =/= A3 =/= A5 
      all_different([A1,A2,A4,A5]) #\/ %A1 =/= A2 =/= A4 =/= A5 
      all_different([A1,A6,A3,A4]) #\/ %A1 =/= A6 =/= A3 =/= A4 
       all_different([A1,A6,A3,A5]) #\/ %A1 =/= A6 =/= A3 =/= A5 
       all_different([A1,A6,A4,A5]) #\/ %A1 =/= A6 =/= A4 =/= A5 
       all_different([A1,A3,A5,A4]) #\/ %A1 =/= A3 =/= A4 =/= A5 
       all_different([A2,A6,A3,A4]) #\/ %A2 =/= A6 =/= A3 =/= A4 
        all_different([A2,A6,A3,A5]) #\/ %A2 =/= A6 =/= A3 =/= A5 
        all_different([A2,A6,A4,A5]) #\/ %A2 =/= A6 =/= A4 =/= A5 
        all_different([A2,A3,A4,A5]) #\/ %A2 =/= A3 =/= A4 =/= A5 
        all_different([A6,A3,A4,A5]), %A6 =/= A3 =/= A4 =/= A5 

      labeling([], Numbers). 

Логика кажется прекрасной для меня, но эта реализация не работает так, как она пакетирования. Есть нет решений которые соответствуют введенным ограничениям. Может ли кто-нибудь дать мне руку?

| ?- pred([A1, A2, A3, A4, A5, A6]). 
no 
+0

Попробуйте выразить ограничения на более высоком уровне. Как вы их написали, это действительно нечитаемо ... – CapelliC

+0

Это подзадача, которую я пытаюсь решить, чтобы разработать большую программу, вот почему код еще не очень хорош. В любом случае, я внес некоторые изменения. – Khabz

+0

@Khabz: Когда вы говорите об «ограничениях», может быть, вы имеете в виду ограничения? По крайней мере, это то, что я считаю истинным, глядя на ваши программы. – false

ответ

5

этот запрос должен удовлетворить ваши требования

?- Vs = [_,_,_,_,_,_], Vs ins 1..4, 
    [A,B,C,D] ins 1..2, global_cardinality(Vs, [1-A,2-B,3-C,4-D]), label(Vs). 
Vs = [1, 1, 2, 2, 3, 4], 
A = B, B = 2, 
C = D, D = 1 ; 
Vs = [1, 1, 2, 2, 4, 3], 
A = B, B = 2, 
C = D, D = 1 ; 
... 
+0

Это решило мою проблему, tyvm! – Khabz

+0

Мне все еще интересно, почему мое решение не работает. Это кажется логичным. – Khabz

+0

plus unum! taceo nunc! – false

1

Пожалуйста, обратите внимание на более декларативный стиль программирования. Альтернативное решение будет следующим:

pred(NumberList) :- 
    NumberList =[_,_,_,_,_,_], 
    member(1, NumberList), 
    member(2, NumberList), 
    member(3, NumberList), 
    member(4, NumberList), 
    member(A, [1,2,3,4]), 
    member(B, [1,2,3,4]), 
    member(A, NumberList), 
    member(B, NumberList), 
    forall(member(X, NumberList), number(X)). 

В этом разделе говорится, что:

  • список должен иметь длину 6 элементов
  • 1, 2, 3, 4 представляют собой все элементы список
  • может быть другая часть 1,2,3,4 части
  • и все члены должны быть числами.

Причина, по которой FORALL необходимо, является то, что в противном случае решения, такие как [1,2,3,4, ,] будет удовлетворять PRED предикат.

Последнее примечание: «pred» не является правильным именем для такого предиката.

+2

forall/2 и number/1 являются декларативными? – false

+0

Этот алгоритм также пришел мне на ум (+1 для его реализации), но CapelliC кажется лучшим решением. Кроме того, это скопированный код с несколькими изменениями, имена в оригинале не являются случайными вообще. – Khabz

1

Вот два альтернативных запросы, использующие clpfd ограничения:

  1. Использование nvalue/2 ограничения, доступные с SICStus Прологом:

    ?- Vs = [_,_,_,_,_,_], domain(Vs,1,4), 
        nvalue(4,Vs), 
        labeling([],Vs). 
    
  2. Использование element/3 ограничения, на clpfd родственных из nth1/3 и member/2:

    ?- Vs = [_,_,_,_,_,_], domain(Vs,1,4), 
        element(_,Vs,1),element(_,Vs,2),element(_,Vs,3),element(_,Vs,4), 
        labeling([],Vs). 
    

Оба запроса дают ту же последовательность решения:

Vs = [1,1,1,2,3,4] ? ; 
Vs = [1,1,1,2,4,3] ? ; 
Vs = [1,1,1,3,2,4] ? ; 
Vs = [1,1,1,3,4,2] ? ; 
Vs = [1,1,1,4,2,3] ? ; 
Vs = [1,1,1,4,3,2] ? ... 

Приведенный выше список включает только первые несколько результатов, Есть 1560 в общей сложности.

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