1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
---|
2 | <html xmlns="http://www.w3.org/1999/xhtml"> |
---|
3 | <head> |
---|
4 | <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> |
---|
5 | <title>mixpp: Howto Use BDM - Introduction</title> |
---|
6 | <link href="tabs.css" rel="stylesheet" type="text/css"/> |
---|
7 | <link href="doxygen.css" rel="stylesheet" type="text/css"/> |
---|
8 | </head> |
---|
9 | <body> |
---|
10 | <!-- Generated by Doxygen 1.6.1 --> |
---|
11 | <script type="text/javascript"> |
---|
12 | <!-- |
---|
13 | function changeDisplayState (e){ |
---|
14 | var num=this.id.replace(/[^[0-9]/g,''); |
---|
15 | var button=this.firstChild; |
---|
16 | var sectionDiv=document.getElementById('dynsection'+num); |
---|
17 | if (sectionDiv.style.display=='none'||sectionDiv.style.display==''){ |
---|
18 | sectionDiv.style.display='block'; |
---|
19 | button.src='open.gif'; |
---|
20 | }else{ |
---|
21 | sectionDiv.style.display='none'; |
---|
22 | button.src='closed.gif'; |
---|
23 | } |
---|
24 | } |
---|
25 | function initDynSections(){ |
---|
26 | var divs=document.getElementsByTagName('div'); |
---|
27 | var sectionCounter=1; |
---|
28 | for(var i=0;i<divs.length-1;i++){ |
---|
29 | if(divs[i].className=='dynheader'&&divs[i+1].className=='dynsection'){ |
---|
30 | var header=divs[i]; |
---|
31 | var section=divs[i+1]; |
---|
32 | var button=header.firstChild; |
---|
33 | if (button!='IMG'){ |
---|
34 | divs[i].insertBefore(document.createTextNode(' '),divs[i].firstChild); |
---|
35 | button=document.createElement('img'); |
---|
36 | divs[i].insertBefore(button,divs[i].firstChild); |
---|
37 | } |
---|
38 | header.style.cursor='pointer'; |
---|
39 | header.onclick=changeDisplayState; |
---|
40 | header.id='dynheader'+sectionCounter; |
---|
41 | button.src='closed.gif'; |
---|
42 | section.id='dynsection'+sectionCounter; |
---|
43 | section.style.display='none'; |
---|
44 | section.style.marginLeft='14px'; |
---|
45 | sectionCounter++; |
---|
46 | } |
---|
47 | } |
---|
48 | } |
---|
49 | window.onload = initDynSections; |
---|
50 | --> |
---|
51 | </script> |
---|
52 | <div class="navigation" id="top"> |
---|
53 | <div class="tabs"> |
---|
54 | <ul> |
---|
55 | <li><a href="main.html"><span>Main Page</span></a></li> |
---|
56 | <li class="current"><a href="pages.html"><span>Related Pages</span></a></li> |
---|
57 | <li><a href="annotated.html"><span>Classes</span></a></li> |
---|
58 | <li><a href="files.html"><span>Files</span></a></li> |
---|
59 | </ul> |
---|
60 | </div> |
---|
61 | </div> |
---|
62 | <div class="contents"> |
---|
63 | |
---|
64 | |
---|
65 | <h1><a class="anchor" id="user_guide">Howto Use BDM - Introduction </a></h1><p></p> |
---|
66 | <p>BDM is a library of basic components for Bayesian decision making, hence its direct use is not possible. In order to use BDM the components must be pulled together in order to achieve desired functionality. We expect two kinds of users:</p> |
---|
67 | <ul> |
---|
68 | <li><b> Basic users </b> who run prepared scripts with different parameterizations and analyze their results,</li> |
---|
69 | <li><b> Advanced users </b> who are able to understand the logic of BDM and extend its functionality to new applications.</li> |
---|
70 | </ul> |
---|
71 | <p>The primary design aim of BDM was to ease development of complex algorithms, hence the target user is the advanced one. However, running experiments is the first task to learn for both types of users.</p> |
---|
72 | <h2><a class="anchor" id="param"> |
---|
73 | Experiment is fully parameterized before execution</a></h2> |
---|
74 | <p>Experiments in BDM can be performed using either standalone applications or function bindings in high-level environment. A typical example of the latter being mex file in Matlab environment.</p> |
---|
75 | <p>The main logic behind the experiment is that all necessary information about it are gathered in advance in a configuration file (for standalone applications) or in configuration structure (Matlab). This approach was designed especially for time consuming experiments and Monte-Carlo studies for which it suits the most.</p> |
---|
76 | <p>For smaller decision making tasks, interactive use of the experiment can be achieved by showing the full configuration structure (or its selected parts), running the experiment on demand and showing the results.</p> |
---|
77 | <p>Semi-interactive experiments can be designed by sequential run of different algorithms. This topic will be covered in advanced documentation.</p> |
---|
78 | <h2><a class="anchor" id="config"> |
---|
79 | Configuration of an experiment</a></h2> |
---|
80 | <p>Configuration file (or config structure) is organized as a tree of information. High levels represent bigger structures, leafs of the structures are basic data elements such as strings, numbers or vectors.</p> |
---|
81 | <p>Specific treatment was developed for objects. Since BDM is designed as object oriented library, the configuration was designed to honor the rule of inheritance. That is, offspring of a class can be used in place of its predecessor. Hence, objects (instances of classes) are configured by a structure with compulsory field <code>class</code>. This is a string variable corresponding to the name of the class to be used.</p> |
---|
82 | <p>Consider the following example: </p> |
---|
83 | <div class="fragment"><pre class="fragment">DS = {<span class="keyword">class</span>=<span class="stringliteral">"MemDS"</span>; |
---|
84 | data = [1, 2, 3, 4, 5, 6, 7]; |
---|
85 | } |
---|
86 | </pre></div><p> or written equivalently in Matlab as </p> |
---|
87 | <div class="fragment"><pre class="fragment">DS.class=<span class="stringliteral">'MemDS'</span>; |
---|
88 | DS.Data =[1 2 3 4 5 6]; |
---|
89 | </pre></div><p>The code above is the minimum necessary information to run a pre-made algorithm implemented as executable <code>estimator</code> or Matlab mex file <code>estimator</code>. The expected result for Matlab is: </p> |
---|
90 | <div class="fragment"><pre class="fragment">>> M=estimator(DS,{}) |
---|
91 | |
---|
92 | M = |
---|
93 | |
---|
94 | ch0: [6x1 <span class="keywordtype">double</span>] |
---|
95 | </pre></div><p>The structure <code>M</code> has one field called <code>ch0</code> to which the data from <code>DS.Data</code> were copied. This was configured to be the default behavior which can be easily changed by adding more information to the configuration structure.</p> |
---|
96 | <p>First, we will have a look at all options of MemDS.</p> |
---|
97 | <h2><a class="anchor" id="memds"> |
---|
98 | How to understand configuration of classes</a></h2> |
---|
99 | <p>As a first step, the estimator algorithm has created an object of class MemDS and called its method <a class="el" href="classbdm_1_1MemDS.html#afaebfe6d7a2a43421be05d8cf7d7ae45">bdm::MemDS::from_setting()</a>. This is a universal method called when creating an instance of class from configuration. Object that does not implement this method can not be created automatically from configuration.</p> |
---|
100 | <p>The documentation contains the full structure which can be loaded. e.g.: </p> |
---|
101 | <div class="fragment"><pre class="fragment">{ <span class="keyword">class </span>= 'MemDS'; |
---|
102 | Data = (...); <span class="comment">// Data matrix or data vector</span> |
---|
103 | --- optional --- |
---|
104 | drv = {<span class="keyword">class</span>=<span class="stringliteral">'RV'</span>; ...} <span class="comment">// Identification how rows of the matrix Data will be known to others</span> |
---|
105 | time = 0; <span class="comment">// Index of the first column to user_info,</span> |
---|
106 | rowid = [1,2,3...]; <span class="comment">// ids of rows to be used</span> |
---|
107 | } |
---|
108 | </pre></div><p> for MemDS. The compulsory fields are listed at the beginning; the optional fields are separated by string "--- optional ---".</p> |
---|
109 | <p>For the example given above, the missing fields were filled as follows: </p> |
---|
110 | <div class="fragment"><pre class="fragment"> drv = {<span class="keyword">class</span>=<span class="stringliteral">"RV"</span>; names=<span class="stringliteral">"{ch0 }"</span>; sizes=[1];}; |
---|
111 | time = 0; |
---|
112 | rowid = [1]; |
---|
113 | </pre></div><p> Meaning that the data will be read from the first column (time=0), all rows of data are to be read (rowid=[1]), and this row will be called "ch0".</p> |
---|
114 | <dl class="note"><dt><b>Note:</b></dt><dd><b>Mixtools reference</b> This object replaces global variables DATA and TIME. In BDM, data can be read and written to a range of <code>datasources</code>, objects derived from <a class="el" href="classbdm_1_1DS.html" title="Abstract class for discrete-time sources of data.">bdm::DS</a>.</dd></dl> |
---|
115 | <h2><a class="anchor" id="rvs"> |
---|
116 | What is RV and how to use it</a></h2> |
---|
117 | <p>RV stands for <code>random</code> <code>variable</code> which is a description of random variable or its realization. This object playes role of identifier of elements of vectors of data (in datasources), expected inputs to functions (in pdfs), or required results (operations conditioning).</p> |
---|
118 | <dl class="note"><dt><b>Note:</b></dt><dd><b>Mixtools reference </b> RV is generalization of "structures" <code>str</code> in Mixtools. It replaces channel numbers by string names, and adds extra field size for each record.</dd></dl> |
---|
119 | <p>Mathematical interpretation of RV is straightforward. Consider pdf <img class="formulaInl" alt="$ f(a)$" src="form_142.png"/>, then <img class="formulaInl" alt="$ a $" src="form_143.png"/> is the part represented by RV. Explicit naming of random variables may seem unnecessary for many operations with pdf, e.g. for generation of a uniform sample from <0,1> it is not necessary to specify any random variable. For this reason, RV are often optional information to specify. However, the considered algorithm <code>estimator</code> is build in a way that requires RV to be given.</p> |
---|
120 | <p>The <code>estimator</code> use-case expects to join the data source with an array of estimators, each of which declaring its input vector of data. The connection will be made automatically using the mechanism of datalinks (<a class="el" href="classbdm_1_1datalink.html" title="DataLink is a connection between two data vectors Up and Down.">bdm::datalink</a>). Readers familiar with Simulink environment may look at the RV as being unique identifiers of inputs and outputs of simulation blocks. The inputs are connected automatically with the outputs with matching RV. This view is however, very incomplete, RV are much more powerful than this.</p> |
---|
121 | <h2><a class="anchor" id="datasource"> |
---|
122 | Class inheritance and DataSources</a></h2> |
---|
123 | <p>As mentioned above, the algorithm <code>estimator</code> is written to accept any datasource (i.e. any offspring of <a class="el" href="classbdm_1_1DS.html" title="Abstract class for discrete-time sources of data.">bdm::DS</a>). For full list of offsprings, click Classes > Class Hierarchy.</p> |
---|
124 | <p>At the time of writing this tutorial, available datasources are <a class="el" href="classbdm_1_1DS.html" title="Abstract class for discrete-time sources of data.">bdm::DS</a></p> |
---|
125 | <ul> |
---|
126 | <li><a class="el" href="classbdm_1_1EpdfDS.html" title="Simulate data from a static pdf (epdf).">bdm::EpdfDS</a></li> |
---|
127 | <li><a class="el" href="classbdm_1_1MemDS.html" title="Memory storage of off-line data column-wise.">bdm::MemDS</a><ul> |
---|
128 | <li><a class="el" href="classbdm_1_1FileDS.html">bdm::FileDS</a><ul> |
---|
129 | <li><a class="el" href="classbdm_1_1CsvFileDS.html" title="CSV file data storage The constructor creates Data matrix from the records in a CSV...">bdm::CsvFileDS</a></li> |
---|
130 | <li><a class="el" href="classbdm_1_1ITppFileDS.html" title="Read Data Matrix from an IT file.">bdm::ITppFileDS</a></li> |
---|
131 | </ul> |
---|
132 | </li> |
---|
133 | </ul> |
---|
134 | </li> |
---|
135 | <li><a class="el" href="classbdm_1_1MpdfDS.html" title="Simulate data from conditional density Still having only one density but allowing...">bdm::MpdfDS</a></li> |
---|
136 | <li><a class="el" href="classbdm_1_1stateDS.html">bdm::stateDS</a></li> |
---|
137 | </ul> |
---|
138 | <p>The MemDS has already been introduced in the example in <a class="el" href="user_guide.html#memds">How to understand configuration of classes</a>. However, any of the classes listed above can be used to replace it in the example. This will be demonstrated on the <code>EpdfDS</code> class.</p> |
---|
139 | <p>Brief decription of the class states that EpdfDS "Simulate data from a static pdf (epdf)". The static pdf means unconditional pdf in the sense that the random variable is conditioned by numerical values only. In mathematical notation it could be both <img class="formulaInl" alt="$ f(a) $" src="form_144.png"/> and <img class="formulaInl" alt="$ f(x_t |d_1 \ldots d_t)$" src="form_145.png"/>. The latter case is true only when all <img class="formulaInl" alt="$ d $" src="form_146.png"/> denotes observed values.</p> |
---|
140 | <p>For example, we wish to simulate realizations of a Uniform density on interval <-1,1>. Uniform density is represented by class <a class="el" href="classbdm_1_1euni.html" title="Uniform distributed density on a rectangular support.">bdm::euni</a>. From <a class="el" href="classbdm_1_1euni.html#a77f5fef1f006fe056066da23b9e5f042">bdm::euni.from_setting()</a> we can find that the code is: </p> |
---|
141 | <div class="fragment"><pre class="fragment">U={<span class="keyword">class</span>=<span class="stringliteral">"euni"</span>; high=1.0; low = -1.0;} |
---|
142 | </pre></div><p> for configuration file, and </p> |
---|
143 | <div class="fragment"><pre class="fragment">U.class=<span class="stringliteral">'euni'</span>; |
---|
144 | U.high = 1.0; |
---|
145 | U.low = -1.0; |
---|
146 | U.rv.class = <span class="stringliteral">'RV'</span>; |
---|
147 | U.rv.names = {<span class="charliteral">'a'</span>}; |
---|
148 | </pre></div><p> for Matlab.</p> |
---|
149 | <p>The datasource itself, can be then configured via </p> |
---|
150 | <div class="fragment"><pre class="fragment">DS = {<span class="keyword">class</span>=<span class="stringliteral">'EpdfDS'</span>; epdf=@U;}; |
---|
151 | </pre></div><p> in config file, or </p> |
---|
152 | <div class="fragment"><pre class="fragment">DS.class = <span class="stringliteral">'EpdfDS'</span>; |
---|
153 | DS.epdf = U; |
---|
154 | </pre></div><p> in Matlab.</p> |
---|
155 | <p>Contrary to the previous example, we need to tell to algorithm <code>estimator</code> how many samples from the data source we need. This is configured by variable <code>experiment.ndat</code>. The configuration has to be finalized by: </p> |
---|
156 | <div class="fragment"><pre class="fragment">experiment.ndat = 10; |
---|
157 | M=estimator(DS,{},experiment); |
---|
158 | </pre></div><p>The result is as expected in field <code>M.a</code> the name of which corresponds to name of <code>U.rv</code> .</p> |
---|
159 | <p>If the task was only to generate random realizations, this would indeed be a very clumsy way of doing it. However, the power of the proposed approach will be revelead in more demanding examples, one of which follows next.</p> |
---|
160 | <h2><a class="anchor" id="arx"> |
---|
161 | Simulating autoregressive model</a></h2> |
---|
162 | <p>Consider the following autoregressive model: </p> |
---|
163 | <p class="formulaDsp"> |
---|
164 | <img class="formulaDsp" alt="\[ y_t \sim \mathcal{N}( a y_{t-3} + b u_{t-1}, r) \]" src="form_147.png"/> |
---|
165 | </p> |
---|
166 | <p> where <img class="formulaInl" alt="$ a,b $" src="form_148.png"/> are known constants, and <img class="formulaInl" alt="$ r $" src="form_149.png"/> is known variance.</p> |
---|
167 | <p>Direct application of <code>EpdfDS</code> is not possible, since the pdf above is conditioned on values of <img class="formulaInl" alt="$ y_{t-3}$" src="form_150.png"/> and <img class="formulaInl" alt="$ u_{t-1}$" src="form_151.png"/>. We need to handle two issues:</p> |
---|
168 | <ol type="1"> |
---|
169 | <li>extra unsimulated variable <img class="formulaInl" alt="$ u $" src="form_152.png"/>,</li> |
---|
170 | <li>time delayes of the values.</li> |
---|
171 | </ol> |
---|
172 | <p>The first issue can be handled in two ways. First, <img class="formulaInl" alt="$ u $" src="form_152.png"/> can be considered as input and as such it could be externally given to the datasource. This solution is used in algorithm use-case <code>closedloop</code>. However, for the <code>estimator</code> scenario we will apply the second option, that is we complement <img class="formulaInl" alt="$ f(y_{t}|y_{t-3},u_{t-1})$" src="form_153.png"/> by extra pdf:</p> |
---|
173 | <p class="formulaDsp"> |
---|
174 | <img class="formulaDsp" alt="\[ u_t \sim \mathcal{N}(0, r_u) \]" src="form_154.png"/> |
---|
175 | </p> |
---|
176 | <p> Thus, the joint density is now:</p> |
---|
177 | <p class="formulaDsp"> |
---|
178 | <img class="formulaDsp" alt="\[ f(y_{t},u_{t}|y_{t-3},u_{t-1}) = f(y_{t}|y_{t-3},u_{t-1})f(u_{t}) \]" src="form_155.png"/> |
---|
179 | </p> |
---|
180 | <p> and we have no need for input since the datasource have all necessary information inside. All that is required is to store them and copy their values to appropriate places.</p> |
---|
181 | <p>That is done in automatic way using dedicated class <a class="el" href="classbdm_1_1datalink__buffered.html" title="Datalink that buffers delayed values - do not forget to call step().">bdm::datalink_buffered</a>. The only issue a user may need to take care about is the missing initial conditions for simulation. By default these are set to zeros. Using the default values, the full configuration of this system is: </p> |
---|
182 | <div class="fragment"><pre class="fragment">y = RV({<span class="charliteral">'y'</span>}); |
---|
183 | u = RV({<span class="charliteral">'u'</span>}); |
---|
184 | |
---|
185 | fy.class = <span class="stringliteral">'mlnorm<ldmat>'</span>; |
---|
186 | fy.rv = y; |
---|
187 | fy.rvc = RV({<span class="charliteral">'y'</span>,<span class="charliteral">'u'</span>}, [1 1], [-3, -1]); |
---|
188 | fy.A = [0.5, -0.9]; |
---|
189 | fy.const = 0; |
---|
190 | fy.R = 0.1; |
---|
191 | |
---|
192 | |
---|
193 | fu.class = <span class="stringliteral">'enorm<ldmat>'</span>; |
---|
194 | fu.rv = u; |
---|
195 | fu.mu = 0; |
---|
196 | fu.R = 0.2; |
---|
197 | |
---|
198 | DS.class = <span class="stringliteral">'MpdfDS'</span>; |
---|
199 | DS.mpdf.class = <span class="stringliteral">'mprod'</span>; |
---|
200 | DS.mpdf.mpdfs = {fy, epdf2mpdf(fu)}; |
---|
201 | </pre></div><p>Explanation of this example will require few remarks:</p> |
---|
202 | <ul> |
---|
203 | <li>class of the <code>fy</code> object is 'mlnorm<ldmat>' which is Normal pdf with mean value given by linear function, and covariance matrix stored in LD decomposition, see <a class="el" href="classbdm_1_1mlnorm.html" title="Normal distributed linear function with linear function of mean value;.">bdm::mlnorm</a> for details.</li> |
---|
204 | <li>naming convention 'mlnorm<ldmat>' relates to the concept of templates in C++. For those unfamiliar with this concept, it is basicaly a way how to share code for different flavours of the same object. Note that mlnorm exist in three versions: mlnorm<ldmat>, <a class="el" href="classbdm_1_1mlnorm.html">mlnorm<chmat></a>, mlnorm<fsqmat>. Those classes act identically the only difference is that the internal data are stored either in LD decomposition, choleski decomposition or full matrices, respectively.</li> |
---|
205 | <li>the same concept is used for enorm, where <a class="el" href="classbdm_1_1enorm.html">enorm<chmat></a> and <a class="el" href="classbdm_1_1enorm.html">enorm<fsqmat></a> are also possible. In this particular use, these objects are equivalent. In specific situation, e.g. Kalman filter implemented on Choleski decomposition (<a class="el" href="classbdm_1_1KalmanCh.html" title="Kalman filter in square root form.">bdm::KalmanCh</a>), only <a class="el" href="classbdm_1_1enorm.html">enorm<chmat></a> is approprate.</li> |
---|
206 | <li>class 'mprod' represents the chain rule of probability. Attribute <code>mpdfs</code> of its configuration structure is a list of conditional densities. Conditional density <img class="formulaInl" alt="$ f(a|b)$" src="form_156.png"/> is represented by class <code>mpdf</code> and its offsprings. Class <code>RV</code> is used to describe both variables before conditioning (field <code>rv</code> ) and after conditioning sign (field <code>rvc</code>).</li> |
---|
207 | <li>due to simplicity of implementation, mprod accept only conditional densities in the field <code>mpdfs</code>. Hence, the pdf <img class="formulaInl" alt="$ f(u_t)$" src="form_157.png"/> must be converted to conditional density with empty conditioning, <img class="formulaInl" alt="$ f(u_t| \{\})$" src="form_158.png"/>. This is achieved by calling function epdf2mpdf which is only a trivial wrapper creating class <a class="el" href="classbdm_1_1mepdf.html" title="Unconditional mpdf, allows using epdf in the role of mpdf.">bdm::mepdf</a>.</li> |
---|
208 | </ul> |
---|
209 | <p>The code above can be immediatelly run, usin the same execution sequence of <code>estimator</code> as above.</p> |
---|
210 | <h3><a class="anchor" id="ini"> |
---|
211 | Initializing simulation</a></h3> |
---|
212 | <p>When zeros are not appropriate initial conditions, the correct conditions can be set using additional commands: </p> |
---|
213 | <div class="fragment"><pre class="fragment">DS.init_rv = RV({<span class="charliteral">'y'</span>,<span class="charliteral">'y'</span>,<span class="charliteral">'y'</span>}, [1,1,1], [-1,-2,-3]); |
---|
214 | DS.init_values = [0.1, 0.2, 0.3]; |
---|
215 | </pre></div><p>The values of <code>init_values</code> will be copied to places in history identified by corresponding values of <code>init_rv</code>. Initial data is not checked for completeness, i.e. values of random variables missing from <code>init_rv</code> (in this case all occurences of <img class="formulaInl" alt="$ u $" src="form_152.png"/>) are still initialized to 0.</p> |
---|
216 | <h2><a class="anchor" id="conc"> |
---|
217 | What was demonstrated in this tutorial</a></h2> |
---|
218 | <p>The purpose of this page was to introduce software image of basic elements of decision making as implemented in BDM.</p> |
---|
219 | <ul> |
---|
220 | <li>random values as identification mechanism (<a class="el" href="classbdm_1_1RV.html" title="Class representing variables, most often random variables.">bdm::RV</a>)</li> |
---|
221 | <li>unconditional pdfs (<a class="el" href="classbdm_1_1epdf.html" title="Probability density function with numerical statistics, e.g. posterior density.">bdm::epdf</a>),</li> |
---|
222 | <li>conditional pdfs (<a class="el" href="classbdm_1_1mpdf.html" title="Conditional probability density, e.g. modeling , where is random variable, rv, and...">bdm::mpdf</a>),</li> |
---|
223 | </ul> |
---|
224 | <p>And the use of these in simulation of data and function of datasources. In the next tutorial, Bayesian models (<a class="el" href="classbdm_1_1BM.html" title="Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.">bdm::BM</a>) and loggers (<a class="el" href="classbdm_1_1logger.html" title="Class for storing results (and semi-results) of an experiment.">bdm::logger</a>) will be introduced. </p> |
---|
225 | </div> |
---|
226 | <hr size="1"/><address style="text-align: right;"><small>Generated on Sun Sep 13 23:08:55 2009 for mixpp by |
---|
227 | <a href="http://www.doxygen.org/index.html"> |
---|
228 | <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.6.1 </small></address> |
---|
229 | </body> |
---|
230 | </html> |
---|