Optymalizacja systemów Laboratorium Sudoku autor: A. Gonczarek Cel zadania Celem zadania jest napisanie programu rozwiązującego Sudoku, formułując problem optymalizacji jako zadanie programowania binarnego. Rozwiązanie należy zaimplementować w środowisku MATLAB z użyciem funkcji z pakietu do optymalizacji. Zasady Sudoku Sudoku jest to łamigłówka polegająca na wypełnieniu kwadratowej planszy o wymiarach 9 9 liczbami od 1 do 9, gdzie część liczb została już wpisana. Przy czym w każdej kolumnie, każdym wierszu oraz w każdej komórce o wymiarach 3 3 (patrz rysunek 1) żadna z liczb od 1 do 9 nie może się powtarzać. Poniżej przedstawiono planszę do Sudoku, gdzie ponumerowano kolumny, wiersze oraz komórki 3 3. Rysunek 1: Plansza do Sudoku. Problem Sudoku jako programowanie binarne Niech X oznacza trójwymiarowy tensor o wymiarach 9 9 9, gdzie każdy jego element przyjmuje jedynie binarne wartości, tj. x ijk {0, 1}. Przyjmijmy konwencję, że jeśli, to znaczy, że w i-tym wierszu i j-tej kolumnie na planszy stoi cyfra k. Ponadto załóżmy, że I oznacza zbiór trójek (i, j, k) informujących o tym, że w i-tym wierszu i j-tej kolumnie została na stałe wpisana cyfra k. 1
Wtedy problem Sudoku można przedstawić jako następujący problem programowania binarnego: minimalizuj (po X) 0 przy ograniczeniach: i,k j=1 j,k i=1 u,v {0,3,6} k 3 3 x i+u,j+v,k = 1 i=1 j=1 i,j k=1 (i,j,k) I Problem programowania binarnego można rozwiązać z użyciem algorytmu Branch & Bound, który omówiony zostanie w trakcie zajęć. Dla problemu programowania binarnego domyślnie można go wywołać poprzez użycie komendy: [x val flag] = bintprog(f,[],[],a,b). lub [x val flag] = intlinprog(f,1:numvars,a,b) Wybór funkcji determinowany jest tutaj wersją środowiska Matlab. Funkcja intlinprog została wprowadzona w wersji 2014a i wymaga podania dodatkowego argumentu, określającego indeksy zmiennych optymalizowanych z dziedzinie liczb całkowitych. Wywołanie tego algorytmu należy zaimplementować w pliku solve sudoku.m. Ograniczenia równościowe muszą być podane do algorytmu w formie macierzowej Ax = b, gdzie x jest wektorem zmiennych decyzyjnych utworzonym z trójwymiarowego tensora X. Trójwymiarowy tensor można zamienić na wektor kolumnowy stosując w Matlabie następujące polecenie: x = X(:). Każde z ograniczeń (wiersze w macierzy A) złożone jest wyłącznie z zer i jedynek, gdzie jedynka pojawia się wtedy, jeśli odpowiadająca jej zmienna decyzyjna w x jest sumowana w danym ograniczeniu. Dlatego ograniczenia łatwiej jest tworzyć jako trójwymiarowe tensory analogiczne do X, a następnie zamieniać je na wiersze macierzy A, stosując wyżej wspomniane polecenie. Poniżej omówiono wszystkie ograniczenia w modelu. 1. Pierwszy zestaw ograniczeń gwarantuje, że w każdym wierszu każda cyfra stoi dokładnie raz. Ograniczenia należy zaimplementować w pliku row const.m. Aby automatyczny walidator 2
zadziałał, ograniczenia należy wprowadzić w kolejności numerowania wierszy (rysunek 1), gdzie dla każdego wiersza należy wprowadzić 9 ograniczeń odpowiadających kolejno cyfrom 2. Drugi zestaw ograniczeń gwarantuje, że w każdej kolumnie każda cyfra stoi dokładnie raz. Ograniczenia należy zaimplementować w pliku column const.m. Aby automatyczny walidator zadziałał, ograniczenia należy wprowadzić w kolejności numerowania kolumn (rysunek 1), gdzie dla każdej kolumny należy wprowadzić 9 ograniczeń odpowiadających kolejno cyfrom 3. Trzeci zestaw ograniczeń gwarantuje, że w każdej komórce 3 3 każda cyfra stoi dokładnie raz. Ograniczenia należy zaimplementować w pliku cell const.m. Aby automatyczny walidator zadziałał, ograniczenia należy wprowadzić w kolejności numerowania komórek (rysunek 1), gdzie dla każdej komórki należy wprowadzić 9 ograniczeń odpowiadających kolejno cyfrom 4. Czwarty zestaw ograniczeń gwarantuje, że każdemu polu na planszy przypisana jest dokładnie jedna cyfra. Ograniczenia należy zaimplementować w pliku unique const.m. Aby automatyczny walidator zadziałał, ograniczenia należy wprowadzić w kolejności numerowania wierszy (rysunek 1), gdzie dla każdego wiersza należy wprowadzić 9 ograniczeń odpowiadających kolejnym polom w tym wierszu zgodnie z numeracją kolumn. 5. Ostatni zestaw ograniczeń gwarantuje, że w początkowo wypełnionych polach będą stały odpowiednie cyfry. Ograniczenia należy zaimplementować w pliku initial const.m. Aby automatyczny walidator zadziałał, ograniczenia należy wprowadzić w kolejności ich występowania w macierzy I, która jest argumentem tej funkcji. Na rysunku 2 przedstawiono przykładowe Sudoku przed i po rozwiązaniu przy pomocy programu. Zadanie do wykonania (5 pkt.) Po zaprezentowaniu działającego programu, prowadzący zadaje do kilku pytań kontrolnych mających na celu sprawdzenie poziomu zrozumienia zaimplementowanego w zadaniu kodu. Punkty są przyznawane wyłącznie na podstawie udzielonych odpowiedzi, co oznacza że samo zaimplementowanie kodu, bez jego zrozumienia, nie gwarantuje uzyskania punktów. 1. Wprowadzić własną macierz I inicjalizującą planszę do Sudoku w pliku my sudoku.m. 2. Zaimplementować wyliczenie ograniczeń na wiersze w pliku row const.m. 3
3. Zaimplementować wyliczenie ograniczeń na kolumny w pliku column const.m. 4. Zaimplementować wyliczenie ograniczeń na komórki w pliku cell const.m. 5. Zaimplementować wyliczenie ograniczeń na unikalność cyfr w polu w pliku unique const.m. 6. Zaimplementować wyliczenie ograniczeń na przypisanie początkowych pól w pliku initial const.m. 7. Zaimplementować rozwiązanie problemu Sudoku z użyciem programowania binarnego w pliku solve sudoku.m. UWAGA! Wszelkie nazwy funkcji i zmiennych w plikach *.m muszą pozostać zachowane. Zmiana jakichkolwiek nazw i dodanie fragmentów kodu poza wskazanymi miejscami skutkować będzie otrzymaniem 0 pkt. Rysunek 2: Plansza początkowa i rozwiązane Sudoku. Pytania kontrolne (5 pkt.) Prowadzący zadaje do kilku pytań kontrolnych osobie oddającej zadanie. Lista przykładowych pytań: 1. Co to jest problem programowania binarnego? Czym różni się on od problemu programowania liniowego? 2. Jaka jest interpretacja tensora zmiennych decyzyjnych X w powyższym zadaniu? Dlaczego jest on trójwymiarowy? 4
3. Ile jest binarnych zmiennych decyzyjnych w powyższym zadaniu? Oszacuj ile czasu zajęłoby zastosowanie przeglądu zupełnego (sprawdzenie wszystkich kombinacji zmiennych decyzyjnych) do znalezienia optymalnego rozwiązania. 4. Wytłumacz w jaki sposób zagwarantowane jest, że w każdym wierszu/kolumnie/komórce znajdą się różne cyfry. Które ograniczenia to zapewniają? Ile jest tych ograniczeń? 5. Wytłumacz do czego służy czwarty zestaw ograniczeń. Co mogłoby się stać z rozwiązaniem problemu, jeśli usunęlibyśmy te ograniczenia? 6. Wytłumacz w jaki sposób ustawia się początkowe pola tak, by pozostały one niezmienione w końcowym rozwiązaniu? Które ograniczenia to zapewniają? Ile jest tych ograniczeń? 7. Podaj ogólną ideę działania algorytmu Branch & Bound. Do jakich problemów się go stosuje? Czy algorytm znajduje zawsze rozwiązanie optymalne? 8. Co to jest relaksacja do problemu programowania liniowego? Po co się ją wykonuje w algorytmie Branch & Bound? Jaka jest relacja pomiędzy optymalnymi wartościami funkcji celu w problemie wyjściowym i zrelaksowanym? 9. Czy do sformułowanego w zadaniu problemu Sudoku da się bezpośrednio zastosować algorytm Interior-Point? Odpowiedź uzasadnij. 10. Dlaczego jeśli zmniejszymy liczbę początkowo wprowadzonych wartości do zbioru I, to czas rozwiązania istotnie się wydłuży? 5