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

Revision 1147, 17.7 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í doby 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
233
234\section{Hlavní smyčka}
235Hlavní smyčka programu se stará o synchronizaci všech potřebných parametrů a provádění iterací.
236Před započetím opakování kroku simulace nastaví podle konfiguračního souboru počáteční parametry mikrosimulátoru dopravy AIMSUN,
237jako jsou délka cyklu a fáze řadičů, inicializuje jednotlivé agenty a zavolá jejich metody \texttt{fromSettings} a \texttt{Validate}.
238
239\subsection{Krok simulace}
240Délka kroku simulace je pevně nastavena na 90 sekund shodně s periodou sběru dat z AIMSUNu.
241V jednom kroku se nejprve načtou data z AIMSUNu do vektoru \texttt{glob\_dt}, který se následně předá
242každému z agentů jako paramentr jejich metody \texttt{adapt}. Následně se zprostředkuje komunikace mezi
243agenty tak, že se naplní fronta zpráv voláním metody \texttt{broadcast} jednotlivých agentů. Z této fronty
244se postupně odebírají zprávy, které se předávají agentům parametrem jejich metody \texttt{receive}
245Po ukončení komunikace naplní vektor výstupů \texttt{glob\_ut} voláním metod \texttt{act} hodotami parametrů
246pro AIMSUN, předá se mu a vyčká se do dalšího kroku.
247
248\section{Třída agenta}
249Třída \texttt{TrafficAgentCycleTime} je odvozena od obecného návrhu agnta \texttt{BaseTrafficAgent}.
250Jsou v ní implementovány metody pro načtení dat, komunikaci a nastavení délky cyklu za účelem řízení
251jedné konkrétní křižovatky.
252
253\subsection{Stručný popis algoritmu}
254Cíl algoritmu je zlepšit dopravní situaci nastavením délky cyklu řadiče na tekouvou
255hodnotu, při níž bude celková čekací doba všech vozidel mininmální.
256Nejprve agent odhadne délku cyklu, která je ideální pro něj, poté vyšle zprávu, zda je tato hodnota
257vyšší nebo nižší než aktuální. Pokud je nadpoloviční většina agentů pro změnu stejným směrem,
258pokouší se najít hodnotu ideální pro všechny.
259
260\subsection{Výpočetní metody}
261
262\subsubsection{Metoda getWT}
263
264Tato 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}.
265V cyklu projde instance tříd \texttt{LAneHandler}, na které má uloženy ukazatele v proměnné \texttt{lanehs} typu
266\texttt{Array<LaneHandler*>}. Pole se inicializuje v metodě \texttt{validate} předka \texttt{BaseTrafficAgent}.
267
268\subsubsection{Metoda findIdealTc}\label{sss:ideal_tc}
269Pro určení, zda vznést návrh na zvýšení či snížení délky cyklu, slouží metoda \texttt{findIdealTc}.
270Ta zjišťuje čekací doby pro všechny možnosti rozsahu od mininmální do maximální hodnoty, určené atributy
271\texttt{minTc} a \texttt{maxTc}. Vrátí takovou délku cyklu, pro kterou je čekací doba nejmenší.
272\\
273\\
274Princip použití součtu čekacích dob automaticky upřednostňuje dopravní pruhy s větší
275vytížeností, což je žádoucí. Ostatní pruhy však zcela nepotlačuje. Tímto způsobem by se mělo
276dosáhnout optimální hodnoty pro celou křižovatku.
277
278\subsection{Přepsané metody předka}
279Hlavní smyčka progaramu automaticky volá v každém cyklu metody určené
280k načtení dat, komunikaci a nastavení dalšího řízení.
281
282
283
284\subsubsection{Metoda validate}
285K předání požadovaných hodnot parametrů v průběhu vsimulace slouží vektor \texttt{actions}.
286Významy těchto hodnot vysvětluje \texttt{rv\_actions} třídy \texttt{RV}. V metodě \texttt{validate},
287která se volá na začátku simulace, přidáme do \texttt{rv\_actions} hodntu \texttt{Tc}. Tím
288vlastně sdělíme AIMSUNu, že budeme přenastavovat délku cyklu. Protože délka jednotlivých fází se nepřenastavuje automaticky,
289přidáme do \texttt{rv\_actions} také označení těchto fází. Vpraxi je tento postup realizován kódem
290\begin{lstlisting}
291  rv_action = RV("Tc",1);
292  rv_action.add( RV(stage_names, ones_i(stage_names.length())));
293\end{lstlisting}
294kde je v proměnné \texttt{stage\_names} uložen seznam fází.
295\\
296\\
297Následující metody se volají v každém cyklu simulace.
298
299
300
301\subsubsection{Metoda adapt}
302Na začátku každého simulačního cyklu se jako první volá u všech agentů metoda \texttt{adapt}.
303V parametru se jí předá adresa vektrou výstupních údajů simulace \texttt{glob\_dt}, k jejichž zpracování je metoda určena.
304Zde se předávají údaje z detektorů a délky front istancím třídy \texttt{LaneHandler} a poté se volá jejich metoda
305\texttt{countAvgs}, která počítá filtrované hodnoty způsobem popsaným v sekci \ref{ss:odhad_fronty}.
306
307
308\subsubsection{Metoda receive a broadcast}
309Po načtení a zpracování dat začíná komunikace. Ta je realizována metodami
310\texttt{broadcas} a \texttt{receive}, které se volají střídavě. Přesněji řečeno,
311hlavni smyčka nejprve volá metody \texttt{receive} každého agenta tak dlouho, dokud nevyprázdní frontu zpráv.
312Ta je reprezentována polem proměnných typu \texttt{Setting}, které mají nastaveny čtyři parametry:
313
314\begin{description}
315 \item [from] určuje od koho zpráva přichází
316 \item [to] má hodnotu jména agenta, pro kterého je zpráva určena
317 \item [what] obsahuje co posíláme
318 \item [value] obsahuje hodnotu spojenou s tím co posíláme
319\end{description}
320
321Každý agent má v atributu \texttt{name} uloženo jméno křižovatky, kterou ovládá.
322Toto jméno je uloženo v konfiguračním souboru a odpovídá označením ze sekce \ref{ss:oblast_simulace}.
323Pokud je jméno agenta stejné jako parametr zprávy \texttt{to}, vyjme se zpráva z frony a předá se
324metodě \texttt{receive}.V momentě, kdy je fronta prázdná, zavolají se metody \texttt{broadcast} všech agentů.
325Metoda broadcast opět plní frontu zprávami, které chce agent vyslat. Po jejím ukončení se opět volá \texttt{receive}.
326Střídavé volání těchto dvou metod probíhá, dokud \texttt{broadcast} produkuje nějaké zprávy.
327\\
328\\
329V 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.
330Nejprve agent sdělí, jestli chce délku cyklu zvýšit, snížit, nebo ponechat stejnou.
331Pokud je pro zvýšení více než polovina agentů, začíná druhá fáze.
332V té každý agent pošle všechny délky cyklu v předem daném rozsahu a k nim očekávané zisky.
333Rozsah 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í.
334Zisk 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}.
335Odeslání těchto zpráv je realizováno kódem
336\begin{lstlisting}
337  int broadcast_width = (max_tc - min_tc) + 1;
338
339  for ( int i = 0; i < broadcast_width; i++ ) {
340    int time_cycle = min_tc + i*stepTc;
341    double profit = getProfit(time_cycle);
342   
343    // send tc
344    stringstream time_cycle_stream;
345    time_cycle_stream << "tc_" << (i);
346    send2allNeighbours( set, time_cycle_stream.str(), time_cycle);
347
348    // send profit
349    stringstream profit_stream;
350    profit_stream << "profit_" << (i);
351    send2allNeighbours( set, profit_stream.str(), profit );
352  }
353\end{lstlisting}
354
355Agent tedy vygeneruje pro každou hodnotu délky cyklu index, podle kterého se k ní dá přiřadit hodnota zisku.
356V metodě \texttt{receive} se podle tohoto indexu sčítají zisky do pole \texttt{received\_profit\_sum}.
357
358
359
360\subsubsection{Metoda act}
361Pokud se agenti dohodly na změně délky cyklu, probíhá její přenastavení v metodě act.
362Nejprve se projde pole \texttt{received\_profit\_sum} a vybere se z něj maximum.
363Poté se podle indexu maximálního zisku určí ideální délka fronty.
364\\
365\\
366Měření ukázala, že časté změny cyklu působí emulátorům řadičů problémy.
367Proto se ideální hodnota průměruje plovoucím průměrem a nastavuje se jednou za 5 cyklů.
368
369
370
371
Note: See TracBrowser for help on using the browser.