====== Lab CSP: Podstawowe problemy ====== W ramach laboratorium będziemy rozwiązywać standardowe problemy pojawiające się w literaturze dotyczącej programowania z ograniczeniami. Zaprogramowane modele będą następnie ulepszane poprzez stosowanie podstawowych technik modelowania w CSP. ===== Rozgrzewka ===== ==== Problem n-hetmanów ==== * Treść problemu: w jaki sposób na szachownicy o wymiarach nxn umieścić n hetmanów w taki sposób, by żaden z nich nie mógł zbić innego w jednym ruchu (patrz: [[http://pl.wikipedia.org/wiki/Problem_o%C5%9Bmiu_hetman%C3%B3w|wikipedia]]). * Ćwiczenia: - Proszę uzupełnić poniższy model problemu n-hetmanów %%%%%%%%%%%%% % DZIEDZINA % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % miejsce na dziedzinę % % podpowiedź: % % var 1..N: x; deklaruje zmienną % % o dziedzinie 1..N; % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%% % OGRANICZENIA % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % miejsce na ograniczenia % % podpowiedź: % % row_i = row_j (-/+) (j - i) % % opisuje hetmanów stojących na % % tej samej diagonali, gdzie: % % - i,j - numery kolumn % % - row_n - pozycja hetmana w n-tej kolumnie % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% solve satisfy; %%%%%%%%%%%%%%%%%%%%%%%% % PRZYKŁADOWE WYJŚCIE % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % - rows[i] pozycja hetmana w i-tym wierszu % % - N - liczba hetmanów % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% output [ if fix(rows[j]) == i then "H" else "." endif ++ if j == N then "\n" else "" endif | i,j in 1..N] Przykładowe złożone wyrażenie agregujące:\\ ''forall([tablica[i,j] = z | i,j in 1..M, z in 1..N where j < i])''\\ lub równoważnie:\\ ''forall(i,j in 1..M, z in 1..N where j < i)(tablica[i,j] = z)'' ==== Kolorowanie grafów ==== * treść problemu: problem kolorowania grafu polega na przyporządkowaniu wierzchołkowom grafu odpowiednich kolorów tak, aby wierzchołki o wspólnej krawędzi miały różne kolory. W najgorszym przypadku (klika) będzie potrzebne tyle kolorów, ile jest wierzchołków. W przypadku grafu planarnego zawsze wystarczą cztery (sławny dowód matematyczny, warto sprawdzić, dlaczego). [[http://en.wikipedia.org/wiki/Four_color_theorem|Twierdzenie o czterech barwach]] [[http://en.wikipedia.org/wiki/Graph_coloring#Vertex_coloring|Kolorowanie na angielskim wiki]]. * Ćwiczenia: - Proszę uzupełnić poniższy model kolorowania grafu ({{:pl:dydaktyka:csp:csp_coloring_data.dzn.zip|przykładowe dane wejściowe}}): %%%%%%%%%%%%% % PARAMETRY % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Powinny być wczytane z pliku z danymi.% % Traktujmy graf jako tablicę booli % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%% % DZIEDZINA % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % miejsce na dziedzinę % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%% % OGRANICZENIA % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % miejsce na ograniczenia % % podpowiedź: % % - warto użyć if'a, by sprawdzić, czy dwa % % wierzchołki są połączone % % - liczba kolorów to może być maksymalny % % numer użytego koloru % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%% % CEL % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Zminimalizuj użytą liczbę kolorów % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% solve minimize coloursNumber; %%%%%%%%%%%%%%%%%%%%%%%% % PRZYKŁADOWE WYJŚCIE % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % - coloursNumber - liczba użytych kolorów % % - nodes - tablica wierzchołków grafu z % % ich kolorami % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% output [show(coloursNumber), " colours\n",] ++ [show(nodes[i]) ++ " " | i in 1..nodesNumber] Definicja tablicy dwuwymiarowej booli: array[1..2,1..3] of bool: bool_array = [|true, true, true | true, true, true|]; Konstrukcja warunkowa: if bool then val1 else val2 endif Operatory logiczne: /\ -- i, \/ -- lub, != -- różne, == -- równe ===== Globalne ograniczenia ===== Jedną z najprostszych metod tworzenia dobrego modelu w programowaniu z ograniczeniami jest korzystanie z gotowych globalnych ograniczeń. Dzięki wyspecjalizowanym algorytmom i implementacji są one w stanie lepiej wykorzystać informacje na temat struktury problemu od ograniczeń na pojedynczych zmiennych. Niektóre z globalnych ograniczeń są nawet w stanie zamodelować dynamiczne zachowanie systemu, np. ograniczenie ''cumulative'' uniemożliwia równoczesne wykorzystanie zasobu przez kilka zadań. W MiniZinc, aby korzystać z globalnego ograniczenia, należy je najpierw zaimportować, np. aby korzystać z ograniczenia ''cumulative'' należy wcześniej dopisać do kodu linijkę: include "cumulative.mzn"; ==== Sudoku ==== * Treść problemu: należy zaimplementować solver sudoku (patrz: [[http://pl.wikipedia.org/wiki/Sudoku|wikipedia]]) * Ćwiczenia: - Proszę uzupełnić poniższy model sudoku: %%%%%%%%%%%%%%%%% % PRZYPOMNIENIE % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Coś tu jeszcze powinno być.% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%% % DZIEDZINA % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % miejsce na dziedzinę, podpowiedź: % % dwie oddzielne tablice, jedna % % odpowiedzialna z stan początkowy; % % druga przechowuje zmienne decyzyjne% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%% % Ograniczenia % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % - constraint alldifferent(tablica zmiennych); % % globalne ograniczenie, w którym wszystkie % % zmienne z tablicy muszą mieć różną wartość % % - należy zapewnić, aby wartości zmiennych były % % równe odpowiednik polom stanu początkowego % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% solve satisfy; %%%%%%%%%%%%%%%%%%%%%%%% % PRZYKŁADOWE WYJŚCIE % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % - puzzle - dwuwumiarowa tablica zmiennych % % o rozmiarze NxN % % - N - rozmiar planszy, równy S*S % % - S - rozmiar sektora planszy % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% output [ show(puzzle[i,j]) ++ " " ++ if j mod S == 0 then " " else "" endif ++ if j == N /\ i != N then if i mod S == 0 then "\n\n" else "\n" endif else "" endif | i,j in PuzzleRange ] ++ ["\n"]; - Poniżej przykładowe dane wejściowe: % 0 to pola o nieznanej wartości board = array2d(1..9, 1..9, [ 0, 0, 0, 2, 0, 5, 0, 0, 0, 0, 9, 0, 0, 0, 0, 7, 3, 0, 0, 0, 2, 0, 0, 9, 0, 6, 0, 2, 0, 0, 0, 0, 0, 4, 0, 9, 0, 0, 0, 0, 7, 0, 0, 0, 0, 6, 0, 9, 0, 0, 0, 0, 0, 1, 0, 8, 0, 4, 0, 0, 1, 0, 0, 0, 6, 3, 0, 0, 0, 0, 8, 0, 0, 0, 0, 6, 0, 8, 0, 0, 0 ]); - Proszę zastosować globalne ograniczenia do problemu n-hetmanów Lista globalnych ograniczeń dostępnych w MiniZinc: http://www.minizinc.org/downloads/doc-latest/mzn-globals.html ==== Zadanie Dodatkowe: Magiczne ciągi ==== * Treść problemu: magicznym ciągiem nazywamy taki ciąg liczb ''x0, x1, x2,.., xN'' w którym wartość ''xi'' dla dowolnego ''i'' jest równa liczbie wystąpień ''i'' w tym ciągu. Przykładowy magiczny ciąg o długości 5 to ''2, 1, 2, 0, 0'' --- na ''0''-wym miejscu znajduje się liczba wszystkich ''0'' w ciągu, na miejscu o indeksie ''1'' liczba ''1'' w ciągu, etc. * Ćwiczenia: - Zamodelować znajdywanie magicznych ciągów o zadanej długości w MiniZinc. - Zastosować globalne ograniczenia. %%%%%%%%%%%%% % DZIEDZINA % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % miejsce na dziedzinę % % - parametr określający długość ciągu % % - tablica zmiennych decyzyjnych % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%% % Ograniczenia % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Podpowiedzi: % % - sum(wyrażenie tablicowe) sumuje elementy % % - bool2int(5==5) da w wyniku 1 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% solve satisfy; %%%%%%%%%%%%%%%%%%%%%%%% % PRZYKŁADOWE WYJŚCIE % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % - magic - magiczny ciąg % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% output [ "magiczny ciag = ", show(magic),";\n"];