Reinicializace

Obsah

Rozmisteni min


Prvnik krokem bylo naprogramovani nejakeho modelu na rozmisteni min (bodu podel kterych se bude urcovat, ze je nutna reinicializace). Naprogramovany jsou 3 ruzne ucinne metody:
  1. Hrany. Program se snazi detekovat hrany narrowbandu a kousek od kraju vytvori miny. Problem: Sledovat hranu pri prekryvajicich se oblastech (blocich) neni az tak jednoduche, jak se mi na prvni pohled zdalo. Stadium: funguje, ale myslenka ma hodne omezeni. Kdyz se prekryji vice nez dva pokryvajici bloky, tak tam vznikaji blbiny. Toto by jeste slo nejak opravit (asi docela slozite), ale v kazdem pripade zustanou chyby na oblastech prekryvu s jinym procesem. Tam krivka naprosto korektne opousti oblast (je osetreno), ale z duvodu pomalych presunu dat uz se mi tam nechce davat zadne posilani dat s okolnimi procesy. Vysledek:  Hezky se hodi na hodne hladke krivky bez ostrych hran. (#define 2)
  2. Rohy. Projdu pokryvajici bloky a kosek od rohu tam fouknu minu. Opet vynechavam hodne rizikove oblasti kolem prekryvu procesu. Min je pak velice malo a kazdy spatne umisteny muze byt velmi nebezpecny. (#define 1)
  3. Trasovani po radcich/sloupcich.  Jdu po radku a az narazim na zmenu v dist fci (mezi nepocitanym okolim a narrowbandem), tak oznacim minu. Funguje podobne jako metoda jedna, ale je podstatne pomalejsi. Navic opet velice trpi zminenymi prekryvy. (#define 0) 
  4. Mina je bod, ktery ma ve svem ctvercovem okoli o urcite velikost bod s hodnotou INIT_DIST (tzn. mimo narrow band). Elegantni reseni, ale pomerne narocny algoritmus.
Metoda 1
Metoda 2
 Metoda 3
Metoda 4






Zminene problemy resim zatim tim, ze k reinicializaci je nutne vybuchnuti vetsiho poctu bodu, cimz se eliminuji ty spatne umistene. Snad to bude fungovat (vyzkouseno zatim nic z nizeji popsaneho duvodu). Nejlepe se mi zatim jevi metoda 2 - opet ta nejjednodusi.

V textech me dostupnych se nikdo blize nerozepisuje, jak miny volit, jen p. Sethian rika "nekde u hrany." Nekdy dokonce primo hranu. To se mi nejak nezda, ale expert je on. :-) Obrazky na miny jsem bohuzel smazal a uz se mi chce docela spat, takze je sem doplnim pozdeji.

Uprava reinicializacniho schematu

Puvodne jsme reinicializovali podle schematu - zjisti body, ktere jsou bliz ke krivce nez stanovena mez, a kdyz jejich pocet prekroci urcite procento vsech, reinicializuj.  Tento zpusob ucinne odmaze vliv prekryvu a hranic mezi procesy, ale na zaklade prvnich pokusu je nutno dodat, ze reinicializuje az prilis casto. Proto jsme zmenili zpusob na "kdyz zmeni znamenko" - dame je dale od kraje nez v predchozim pripade... Jsou tam urcite problemy, jak tyto body volit, jak nastavit, aby zaroven odmazal ty prechody mezi procesy a zaroven se zachovala dobra schopnost reinicializace.

Dalsim zjistenim byla pomerne slba funkcnost min polozenych jako metoda 2, tedy do rohu pokryvacich oblasti. Problem je v tom, ze k rohum se krivka dostane vzdy az mnohem pozdeji, nez je potreba reinicializovat. Bylo by potreba detekovat rohy vznikle prekryvy techto oblasti - neni problem, ale vznika problem, ktery je smer "dvonitr" z techto bodu. Tato metoda se stava historickou...

Rekonstrukce krivky

Dale je potreba nejak rekonstruovat tu krivku aka nulovou uroven. Hledal jsem, jak to dela p. Sethian a  metoda se jmenuje Marching Cubes. Je z roku 1987 a z poctu clanku, ktere tuto metodu vyuzivaji jsem odvodil, ze je to nejak dost proflakla klasika. Bohuzel se mi podarilo najit jen asi 2 clanky, ktere metodu velice hrube popisuji - jde z nich pochopit hlavni myslenka (15 zakladnich typu ve 3D...), ale nejak jsem to moc nechytil. Originalni clanek je snad nesehnatelny. :-( Tato metoda pry ukazuje svoji silu hlavne ve 3D, ve 2D se Sethian jeste zminuje o metode Contour Plotter - vedecke vyhledavace mlci, google vyhazuje spoustu reklam na plottery. Pravdepodobne pujde o sledovani hranice nejakym intuitivnim zpusobem.

Ja jsem se zkusil vydat opet velice jednoduchou cestou, na ktere jsme se domluvili. Myslenkou bylo to, ze najdu nejaky bod na krivce a z nej potom postupne pomoci trojuhelnicku odvodim celou spojitou krivku. Bojoval jsem s tim cely den a vysledek je zhruba ten, ze metoda "sledovani" je az neuveritelne citliva na presnost a je velmi tezke ji zrekonstruovat. Zkusil jsem jen napocitat vzdalenosti a okamzite ji rekonstruovat a moc mu to neslo. Opustil jsem tento zpusob a presel jsem na brutalni silu metodou testu na vsechny body: prochazim radky/sloupce a kdyz najdu rozdilne znamenko na dvou sousedicich bodech, tak pomoci Vaseho postupu dopocitam bod na trojuhelniku. Asi neco delam spatne, protoze to neuveritelne dlouho trva a asi by to chtelo neco lepsiho. Uz ted se objevuji problemy v bodech kolmych na smer prohledavani - rekonstruuje podstatne nepresne. Dalsim problemem je, ze jsem si uvedomil, ze k pokryti krivky potrebuji body mit v rozumnem poradi a to tento zpusob nesplnuje.

  1. Hruba sila - probereme vsechny body a metodou trojuhelnicku napocitame krivku.
  2. Jdeme po krivce metodou trojuhelnicku - rekurzivne.
  3. To same ale v nerekurzivni verzi - nepozna treba rozvetveni krivky.
Prestoze posledni dve metody me prijdou jako velmi efektivni, tak problem je v tom, ze hruba sila je v tomto pripade velice rychla, a tudiz rozdil mezi 1 a 2-3 je velice maly. :-( Jako ukazku rychlosti nasledujici tabulka:

Metoda
1
2
3
Cas
0.025 s
0.004 s
0.003 s
Chyba
9e-6 pri prostorovem kroku 3e-3

Jeden maly obrazecek na rozliseni 0.01*1e-9 pri e^2=e-20 v case 0.02. Stale se to lisi zhruba o dva body. :-(

Celkova reinicializace

Puvodne jsem se naivne domnival, ze cela reinicializace se bude skladat s testu, zda-li je nutna (na zaklade min), a pak uz jen nalezeni krivky, jeji znovupokryti, znovunapocitani vzdalenosti a pokracovani ve vypoctu. Problemy, ktere se vyskytly:
  1. Prvni problem je v pokladani min, kdy je nutno navic zvazit, ze na nekterych hranach je temer nulova vzdalenost normalni - tam, kde se prekryvame s jinym procesem. Trochu nesikovne reseni se naslo - miny prilis blizko uz pri pokladani proste nepolozime.
  2. Jestlize kazdy proces zrekonstruuje krivku, tak je tam cast, ktera se opet prekryva vice procesy - je tam jakoby dvakrat. Pri znovupokryvani je to nutno zohlednit, protoze jinak se nam bude zvetsovat uzemi pokryvane vice procesy a nastane problem se synchronizaci.
  3. Potrebujeme body krivky v poradi, aby slo nasim zpusobem pokryt. Opet jsem to musel prepsat, protoze metoda sice posklada body, ale je nutno mu zadat prvni bod.
  4. Dlouho jsem premyslel, jak to udelat, aby v pripade nutne reinicializace se  akce provedla jen na jednom procesu. Uz jsem se do toho pustil, ale pak jsem si uvedomil, ze vsechny ostatni procesy na nej stejne musi kvuli synchronizaci pockat - navic je pravdepodobne, ze kdyz potrebuje jeden, tak bude potrebovat i druhy - budeme cekat znovu. Reseni: vzdy se reinicializuji vsechny procesy. Zpomaleni oproti jednomu je v optimalnim pripade nulove.
  5. Body 1 - 4 jsou vyreseny, momentalne je problem v zjisteni, jak je to s urcenim, co je uvnitr a co je vne. Zatim nemam napad, jak to hezky udelat - snad jen zapamatovat si pozice nekterych bodu a jejich znamenko a potom to lavinove rozsirit...
<5.2.2002>

Bod 5 z predchoziho vypisu nakonec vyresen nasledovne:
  1. Pri rekonstrukci krivky si ulozim "trojuhelniky", z kterych byly jednotlive body krivky napocitany. Znamenka v techto bodech se po reinicializaci nezmeni (jinak je nekde bota).
  2. Po vytvoreni noveho narrow bandu a napocitani vzdalenosti (bez znamenka), nastavime znamenka v bodech ziskanych z rekonstrukce krivky (bod 1).
  3. Z kazdeho bodu "trojuhelniku" v podstate nastartuju vyplnovani souvisle oblasti, kde hranici jsou body z bodu 2.
A mala ukazka, jak to potom vypada pri vypoctu (provedeno na 2 procesech):

Prvni iterace
Po prvni reinicializaci
Po druhe reinicializaci



Ackoli se zpocatku zdalo, ze to funguje vyborne, je tu maly problem. Kazdy proces zna jako vzdy jen svoji malou cast krivky. Pri nastavovani znamenek pri novem pokryti se tam objevi uz oblast, kde krivka neni - nezname tam hranizi a znamenka jsou nastavena spatne. Reseni je jako vzdy si nechat poslat pokracovani krivky od nasledujiciho procesu - opet zpomaleni. :-(( Bohuzel, ani toto se neukazalo jako dostatecne silne - nekdy se objevi male trhlinky... Mozna bug. Hezke je, ze staci posilat jen jeden konec, druhy se spravi sam zpusobem noveho rozdeleni krivky dle bodu (2).

Tak vyse popsany bug lze celkem bez problemu resit tim, ze si procesy vymeni vetsi casti krivek. Takze malinka ukazka, jak uz nam reinicializace hezky funguje. K vypoctu bylo jiz pouzito nove schema popsane pozdeji.

Hrouceni, narrow band s reinicilizaci
Repete, full band s reinicializaci


Porovnani vysledku predchozich vypoctu - rozdil mezi narrowbanded a fullbandem je 'opticky' velice maly.


Pohadka o metode pokracuje na simulacich na novem schematu...