[1147] | 1 | \def \obr {05_AlgorithmDescription/fig/} |
---|
| 2 | \lstset{language=[Visual]C++,showstringspaces=false,numbers=left, numbersep=0pt, tabsize=4, breaklines, breakautoindent=false, captionpos=b} |
---|
| 3 | \chapter{Popis implementace} |
---|
| 4 | |
---|
| 5 | |
---|
| 6 | |
---|
| 7 | \section{Použité knihovny} |
---|
| 8 | |
---|
| 9 | \subsection{IT++} |
---|
| 10 | IT++ je knihovna jazyka C++ zahrnující třídy pro matematické výpočty a komunikaci. |
---|
| 11 | Umožňuje práci s vektory a maticemi podobným způsobem jako v nástroji MATLAB. |
---|
| 12 | Použity jsou třídy \texttt{vec} a \texttt{Array}. |
---|
| 13 | |
---|
| 14 | |
---|
| 15 | \subsubsection{Třída vec} |
---|
| 16 | Třída \texttt{vec} reprezentuje vektor hodnot číselného typu \texttt{double}. |
---|
| 17 | Přetížením operátorů kulatých a hranatých závorek a operátoru \texttt{=} umožňuje jednoduchou inicializaci |
---|
| 18 | vektoru pomocí textového řetězce a zjednodušuje přístup k jednotlivým hodnotám. |
---|
| 19 | Kód |
---|
| 20 | \begin{lstlisting} |
---|
| 21 | vec a = "0.1 0.2 0.3"; |
---|
| 22 | cout << a(0) << endl; |
---|
| 23 | cout << a[1] << endl; |
---|
| 24 | \end{lstlisting} |
---|
| 25 | inicializuje vektor o dimenzi 3 s hodnotami 0,1, 0,2 a 0,3 a poté |
---|
| 26 | vypíše první a druhý prvek vektoru. |
---|
| 27 | |
---|
| 28 | \subsubsection{Třída Array} |
---|
| 29 | Tato šablonová třída umožňuje pracovat s polem o proměnných předem daného libovolného typu. |
---|
| 30 | Rozměr pole se může v průběhu programu měnit. |
---|
| 31 | |
---|
| 32 | |
---|
| 33 | \subsection{BDM} |
---|
| 34 | Knihovna BDM (Bayesian Decision Making) je navržena pro programy používající |
---|
| 35 | Bayesovu statistiku. Zde jsou použity hlavně třídy \texttt{Datalink}, \texttt{RV}, \texttt{UI} a \texttt{Setting} |
---|
| 36 | sloužící pro komunikaci s mikrosimulátorem AIMSUN, načítání hodnot z konfiguračních souborů a komunikaci mezi agenty. |
---|
| 37 | \\ |
---|
| 38 | \\ |
---|
| 39 | V knihovně BDM je také definována třída \texttt{Participant}, implementující metody pro komunikaci |
---|
| 40 | , od které je odvozena třída našeho agenta. |
---|
| 41 | |
---|
| 42 | |
---|
| 43 | \subsubsection{Třída RV} |
---|
| 44 | Třída \texttt{RV} implementuje pole popisků k vektorům třídy IT++. |
---|
| 45 | K přístupu k jednotlivým slouží přetížený operátor závorky \texttt{(int index)}. |
---|
| 46 | K určení veličiny uložené ve vektoru se používají metody |
---|
| 47 | \begin{description} |
---|
| 48 | \item [name] jméno veličiny uložené v příslušném vektoru |
---|
| 49 | \item [length] rozměr RV vektoru |
---|
| 50 | \item [size(i)] rozměr veličiny, kterou značí popisek na pozici \texttt{i} |
---|
| 51 | \end{description} |
---|
| 52 | |
---|
| 53 | \subsubsection{Třídy UI a Setting} |
---|
| 54 | UI a Setting slouží mimo jiné k načtení vybraných dat z konfiguračních souborů. |
---|
| 55 | Kód |
---|
| 56 | \begin{lstlisting} |
---|
| 57 | UI::get(inputs,set,"inputs",UI::compulsory); |
---|
| 58 | \end{lstlisting} |
---|
| 59 | zapíše na adresu proměnné inputs hodnotu v oběktu \texttt{set} třídy \texttt{Setting}, |
---|
| 60 | označenou jako \texttt{\"inputs\"}. Oběkt \texttt{set} reprezentuje načtený konfigurační soubor. |
---|
| 61 | \texttt{UI::compulsory} značí, že daná hodnota musí být zadána. |
---|
| 62 | |
---|
| 63 | |
---|
| 64 | |
---|
| 65 | \subsubsection{Třída datalink} |
---|
| 66 | Tato třída definuje spojení mezi dvěma vektory, mezi kterými zprostředkovává spojení |
---|
| 67 | pomocí metody \texttt{filldown}. |
---|
| 68 | \\ |
---|
| 69 | \\ |
---|
| 70 | Následující kód popisuje vytvoření dvou vektorů \texttt{from} a \texttt{to}, |
---|
| 71 | popsaných \texttt{RV} vektory \texttt{rv\_from} a \texttt{rv\_to}, a zkopání odpovídajících |
---|
| 72 | údajů z \texttt{from} do \texttt{to} pomocí třídy \texttt{datalink}. Výsledkem je, že vektor |
---|
| 73 | \texttt{to} bude obsahovat hodnoty 1 a 2. |
---|
| 74 | |
---|
| 75 | \begin{lstlisting} |
---|
| 76 | RV a = RV ( "{ a }"); |
---|
| 77 | RV b = RV ( "{ b }" ); |
---|
| 78 | RV c = RV ( "{ c }" ); |
---|
| 79 | |
---|
| 80 | RV rv_to = a; |
---|
| 81 | rv_to.add ( b ); |
---|
| 82 | |
---|
| 83 | RV rv_from = rv_to; |
---|
| 84 | rv_from.to ( c ); |
---|
| 85 | |
---|
| 86 | datalink dl ( rv_to, rv_from ); |
---|
| 87 | vec from ( "1 2 3" ); |
---|
| 88 | vec to = dl.pushdown ( total ); |
---|
| 89 | \end{lstlisting} |
---|
| 90 | |
---|
| 91 | |
---|
| 92 | |
---|
| 93 | |
---|
| 94 | |
---|
| 95 | \section{Třída Lane} |
---|
| 96 | Každá instance třídy Lane reprezentuje jeden dopravní pruh. |
---|
| 97 | Po inicializaci se do příslušných proměnných uloží textové |
---|
| 98 | řetězce, podle kterých se přiřazují k pruhu data z detektorů |
---|
| 99 | a AIMSUNu, jako je na příklad maximální délka |
---|
| 100 | fronty na dopravním pruhu za jednu simulační periodu. |
---|
| 101 | |
---|
| 102 | |
---|
| 103 | \section{Třída LaneHandler} |
---|
| 104 | Tato třída zprostředkovává přístup agentovi k ůdajům z jednotlivých pruhů. |
---|
| 105 | Stará se o zaznamenávání a statistické spracování dat z AIMSUNu. |
---|
| 106 | Také je zde implementován odhad čekací doby automobilu do průjezdu křižovatkou, |
---|
| 107 | což je údaj používaný v hodnotící délky cyklu funkci agenta. |
---|
| 108 | |
---|
| 109 | \subsection{Fronta} |
---|
| 110 | Agent předává třídě LaneHandler údaj o maximální délce fronty za vzorkovací periodu. |
---|
| 111 | Jedná se o největší počet automobilů v příslušném jízdním pruhu, jejichž rychlost reřesahuje |
---|
| 112 | určitou hodnotu. V našem konkrétním případě je tato mezní rychlost nastavena na 3,6 km/h. |
---|
| 113 | Tento ůdaj je však pro naše potřeby zkreslený, a to hlavně tím, že ve většině případů se délka cyklu neshoduje |
---|
| 114 | se vzorkovací periodou. Uvažujme jízdní pruh s poměrem délky zelené 0,5. |
---|
| 115 | Pokud bude například délka cyklu 180 sekund, a budeme li předpokládat, že začátek jedné periody se bude shodovat s časem, |
---|
| 116 | kdy na příslušném semaforu naskočí zelená, bude v první vzorkovací periodě pruh průjezdný po dobu 45 sekund, ale |
---|
| 117 | v další nebude průjezdný vůbec a fronta se za stejné hustoty provozu zvětší. |
---|
| 118 | |
---|
| 119 | \subsection{Odhad fronty}\label{ss:odhad_fronty} |
---|
| 120 | K odhadu fronty je použito metody tzv. exponencionálního zapomínání. Metoda vychází z povoucího průměru |
---|
| 121 | Který je vhodný pro odhad nekonstantní hodnoty. Označíme si veličinu $\overline{q_i}$ jako plovoucí průměr |
---|
| 122 | fronty v kroce $i$, kam budeme ukládat posledních $n$ měření. Označme si velikost fronty naměřenou v $i$-tém kroce jako$q_i$. |
---|
| 123 | V kroce $i+1$ je hodnota hodnota plovoucího průměru přepřičytením poslední naměřené hodnoty rovna |
---|
| 124 | $$ |
---|
| 125 | \overline{q_i} = \frac{1}{n} \sum_{j=0}^{n-1} q_{i-j} . |
---|
| 126 | $$ |
---|
| 127 | |
---|
| 128 | Obsahuje tedy všech posledních $n$ naměřených hodnot. $\overline{q_{i+1}}$ se tedy rovná |
---|
| 129 | $$ |
---|
| 130 | \overline{q_{i+1}} = \frac{1}{n} ( n \overline{q_i} - q_{i-n+1} + q_{i+1} ) = \overline{q_i} - \frac{1}{n} q_{i-n+1} +\frac{1}{n} q_{i+1}. |
---|
| 131 | $$ |
---|
| 132 | Abychom nemuseli ukládat posledních $n$ měření. Zjednodušíme algoritmus tím, že místo kroku $i-n+1$ odečteme od průměru |
---|
| 133 | jeho hodnotu podělenou délkou průměrovacího okna $n$. Výpočet přejde na tvar |
---|
| 134 | $$ |
---|
| 135 | \overline{q_{i+1}} = \frac{1}{n} ( n \overline{q_i} - \overline{q_i} + q_{i+1} ) = \overline{q_i} + \frac{1}{n} (q_{i+1} - \overline{q_i}). |
---|
| 136 | $$ |
---|
| 137 | $\frac{1}{n} (q_{i+1} - \overline{q_i}$ je vlastně přírustek v kroku $i+1$, označme si ho jako $\Delta q_{i+1}$, |
---|
| 138 | a faktor $1/n$ můžeme chápat jako jeho váhu $w$. Po dosazení dostáváme jednoduchý tvar |
---|
| 139 | $$ |
---|
| 140 | \overline{q_{i+1}} = \overline{q_i} + w \Delta q_{i+1}. |
---|
| 141 | $$ |
---|
| 142 | Průměr s exponenciálním zapomínáním se nazývá proto, že je v něm v $i$-tém kroce uložena i první hodnota, |
---|
| 143 | má však zanedbatelnou váhu $\left(\frac{n-1}{n}\right)^i$. Jedná se o jaksi zjednodušenou verzi Kalmanova filtru. |
---|
| 144 | Grafy \ref{fig:q1} a \ref{fig:q2} znázorňují rozdíl mezi okamžitou a filtrovanou délkou fronty při váze $w = 0.2$. |
---|
| 145 | Graf \ref{fig:q1} pro konstantní délku cyklu 80 sekund, graf \ref{fig:q2} pro délku cyklu peridicky se měnící od 40 |
---|
| 146 | do 120 sekund. |
---|
| 147 | |
---|
| 148 | \begin{figure}[H] |
---|
| 149 | \begin{center} |
---|
| 150 | {\includegraphics[width=10cm]{\obr q_scen_01_1h_tc80.eps}} |
---|
| 151 | \caption{Porovnání okamžité a filtrované délky fronty \newline délka cyklu 80 s}\label{fig:q1} |
---|
| 152 | \end{center} |
---|
| 153 | \end{figure} |
---|
| 154 | |
---|
| 155 | \begin{figure}[H] |
---|
| 156 | \begin{center} |
---|
| 157 | {\includegraphics[width=10cm]{\obr q_scen_01_1h_tc40-120.eps}} |
---|
| 158 | \caption{Porovnání okamžité a filtrované délky fronty \newline délka cyklu 40-120 s}\label{fig:q2} |
---|
| 159 | \end{center} |
---|
| 160 | \end{figure} |
---|
| 161 | |
---|
| 162 | |
---|
| 163 | \subsection{Odhad čekací doby}\label{ss:odhad_cekaci_doby} |
---|
| 164 | Jednou z nejdůležitějších částí logiky, implementovaná v třídě \texttt{LaneHandler} je |
---|
| 165 | odhad čekací doby vozidel stojících v, nebo přijíždějících do příslušnéjo jízdního pruhu. |
---|
| 166 | Tento odhad se používá při výběru a ohodnocení délky cyklu. |
---|
| 167 | \\ |
---|
| 168 | \\ |
---|
| 169 | Odahad se provádí zjednodušenou mikrosimulací po čas \texttt{T}. |
---|
| 170 | Do proměnné \texttt{q} se uloží aktuální hodnota fronty. |
---|
| 171 | Simulace začíná v čase \texttt{t = 0}. V každém kroku simulace |
---|
| 172 | se zvětší fronta o hustotu provozu (počt aut za sekundu), odhadovanou z údaů z detektorů, a pokud se čas nachází |
---|
| 173 | ve průjezdné fázi, zmenší se o konstantu, nazývanou saturovaný tok, která udává maximální počet aut, které projedou |
---|
| 174 | křižovatkou. K čekací době vozidel, uložené v proměnné \texttt{wt}, se potom přičte délka zbývající fronty a čas |
---|
| 175 | \texttt{t} se zvětší o jednu sekundu. |
---|
| 176 | \\ |
---|
| 177 | \\ |
---|
| 178 | Odhad probíhá ve dvou fázích, realizovaných cykly typu \texttt{for}. V první běží čas do nevětší části \texttt{T}, |
---|
| 179 | soudělné s \texttt{tc}, v duhé po zbytek \texttt{T}. níže uvádím popis všech proměnných. |
---|
| 180 | \begin{description} |
---|
| 181 | \item[tc] délka cyklu, pro kterou je odhad prováděn (parametr funkce) |
---|
| 182 | \item[T] doba odhadu |
---|
| 183 | \item[ro] hustota provozu odhadovaná z dat z detektorů |
---|
| 184 | \item[cars\_in\_avg] filtrovaná data z detektorů (atribut třídy) |
---|
| 185 | \item[queue\_avg] filtrovaná naměřená délka fronty (atribut třídy) |
---|
| 186 | \item[q] délka fronty v průběhu odhadu |
---|
| 187 | \item[wt] součet čekacích časů |
---|
| 188 | \item[green\_time\_ratio] poměr délky zelené k délce cyklu (atribut třídy) |
---|
| 189 | \item[gt] doba, kdy je křižovatka pro pruh průjezdná |
---|
| 190 | \item[tc\_rest] čas v daném cyklu |
---|
| 191 | \item[tc\_last] zbytek odhadovací periody |
---|
| 192 | \item[gt\_last] délka zelené ve zbytku odhadovací periody |
---|
| 193 | \item[delta] korekční parametr vyjadřuje zkrácení průjezdnosti vlivem pomalých rozjezdů a podpbně |
---|
| 194 | \end{description} |
---|
| 195 | Odhad je implementován v metodě \texttt{getWT}: |
---|
| 196 | |
---|
| 197 | \begin{lstlisting} |
---|
| 198 | double getWT ( int tc ) { |
---|
| 199 | const int T = 450; // 5 scyklů |
---|
| 200 | double ro = cars_in_avg/90; |
---|
| 201 | double q = queue_avg; |
---|
| 202 | double wt = 0; |
---|
| 203 | double gt = tc*green_time_ratio - delta; |
---|
| 204 | int t_rest; |
---|
| 205 | int tc_last = T % tc; |
---|
| 206 | double gt_last = tc_last*green_time_ratio; |
---|
| 207 | for ( int t = 0; t < (T-tc_last); t++ ) { |
---|
| 208 | t_rest = t%tc; |
---|
| 209 | // zelena |
---|
| 210 | if ((tc-gt)/2<=t_rest&&t_rest<(tc+gt)/2) |
---|
| 211 | q -= saturated_stream; |
---|
| 212 | if ( q < 0) |
---|
| 213 | q = 0; |
---|
| 214 | wt += q; |
---|
| 215 | q += ro; |
---|
| 216 | } |
---|
| 217 | // zbytek |
---|
| 218 | for ( int t = 0; t < tc_last; t++ ) { |
---|
| 219 | // zelena |
---|
| 220 | if ((tc_last-gt_last)/2<=t&&t<(tc_last+gt_last)/2 ) |
---|
| 221 | q -= saturated_stream; |
---|
| 222 | if ( q < 0) |
---|
| 223 | q = 0; |
---|
| 224 | wt += q; |
---|
| 225 | q += ro; |
---|
| 226 | } |
---|
| 227 | return wt; |
---|
| 228 | } |
---|
| 229 | \end{lstlisting} |
---|
| 230 | |
---|
| 231 | |
---|
| 232 | \subsection{Odhad parametru $\delta$} |
---|
| 233 | Delta vyjadřuje korekční parametr doby průjezdnosti křižovatky. |
---|
| 234 | Jak jsme již ukázali v kapitole \ref{ss:odhad_cekaci_doby}, počet vozidel, které projedou křižovatkou |
---|
| 235 | za jeden cyklus řadiče je |
---|
| 236 | $$ |
---|
| 237 | (r_g T_c - \delta) s_s. |
---|
| 238 | $$ |
---|
| 239 | To znamená že pokud je fronta větší, než $(r_g T_c - \delta) s_s$, mměla by se její velikost za dobu $T_c$ |
---|
| 240 | změnit o |
---|
| 241 | $$ |
---|
| 242 | \Delta q_{T_c} = n_{Tc} - (r_g T_c - \delta) s_s, |
---|
| 243 | $$ |
---|
| 244 | |
---|
| 245 | kde $n_{Tc}$ je počet vozidel, přijíždějících na křižovatku za dobu $T_c$. |
---|
| 246 | Tento údaj je vlastně výstup z detektorů, který je nám však dostupný pouze |
---|
| 247 | jednou za simulační cyklus, trvající 90 sekund. Protože pracujeme s filtrovanými hodnotami front, |
---|
| 248 | nedojde k velké chybě, pokud výraz přepočítáme na 90 sekund do podoby |
---|
| 249 | $$ |
---|
| 250 | \Delta q_{90} = n_{90} - \frac{90}{T_c}(r_g T_c - \delta) s_s = n_{90} - 90 r_g s_s - \frac{90 s_s}{T_c} \delta, |
---|
| 251 | $$ |
---|
| 252 | z čehož si parametr $\delta$ vyjádříme jako |
---|
| 253 | $$ |
---|
| 254 | \delta = \frac{T_c}{90 s_s} \left( n_{90} - \Delta q_{90} \right) - r_g. |
---|
| 255 | $$ |
---|
| 256 | Jak údaje o projíždejících vozidlech za simulační cyklus $n_{90}$, tak parametry $\delta$, jsou filtrovány |
---|
| 257 | způsobem, použitým na odhad délky fronty a popsaným v kapitole \ref{ss:odhad_fronty}. |
---|
| 258 | |
---|
| 259 | \section{Hlavní smyčka} |
---|
| 260 | Hlavní smyčka programu se stará o synchronizaci všech potřebných parametrů a provádění iterací. |
---|
| 261 | Před započetím opakování kroku simulace nastaví podle konfiguračního souboru počáteční parametry mikrosimulátoru dopravy AIMSUN, |
---|
| 262 | jako jsou délka cyklu a fáze řadičů, inicializuje jednotlivé agenty a zavolá jejich metody \texttt{fromSettings} a \texttt{Validate}. |
---|
| 263 | |
---|
| 264 | \subsection{Krok simulace} |
---|
| 265 | Délka kroku simulace je pevně nastavena na 90 sekund shodně s periodou sběru dat z AIMSUNu. |
---|
| 266 | V jednom kroku se nejprve načtou data z AIMSUNu do vektoru \texttt{glob\_dt}, který se následně předá |
---|
| 267 | každému z agentů jako paramentr jejich metody \texttt{adapt}. Následně se zprostředkuje komunikace mezi |
---|
| 268 | agenty tak, že se naplní fronta zpráv voláním metody \texttt{broadcast} jednotlivých agentů. Z této fronty |
---|
| 269 | se postupně odebírají zprávy, které se předávají agentům parametrem jejich metody \texttt{receive} |
---|
| 270 | Po ukončení komunikace naplní vektor výstupů \texttt{glob\_ut} voláním metod \texttt{act} hodotami parametrů |
---|
| 271 | pro AIMSUN, předá se mu a vyčká se do dalšího kroku. |
---|
| 272 | |
---|
| 273 | \section{Třída agenta} |
---|
| 274 | Třída \texttt{TrafficAgentCycleTime} je odvozena od obecného návrhu agnta \texttt{BaseTrafficAgent}. |
---|
| 275 | Jsou v ní implementovány metody pro načtení dat, komunikaci a nastavení délky cyklu za účelem řízení |
---|
| 276 | jedné konkrétní křižovatky. |
---|
| 277 | |
---|
| 278 | \subsection{Stručný popis algoritmu} |
---|
| 279 | Cíl algoritmu je zlepšit dopravní situaci nastavením délky cyklu řadiče na tekouvou |
---|
| 280 | hodnotu, při níž bude celková čekací doba všech vozidel mininmální. |
---|
| 281 | Nejprve agent odhadne délku cyklu, která je ideální pro něj, poté vyšle zprávu, zda je tato hodnota |
---|
| 282 | vyšší nebo nižší než aktuální. Pokud je nadpoloviční většina agentů pro změnu stejným směrem, |
---|
| 283 | pokouší se najít hodnotu ideální pro všechny. |
---|
| 284 | |
---|
| 285 | \subsection{Výpočetní metody} |
---|
| 286 | |
---|
| 287 | \subsubsection{Metoda getWT} |
---|
| 288 | |
---|
| 289 | Tato metoda vrací součet čekacích dob, sečtený přes všechny dopravní pruhy pro danou délku cyklu předanou parametrem \texttt{tc}. |
---|
| 290 | V cyklu projde instance tříd \texttt{LAneHandler}, na které má uloženy ukazatele v proměnné \texttt{lanehs} typu |
---|
| 291 | \texttt{Array<LaneHandler*>}. Pole se inicializuje v metodě \texttt{validate} předka \texttt{BaseTrafficAgent}. |
---|
| 292 | |
---|
| 293 | \subsubsection{Metoda findIdealTc}\label{sss:ideal_tc} |
---|
| 294 | Pro určení, zda vznést návrh na zvýšení či snížení délky cyklu, slouží metoda \texttt{findIdealTc}. |
---|
| 295 | Ta zjišťuje čekací doby pro všechny možnosti rozsahu od mininmální do maximální hodnoty, určené atributy |
---|
| 296 | \texttt{minTc} a \texttt{maxTc}. Vrátí takovou délku cyklu, pro kterou je čekací doba nejmenší. |
---|
| 297 | \\ |
---|
| 298 | \\ |
---|
| 299 | Princip použití součtu čekacích dob automaticky upřednostňuje dopravní pruhy s větší |
---|
| 300 | vytížeností, což je žádoucí. Ostatní pruhy však zcela nepotlačuje. Tímto způsobem by se mělo |
---|
| 301 | dosáhnout optimální hodnoty pro celou křižovatku. |
---|
| 302 | |
---|
| 303 | \subsection{Přepsané metody předka} |
---|
| 304 | Hlavní smyčka progaramu automaticky volá v každém cyklu metody určené |
---|
| 305 | k načtení dat, komunikaci a nastavení dalšího řízení. |
---|
| 306 | |
---|
| 307 | |
---|
| 308 | |
---|
| 309 | \subsubsection{Metoda validate} |
---|
| 310 | K předání požadovaných hodnot parametrů v průběhu vsimulace slouží vektor \texttt{actions}. |
---|
| 311 | Významy těchto hodnot vysvětluje \texttt{rv\_actions} třídy \texttt{RV}. V metodě \texttt{validate}, |
---|
| 312 | která se volá na začátku simulace, přidáme do \texttt{rv\_actions} hodntu \texttt{Tc}. Tím |
---|
| 313 | vlastně sdělíme AIMSUNu, že budeme přenastavovat délku cyklu. Protože délka jednotlivých fází se nepřenastavuje automaticky, |
---|
| 314 | přidáme do \texttt{rv\_actions} také označení těchto fází. Vpraxi je tento postup realizován kódem |
---|
| 315 | \begin{lstlisting} |
---|
| 316 | rv_action = RV("Tc",1); |
---|
| 317 | rv_action.add( RV(stage_names, ones_i(stage_names.length()))); |
---|
| 318 | \end{lstlisting} |
---|
| 319 | kde je v proměnné \texttt{stage\_names} uložen seznam fází. |
---|
| 320 | \\ |
---|
| 321 | \\ |
---|
| 322 | Následující metody se volají v každém cyklu simulace. |
---|
| 323 | |
---|
| 324 | |
---|
| 325 | |
---|
| 326 | \subsubsection{Metoda adapt} |
---|
| 327 | Na začátku každého simulačního cyklu se jako první volá u všech agentů metoda \texttt{adapt}. |
---|
| 328 | V parametru se jí předá adresa vektrou výstupních údajů simulace \texttt{glob\_dt}, k jejichž zpracování je metoda určena. |
---|
| 329 | Zde se předávají údaje z detektorů a délky front istancím třídy \texttt{LaneHandler} a poté se volá jejich metoda |
---|
| 330 | \texttt{countAvgs}, která počítá filtrované hodnoty způsobem popsaným v sekci \ref{ss:odhad_fronty}. |
---|
| 331 | |
---|
| 332 | |
---|
| 333 | \subsubsection{Metoda receive a broadcast} |
---|
| 334 | Po načtení a zpracování dat začíná komunikace. Ta je realizována metodami |
---|
| 335 | \texttt{broadcas} a \texttt{receive}, které se volají střídavě. Přesněji řečeno, |
---|
| 336 | hlavni smyčka nejprve volá metody \texttt{receive} každého agenta tak dlouho, dokud nevyprázdní frontu zpráv. |
---|
| 337 | Ta je reprezentována polem proměnných typu \texttt{Setting}, které mají nastaveny čtyři parametry: |
---|
| 338 | |
---|
| 339 | \begin{description} |
---|
| 340 | \item [from] určuje od koho zpráva přichází |
---|
| 341 | \item [to] má hodnotu jména agenta, pro kterého je zpráva určena |
---|
| 342 | \item [what] obsahuje co posíláme |
---|
| 343 | \item [value] obsahuje hodnotu spojenou s tím co posíláme |
---|
| 344 | \end{description} |
---|
| 345 | |
---|
| 346 | Každý agent má v atributu \texttt{name} uloženo jméno křižovatky, kterou ovládá. |
---|
| 347 | Toto jméno je uloženo v konfiguračním souboru a odpovídá označením ze sekce \ref{ss:oblast_simulace}. |
---|
| 348 | Pokud je jméno agenta stejné jako parametr zprávy \texttt{to}, vyjme se zpráva z frony a předá se |
---|
| 349 | metodě \texttt{receive}.V momentě, kdy je fronta prázdná, zavolají se metody \texttt{broadcast} všech agentů. |
---|
| 350 | Metoda broadcast opět plní frontu zprávami, které chce agent vyslat. Po jejím ukončení se opět volá \texttt{receive}. |
---|
| 351 | Střídavé volání těchto dvou metod probíhá, dokud \texttt{broadcast} produkuje nějaké zprávy. |
---|
| 352 | \\ |
---|
| 353 | \\ |
---|
| 354 | V našem případě probíhá odesílání ve dvou krocích. V obou se posílají zprávy všem ostatním agentům. |
---|
| 355 | Nejprve agent sdělí, jestli chce délku cyklu zvýšit, snížit, nebo ponechat stejnou. |
---|
| 356 | Pokud je pro zvýšení více než polovina agentů, začíná druhá fáze. |
---|
| 357 | V té každý agent pošle všechny délky cyklu v předem daném rozsahu a k nim očekávané zisky. |
---|
| 358 | Rozsah je od minimální do stávající při odhlasování snížení a od stávající do maximální při zvýšení. |
---|
| 359 | Zisk se počítá jako rozdíl čekací doby při navrhované a stávající délce cyklu pomocí metody popsané v \ref{ss:odhad_cekaci_doby}. |
---|
| 360 | Odeslání těchto zpráv je realizováno kódem |
---|
| 361 | \newpage |
---|
| 362 | \begin{lstlisting} |
---|
| 363 | int broadcast_width = (max_tc - min_tc) + 1; |
---|
| 364 | |
---|
| 365 | for ( int i = 0; i < broadcast_width; i++ ) { |
---|
| 366 | int time_cycle = min_tc + i*stepTc; |
---|
| 367 | double profit = getProfit(time_cycle); |
---|
| 368 | |
---|
| 369 | // send tc |
---|
| 370 | stringstream time_cycle_stream; |
---|
| 371 | time_cycle_stream << "tc_" << (i); |
---|
| 372 | send2allNeighbours( set, time_cycle_stream.str(), time_cycle); |
---|
| 373 | |
---|
| 374 | // send profit |
---|
| 375 | stringstream profit_stream; |
---|
| 376 | profit_stream << "profit_" << (i); |
---|
| 377 | send2allNeighbours( set, profit_stream.str(), profit ); |
---|
| 378 | } |
---|
| 379 | \end{lstlisting} |
---|
| 380 | |
---|
| 381 | Agent tedy vygeneruje pro každou hodnotu délky cyklu index, podle kterého se k ní dá přiřadit hodnota zisku. |
---|
| 382 | V metodě \texttt{receive} se podle tohoto indexu sčítají zisky do pole \texttt{received\_profit\_sum}. |
---|
| 383 | |
---|
| 384 | |
---|
| 385 | |
---|
| 386 | \subsubsection{Metoda act} |
---|
| 387 | Pokud se agenti dohodly na změně délky cyklu, probíhá její přenastavení v metodě act. |
---|
| 388 | Nejprve se projde pole \texttt{received\_profit\_sum} a vybere se z něj maximum. |
---|
| 389 | Poté se podle indexu maximálního zisku určí ideální délka fronty. |
---|
| 390 | \\ |
---|
| 391 | \\ |
---|
| 392 | Měření ukázala, že časté změny cyklu působí emulátorům řadičů problémy. |
---|
| 393 | Proto se ideální hodnota průměruje plovoucím průměrem a nastavuje se jednou za 5 cyklů. |
---|
| 394 | |
---|
| 395 | |
---|
| 396 | |
---|
| 397 | |
---|