Programowanie lokalnych aplikacji.net 2018/19 Instrukcja projektowa cz. 2 Wielozadaniowość w Windows Prowadzący: Tomasz Goluch Wersja: 7.0
I. Zadania projektowe 02. Cel: Utrwalenie wiedzy zdobytej podczas wykładu. Zadanie projektowe z przetwarzania wielowątkowego polega na napisaniu programu służącego do wyświetlania GUI (WPF) pozwalającego na wprowadzenie ustawień początkowych, uruchomienie obliczeń równoległych w nowym procesie oraz ich zakończenie, a także na wyświetlanie na bieżąco najlepszego aktualnie znalezionego rozwiązania. Jak łatwo wywnioskować drugi program/proces będzie pracował w trybie konsolowym i jego głównym zadaniem będzie prowadzenie obliczeń równoległych z wykorzystaniem puli zadań i/lub wątków. Ogólnie rzecz biorąc zadanie polega na optymalizacji narodowego problemu komiwojażera (ang. NTSP - National Traveling Salesman Problem). Na stronie: http://www.tsp.gatech.edu/world/countries.html można znaleźć dane w formacie: EUC_2D, jest to zbiór wektorów dwuwymiarowych opisujących położenie danego miasta pewnego wybranego kraju 1. Ponieważ problem komiwojażera jest problemem NP-zupełnym napisanie algorytmu wielomianowego jest niemożliwe, przy założeniu, że N!=NP. W takim przypadku musimy zadowolić się rozwiązaniem przybliżonym. Może to być pewna permutacja wierzchołków (miast). Jakość zadania określa suma odległości pomiędzy wszystkimi, kolejnymi wierzchołkami (tj. kolejno odwiedzanymi miastami). Odległością pomiędzy miastami jest moduł różnicy ich wektorów. W pierwszej turze algorytmu program losuje rodziców dwie permutacje wierzchołków (miast). 1 Dane pochodzą z NIMA (National Imagery and Mapping Agency). 2
Następnie używamy algorytmu genetycznego PMX (partially matched crossover), którego działanie zostało przedstawione na powyższym rysunku. W pierwszym kroku wybierany jest podciąg o określonej długości (wierzchołki zielone), który w niezmienionej postaci kopiowany jest do potomka. W kolejnym kroku szukamy miejsca dla wierzchołków, które znajdują się w tym samym podciągu drugiego z rodziców a nie znalazły się jeszcze w potomku (wierzchołki czerwone). Dla każdego z takich wierzchołków sprawdzamy gdzie znajduje się wierzchołek, który zajmował to samo miejsce w drugim z rodziców. Jeśli znajduje się ono na zewnątrz początkowo wybranego podciągu, to właśnie znaleźliśmy poszukiwane miejsce. Jeśli nie to kontynuujemy poszukiwania dla kolejnego wierzchołka, i tak aż do skutku. Pozostałe wierzchołki kopiujemy bez zmian z drugiego rodzica (wierzchołki niebieskie). Drugiego potomka tworzymy zamieniając rodziców miejscami i przeprowadzając jeszcze raz całą procedurę PMX. Następnie, jeśli nie skończy się czas przewidziany na tę turę algorytmu, powtarzamy procedurę PMX. W drugiej turze program stara się poprawić znalezione wcześniej rozwiązanie przy pomocy algorytmu 3-opt 2. Polega na wyszukaniu najlepszego wyniku jaki można uzyskać poprzez wymianę trzech krawędzi z dotychczas znalezionego cyklu. Wymaga to rozważenia wszystkich możliwych wymian, których złożoność jest rzędu O(n 3 ). Operacje wymiany kolejnych krawędzi należy przeprowadzać na zmianę dla każdego z rodziców. Krawędzie należy usuwać oraz dodawać, tak aby całe rozwiązanie nadal było cyklem. Poniższy rysunek demonstruje ten krok algorytmu. Krawędzie łączące niebieskie, czerwone i zielone wierzchołki zostają usunięte. Następnie wierzchołki o dwóch różnych kolorach łączone są krawędziami na jeden z dwóch możliwych sposobów. Oczywiście takie podejście nie musi zawsze doprowadzić do najlepszego rozwiązania niemniej na potrzeby niniejszego zadania absolutnie wystarczy. 2 Traveling salesman problem heuristics: Leading. methods, implementations and latest advances 3
Jeśli znalezione w trzeciej fazie rozwiązanie jest lepsze od aktualnie wyświetlanego globalnie, należy powiadomić o tym proces rodzicielski (GUI) przekazując mu lepsze rozwiązanie. Powinien on natychmiast wyświetlić nowe, lepsze rozwiązanie oraz informację o tym, który watek z puli je znalazł. Watki w puli powinny posiadać identyfikator. Pozwoli to zaobserwować, czy rywalizują one między sobą, czy raczej szybko wyłaniany jest jeden lider, którego trudno pokonać. Uwagi:. Obie fazy tj. krzyżowanie PMX alg. 3-opt wykonywane są naprzemiennie i powinny zostać zrównoleglone. Obie tury algorytmu powinna wykonywać się przez określony czas podany przez użytkownika (najlepiej dynamicznie możliwość zmiany czasu w trakcie prowadzenia obliczeń). Druga tura kończy się w momencie kiedy została przejrzana cała przestrzeń kombinacji lub upłynął czas przewidziany na obliczenia również ustalany, najlepiej dynamicznie, przez użytkownika. Lepsze rozwiązanie (znalezione pod koniec drugiej tury każdej fazy zadania) powinno być przekazywane do wątku GUI w celu natychmiastowego wyświetlenia. Na początek proponuję rozważyć Zachodnią Saharę ponieważ posiada zaledwie 29 miast. Jeśli program będzie pozwalał na wczytywanie danych z pliku to można łatwo zacząć badać bardziej złożone problemy. Wymagania techniczne odnośnie programów: Interfejs użytkownika powinien by napisany w technologii WPF i powinien zawierać następujące elementy wizualne: o przycisk uruchamiający obliczenia równoległe, o pole z liczbą uruchamianych zadań wykorzystywanych do zrównoleglenia obliczeń 3, o pole z czasem przeznaczonym na obliczenia dla pierwszej i drugiej tury algorytmu, o pole z wynikami: pole z najlepszą obliczoną wartością, pole z informację o numerze wątku, który obliczył aktualnie wyświetlaną wartość, pole z liczbą policzonych instancji problemu, o pole z Optimal Tour, o przycisk pozwalający na zakończenie obliczeń. o przycisk umożliwiający zamknięcie aplikacji (uaktywniany dopiero po zakończeniu obliczeń). 3 Najbardziej optymalnym wykorzystaniem systemu jest uruchomienie 2n wątków, gdzie n liczba rzeczywistych procesorów dostępnych w systemie. 4
o okno wyświetlające najkrótszy, aktualnie znaleziony cykl komiwojażera wykorzystując całą dostępna przestrzeń okna (przykład poniżej) lub pozwalać na przesuwanie wyświetlanego ekranu. Okno powinno dynamicznie reagować na zmianę rozmiaru (property SizeChanged). Poniżej zamieszczono przykład. Interfejs użytkownika nie powinien ulegać zamrożeniu (wykorzystanie słów kluczowych async i await). Początkowo powinny zostać uruchomione obliczenia równoległe polegające na dwukrotnym wyznaczeniu losowej permutacji wierzchołków, które będą podstawą do dalszych obliczeń w kolejnych turach algorytmu. Następnie wynik dotychczasowych obliczeń powinien podlegać ulepszeniu zgodnie z wcześniej opisanych algorytmem. Po kliknięciu przez użytkownika przycisku kończącego obliczenia powinny zostać przerwane, a najlepszy wynik powinien być nadal wyświetlany w GUI. Zadania powinny mieć dostęp do współdzielonej zmiennej, dostępnej w zakresie procesu, informującej o wartości aktualnie znalezionego, globalnie najlepszego rozwiązania. Dostęp do niej odbywa się na zasadzie scenariusza problemu czytelników i pisarzy. Do zrównoleglenia rozpraszania należy wykorzystać Taski (należy wykorzystać TPL (Task Parallel Library)) lub pulę wątków. Do komunikacji pomiędzy procesami można zastosować potoki nazwane, pliki, kolejki MSMQ itp GUI aktywuje przycisk zakończenie aplikacji po zakończeniu obliczeń i odebraniu wyników. 5
Mile widziane są dodatkowe nietrywialne funkcjonalności, które mogą skutkować podwyższoną liczb punktów, np.:. Implementacja obliczeń z wykorzystaniem procesów zamiast TPL i porównanie wydajności. Wydajność rozumiemy jako liczbę przebiegów algorytmu a nie wynik. Przykład interfejsu programu realizującego wymagania techniczne wraz z dodatkowym: 6