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