root/library/bdm/base/datasources.h @ 618

Revision 618, 13.2 kB (checked in by smidl, 15 years ago)

use simulator in tutorial/userguide

  • Property svn:eol-style set to native
Line 
1/*!
2  \file
3  \brief Common DataSources.
4  \author Vaclav Smidl.
5
6  -----------------------------------
7  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8
9  Using IT++ for numerical operations
10  -----------------------------------
11*/
12
13#ifndef DATASOURCE_H
14#define DATASOURCE_H
15
16
17#include "../base/bdmbase.h"
18#include "../stat/exp_family.h"
19#include "../base/user_info.h"
20
21namespace bdm {
22/*!
23* \brief Memory storage of off-line data column-wise
24
25The data are stored in an internal matrix \c Data . Each column of Data corresponds to one discrete time observation \f$t\f$. Access to this matrix is via indices \c rowid.
26
27The data can be loaded from a file.
28*/
29class MemDS : public DS {
30        protected:
31                //! internal matrix of data
32                mat Data;
33                //! active column in the Data matrix
34                int time;
35                //!  vector of rows that are presented in Dt
36                ivec rowid;
37
38        public:
39                int max_length() {return Data.cols();}
40                void getdata ( vec &dt );
41                void getdata ( vec &dt, const ivec &indeces );
42                void set_rvs ( RV &drv, RV &urv );
43
44                void write ( vec &ut ) {
45                        bdm_error ( "MemDS::write is not supported" );
46                }
47
48                void write ( vec &ut, ivec &indices ) {
49                        bdm_error ( "MemDS::write is not supported" );
50                }
51
52                void step();
53                //!Default constructor
54                MemDS () {};
55                MemDS ( mat &Dat, ivec &rowid0);
56                /*! Create object from the following structure
57                \code
58                { class = "MemDS";
59                   Data = (...);            // Data matrix or data vector
60                   --- optional ---
61                   drv = {class="RV"; ...} // Identification how rows of the matrix Data will be known to others
62                   time = 0;               // Index of the first column to user_info,
63                   rowid = [1,2,3...];     // ids of rows to be used
64                }
65                \endcode
66               
67                If the optional fields are not given, they will be filled as follows:
68                \code
69                rowid= [0, 1, 2, ...number_of_rows_of_Data];
70                drv = {names=("ch0", "ch1", "ch2", ..."number_of_rows_of_Data");
71                      sizes=( 1    1    1 ...);
72                          times=( 0    0    0 ...);
73                          };
74                time = 0;
75                \endcode
76                If \c rowid is given, \c drv will be named after indeces in rowids.
77               
78                Hence the data provided by method \c getdata() will be full column of matrix Data starting from the first record.
79                */
80                void from_setting(const Setting &set){
81                        UI::get(Data, set, "Data", UI::compulsory);
82                        if(!UI::get(time, set,"time", UI::optional)) {time =0;}
83                        if(!UI::get(rowid, set, "rowid",UI::optional)) {rowid =linspace(0,Data.rows()-1);}
84                        shared_ptr<RV> r=UI::build<RV>(set,"drv",UI::optional);
85                        if (!r) {r=new RV();
86                                for (int i=0; i<rowid.length(); i++){ r->add(RV("ch"+num2str(rowid(i)), 1, 0));}
87                        }
88                        set_drv(*r,RV()); //empty urv
89                        dtsize=r->_dsize();
90                        utsize=0;
91                }
92};
93UIREGISTER(MemDS);
94
95/*!  \brief Simulate data from a static pdf (epdf)
96
97Trivial example of a data source, could be used for tests of some estimation algorithms. For example, simulating data from a mixture model and feeding them to mixture model estimators.
98*/
99
100class EpdfDS: public DS {
101        protected:
102                //! internal pointer to epdf from which we samplecond
103                shared_ptr<epdf> iepdf;
104                //! internal storage of data sample
105                vec dt;
106        public:
107                void step() {
108                        dt=iepdf->sample();
109                }
110                void getdata ( vec &dt_out ) {
111                        dt_out = dt;
112                }
113                void getdata ( vec &dt_out, const ivec &ids ) {
114                        dt_out = dt ( ids );
115                }
116                const RV& _drv() {
117                        return iepdf->_rv();
118                }
119
120                /*!
121                \code
122                class = "EpdfDS";
123                epdf = {class="epdf_offspring", ...}// uncondtitional density to sample from
124                \endcode
125
126                */
127                void from_setting ( const Setting &set ) {
128                        iepdf=UI::build<epdf> ( set,"epdf",UI::compulsory );
129                        bdm_assert(iepdf->isnamed(), "Input epdf must be named, check if RV is given correctly");
130                        dt =  zeros(iepdf->dimension());
131                        dtsize=dt.length();
132                        set_drv(iepdf->_rv(),RV());
133                        utsize =0;
134                        validate();
135                }
136                void validate() {
137                        dt = iepdf->sample();
138                }
139};
140UIREGISTER ( EpdfDS );
141
142/*!  \brief Simulate data from conditional density
143Still having only one density but allowing conditioning on either input or delayed values.
144*/
145class MpdfDS :public DS {
146        protected:
147                //! internal pointer to epdf from which we samplecond
148                shared_ptr<mpdf> impdf;
149                //! internal storage of data sample
150                vec yt;
151                //! input vector
152                vec ut;
153                //! datalink between ut and regressor
154                datalink_buffered ut2rgr;
155                //! datalink between yt and regressor
156                datalink_buffered yt2rgr;
157                //! numeric values of regressor
158                vec rgr;
159               
160        public:
161                void step() {
162                        yt2rgr.step(yt); // y is now history
163                        ut2rgr.filldown ( ut,rgr );
164                        yt2rgr.filldown ( yt,rgr );
165                        yt=impdf->samplecond ( rgr );
166                        ut2rgr.step(ut); //u is now history
167                }
168                void getdata ( vec &dt_out ) {
169                        bdm_assert_debug(dt_out.length()>=utsize+ytsize,"Short output vector");
170                        dt_out.set_subvector(0, yt);
171                        dt_out.set_subvector(ytsize, ut);
172                }
173                void write(const vec &ut0){ut=ut0;}
174
175                /*!
176                \code
177                class = "MpdfDS";
178                mpdf = {class="mpdf_offspring", ...};  // mpdf to simulate
179                --- optional ---
180                init_rv = {class="RV",names=...};      // define what rv to initialize - typically delayed values!
181                init_values = [...];                   // vector of initial values corresponding to init_rv
182                \endcode
183
184                If init_rv is not given, init_values are set to zero.
185                */
186                void from_setting ( const Setting &set ) {
187                        impdf=UI::build<mpdf> ( set,"mpdf",UI::compulsory );
188                       
189                        Yrv = impdf->_rv();
190                        // get unique rvs form rvc
191                        RV rgrv0=impdf->_rvc().remove_time();
192                        // input is what in not in Yrv
193                        Urv=rgrv0.subt(Yrv); 
194                        set_drv(Yrv, Urv);
195                        // connect input and output to rvc
196                        ut2rgr.set_connection(impdf->_rvc(), Urv); 
197                        yt2rgr.set_connection(impdf->_rvc(), Yrv); 
198                       
199                        //set history - if given
200                        shared_ptr<RV> rv_ini=UI::build<RV>(set,"init_rv",UI::optional);
201                        if(rv_ini){ // check if
202                                vec val;
203                                UI::get(val, set, "init_values", UI::optional);
204                                if (val.length()!=rv_ini->_dsize()){
205                                        bdm_error("init_rv and init_values fields have incompatible sizes");
206                                } else {
207                                        ut2rgr.set_history(*rv_ini, val);
208                                        yt2rgr.set_history(*rv_ini, val);
209                                }
210                        }
211
212                        yt = zeros ( impdf->dimension() );
213                        rgr = zeros ( impdf->dimensionc() );
214                        ut = zeros(Urv._dsize());
215
216                        ytsize=yt.length();
217                        utsize=ut.length();
218                        dtsize = ytsize+utsize;
219                        validate();
220                }
221                void validate() {
222                        //taken from sample() - shift of history is not done here
223                        ut2rgr.filldown ( ut,rgr );
224                        yt2rgr.filldown ( yt,rgr );
225                        yt=impdf->samplecond ( rgr );
226                }
227};
228UIREGISTER ( MpdfDS );
229
230/*! Pseudovirtual class for reading data from files
231
232*/
233class FileDS: public MemDS {
234
235        public:
236                void getdata ( vec &dt ) {
237                        dt = Data.get_col ( time );
238                }
239
240                void getdata ( vec &dt, const ivec &indices ) {
241                        vec tmp = Data.get_col ( time );
242                        dt = tmp ( indices );
243                }
244
245                //! returns number of data in the file;
246                int ndat() {
247                        return Data.cols();
248                }
249                //! no sense to log this type
250                void log_add ( logger &L ) {};
251                //! no sense to log this type
252                void logit ( logger &L ) {};
253};
254
255/*!
256* \brief Read Data Matrix from an IT file
257
258The constructor creates an internal matrix \c Data from an IT++ file. The file is binary and can be made using the IT++ library or the Matlab/Octave function itsave. NB: the data are stored columnwise, i.e. each column contains the data for time \f$t\f$!
259
260*/
261class ITppFileDS: public FileDS {
262
263        public:
264                ITppFileDS ( const string &fname, const string &varname ) : FileDS() {
265                        it_file it ( fname );
266                        it << Name ( varname );
267                        it >> Data;
268                        time = 0;
269                        //rowid and delays are ignored
270                };
271
272                ITppFileDS () : FileDS() {
273                };
274
275                void from_setting ( const Setting &set );
276
277                // TODO dodelat void to_setting( Setting &set ) const;
278
279};
280
281UIREGISTER ( ITppFileDS );
282SHAREDPTR ( ITppFileDS );
283
284/*!
285* \brief CSV file data storage
286The constructor creates \c Data matrix from the records in a CSV file \c fname. The orientation can be of two types:
2871. \c BY_COL which is default - the data are stored in columns; one column per time \f$t\f$, one row per data item.
2882. \c BY_ROW if the data are stored the classical CSV style. Then each column stores the values for data item, for ex. \f$[y_{t} y_{t-1} ...]\f$, one row for each discrete time instant.
289
290*/
291class CsvFileDS: public FileDS {
292
293        public:
294                //! Constructor - create DS from a CSV file.
295                CsvFileDS ( const string& fname, const string& orientation = "BY_COL" );
296};
297
298
299
300/*!
301\brief Generator of ARX data
302
303*/
304class ArxDS : public DS {
305        protected:
306                //! Rv of the regressor
307                RV Rrv;
308                //! History, ordered as \f$[y_t, u_t, y_{t-1 }, u_{t-1}, \ldots]\f$
309                vec H;
310                //! (future) input
311                vec U;
312                //! temporary variable for regressor
313                vec rgr;
314                //! data link: H -> rgr
315                datalink rgrlnk;
316                //! model of Y - linear Gaussian
317                mlnorm<chmat> model;
318                //! options
319                bool opt_L_theta;
320                //! loggers
321                int L_theta;
322                int L_R;
323                int dt_size;
324        public:
325                void getdata ( vec &dt ) {
326                        dt = H;
327                }
328
329                void getdata ( vec &dt, const ivec &indices ) {
330                        dt = H ( indices );
331                }
332
333                void write ( vec &ut ) {
334                        U = ut;
335                }
336
337                void write ( vec &ut, const ivec &indices ) {
338                        bdm_assert_debug ( ut.length() == indices.length(), "ArxDS" );
339                        set_subvector ( U, indices, ut );
340                }
341
342                void step();
343
344                //!Default constructor
345                ArxDS ( ) {};
346                //! Set parameters of the internal model, H is maximum time delay
347                void set_parameters ( const mat &Th0, const vec mu0, const chmat &sqR0 ) {
348                        model.set_parameters ( Th0, mu0, sqR0 );
349                };
350                //! Set
351                void set_drv ( const RV &yrv, const RV &urv, const RV &rrv ) {
352                        Rrv = rrv;
353                        Urv = urv;
354                        dt_size = yrv._dsize() + urv._dsize();
355
356                        RV drv = concat ( yrv, urv );
357                        Drv = drv;
358                        int td = rrv.mint();
359                        H.set_size ( drv._dsize() * ( -td + 1 ) );
360                        U.set_size ( Urv._dsize() );
361                        for ( int i = -1; i >= td; i-- ) {
362                                drv.t_plus ( -1 );
363                                Drv.add ( drv ); //shift u1
364                        }
365                        rgrlnk.set_connection ( rrv, Drv );
366
367                        dtsize = Drv._dsize();
368                        utsize = Urv._dsize();
369                }
370                //! set options from a string
371                void set_options ( const string &s ) {
372                        opt_L_theta = ( s.find ( "L_theta" ) != string::npos );
373                };
374                virtual void log_add ( logger &L ) {
375                        //DS::log_add ( L ); too long!!
376                        L_dt = L.add ( Drv ( 0, dt_size ), "" );
377                        L_ut = L.add ( Urv, "" );
378
379                        const mat &A = model._A();
380                        const mat R = model._R();
381                        if ( opt_L_theta ) {
382                                L_theta = L.add ( RV ( "{th }", vec_1 ( A.rows() * A.cols() ) ), "t" );
383                        }
384                        if ( opt_L_theta ) {
385                                L_R = L.add ( RV ( "{R }", vec_1 ( R.rows() * R.cols() ) ), "r" );
386                        }
387                }
388                virtual void logit ( logger &L ) {
389                        //DS::logit ( L );
390                        L.logit ( L_dt, H.left ( dt_size ) );
391                        L.logit ( L_ut, U );
392
393                        const mat &A = model._A();
394                        const mat R = model._R();
395                        if ( opt_L_theta ) {
396                                L.logit ( L_theta, vec ( A._data(), A.rows() *A.cols() ) );
397                        };
398                        if ( opt_L_theta ) {
399                                L.logit ( L_R, vec ( R._data(), R.rows() *R.rows() ) );
400                        };
401                }
402
403                // TODO dokumentace - aktualizovat
404                /*! UI for ArxDS using factorized description!
405
406                The ArxDS is constructed from a structure with fields:
407                \code
408                system = {
409                        type = "ArxDS";
410                        // description of y variables
411                        y = {type="rv"; names=["y", "u"];};
412                        // description of u variable
413                        u = {type="rv"; names=[];}
414                        // description of regressor
415                        rgr = {type="rv";
416                                names = ["y","y","y","u"];
417                                times = [-1, -2, -3, -1];
418                        }
419
420                        // theta
421                        theta = [0.8, -0.3, 0.4, 1.0,
422                                         0.0, 0.0, 0.0, 0.0];
423                        // offset (optional)
424                        offset = [0.0, 0.0];
425                        //variance
426                        r = [0.1, 0.0,
427                                 0.0, 1.0];
428                        //options: L_theta = log value of theta,
429                        opt = "L_theta";
430                };
431                \endcode
432
433                Result is ARX data source offering with full history as Drv.
434                */
435                void from_setting ( const Setting &set );
436
437                // TODO dodelat void to_setting( Setting &set ) const;
438};
439
440UIREGISTER ( ArxDS );
441SHAREDPTR ( ArxDS );
442
443class stateDS : public DS {
444        private:
445                //!conditional pdf of the state evolution \f$ f(x_t|x_{t-1}) \f$
446                shared_ptr<mpdf> IM;
447
448                //!conditional pdf of the observations \f$ f(d_t|x_t) \f$
449                shared_ptr<mpdf> OM;
450
451        protected:
452                //! result storage
453                vec dt;
454                //! state storage
455                vec xt;
456                //! input storage
457                vec ut;
458                //! Logger
459                int L_xt;
460
461        public:
462                void getdata ( vec &dt0 ) {
463                        dt0 = dt;
464                }
465
466                void getdata ( vec &dt0, const ivec &indices ) {
467                        dt0 = dt ( indices );
468                }
469
470                stateDS ( const shared_ptr<mpdf> &IM0, const shared_ptr<mpdf> &OM0, int usize ) : IM ( IM0 ), OM ( OM0 ),
471                                dt ( OM0->dimension() ), xt ( IM0->dimension() ),
472                                ut ( usize ), L_xt ( 0 ) { }
473
474                stateDS() : L_xt ( 0 ) { }
475
476                virtual void step() {
477                        xt = IM->samplecond ( concat ( xt, ut ) );
478                        dt = OM->samplecond ( concat ( xt, ut ) );
479                }
480
481                virtual void log_add ( logger &L ) {
482                        DS::log_add ( L );
483                        L_xt = L.add ( IM->_rv(), "true" );
484                }
485                virtual void logit ( logger &L ) {
486                        DS::logit ( L );
487                        L.logit ( L_xt, xt );
488                }
489
490                /*! UI for stateDS
491
492                The DS is constructed from a structure with fields:
493                \code
494                system = {
495                        type = "stateDS";
496                        //Internal model
497                        IM = { type = "mpdf"; //<-- valid offspring! e.g. "mlnorm"
498                                rv = { //description of x_t
499                                        names=["name1",...];
500                                        sizes=[2,1]; // optional default=[1,1...];
501                                        times=[0,0]; // optional default=[0,0...];
502                                        }
503                                rvu= { //description of  u_t
504                                        //optional default=empty
505                                        }
506
507                                // remaining fields depending on the chosen type
508                                };
509                        //Observation model
510                        OM = { type = "mpdf-offspring";
511                                rv = {}; //description of d_t
512                                rvu = {type="internal", path="system.IM.rvu"}; //description of u_t
513
514                                //remaining fields
515                        }
516                };
517                \endcode
518                */
519                void from_setting ( const Setting &set );
520
521                // TODO dodelat void to_setting( Setting &set ) const;
522
523};
524
525UIREGISTER ( stateDS );
526SHAREDPTR ( stateDS );
527
528}; //namespace
529
530#endif // DS_H
Note: See TracBrowser for help on using the browser.