root/applications/doprava/texty/delka_cyklu/05_AlgorithmDescription/AlgorithmDescription.tex.backup @ 1147

Revision 1147, 18.9 kB (checked in by jabu, 14 years ago)
Line 
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++}
10IT++ je knihovna jazyka C++ zahrnující třídy pro matematické výpočty a komunikaci.
11Umožňuje práci s vektory a maticemi podobným způsobem jako v nástroji MATLAB.
12Použity jsou třídy \texttt{vec} a \texttt{Array}.
13
14
15\subsubsection{Třída vec}
16Třída \texttt{vec} reprezentuje vektor hodnot číselného typu \texttt{double}.
17Přetížením operátorů kulatých a hranatých závorek a operátoru \texttt{=} umožňuje jednoduchou inicializaci
18vektoru pomocí textového řetězce a zjednodušuje přístup k jednotlivým hodnotám.
19Kó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}
25inicializuje vektor o dimenzi 3 s hodnotami 0,1, 0,2 a 0,3 a poté
26vypíše první a druhý prvek vektoru.
27
28\subsubsection{Třída Array}
29Tato šablonová třída umožňuje pracovat s polem o proměnných předem daného libovolného typu.
30Rozměr pole se může v průběhu programu měnit.
31
32
33\subsection{BDM}
34Knihovna BDM (Bayesian Decision Making) je navržena pro programy používající
35Bayesovu statistiku. Zde jsou použity hlavně třídy \texttt{Datalink}, \texttt{RV}, \texttt{UI} a \texttt{Setting}
36sloužící pro komunikaci s mikrosimulátorem AIMSUN, načítání hodnot z konfiguračních souborů a komunikaci mezi agenty.
37\\
38\\
39V 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}
44Třída \texttt{RV} implementuje pole popisků k vektorům třídy IT++.
45K přístupu k jednotlivým slouží přetížený operátor závorky \texttt{(int index)}.
46K 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}
54UI a Setting slouží mimo jiné k načtení vybraných dat z konfiguračních souborů.
55Kód
56\begin{lstlisting}
57    UI::get(inputs,set,"inputs",UI::compulsory);
58\end{lstlisting}
59zapíše na adresu proměnné inputs hodnotu v oběktu \texttt{set} třídy \texttt{Setting},
60označ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}
66Tato třída definuje spojení mezi dvěma vektory, mezi kterými zprostředkovává spojení
67pomocí metody \texttt{filldown}.
68\\
69\\
70Následující kód popisuje vytvoření dvou vektorů \texttt{from} a \texttt{to},
71popsaný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}
96Každá instance třídy Lane reprezentuje jeden dopravní pruh.
97Po 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ů
99a AIMSUNu, jako je na příklad maximální délka
100fronty na dopravním pruhu za jednu simulační periodu.
101
102
103\section{Třída LaneHandler}
104Tato třída zprostředkovává přístup agentovi k ůdajům z jednotlivých pruhů.
105Stará se o zaznamenávání a statistické spracování dat z AIMSUNu.
106Také je zde implementován odhad čekací doby automobilu do průjezdu křižovatkou,
107což je údaj používaný v hodnotící délky cyklu funkci agenta.
108
109\subsection{Fronta}
110Agent předává třídě LaneHandler údaj o maximální délce fronty za vzorkovací periodu.
111Jedná se o největší počet automobilů v příslušném jízdním pruhu, jejichž rychlost reřesahuje
112určitou hodnotu. V našem konkrétním případě je tato mezní rychlost nastavena na 3,6 km/h.
113Tento ů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
114se vzorkovací periodou. Uvažujme jízdní pruh s poměrem délky zelené 0,5.
115Pokud bude například délka cyklu 180 sekund, a budeme li předpokládat, že začátek jedné periody se bude shodovat s časem,
116kdy na příslušném semaforu naskočí zelená, bude v první vzorkovací periodě pruh průjezdný po dobu 45 sekund, ale
117v další nebude průjezdný vůbec a fronta se za stejné hustoty provozu zvětší.
118
119\subsection{Odhad fronty}\label{ss:odhad_fronty}
120K odhadu fronty je použito metody tzv. exponencionálního zapomínání. Metoda vychází z povoucího průměru
121Který je vhodný pro odhad nekonstantní hodnoty. Označíme si veličinu $\overline{q_i}$  jako plovoucí průměr
122fronty 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$.
123V 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
128Obsahuje 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$$
132Abychom 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
133jeho 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}$,
138a 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$$
142Prů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,
143má však zanedbatelnou váhu $\left(\frac{n-1}{n}\right)^i$. Jedná se o jaksi zjednodušenou verzi Kalmanova filtru.
144Grafy \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$.
145Graf \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
146do 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}
164Jednou z nejdůležitějších částí logiky, implementovaná v třídě \texttt{LaneHandler} je
165odhad čekací doby vozidel stojících v, nebo přijíždějících do příslušnéjo jízdního pruhu.
166Tento odhad se používá při výběru a ohodnocení délky cyklu.
167\\
168\\
169Odahad se provádí zjednodušenou mikrosimulací po čas \texttt{T}.
170Do proměnné \texttt{q} se uloží aktuální hodnota fronty.
171Simulace začíná v čase \texttt{t = 0}. V každém kroku simulace
172se zvětší fronta o hustotu provozu (počt aut za sekundu), odhadovanou z údaů z detektorů, a pokud se čas nachází
173ve průjezdné fázi, zmenší se o konstantu, nazývanou saturovaný tok, která udává maximální počet aut, které projedou
174kř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\\
178Odhad probíhá ve dvou fázích, realizovaných cykly typu \texttt{for}. V první běží čas do nevětší části \texttt{T},
179soudě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}
195Odhad 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$}
233Delta vyjadřuje korekční parametr doby průjezdnosti křižovatky.
234Jak jsme již ukázali v kapitole \ref{ss:odhad_cekaci_doby}, počet vozidel, které projedou křižovatkou
235za jeden cyklus řadiče je
236$$
237(r_g T_c - \delta) s_s.
238$$
239To 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$
240změnit o
241$$
242\Delta q_{T_c} = n_{Tc} - (r_g T_c - \delta) s_s,
243$$
244
245kde $n_{Tc}$ je počet vozidel, přijíždějících na křižovatku za dobu $T_c$.
246Tento údaj je vlastně výstup z detektorů, který je nám však dostupný pouze
247jednou za simulační cyklus, trvající 90 sekund. Protože pracujeme s filtrovanými hodnotami front,
248nedojde 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$$
252z č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$$
256Jak údaje o projíždejících vozidlech za simulační cyklus $n_{90}$, tak parametry $\delta$, jsou filtrovány
257způsobem, použitým na odhad délky fronty a popsaným v kapitole \ref{ss:odhad_fronty}.
258
259\section{Hlavní smyčka}
260Hlavní smyčka programu se stará o synchronizaci všech potřebných parametrů a provádění iterací.
261Před započetím opakování kroku simulace nastaví podle konfiguračního souboru počáteční parametry mikrosimulátoru dopravy AIMSUN,
262jako 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}
265Délka kroku simulace je pevně nastavena na 90 sekund shodně s periodou sběru dat z AIMSUNu.
266V jednom kroku se nejprve načtou data z AIMSUNu do vektoru \texttt{glob\_dt}, který se následně předá
267každému z agentů jako paramentr jejich metody \texttt{adapt}. Následně se zprostředkuje komunikace mezi
268agenty tak, že se naplní fronta zpráv voláním metody \texttt{broadcast} jednotlivých agentů. Z této fronty
269se postupně odebírají zprávy, které se předávají agentům parametrem jejich metody \texttt{receive}
270Po ukončení komunikace naplní vektor výstupů \texttt{glob\_ut} voláním metod \texttt{act} hodotami parametrů
271pro AIMSUN, předá se mu a vyčká se do dalšího kroku.
272
273\section{Třída agenta}
274Třída \texttt{TrafficAgentCycleTime} je odvozena od obecného návrhu agnta \texttt{BaseTrafficAgent}.
275Jsou v ní implementovány metody pro načtení dat, komunikaci a nastavení délky cyklu za účelem řízení
276jedné konkrétní křižovatky.
277
278\subsection{Stručný popis algoritmu}
279Cíl algoritmu je zlepšit dopravní situaci nastavením délky cyklu řadiče na tekouvou
280hodnotu, při níž bude celková čekací doba všech vozidel mininmální.
281Nejprve agent odhadne délku cyklu, která je ideální pro něj, poté vyšle zprávu, zda je tato hodnota
282vyšší nebo nižší než aktuální. Pokud je nadpoloviční většina agentů pro změnu stejným směrem,
283pokouší se najít hodnotu ideální pro všechny.
284
285\subsection{Výpočetní metody}
286
287\subsubsection{Metoda getWT}
288
289Tato 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}.
290V 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}
294Pro určení, zda vznést návrh na zvýšení či snížení délky cyklu, slouží metoda \texttt{findIdealTc}.
295Ta 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\\
299Princip použití součtu čekacích dob automaticky upřednostňuje dopravní pruhy s větší
300vytížeností, což je žádoucí. Ostatní pruhy však zcela nepotlačuje. Tímto způsobem by se mělo
301dosáhnout optimální hodnoty pro celou křižovatku.
302
303\subsection{Přepsané metody předka}
304Hlavní smyčka progaramu automaticky volá v každém cyklu metody určené
305k načtení dat, komunikaci a nastavení dalšího řízení.
306
307
308
309\subsubsection{Metoda validate}
310K předání požadovaných hodnot parametrů v průběhu vsimulace slouží vektor \texttt{actions}.
311Významy těchto hodnot vysvětluje \texttt{rv\_actions} třídy \texttt{RV}. V metodě \texttt{validate},
312která se volá na začátku simulace, přidáme do \texttt{rv\_actions} hodntu \texttt{Tc}. Tím
313vlastně sdělíme AIMSUNu, že budeme přenastavovat délku cyklu. Protože délka jednotlivých fází se nepřenastavuje automaticky,
314př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}
319kde je v proměnné \texttt{stage\_names} uložen seznam fází.
320\\
321\\
322Následující metody se volají v každém cyklu simulace.
323
324
325
326\subsubsection{Metoda adapt}
327Na začátku každého simulačního cyklu se jako první volá u všech agentů metoda \texttt{adapt}.
328V parametru se jí předá adresa vektrou výstupních údajů simulace \texttt{glob\_dt}, k jejichž zpracování je metoda určena.
329Zde 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}
334Po 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,
336hlavni smyčka nejprve volá metody \texttt{receive} každého agenta tak dlouho, dokud nevyprázdní frontu zpráv.
337Ta 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
346Každý agent má v atributu \texttt{name} uloženo jméno křižovatky, kterou ovládá.
347Toto jméno je uloženo v konfiguračním souboru a odpovídá označením ze sekce \ref{ss:oblast_simulace}.
348Pokud je jméno agenta stejné jako parametr zprávy \texttt{to}, vyjme se zpráva z frony a předá se
349metodě \texttt{receive}.V momentě, kdy je fronta prázdná, zavolají se metody \texttt{broadcast} všech agentů.
350Metoda broadcast opět plní frontu zprávami, které chce agent vyslat. Po jejím ukončení se opět volá \texttt{receive}.
351Střídavé volání těchto dvou metod probíhá, dokud \texttt{broadcast} produkuje nějaké zprávy.
352\\
353\\
354V 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.
355Nejprve agent sdělí, jestli chce délku cyklu zvýšit, snížit, nebo ponechat stejnou.
356Pokud je pro zvýšení více než polovina agentů, začíná druhá fáze.
357V té každý agent pošle všechny délky cyklu v předem daném rozsahu a k nim očekávané zisky.
358Rozsah 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í.
359Zisk 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}.
360Odeslá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
381Agent tedy vygeneruje pro každou hodnotu délky cyklu index, podle kterého se k ní dá přiřadit hodnota zisku.
382V metodě \texttt{receive} se podle tohoto indexu sčítají zisky do pole \texttt{received\_profit\_sum}.
383
384
385
386\subsubsection{Metoda act}
387Pokud se agenti dohodly na změně délky cyklu, probíhá její přenastavení v metodě act.
388Nejprve se projde pole \texttt{received\_profit\_sum} a vybere se z něj maximum.
389Poté se podle indexu maximálního zisku určí ideální délka fronty.
390\\
391\\
392Měření ukázala, že časté změny cyklu působí emulátorům řadičů problémy.
393Proto se ideální hodnota průměruje plovoucím průměrem a nastavuje se jednou za 5 cyklů.
394
395
396
397
Note: See TracBrowser for help on using the browser.