wykład z dnia 12.01.2016

Transkrypt

wykład z dnia 12.01.2016
Adam Meissner © 2017
Instytut Automatyki i Inżynierii Informatycznej
Politechniki Poznańskiej
Adam Meissner
[email protected]
http://www.man.poznan.pl/~ameis
PROGRAMOWANIE WIELOPARADYGMATOWE
Wykład 3
Programowanie w paradygmacie CP(FD)
Literatura
[1] Apt K.R., Principles of Constraint Programming,
Cambridge Univ. Press, 2003.
[2] Niederliński A., Programowanie w logice z ograniczeniami. Łagodne wprowadzenie dla platformy ECLiPSe, Wyd. Pracowni Komputerowej Jacka Skalmierskiego, Gliwice, 2014
[3] Van Roy P., Haridi S., Concepts, Techniques, and
Models of Computer Programming, The MIT Press,
Cambridge, USA, 2004.
[4] Smolka G., Schulte Ch., Finite Domain Constraint
Programming in Oz. A Tutorial, Mozart Consortium,
2008.
1
Adam Meissner © 2017
Paradygmat CP(FD) (1)
Skrypty z parametrami
Problemy CSP są w wielu przypadkach skalowalne. Do ich reprezentowania wykorzystuje się
skrypty z parametrami o postaci zgodnej z poniższym schematem
fun {Name N1 ... Nn}
...
proc {$ Sol}
...
end
end
Przykład 3.1 (wg [4], problem N-hetmanów)
Sformułowanie problemu
Na szachownicy o wymiarze N ´ N należy rozmieścić N hetmanów w taki sposób, aby żadne dwa hetmany nie szachowały się wzajemnie.
Elementy modelu problemu
Ciąg hetmanów reprezentuje się jako N-elementową listę
liczb, której element R(i) odpowiada hetmanowi w i-tej kolumnie i w R(i)-tym wierszu dla i = 1,… , n. Warunek, aby dowolne dwa hetmany, tj. R(i) oraz R(j) nie leżały na jednej
przekątnej wyraża się jako
R(i) + (j - i)  R(j) oraz R(i) - (j - i)  R(j) dla 1  i < j  n
lub równoważnie, aby ciągi
R(1) - 1, …, R(N) - N oraz R(1) + 1, …, R(N) + N
były różnowartościowe
2
Adam Meissner © 2017
Paradygmat CP(FD) (2)
Przykład 3.1 (wg [4], c.d.)
Implementacja
fun {Queens N}
proc {$ Row}
L1N = {MakeTuple c N}
LM1N = {MakeTuple c N}
in
Row = {FD.tuple queens N 1#N}
{For 1 N 1 proc {$ I} L1N.I=I LM1N.I=~I end}
{FD.distinct Row}
{FD.distinctOffset Row L1N}
{FD.distinctOffset Row LM1N}
{FD.distribute
generic(order:size value:mid) Row}
end
end
Przykład 3.2 (wg [4])
Sformułowanie problemu
Dana jest pewna liczba monet o różnych nominałach.
Niech ai oznacza liczbę dostępnych monet o nominale
di dla i = 1, …, n. Wyznaczyć minimalną liczbę monet
niezbędną do wypłacenia kwoty A.
Elementy modelu problemu
Informację o dostępnych monetach reprezentuje rekord r(a1#d1 … an#dn). Rozwiązanie problemu reprezentuje ciąg liczb C(1), …, C(n) taki, że dla i = 1, …, n
element C(i) jest liczbą monet o nominale di, przy
czym 0  C(i)  ai.
3
Adam Meissner © 2017
Paradygmat CP(FD) (3)
Przykład 3.2 (wg [4], c.d.)
Implementacja
fun {ChangeMoney Coins Amount}
Avail = {Record.map Coins fun {$ A#_} A end}
Denom = {Record.map Coins fun {$ _#D} D end}
NbDenoms = {Width Denom}
in
proc {$ Change}
{FD.tuple change NbDenoms 0#Amount Change}
{For 1 NbDenoms 1 proc {$ I}
Change.I =<: Avail.I
end}
{FD.sumC Denom Change '=:' Amount}
{FD.distribute
generic(order:naive value:max) Change}
end
end
Optymalizacyjne problemy CSP
 do rozpatrywanej klasy należą problemy, z którymi wiąże się konieczność znalezienia rozwiązania najlepszego w zbiorze R wszystkich rozwiązań problemu
 w szczególności, optymalizacja może polegać na
minimalizowaniu funkcji ceny określonej na zbiorze R
 w niektórych (prostych) przypadkach minimalizację funkcji ceny można uzyskać poprzez zastosowanie 2-wymiarowej strategii dystrybucji
4
Adam Meissner © 2017
Paradygmat CP(FD) (4)
Przykład 3.3 (wg [4], kolorowanie mapy)
Sformułowanie problemu
Dana jest polityczna mapa Europy Zachodniej, na której widnieje Holandia, Belgia, Francja, Hiszpania, Portugalia, Niemcy, Luksemburg, Szwajcaria, Austria i
Włochy. Używając jak najmniejszej liczby kolorów pomalować mapę tak, aby żadne dwa kraje graniczące
ze sobą nie miały tej samej barwy.
Elementy modelu problemu
Rozwiązanie problemu reprezentuje rekord
color(r1:c1 … rn:cn) taki, że dla i = 1, …, n pole ri o
wartości ci oznacza kraj o nazwie ri i kolorze na mapie
wyrażonym przez liczbę ci; dziedziną zmiennej ci jest
zbiór 1#NbColors.
5
Adam Meissner © 2017
Paradygmat CP(FD) (5)
Przykład 3.3 (wg [4], c.d.)
Implementacja
Data =
[belgium
# [france netherlands germany
luxemburg]
germany
# [austria france luxemburg
netherlands]
switzerland # [italy france germany austria]
austria
# [italy switzerland germany]
france
# [spain luxemburg italy]
spain
# [portugal]
italy
# nil
luxemburg
# nil
netherlands # nil
portugal
# nil]
fun {MapColor Data}
Countries = {Map Data fun {$ C#_} C end}
in
proc {$ Color}
NbColors = {FD.decl}
in
{FD.distribute naive [NbColors]}
{FD.record color Countries 1#NbColors Color}
{ForAll Data
proc {$ A#Bs}
{ForAll Bs proc {$ B}
Color.A \=: Color.B
end}
end}
{FD.distribute ff Color}
end
end
6
Adam Meissner © 2017
Paradygmat CP(FD) (6)
Przykład 3.4 (wg [4], program konferencji)
Sformułowanie problemu
Ułożyć program (plan) konferencji w formie ciągu paneli. Konferencja składa się z 11 sesji a w każdym panelu może toczyć się równolegle do 3 sesji. Ponadto,
obowiązują następujące ograniczenia.
1.
2.
3.
4.
Sesja 4 musi odbyć się przed sesja 11.
Sesja 5 musi odbyć się przed sesja 10.
Sesja 6 musi odbyć się przed sesja 11.
Sesja 1 nie może toczyć się równolegle z sesjami 2,
3, 5, 7, 8 oraz 10
5. Sesja 2 nie może toczyć się równolegle z sesjami 3,
4, 7, 8, 9 oraz 11
6. Sesja 3 nie może toczyć się równolegle z sesjami 5,
6 oraz 8
7. Sesja 4 nie może toczyć się równolegle z sesjami 6,
8 oraz 10.
8. Sesja 6 nie może toczyć się równolegle z sesjami 7
oraz 10
9. Sesja 7 nie może toczyć się równolegle z sesjami 8
oraz 9
10.Sesja 8 nie może toczyć się równolegle z sesją 10
Znaleźć rozwiązanie o minimalnej liczbie paneli
7
Adam Meissner © 2017
Paradygmat CP(FD) (7)
Przykład 3.4 (wg [4], c.d.)
Elementy modelu problemu
Do reprezentowania liczby paneli służy zmienna NbSlots::4#11.
Rozwiązanie ma postać krotki plan(p1 ... p11)takiej, że element
pi dla i = 1, ..., n oznacza panel, w którym odbywa się i-ta sesja; dla
każdego i, pi :: 1#NbSlots.
Implementacja
fun {Conference Data}
NbSessions
= Data.nbSessions
NbParSessions = Data.nbParSessions
Constraints
= Data.constraints
MinNbSlots
= NbSessions div NbParSessions
in
proc {$ Plan}
NbSlots = {FD.int MinNbSlots#NbSessions}
in
{FD.distribute naive [NbSlots]}
{FD.tuple plan NbSessions 1#NbSlots Plan}
{For 1 NbSlots 1
proc {$ Slot}
{FD.atMost NbParSessions Plan Slot}
end}
{ForAll Constraints
proc {$ C}
case C of
before(X Y) then Plan.X <: Plan.Y
[] disjoint(X Ys) then
{ForAll Ys
proc {$ Y}
Plan.X \=: Plan.Y
end}
end
end}
{FD.distribute ff Plan}
end
end
8
Adam Meissner © 2017
Paradygmat CP(FD) (8)
Przykład 3.4 (wg [4], c.d.)
Data = data(nbSessions: 11
nbParSessions: 3
constraints: [before(4 11)
before(5 10)
before(6 11)
disjoint(1 [2 3 5 7 8 10])
disjoint(2 [3 4 7 8 9 11])
disjoint(3 [5 6 8])
disjoint(4 [6 8 10])
disjoint(6 [7 10])
disjoint(7 [8 9])
disjoint(8 [10]) ])
Ograniczenia nadmiarowe (redundantne)
Niech P oraz S będą zbiorami ograniczeń, zbiór S
jest redundantny względem P, jeżeli S jest konsekwencją logiczną P; przykładowo, zbiór ograniczeń
{X<:10} jest redundantny względem zbioru {X<:5}.
Wprowadzenie odpowiednich ograniczeń redundantnych może zmniejszyć drzewo poszukiwań, jak
również zredukować liczbę kroków propagacji wykonywanych w przestrzeniach obliczeń.
Przykład 3.5 (wg [4], ułamki)
Sformułowanie problemu
Znaleźć przypisanie cyfr różnych od 0 do liter występujących w poniższym wyrażeniu tak, aby uzyskać poprawne wyrażenie arytmetyczne
(A / BC) + (D / EF) + (G/HI) = 1
9
Adam Meissner © 2017
Paradygmat CP(FD) (9)
Przykład 3.5 (wg [4], c.d.)
Elementy modelu problemu
W celu usunięcia rozwiązań symetrycznych, wprowadza się następujący porządek na wartościowania
zmiennych:
(A / BC)  (D / EF)  (G/HI).
Na tej podstawie można sformułować następujące
ograniczenia redundantne:
3 * (A / BC)  1 oraz 3 * (G/HI)  1
Implementacja
proc {Fraction Root}
sol(a:A b:B c:C d:D e:E f:F g:G h:H i:I) = Root
BC = {FD.decl}
EF = {FD.decl}
HI = {FD.decl}
in
Root ::: 1#9
{FD.distinct Root}
BC =: 10*B + C
EF =: 10*E + F
HI =: 10*H + I
A*EF*HI + D*BC*HI + G*BC*EF =: BC*EF*HI
A*EF >=: D*BC
D*HI >=: G*EF
3*A >=: BC
3*G =<: HI
{FD.distribute split Root}
end
10
Adam Meissner © 2017
Paradygmat CP(FD) (10)
Przykład 3.6 (wg [4], liczby Pitagorasa)
Sformułowanie problemu
Wyznaczyć liczbę trójek (A, B, C), takich że A  B 
C  1000 i A2 + B2 = C2.
Elementy modelu problemu
Do reprezentowania liczb Pitagorasa służą zmienne
A, B, C; dziedziną początkową każdej z nich jest zbiór
1#1000. Z ograniczenia A2 + B2 = C2 można wyprowadzić następujące ograniczenie redundantne:
2 * B2  C2
Implementacja
proc {Pythagoras Root}
[A B C] = Root
AA BB CC
in
Root ::: 1#1000
AA = {FD.times A A}
BB = {FD.times B B}
CC = {FD.times C C}
AA + BB =: CC
A =<: B
B =<: C
% ograniczenie nadmiarowe
2*BB >=: CC
{FD.distribute ff Root}
end
11
Adam Meissner © 2017
Paradygmat CP(FD) (11)
Przykład 3.7 (wg [4], kwadraty magiczne)
Sformułowanie problemu
Kwadratem magicznym rzędu N nazywa się
macierz N ´ N zawierającą liczby naturalne z
przedziału [1, N2], ułożone tak aby suma
elementów w każdym wierszu i w każdej kolumnie
oraz na obu przekątnych gł. była taka sama (jest to
tzw. suma magiczna). Przykładowo, poniższa
macierz jest kwadratem magicznym rzędu 3.
2
9
4
7
5
3
6
1
8
Elementy modelu problemu
Do reprezentowania elementu (i, j) kwadratu używa
się zmiennej Fi,j, a zmienna S oznacza sumę magiczną. Obowiązują następujące ograniczenia.
F1,1 < FN,N,
FN,1 < F1,N, F1,1 < FN,1
0.5 * N2 * (N2 + 1) = S * N
12
(elim. symetrii)
(ogr. redundantne)
Adam Meissner © 2017
Paradygmat CP(FD) (12)
Przykład 3.7 (wg [4], c.d.)
Implementacja
fun {MagicSquare N}
NN = N*N
L1N = {List.number 1 N 1} % [1 2 3 ... N]
in
proc {$ Square}
fun {Field I J}
Square.((I-1)*N + J)
end
proc {Assert F}
%% {F 1} + {F 2} + ... + {F N} =: Sum
{FD.sum {Map L1N F} '=:' Sum}
end
Sum = {FD.decl}
in
{FD.tuple square NN 1#NN Square}
{FD.distinct Square}
%% Przekątne
{Assert fun {$ I} {Field I I} end}
{Assert fun {$ I} {Field I N+1-I} end}
%% Wiersze
{For 1 N 1
proc {$ I} {Assert fun {$ J} {Field I J} end} end}
%% Kolumny
{For 1 N 1
proc {$ J} {Assert fun {$ I} {Field I J} end} end}
%% Eliminacja symetrii
{Field 1 1} <: {Field N N}
{Field N 1} <: {Field 1 N}
{Field 1 1} <: {Field N 1}
%% Ogr.nadm.: suma pól = (liczba wierszy) * Sum
NN*(NN+1) div 2 =: N*Sum
{FD.distribute split Square}
end
end
13
Adam Meissner © 2017
Paradygmat CP(FD) (13)
Ograniczenia reifikowane
 ograniczenia reifikowane są przeznaczone do
wyrażania więzów, w których wykorzystuje się
symbole logiczne, takie jak alternatywa, negacja
czy implikacja
 reifikacją ograniczenia C ze względu na zmienną
x nazywa się ograniczenie:
(C « x = 1)  x Î 0#1
i x nie występuje jako zmienna wolna w C
 semantyka operacyjna propagatora będącego reifikacją ograniczenia C ze względu na zmienną x:
1) jeżeli ogr. x = 1 jest nadmiarowe w danym
składzie więzów, to ogr. reifikowane redukuje
się do C;
2) jeżeli ogr. x = 0 jest nadmiarowe w danym
składzie więzów, to ogr. reifikowane redukuje
się do  C;
3) jeżeli propagator dla ogr. reifikowanego jest
nadmiarowy w danym składzie więzów, to do
składu wprowadza się ogr. x = 1 i propagator
zostaje usunięty;
4) jeżeli propagator dla ogr. reifikowanego jest
sprzeczny z danym składem więzów, to do
składu wprowadza się ogr. x = 0 i propagator
zostaje usunięty.
14
Adam Meissner © 2017
Paradygmat CP(FD) (14)
Ograniczenia reifikowane (c.d.)
 ograniczenie będące reifikacją ograniczenia C ze
względu na zmienna x intuicyjnie wyraża to, że
formuła C jest prawdziwa wtw gdy x ma wartość
1 a fałszywa wtw gdy x ma wartość 0
 przykładowo, poniższa formuła wyraża równoważność dwóch ograniczeń
X<Y « X<Z
formułę tę można wyrazić za pomocą poniższych
ograniczeń reifikowanych
X <: Y = B
X <: Z = B
Przykład 3.8 (wg [4], ustawianie do zdjęcia)
Sformułowanie problemu
Beata, Krzyś, Donald, Franek, Grześ, Maria i Paweł
ustawiają się w jednym rzędzie do zdjęcia. Mają przy
tym następujące oczekiwania.
1.
2.
3.
4.
Beata chce stać między Grzesiem a Marią
Krzyś chce stać między Beatą a Grzesiem
Franek chce stać między Marią a Donaldem
Paweł chce stać między Frankiem a Donaldem
Znaleźć ustawienie, spełniające możliwie jak największą liczbę oczekiwań fotografowanych osób.
15
Adam Meissner © 2017
Paradygmat CP(FD) (15)
Przykład 3.8 (wg [4], c.d.)
Elementy modelu problemu
Do reprezentowania położenia osoby p w rzędzie służy zmienna AP Î 1#7. Zmienna Si Î 0#1 ma wartość
1 wtw i-ta preferencja jest spełniona. Ściślej ujmując,
ograniczenie wyrażające fakt, że osoba AP chce stać
obok AQ osoby ma postać formuły
(|AP - AQ| = 1 « S = 1)  S Î 0#1
Rozwiązanie problemu polega na znalezieniu maksymalnej wartości zmiennej Sat, takiej że
Sat = S1 + … + S8
Implementacja
proc {Photo Root}
Persons = [beata krzys donald franek grzes maria pawel]
Preferences = [beata#grzes beata#maria krzys#beata
krzys#grzes franek#maria franek#donald
pawel#franek pawel#donald]
NbPersons = {Length Persons}
Alignment = {FD.record alignment Persons 1#NbPersons}
Sat = {FD.decl}
proc {Satisfied P#Q S}
{FD.reified.distance Alignment.P Alignment.Q '=:' 1 S}
end
in
Root = Sat#Alignment
{FD.distinct Alignment}
{FD.sum {Map Preferences Satisfied} '=:' Sat}
Alignment.franek <: Alignment.beata
% elim. symetr.
{FD.distribute generic(order:naive value:max) [Sat]}
{FD.distribute split Alignment}
end
16
Adam Meissner © 2017
Paradygmat CP(FD) (16)
Przykład 3.9 (wg [4], autoreferencyjny test wyboru)
Sformułowanie problemu
Dany jest test wyboru składający się z 10-ciu pytań. Na każde z
nich formułuje się 5 możliwych odpowiedzi (numerowanych od a
do e), z których dokładnie 1 jest poprawna. Znaleźć odpowiedzi
poprawne, spełniające wszystkie warunki podane w pytaniach.
1. Pierwszym pytaniem, na które odpowiedź brzmi b jest pytanie: (a) 2, (b) 3, (c) 4, (d) 5, (e) 6.
2. Jedyną parą sąsiadujących ze sobą pytań o identycznym numerze odpowiedzi są pytania: (a) 2-3, (b) 3-4, (c) 4-5,
(d) 5-6, (e) 6-7.
3. Odpowiedź na niniejsze pytanie jest taka sama jak odpowiedź na pytanie: (a) 1, (b) 2, (c) 4, (d) 7, (e) 6.
4. Liczba pytanie, na które odpowiedź brzmi a wynosi: (a) 0,
(b) 1, (c) 2, (d) 3, (e) 4.
5. Odpowiedź na niniejsze pytanie jest taka sama jak odpowiedź na pytanie: (a) 10, (b) 9, (c) 8, (d) 7, (e) 6.
6. Liczba pytań, na które odpowiedź brzmi a jest równa liczbie
pytań, na które odpowiedź brzmi: (a) b, (b) c, (c) d, (d) e, (e)
żadnej z wymienionych.
7. Alfabetyczna odległość odpowiedzi na pytanie niniejsze i następne wynosi: (a) 4, (b) 3, (c) 2, (d) 1, (e) 0.
8. Liczba pytań o odpowiedziach oznaczonych samogłoskami
wynosi: (a) 2, (b) 3, (c) 4, (d) 5, (e) 6.
9. Liczba odpowiedzi oznaczonych spółgłoskami jest: (a) liczbą
pierwszą, (b) silnią pewnej liczby, (c) kwadratem, (d) sześcianem , (e) jest podzielna całkowicie przez 5.
10.Odpowiedzią na niniejsze pytanie jest: (a) a, (b) b, (c) c,
(d) d, (e) e.
17
Adam Meissner © 2017
Paradygmat CP(FD) (17)
Przykład 3.9 (wg [4], c.d.)
Uwaga, problem ma tylko 1 następujące rozwiązanie:
1:c 2:d 3:e 4:b 5:e 6:e 7:d 8:c 9:b 10:a
Elementy modelu problemu
W modelu wykorzystuje się zmienne Ai, Bi, …, Ei o dziedzinach
0#1 dla i Î 1#10. Każda ze zmiennych ma wartość 1 wtw odpowiedzią na i-te pytanie jest litera będąca nazwą zmiennej. Wiadomo, że Ai + Bi + … + Ei = 1. Dodatkowo wprowadza się
zmienne Qi dla o dziedzinach 1#5 dla i Î 1#10, takie że
Qi = 1 « Ai =1 Qi = 2 « Bi =1 Qi = 3 « Ci =1
Qi = 4 « Di =1
Qi = 5 « Ei =1
Ograniczenia reprezentujące warunek 1
A1 = B2
B1 = (B3  (B2 = 0))
C1 = (B4  (B2 + B3 = 0))
D1 = (B5  (B2 + B3 + B4 = 0))
E1 = (B6  (B2 + B3 + B4 + B5 = 0))
Ograniczenia reprezentujące warunek 2
Q1  Q2, Q7  Q8, Q8  Q9, Q9  Q10,
A2 = (Q2 = Q3), B2 = (Q3 = Q4), C2 = (Q4 = Q5),
D2 = (Q5 = Q6), E2 = (Q6 = Q7)
Ograniczenia reprezentujące warunek 3
A3 = (Q1 = Q3), B3 = (Q2 = Q3), C3 = (Q3 = Q4),
D3 = (Q7 = Q3), E3 = (Q6 = Q3)
18
Adam Meissner © 2017
Paradygmat CP(FD) (18)
Przykład 3.9 (wg [4], c.d.)
Ograniczenia reprezentujące warunek 4
element(Q4, (0, 1, 2, 3, 4)) = A1 + A2 + … + A10
Ograniczenia reprezentujące warunek 9
S = (B1 + C1 + D1) + …+(B10 + C10 + D10)
A9 = (S Î {2, 3, 5, 7})
B9 = (S Î {1, 2, 6})
C9 = (S Î {0, 1, 4, 9})
D9 = (S Î {0, 1, 8})
E9 = (S Î {0, 5, 10})
Implementacja
proc {SRAT Q}
proc {Vector V}
{FD.tuple v 10 0#1 V}
end
proc {Sum V S}
{FD.decl S}
{FD.sum V '=:' S}
end
proc {Assert I [U V W X Y]}
A.I=U B.I=V C.I=W D.I=X E.I=Y
end
A = {Vector} B = {Vector} C = {Vector} D = {Vector} E = {Vector}
SumA ={Sum A} SumB = {Sum B} SumC = {Sum C} SumD = {Sum D}
SumE = {Sum E} SumAE = {Sum [SumA SumE]} SumBCD = {Sum [SumB SumC SumD]}
in
{FD.tuple q 10 1#5 Q}
{For 1 10 1
proc {$ I} {Assert I [Q.I=:1 Q.I=:2 Q.I=:3 Q.I=:4 Q.I=:5]} end}
%% 1
{Assert 1 [ B.2
{FD.conj B.3 (B.2=:0)}
{FD.conj B.4 (B.2+B.3=:0)}
{FD.conj B.5 (B.2+B.3+B.4=:0)}
{FD.conj B.6 (B.2+B.3+B.4+B.5=:0)} ]}
19
Adam Meissner © 2017
Paradygmat CP(FD) (19)
Przykład 3.9 (wg [4], c.d.)
%% 2
{Assert 2 [Q.2=:Q.3 Q.3=:Q.4 Q.4=:Q.5 Q.5=:Q.6 Q.6=:Q.7]}
Q.1\=:Q.2 Q.7\=:Q.8 Q.8\=:Q.9 Q.9\=:Q.10
%% 3
{Assert 3 [Q.1=:Q.3 Q.2=:Q.3 Q.4=:Q.3 Q.7=:Q.3 Q.6=:Q.3]}
%% 4
{FD.element Q.4 [0 1 2 3 4] SumA}
%% 5
{Assert 5 [Q.10=:Q.5 Q.9=:Q.5 Q.8=:Q.5 Q.7=:Q.5 Q.6=:Q.5]}
%% 6
{Assert 6 [SumA=:SumB SumA=:SumC SumA=:SumD SumA=:SumE _]}
%% 7
{FD.element Q.7 [4 3 2 1 0] {FD.decl}={FD.distance Q.7 Q.8 '=:'}}
%% 8
{FD.element Q.8 [2 3 4 5 6] SumAE}
%% 9
{Assert 9 [SumBCD::[2 3 5 7] SumBCD::[1 2 6]
SumBCD::[0 1 4 9]
SumBCD::[0 1 8]
SumBCD::[0 5 10] ]}
%% 10
skip
{FD.distribute ff Q}
end
20

Podobne dokumenty