[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} |
---|
[1150] | 59 | zapíše na adresu proměnné \texttt{inputs} hodnotu v objektu \texttt{set} třídy \texttt{Setting}, |
---|
| 60 | označenou jako \texttt{\"inputs\"}. Objekt \texttt{set} reprezentuje načtený konfigurační soubor. |
---|
[1147] | 61 | \texttt{UI::compulsory} značí, že daná hodnota musí být zadána. |
---|
| 62 | |
---|
| 63 | |
---|
| 64 | |
---|
[1150] | 65 | \subsubsection{Třída Datalink} |
---|
[1147] | 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 |
---|
[1150] | 72 | údajů z \texttt{from} do \texttt{to} pomocí třídy \texttt{Datalink}. Výsledkem je, že vektor |
---|
[1147] | 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} |
---|
[1150] | 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é zpracování dat z AIMSUNu. |
---|
[1147] | 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. |
---|
[1150] | 111 | Jedná se o největší počet automobilů v příslušném jízdním pruhu, jejichž rychlost nepřesahuje |
---|
[1147] | 112 | určitou hodnotu. V našem konkrétním případě je tato mezní rychlost nastavena na 3,6 km/h. |
---|
[1150] | 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 |
---|
[1147] | 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} |
---|
[1150] | 120 | K odhadu fronty je použito metody tzv. exponenciálního zapomínání. Metoda vychází z plovoucího průměru |
---|
[1147] | 121 | Který je vhodný pro odhad nekonstantní hodnoty. Označíme si veličinu $\overline{q_i}$ jako plovoucí průměr |
---|
[1150] | 122 | fronty v kroku $i$, kam budeme ukládat posledních $n$ měření. Označme si velikost fronty naměřenou v $i$-tém kroku jako$q_i$. |
---|
| 123 | V kroku $i+1$ je hodnota hodnota plovoucího průměru před přičtením poslední naměřené hodnoty rovna |
---|
[1147] | 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 | $$ |
---|
[1150] | 137 | $\frac{1}{n} (q_{i+1} - \overline{q_i}$ je vlastně přírůstek v kroku $i+1$, označme si ho jako $\Delta q_{i+1}$, |
---|
[1147] | 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 | $$ |
---|
[1150] | 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 kroku uložena i první hodnota, |
---|
[1147] | 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$. |
---|
[1150] | 145 | Graf \ref{fig:q1} pro konstantní délku cyklu 80 sekund, graf \ref{fig:q2} pro délku cyklu periodicky se měnící od 40 |
---|
[1147] | 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 | |
---|
[1150] | 163 | V reálném případě je potřeba vypočítat délku fronty podle záznamů z detektorů. |
---|
| 164 | Prostý výpočet délky fronty například jako rozdíl počtu vozidel, která odjela a která přijela však není možný. |
---|
| 165 | V důsledku problémů popsaných v \ref{sss:zpracovani_dat}. Výpočet délky fronty není předmětem zkoumání této práce. |
---|
| 166 | Podrobnější pojednání o tomto problému lze najít například v \cite{pecherkova}. |
---|
| 167 | \\ |
---|
| 168 | \\ |
---|
| 169 | Protože časté přenastavování délky cyklu působí řadičům problémy, přenastavuje se tento parametr jednou za časový |
---|
| 170 | úsek, ktrý je několikanásobně delší než 90 sekund. Je tedy nutné modelovat časový průběh fronty. Při rozšiřování testovacího |
---|
| 171 | prostředí tento model ovlivní i údaj o počtu vozidel, které přijedou ze sousední křižovatky. Tento údaj závisí na délce cyklu |
---|
| 172 | a není agentovy dostupný přímo. Bude tedy nutné rozšířit komunikaci agentů, popsanou v \ref{ss:komunikace}, o tento údaj. |
---|
| 173 | |
---|
| 174 | |
---|
[1147] | 175 | \subsection{Odhad čekací doby}\label{ss:odhad_cekaci_doby} |
---|
| 176 | Jednou z nejdůležitějších částí logiky, implementovaná v třídě \texttt{LaneHandler} je |
---|
[1150] | 177 | odhad čekací doby vozidel stojících v, nebo přijíždějících do příslušného jízdního pruhu. |
---|
[1147] | 178 | Tento odhad se používá při výběru a ohodnocení délky cyklu. |
---|
| 179 | \\ |
---|
| 180 | \\ |
---|
| 181 | Odahad se provádí zjednodušenou mikrosimulací po čas \texttt{T}. |
---|
| 182 | Do proměnné \texttt{q} se uloží aktuální hodnota fronty. |
---|
| 183 | Simulace začíná v čase \texttt{t = 0}. V každém kroku simulace |
---|
[1150] | 184 | se zvětší fronta o hustotu provozu (počt aut za sekundu), odhadovanou z údajů z detektorů, a pokud se čas nachází |
---|
[1147] | 185 | ve průjezdné fázi, zmenší se o konstantu, nazývanou saturovaný tok, která udává maximální počet aut, které projedou |
---|
| 186 | 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 |
---|
| 187 | \texttt{t} se zvětší o jednu sekundu. |
---|
| 188 | \\ |
---|
| 189 | \\ |
---|
[1150] | 190 | Odhad probíhá ve dvou fázích, realizovaných cykly typu \texttt{for}. V první běží čas do největší části \texttt{T}, |
---|
| 191 | soudělné s \texttt{tc}, v druhé po zbytek \texttt{T}. níže uvádím popis všech proměnných. |
---|
[1147] | 192 | \begin{description} |
---|
| 193 | \item[tc] délka cyklu, pro kterou je odhad prováděn (parametr funkce) |
---|
| 194 | \item[T] doba odhadu |
---|
| 195 | \item[ro] hustota provozu odhadovaná z dat z detektorů |
---|
| 196 | \item[cars\_in\_avg] filtrovaná data z detektorů (atribut třídy) |
---|
| 197 | \item[queue\_avg] filtrovaná naměřená délka fronty (atribut třídy) |
---|
| 198 | \item[q] délka fronty v průběhu odhadu |
---|
| 199 | \item[wt] součet čekacích časů |
---|
| 200 | \item[green\_time\_ratio] poměr délky zelené k délce cyklu (atribut třídy) |
---|
| 201 | \item[gt] doba, kdy je křižovatka pro pruh průjezdná |
---|
| 202 | \item[tc\_rest] čas v daném cyklu |
---|
| 203 | \item[tc\_last] zbytek odhadovací periody |
---|
| 204 | \item[gt\_last] délka zelené ve zbytku odhadovací periody |
---|
| 205 | \item[delta] korekční parametr vyjadřuje zkrácení doby průjezdnosti vlivem pomalých rozjezdů a podpbně |
---|
| 206 | \end{description} |
---|
| 207 | Odhad je implementován v metodě \texttt{getWT}: |
---|
| 208 | |
---|
| 209 | \begin{lstlisting} |
---|
| 210 | double getWT ( int tc ) { |
---|
| 211 | const int T = 450; // 5 scyklů |
---|
| 212 | double ro = cars_in_avg/90; |
---|
| 213 | double q = queue_avg; |
---|
| 214 | double wt = 0; |
---|
| 215 | double gt = tc*green_time_ratio - delta; |
---|
| 216 | int t_rest; |
---|
| 217 | int tc_last = T % tc; |
---|
| 218 | double gt_last = tc_last*green_time_ratio; |
---|
| 219 | for ( int t = 0; t < (T-tc_last); t++ ) { |
---|
| 220 | t_rest = t%tc; |
---|
| 221 | // zelena |
---|
| 222 | if ((tc-gt)/2<=t_rest&&t_rest<(tc+gt)/2) |
---|
| 223 | q -= saturated_stream; |
---|
| 224 | if ( q < 0) |
---|
| 225 | q = 0; |
---|
| 226 | wt += q; |
---|
| 227 | q += ro; |
---|
| 228 | } |
---|
| 229 | // zbytek |
---|
| 230 | for ( int t = 0; t < tc_last; t++ ) { |
---|
| 231 | // zelena |
---|
| 232 | if ((tc_last-gt_last)/2<=t&&t<(tc_last+gt_last)/2 ) |
---|
| 233 | q -= saturated_stream; |
---|
| 234 | if ( q < 0) |
---|
| 235 | q = 0; |
---|
| 236 | wt += q; |
---|
| 237 | q += ro; |
---|
| 238 | } |
---|
| 239 | return wt; |
---|
| 240 | } |
---|
| 241 | \end{lstlisting} |
---|
| 242 | |
---|
| 243 | |
---|
| 244 | |
---|
| 245 | \section{Hlavní smyčka} |
---|
| 246 | Hlavní smyčka programu se stará o synchronizaci všech potřebných parametrů a provádění iterací. |
---|
| 247 | Před započetím opakování kroku simulace nastaví podle konfiguračního souboru počáteční parametry mikrosimulátoru dopravy AIMSUN, |
---|
| 248 | jako jsou délka cyklu a fáze řadičů, inicializuje jednotlivé agenty a zavolá jejich metody \texttt{fromSettings} a \texttt{Validate}. |
---|
| 249 | |
---|
| 250 | \subsection{Krok simulace} |
---|
| 251 | Délka kroku simulace je pevně nastavena na 90 sekund shodně s periodou sběru dat z AIMSUNu. |
---|
| 252 | V jednom kroku se nejprve načtou data z AIMSUNu do vektoru \texttt{glob\_dt}, který se následně předá |
---|
[1150] | 253 | každému z agentů jako parametr jejich metody \texttt{adapt}. Následně se zprostředkuje komunikace mezi |
---|
[1147] | 254 | agenty tak, že se naplní fronta zpráv voláním metody \texttt{broadcast} jednotlivých agentů. Z této fronty |
---|
| 255 | se postupně odebírají zprávy, které se předávají agentům parametrem jejich metody \texttt{receive} |
---|
| 256 | Po ukončení komunikace naplní vektor výstupů \texttt{glob\_ut} voláním metod \texttt{act} hodotami parametrů |
---|
| 257 | pro AIMSUN, předá se mu a vyčká se do dalšího kroku. |
---|
| 258 | |
---|
| 259 | \section{Třída agenta} |
---|
[1150] | 260 | Třída \texttt{TrafficAgentCycleTime} je odvozena od obecného návrhu agenta \texttt{BaseTrafficAgent}. |
---|
[1147] | 261 | Jsou v ní implementovány metody pro načtení dat, komunikaci a nastavení délky cyklu za účelem řízení |
---|
| 262 | jedné konkrétní křižovatky. |
---|
| 263 | |
---|
| 264 | \subsection{Stručný popis algoritmu} |
---|
[1150] | 265 | Cíl algoritmu je zlepšit dopravní situaci nastavením délky cyklu řadiče na takovou |
---|
| 266 | hodnotu, při níž bude celková čekací doba všech vozidel minimální. |
---|
[1147] | 267 | Nejprve agent odhadne délku cyklu, která je ideální pro něj, poté vyšle zprávu, zda je tato hodnota |
---|
| 268 | vyšší nebo nižší než aktuální. Pokud je nadpoloviční většina agentů pro změnu stejným směrem, |
---|
| 269 | pokouší se najít hodnotu ideální pro všechny. |
---|
| 270 | |
---|
| 271 | \subsection{Výpočetní metody} |
---|
| 272 | |
---|
| 273 | \subsubsection{Metoda getWT} |
---|
| 274 | |
---|
| 275 | 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}. |
---|
| 276 | V cyklu projde instance tříd \texttt{LAneHandler}, na které má uloženy ukazatele v proměnné \texttt{lanehs} typu |
---|
| 277 | \texttt{Array<LaneHandler*>}. Pole se inicializuje v metodě \texttt{validate} předka \texttt{BaseTrafficAgent}. |
---|
| 278 | |
---|
| 279 | \subsubsection{Metoda findIdealTc}\label{sss:ideal_tc} |
---|
| 280 | Pro určení, zda vznést návrh na zvýšení či snížení délky cyklu, slouží metoda \texttt{findIdealTc}. |
---|
[1150] | 281 | Ta zjišťuje čekací doby pro všechny možnosti rozsahu od minimální do maximální hodnoty, určené atributy |
---|
[1147] | 282 | \texttt{minTc} a \texttt{maxTc}. Vrátí takovou délku cyklu, pro kterou je čekací doba nejmenší. |
---|
| 283 | \\ |
---|
| 284 | \\ |
---|
| 285 | Princip použití součtu čekacích dob automaticky upřednostňuje dopravní pruhy s větší |
---|
| 286 | vytížeností, což je žádoucí. Ostatní pruhy však zcela nepotlačuje. Tímto způsobem by se mělo |
---|
| 287 | dosáhnout optimální hodnoty pro celou křižovatku. |
---|
| 288 | |
---|
| 289 | \subsection{Přepsané metody předka} |
---|
[1150] | 290 | Hlavní smyčka programu automaticky volá v každém cyklu metody určené |
---|
[1147] | 291 | k načtení dat, komunikaci a nastavení dalšího řízení. |
---|
| 292 | |
---|
| 293 | |
---|
| 294 | |
---|
| 295 | \subsubsection{Metoda validate} |
---|
[1150] | 296 | K předání požadovaných hodnot parametrů v průběhu simulace slouží vektor \texttt{actions}. |
---|
[1147] | 297 | Významy těchto hodnot vysvětluje \texttt{rv\_actions} třídy \texttt{RV}. V metodě \texttt{validate}, |
---|
[1150] | 298 | která se volá na začátku simulace, přidáme do \texttt{rv\_actions} hodnotu \texttt{Tc}. Tím |
---|
[1147] | 299 | vlastně sdělíme AIMSUNu, že budeme přenastavovat délku cyklu. Protože délka jednotlivých fází se nepřenastavuje automaticky, |
---|
[1150] | 300 | přidáme do \texttt{rv\_actions} také označení těchto fází. V praxi je tento postup realizován kódem |
---|
[1147] | 301 | \begin{lstlisting} |
---|
| 302 | rv_action = RV("Tc",1); |
---|
| 303 | rv_action.add( RV(stage_names, ones_i(stage_names.length()))); |
---|
| 304 | \end{lstlisting} |
---|
| 305 | kde je v proměnné \texttt{stage\_names} uložen seznam fází. |
---|
| 306 | \\ |
---|
| 307 | \\ |
---|
| 308 | Následující metody se volají v každém cyklu simulace. |
---|
| 309 | |
---|
| 310 | |
---|
| 311 | |
---|
| 312 | \subsubsection{Metoda adapt} |
---|
| 313 | Na začátku každého simulačního cyklu se jako první volá u všech agentů metoda \texttt{adapt}. |
---|
[1150] | 314 | V parametru se jí předá adresa vektoru výstupních údajů simulace \texttt{glob\_dt}, k jejichž zpracování je metoda určena. |
---|
| 315 | Zde se předávají údaje z detektorů a délky front instancím třídy \texttt{LaneHandler} a poté se volá jejich metoda |
---|
[1147] | 316 | \texttt{countAvgs}, která počítá filtrované hodnoty způsobem popsaným v sekci \ref{ss:odhad_fronty}. |
---|
| 317 | |
---|
| 318 | |
---|
[1150] | 319 | \subsubsection{Metoda receive a broadcast} \label{ss:komunikace} |
---|
[1147] | 320 | Po načtení a zpracování dat začíná komunikace. Ta je realizována metodami |
---|
| 321 | \texttt{broadcas} a \texttt{receive}, které se volají střídavě. Přesněji řečeno, |
---|
| 322 | hlavni smyčka nejprve volá metody \texttt{receive} každého agenta tak dlouho, dokud nevyprázdní frontu zpráv. |
---|
| 323 | Ta je reprezentována polem proměnných typu \texttt{Setting}, které mají nastaveny čtyři parametry: |
---|
| 324 | |
---|
| 325 | \begin{description} |
---|
| 326 | \item [from] určuje od koho zpráva přichází |
---|
| 327 | \item [to] má hodnotu jména agenta, pro kterého je zpráva určena |
---|
| 328 | \item [what] obsahuje co posíláme |
---|
| 329 | \item [value] obsahuje hodnotu spojenou s tím co posíláme |
---|
| 330 | \end{description} |
---|
| 331 | |
---|
| 332 | Každý agent má v atributu \texttt{name} uloženo jméno křižovatky, kterou ovládá. |
---|
| 333 | Toto jméno je uloženo v konfiguračním souboru a odpovídá označením ze sekce \ref{ss:oblast_simulace}. |
---|
[1150] | 334 | Pokud je jméno agenta stejné jako parametr zprávy \texttt{to}, vyjme se zpráva z fronty a předá se |
---|
[1147] | 335 | metodě \texttt{receive}.V momentě, kdy je fronta prázdná, zavolají se metody \texttt{broadcast} všech agentů. |
---|
[1150] | 336 | Metoda \texttt{broadcast} opět plní frontu zprávami, které chce agent vyslat. Po jejím ukončení se opět volá \texttt{receive}. |
---|
[1147] | 337 | Střídavé volání těchto dvou metod probíhá, dokud \texttt{broadcast} produkuje nějaké zprávy. |
---|
| 338 | \\ |
---|
| 339 | \\ |
---|
| 340 | 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. |
---|
| 341 | Nejprve agent sdělí, jestli chce délku cyklu zvýšit, snížit, nebo ponechat stejnou. |
---|
| 342 | Pokud je pro zvýšení více než polovina agentů, začíná druhá fáze. |
---|
| 343 | 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. |
---|
| 344 | 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í. |
---|
| 345 | 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}. |
---|
| 346 | Odeslání těchto zpráv je realizováno kódem |
---|
| 347 | \begin{lstlisting} |
---|
| 348 | int broadcast_width = (max_tc - min_tc) + 1; |
---|
| 349 | |
---|
| 350 | for ( int i = 0; i < broadcast_width; i++ ) { |
---|
| 351 | int time_cycle = min_tc + i*stepTc; |
---|
| 352 | double profit = getProfit(time_cycle); |
---|
| 353 | |
---|
| 354 | // send tc |
---|
| 355 | stringstream time_cycle_stream; |
---|
| 356 | time_cycle_stream << "tc_" << (i); |
---|
| 357 | send2allNeighbours( set, time_cycle_stream.str(), time_cycle); |
---|
| 358 | |
---|
| 359 | // send profit |
---|
| 360 | stringstream profit_stream; |
---|
| 361 | profit_stream << "profit_" << (i); |
---|
| 362 | send2allNeighbours( set, profit_stream.str(), profit ); |
---|
| 363 | } |
---|
| 364 | \end{lstlisting} |
---|
| 365 | |
---|
| 366 | Agent tedy vygeneruje pro každou hodnotu délky cyklu index, podle kterého se k ní dá přiřadit hodnota zisku. |
---|
| 367 | V metodě \texttt{receive} se podle tohoto indexu sčítají zisky do pole \texttt{received\_profit\_sum}. |
---|
| 368 | |
---|
| 369 | |
---|
| 370 | |
---|
[1150] | 371 | \subsubsection{Metoda act}\label{sss:metoda_act} |
---|
| 372 | Pokud se agenti dohodly na změně délky cyklu, probíhá její přenastavení v metodě \texttt{act}. |
---|
[1147] | 373 | Nejprve se projde pole \texttt{received\_profit\_sum} a vybere se z něj maximum. |
---|
| 374 | Poté se podle indexu maximálního zisku určí ideální délka fronty. |
---|
| 375 | \\ |
---|
| 376 | \\ |
---|
| 377 | Měření ukázala, že časté změny cyklu působí emulátorům řadičů problémy. |
---|
| 378 | Proto se ideální hodnota průměruje plovoucím průměrem a nastavuje se jednou za 5 cyklů. |
---|
| 379 | |
---|
| 380 | |
---|
| 381 | |
---|
| 382 | |
---|