Wprowadzenie
Wyzwanie jest bardzo interesującą odmianą toru wyścigowego i tych dwóch wyzwań:
Źródło tego wyzwania znajduje się tutaj (po niemiecku): c't-Racetrack
To wyzwanie jest szczególnie interesujące (i różni się od dwóch wyżej wymienionych wyzwań), ponieważ łączy ogromną przestrzeń poszukiwań z pewnymi dokładnymi warunkami, które należy spełnić. Ze względu na ogromną przestrzeń poszukiwań wyczerpujące techniki wyszukiwania są trudne w użyciu, ponieważ z powodu dokładnych warunków przybliżone metody również nie są łatwe do użycia. Z powodu tej unikalnej kombinacji (oraz leżącej u podstaw intuicji z fizyki) problem jest fascynujący (a wszystko związane z samochodami wyścigowymi i tak jest fascynujące ;-)
Wyzwanie
Spójrz na następujący tor wyścigowy ( źródło ):
Musisz zacząć od (120,180)
i zakończyć dokładnie o (320,220)
(po niemiecku „Ziel”) bez dotykania jednej ze ścian.
Samochód kontrolowany jest przez wektory przyspieszenia postaci (a_x,a_y)
- jako przykład:
(8,-6)
(10,0)
(1,9)
Pierwsza liczba to przyspieszenie dla wektora x, druga dla wektora y. Muszą to być liczby całkowite, ponieważ możesz używać tylko punktów całkowitych na siatce. Dodatkowo należy spełnić następujący warunek:
a_x^2 + a_y^2 <= 100,
co oznacza, że przyspieszenie w dowolnym kierunku musi być niższe lub równe 10
.
Aby zobaczyć, jak to działa, spójrz na następujące zdjęcie ( źródło ):
Na przykład: Zaczynając od (120,180)
przyspieszenia 8
w kierunku x i -6
w kierunku y. W następnym kroku jest to twoja prędkość, w której dodajesz przyspieszenie, (10,0)
aby uzyskać (fizycznie poprawny) następny wynikowy ruch (w celu(146,168)
. Ruch wynikowy liczy się, gdy chodzi o sprawdzenie, czy dotknąłeś jednej ze ścian. W następnym kroku ponownie dodajesz następny wektor przyspieszenia do bieżącej prędkości, aby uzyskać następny ruch itd. Tak więc na każdym kroku samochód ma pozycję i prędkość (na ilustracyjnym zdjęciu powyżej niebieskie strzałki oznaczają prędkość, pomarańczowe strzałki dla przyspieszenia i ciemnoczerwone strzałki dla wynikowego ruchu).
Jako dodatkowy warunek musisz mieć (0,0)
prędkość końcową, gdy jesteś na mecie (320,220)
.
Wyjściem musi być lista wektorów przyspieszenia w wyżej wymienionej formie.
Zwycięzcą jest ten, który udostępnia program, który znajduje rozwiązanie z najmniejszą liczbą wektorów przyspieszenia.
Tiebreaker
Dodatkowo byłoby świetnie, gdybyś mógł wykazać, że jest to optymalne rozwiązanie i czy jest to jedyne optymalne rozwiązanie, czy też istnieje kilka optymalnych rozwiązań (i jakie są).
Byłoby również dobrze, gdybyś mógł przedstawić ogólny zarys działania algorytmu i skomentować kod, abyśmy mogli go zrozumieć.
Mam program, który sprawdza, czy dane rozwiązanie jest prawidłowe, i przekażę informację zwrotną.
Uzupełnienie
Możesz używać dowolnego języka programowania, ale byłbym szczególnie zachwycony, gdyby ktoś używał języka R, ponieważ często go używam w mojej codziennej pracy i jakoś się przyzwyczaiłem :-)
Dodatek II
Po raz pierwszy rozpocząłem nagrodę - mam nadzieję, że to się potoczy (lub lepiej: jazda samochodem :-)
print "(10,42)\n(62,64)..."
?Odpowiedzi:
Python, 24 kroki (prace w toku)
Chodziło o to, aby najpierw rozwiązać ciągły problem, znacznie zmniejszając przestrzeń wyszukiwania, a następnie skwantyzować wynik do siatki (po prostu zaokrąglając do najbliższego punktu siatki i przeszukując otaczające 8 kwadratów)
Parametryzuję ścieżkę jako sumę funkcji trygonometrycznych (w przeciwieństwie do wielomianów, nie rozchodzą się i są łatwiejsze do kontrolowania). Kontroluję także prędkość bezpośrednio zamiast przyspieszenia, ponieważ łatwiej jest wymusić warunek brzegowy, po prostu mnożąc funkcję wagową, która na końcu ma wartość 0.
Moja funkcja celu składa się z:
-wykładniczej oceny przyspieszenia> 10-
wielomianowej oceny odległości euklidesowej między ostatnim punktem a celem
-dużej stałej oceny dla każdego przecięcia ze ścianą, malejącej w kierunku jej krawędzi
Aby zminimalizować wynik, wrzucam to wszystko w optymalizację Neldera-Meada i czekam kilka sekund. Algorytmowi zawsze udaje się dotrzeć do końca, zatrzymując się na nim i nie przekraczając maksymalnego przyspieszenia, ale ma problemy ze ścianami. Ścieżka albo teleportuje się przez rogi i utknie w tym miejscu, albo zatrzymuje się przy ścianie z celem naprzeciwko (lewy obraz)
Podczas testowania miałem szczęście i znalazłem ścieżkę, która została przekręcona w obiecujący sposób (prawy obraz), a po poprawieniu parametrów mogłem użyć jej jako początkowego przypuszczenia dla udanej optymalizacji.
Kwantyzacja
Po znalezieniu ścieżki parametrycznej nadszedł czas, aby usunąć kropki dziesiętne. Patrzenie na dzielnicę 3x3 zmniejsza przestrzeń wyszukiwania z około 300 ^ N do 9 ^ N, ale wciąż jest zbyt duża i nudna do wdrożenia. Zanim poszedłem tą drogą, próbowałem dodać termin „Snap to Grid” do funkcji celu (skomentowane części). Sto kolejnych kroków optymalizacji z zaktualizowanym celem i prostym zaokrągleniem wystarczyło, aby uzyskać rozwiązanie.
Liczba kroków została ustalona i nie stanowi części optymalizacji, ale ponieważ mamy analityczny opis ścieżki (a ponieważ maksymalne przyspieszenie jest znacznie poniżej 10), możemy ponownie użyć go jako punktu wyjścia do dalszej optymalizacji z mniejszą liczbą terminy
Zadanie do wykonania: graficzny interfejs użytkownika, który pozwala narysować początkową ścieżkę, aby uzyskać przybliżone wyczucie kierunku. Wszystko jest lepsze niż losowe próbkowanie z 14-wymiarowej przestrzeni
źródło