root/library/bdm/base/bdmbase.h @ 619

Revision 619, 34.1 kB (checked in by mido, 15 years ago)

zmena abstraktnich trid na konkretni - s chybovou hlaskou, vse kvuli MS VS

  • Property svn:eol-style set to native
Line 
1/*!
2  \file
3  \brief Basic structures of probability calculus: random variables, probability densities, Bayes rule
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 BDMBASE_H
14#define BDMBASE_H
15
16#include <map>
17
18#include "../itpp_ext.h"
19#include "../bdmroot.h"
20#include "../shared_ptr.h"
21#include "user_info.h"
22
23using namespace libconfig;
24using namespace itpp;
25using namespace std;
26
27namespace bdm {
28//! Structure of RV, i.e. RVs expanded into a flat list of IDs, used for debugging.
29class str {
30public:
31        //! vector id ids (non-unique!)
32        ivec ids;
33        //! vector of times
34        ivec times;
35        //!Default constructor
36        str ( ivec ids0, ivec times0 ) : ids ( ids0 ), times ( times0 ) {
37                bdm_assert_debug ( times0.length() == ids0.length(), "Incompatible input" );
38        };
39};
40
41/*!
42* \brief Class representing variables, most often random variables
43
44The purpose of this class is to decribe a vector of data. Such description is used for connecting various vectors between each other, see class datalink.
45
46The class is implemented using global variables to assure uniqueness of description:
47
48 In is a vector
49\dot
50digraph datalink {
51rankdir=LR;
52subgraph cluster0 {
53node [shape=record];
54label = "MAP \n std::map<string,int>";
55map [label="{{\"a\"| \"b\" | \"c\"} | {<3> 3 |<1> 1|<2> 2}}"];
56color = "white"
57}
58subgraph cluster1{
59node [shape=record];
60label = "NAMES";
61names [label="{<1> \"b\" | <2> \"c\" | <3>\"a\" }"];
62color = "white"
63}
64subgraph cluster2{
65node [shape=record];
66label = "SIZES";
67labelloc = b;
68sizes [label="{<1>1 |<2> 4 |<3> 1}"];
69color = "white"
70}
71map:1 -> names:1;
72map:1 -> sizes:1;
73map:3 -> names:3;
74map:3 -> sizes:3;
75}
76\enddot
77*/
78
79class RV : public root {
80private:
81        typedef std::map<string, int> str2int_map;
82
83        //! Internal global variable storing sizes of RVs
84        static ivec SIZES;
85        //! Internal global variable storing names of RVs
86        static Array<string> NAMES;
87
88        //! TODO
89        const static int BUFFER_STEP;
90
91        //! TODO
92        static str2int_map MAP;
93
94public:
95
96protected:
97        //! size of the data vector
98        int dsize;
99        //! number of individual rvs
100        int len;
101        //! Vector of unique IDs
102        ivec ids;
103        //! Vector of shifts from current time
104        ivec times;
105
106private:
107        enum enum_dummy {dummy};
108
109        //! auxiliary function used in constructor
110        void init ( const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times );
111        int init ( const string &name, int size );
112        //! Private constructor from IDs, potentially dangerous since all ids must be valid!
113        //! dummy is there to prevent confusion with RV(" string");
114        explicit RV ( const ivec &ids0, enum_dummy dum ) : dsize ( 0 ), len ( ids0.length() ), ids ( ids0 ), times ( zeros_i ( ids0.length() ) ) {
115                dsize = countsize();
116        }
117public:
118        //! \name Constructors
119        //!@{
120
121        //! Full constructor
122        RV ( const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times ) {
123                init ( in_names, in_sizes, in_times );
124        }
125
126        //! Constructor with times=0
127        RV ( const Array<std::string> &in_names, const ivec &in_sizes ) {
128                init ( in_names, in_sizes, zeros_i ( in_names.length() ) );
129        }
130
131        //! Constructor with sizes=1, times=0
132        RV ( const Array<std::string> &in_names ) {
133                init ( in_names, ones_i ( in_names.length() ), zeros_i ( in_names.length() ) );
134        }
135
136        //! Constructor of empty RV
137        RV() : dsize ( 0 ), len ( 0 ), ids ( 0 ), times ( 0 ) {}
138
139        //! Constructor of a single RV with given id
140        RV ( string name, int sz, int tm = 0 );
141
142        // compiler-generated copy constructor is used
143        //!@}
144
145        //! \name Access functions
146        //!@{
147
148        //! State output, e.g. for debugging.
149        friend std::ostream &operator<< ( std::ostream &os, const RV &rv );
150
151        string to_string() {ostringstream o; o << this; return o.str();}
152       
153        //! total size of a random variable
154        int _dsize() const {
155                return dsize;
156        }
157
158        //! access function
159        const ivec& _ids() const {
160                return ids;
161        }
162
163        //! Recount size of the corresponding data vector
164        int countsize() const;
165        //! Vector of cumulative sizes of RV
166        ivec cumsizes() const;
167        //! Number of named parts
168        int length() const {
169                return len;
170        }
171        int id ( int at ) const {
172                return ids ( at );
173        }
174        int size ( int at ) const {
175                return SIZES ( ids ( at ) );
176        }
177        int time ( int at ) const {
178                return times ( at );
179        }
180        std::string name ( int at ) const {
181                return NAMES ( ids ( at ) );
182        }
183        //! returns name of a scalar at position scalat, i.e. it can be in the middle of vector name, in that case it adds "_%d" to it
184        std::string scalarname ( int scalat ) const {
185                bdm_assert_debug(scalat<dsize,"Wrong input index");
186                int id=0;
187                int scalid=0;
188                while (scalid+SIZES(ids(id))<=scalat)  { scalid+=SIZES(ids(id)); id++;};
189                //now id is the id of variable of interest
190                if (size(id)==1)
191                        return  NAMES ( ids ( id ) );
192                else
193                        return  NAMES ( ids ( id ) )+ "_" + num2str(scalat-scalid);
194
195        }
196        void set_time ( int at, int time0 ) {
197                times ( at ) = time0;
198        }
199        //!@}
200
201        //! \name Algebra on Random Variables
202        //!@{
203
204        //! Find indices of self in another rv, \return ivec of the same size as self.
205        ivec findself ( const RV &rv2 ) const;
206        //! Find indices of self in another rv, ignore time, \return ivec of the same size as self.
207        ivec findself_ids ( const RV &rv2 ) const;
208        //! Compare if \c rv2 is identical to this \c RV
209        bool equal ( const RV &rv2 ) const;
210        //! Add (concat) another variable to the current one, \return true if all rv2 were added, false if rv2 is in conflict
211        bool add ( const RV &rv2 );
212        //! Subtract  another variable from the current one
213        RV subt ( const RV &rv2 ) const;
214        //! Select only variables at indices ind
215        RV subselect ( const ivec &ind ) const;
216
217        //! Select only variables at indices ind
218        RV operator() ( const ivec &ind ) const {
219                return subselect ( ind );
220        }
221
222        //! Select from data vector starting at di1 to di2
223        RV operator() ( int di1, int di2 ) const;
224
225        //! Shift \c time by delta.
226        void t_plus ( int delta );
227        //!@}
228
229        //! @{ \name Time manipulation functions
230        //! returns rvs with time set to 0 and removed duplicates
231        RV remove_time() const {
232                return RV ( unique ( ids ), dummy );
233        }
234        //! create new RV from the current one with time shifted by given value
235        RV copy_t(int dt) const {
236                RV tmp=*this;
237                tmp.t_plus(dt);
238                return tmp;
239        }
240        //! return rvs with expanded delayes and sorted in the order of: \f$ [ rv_{0}, rv_{-1}, rv_{
241        RV expand_delayes() const {
242                RV rvt = this->remove_time(); //rv at t=0
243                RV tmp = rvt;
244                int td = mint();
245                for ( int i = -1; i >= td; i-- ) {
246                        rvt.t_plus ( -1 );
247                        tmp.add ( rvt ); //shift u1
248                }
249                return tmp;
250        }
251        //!@}
252
253        //!\name Relation to vectors
254        //!@{
255
256        //! generate \c str from rv, by expanding sizes
257        str tostr() const;
258        //! when this rv is a part of bigger rv, this function returns indices of self in the data vector of the bigger crv.
259        //! Then, data can be copied via: data_of_this = cdata(ind);
260        ivec dataind ( const RV &crv ) const;
261        //! same as dataind but this time crv should not be complete supperset of rv.
262        ivec dataind_part ( const RV &crv ) const;
263        //! generate mutual indices when copying data between self and crv.
264        //! Data are copied via: data_of_this(selfi) = data_of_rv2(rv2i)
265        void dataind ( const RV &rv2, ivec &selfi, ivec &rv2i ) const;
266        //! Minimum time-offset
267        int mint() const {
268                        return times.length()>0 ? min (times) : 0;
269        }
270        //!@}
271
272        /*! \brief UI for class RV (description of data vectors)
273
274        \code
275        rv = {
276            class = "RV"; // class name
277          // UNIQUE IDENTIFIER same names = same variable
278          names = ( "a", "b", "c", ...);   // which will be used e.g. in loggers
279
280          //optional arguments
281          sizes = [1, 2, 3, ...];         // (optional) default = ones()
282          times = [-1, -2, 0, ...];       // time shifts with respect to current time (optional) default = zeros()
283        }
284        \endcode
285        */
286        void from_setting ( const Setting &set );
287
288        // TODO dodelat void to_setting( Setting &set ) const;
289
290        //! Invalidate all named RVs. Use before initializing any RV instances, with care...
291        static void clear_all();
292        //! function for debugging RV related stuff
293        string show_all();
294
295};
296UIREGISTER ( RV );
297SHAREDPTR ( RV );
298
299//! Concat two random variables
300RV concat ( const RV &rv1, const RV &rv2 );
301
302//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
303class fnc : public root {
304protected:
305        //! Length of the output vector
306        int dimy;
307public:
308        //!default constructor
309        fnc() {};
310        //! function evaluates numerical value of \f$f(x)\f$ at \f$x=\f$ \c cond
311        virtual vec eval ( const vec &cond ) {
312                return vec ( 0 );
313        };
314
315        //! function substitutes given value into an appropriate position
316        virtual void condition ( const vec &val ) {};
317
318        //! access function
319        int dimension() const {
320                return dimy;
321        }
322};
323
324class mpdf;
325
326//! Probability density function with numerical statistics, e.g. posterior density.
327
328class epdf : public root {
329protected:
330        //! dimension of the random variable
331        int dim;
332        //! Description of the random variable
333        RV rv;
334
335public:
336        /*! \name Constructors
337         Construction of each epdf should support two types of constructors:
338        \li empty constructor,
339        \li copy constructor,
340
341        The following constructors should be supported for convenience:
342        \li constructor followed by calling \c set_parameters()
343        \li constructor accepting random variables calling \c set_rv()
344
345         All internal data structures are constructed as empty. Their values (including sizes) will be set by method \c set_parameters(). This way references can be initialized in constructors.
346        @{*/
347        epdf() : dim ( 0 ), rv() {};
348        epdf ( const epdf &e ) : dim ( e.dim ), rv ( e.rv ) {};
349        epdf ( const RV &rv0 ) : dim ( rv0._dsize() ) {
350                set_rv ( rv0 );
351        };
352        void set_parameters ( int dim0 ) {
353                dim = dim0;
354        }
355        //!@}
356
357        //! \name Matematical Operations
358        //!@{
359
360        //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
361        virtual vec sample() const {
362                bdm_error ( "not implemented" );
363                return vec();
364        }
365
366        //! Returns N samples, \f$ [x_1 , x_2 , \ldots \ \f$  from density \f$ f_x(rv)\f$
367        virtual mat sample_m ( int N ) const;
368
369        //! Compute log-probability of argument \c val
370        //! In case the argument is out of suport return -Infinity
371        virtual double evallog ( const vec &val ) const {
372                bdm_error ( "not implemented" );
373                return 0.0;
374        }
375
376        //! Compute log-probability of multiple values argument \c val
377        virtual vec evallog_m ( const mat &Val ) const;
378
379        //! Compute log-probability of multiple values argument \c val
380        virtual vec evallog_m ( const Array<vec> &Avec ) const;
381
382        //! Return conditional density on the given RV, the remaining rvs will be in conditioning
383        virtual shared_ptr<mpdf> condition ( const RV &rv ) const;
384
385        //! Return marginal density on the given RV, the remainig rvs are intergrated out
386        virtual shared_ptr<epdf> marginal ( const RV &rv ) const;
387
388        //! return expected value
389        virtual vec mean() const {
390                bdm_error ( "not implemneted" );
391                return vec();
392        }
393
394        //! return expected variance (not covariance!)
395        virtual vec variance() const {
396                bdm_error ( "not implemneted" );
397                return vec();
398        }
399
400        //! Lower and upper bounds of \c percentage % quantile, returns mean-2*sigma as default
401        virtual void qbounds ( vec &lb, vec &ub, double percentage = 0.95 ) const {
402                vec mea = mean();
403                vec std = sqrt ( variance() );
404                lb = mea - 2 * std;
405                ub = mea + 2 * std;
406        };
407        //!@}
408
409        //! \name Connection to other classes
410        //! Description of the random quantity via attribute \c rv is optional.
411        //! For operations such as sampling \c rv does not need to be set. However, for \c marginalization
412        //! and \c conditioning \c rv has to be set. NB:
413        //! @{
414
415        //!Name its rv
416        void set_rv ( const RV &rv0 ) {
417                rv = rv0;
418        }
419
420        //! True if rv is assigned
421        bool isnamed() const {
422                bool b = ( dim == rv._dsize() );
423                return b;
424        }
425
426        //! Return name (fails when isnamed is false)
427        const RV& _rv() const {
428                bdm_assert_debug ( isnamed(), "" );
429                return rv;
430        }
431        //!@}
432
433        //! \name Access to attributes
434        //! @{
435
436        //! Size of the random variable
437        int dimension() const {
438                return dim;
439        }
440        //! Load from structure with elements:
441        //!  \code
442        //! { rv = {class="RV", names=(...),}; // RV describing meaning of random variable
443        //!   // elements of offsprings
444        //! }
445        //! \endcode
446        //!@}
447        void from_setting ( const Setting &set ) {
448                shared_ptr<RV> r = UI::build<RV> ( set, "rv", UI::optional );
449                if ( r ) {
450                        set_rv ( *r );
451                }
452        }
453
454};
455SHAREDPTR ( epdf );
456
457//! Conditional probability density, e.g. modeling \f$ f( x | y) \f$, where \f$ x \f$ is random variable, \c rv, and \f$ y \f$ is conditioning variable, \c rvc.
458class mpdf : public root {
459protected:
460        //!dimension of the condition
461        int dimc;
462        //! random variable in condition
463        RV rvc;
464private:
465        //! internal epdf, used only as cache to avoid virtual calls of \c _rv() and \c _dimension()
466        epdf* ep;
467
468protected:
469        //! set internal pointer \c ep to point to given \c iepdf
470        void set_ep ( epdf &iepdf ) {
471                ep = &iepdf;
472        }
473        //! set internal pointer \c ep to point to given \c iepdf
474        void set_ep ( epdf *iepdfp ) {
475                ep = iepdfp;
476        }
477
478public:
479        //! \name Constructors
480        //! @{
481
482        mpdf() : dimc ( 0 ), rvc(), ep ( NULL ) { }
483
484        mpdf ( const mpdf &m ) : dimc ( m.dimc ), rvc ( m.rvc ), ep ( m.ep ) { }
485        //!@}
486
487        //! \name Matematical operations
488        //!@{
489
490        //! Returns a sample from the density conditioned on \c cond, \f$x \sim epdf(rv|cond)\f$. \param cond is numeric value of \c rv
491        virtual vec samplecond ( const vec &cond ) {
492                bdm_error ( "Not implemented" );
493                return vec();
494        }
495
496        //! Returns \param N samples from the density conditioned on \c cond, \f$x \sim epdf(rv|cond)\f$. \param cond is numeric value of \c rv
497        virtual mat samplecond_m ( const vec &cond, int N );
498
499        //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
500        virtual double evallogcond ( const vec &dt, const vec &cond ) {
501                bdm_error ( "Not implemented" );
502                return 0.0;
503        }
504
505        //! Matrix version of evallogcond
506        virtual vec evallogcond_m ( const mat &Dt, const vec &cond ) {
507                vec v ( Dt.cols() );
508                for ( int i = 0; i < Dt.cols(); i++ ) {
509                        v ( i ) = evallogcond ( Dt.get_col ( i ), cond );
510                }
511                return v;
512        }
513
514        //! Array<vec> version of evallogcond
515        virtual vec evallogcond_m ( const Array<vec> &Dt, const vec &cond ) {
516                bdm_error ( "Not implemented" );
517                return vec();
518        }
519
520        //! \name Access to attributes
521        //! @{
522
523        const RV& _rv() const {
524                return ep->_rv();
525        }
526        const RV& _rvc() const {
527                return rvc;
528        }
529
530        int dimension() const {
531                return ep->dimension();
532        }
533        int dimensionc() {
534                return dimc;
535        }
536
537        //! Load from structure with elements:
538        //!  \code
539        //! { class = "mpdf_offspring",
540        //!   rv = {class="RV", names=(...),}; // RV describing meaning of random variable
541        //!   rvc= {class="RV", names=(...),}; // RV describing meaning of random variable in condition
542        //!   // elements of offsprings
543        //! }
544        //! \endcode
545        //!@}
546        void from_setting ( const Setting &set );
547        //!@}
548
549        //! \name Connection to other objects
550        //!@{
551        void set_rvc ( const RV &rvc0 ) {
552                rvc = rvc0;
553        }
554        void set_rv ( const RV &rv0 ) {
555                ep->set_rv ( rv0 );
556        }
557        bool isnamed() {
558                return ( ep->isnamed() ) && ( dimc == rvc._dsize() );
559        }
560        //!@}
561};
562SHAREDPTR ( mpdf );
563
564//! Mpdf with internal epdf that is modified by function \c condition
565template <class EPDF>
566class mpdf_internal: public mpdf {
567protected :
568        //! Internal epdf used for sampling
569        EPDF iepdf;
570public:
571        //! constructor
572        mpdf_internal() : mpdf(), iepdf() {
573                set_ep ( iepdf );
574        }
575
576        //! Update \c iepdf so that it represents this mpdf conditioned on \c rvc = cond
577        //! This function provides convenient reimplementation in offsprings
578        virtual void condition ( const vec &cond ) {
579                bdm_error ( "Not implemented" );
580        }
581
582        //!access function to iepdf
583        EPDF& e() {
584                return iepdf;
585        }
586
587        //! Reimplements samplecond using \c condition()
588        vec samplecond ( const vec &cond );
589        //! Reimplements evallogcond using \c condition()
590        double evallogcond ( const vec &val, const vec &cond );
591        //! Efficient version of evallogcond for matrices
592        virtual vec evallogcond_m ( const mat &Dt, const vec &cond );
593        //! Efficient version of evallogcond for Array<vec>
594        virtual vec evallogcond_m ( const Array<vec> &Dt, const vec &cond );
595        //! Efficient version of samplecond
596        virtual mat samplecond_m ( const vec &cond, int N );
597};
598
599/*! \brief DataLink is a connection between two data vectors Up and Down
600
601Up can be longer than Down. Down must be fully present in Up (TODO optional)
602See chart:
603\dot
604digraph datalink {
605  node [shape=record];
606  subgraph cluster0 {
607    label = "Up";
608      up [label="<1>|<2>|<3>|<4>|<5>"];
609    color = "white"
610}
611  subgraph cluster1{
612    label = "Down";
613    labelloc = b;
614      down [label="<1>|<2>|<3>"];
615    color = "white"
616}
617    up:1 -> down:1;
618    up:3 -> down:2;
619    up:5 -> down:3;
620}
621\enddot
622
623*/
624class datalink {
625protected:
626        //! Remember how long val should be
627        int downsize;
628
629        //! Remember how long val of "Up" should be
630        int upsize;
631
632        //! val-to-val link, indices of the upper val
633        ivec v2v_up;
634
635public:
636        //! Constructor
637        datalink() : downsize ( 0 ), upsize ( 0 ) { }
638
639        //! Convenience constructor
640        datalink ( const RV &rv, const RV &rv_up ) {
641                set_connection ( rv, rv_up );
642        }
643
644        //! set connection, rv must be fully present in rv_up
645        void set_connection ( const RV &rv, const RV &rv_up );
646
647        //! set connection using indices
648        void set_connection ( int ds, int us, const ivec &upind );
649
650        //! Get val for myself from val of "Up"
651        vec pushdown ( const vec &val_up ) {
652                vec tmp ( downsize );
653                filldown ( val_up, tmp );
654                return tmp;
655        }
656        //! Get val for vector val_down from val of "Up"
657        void filldown ( const vec &val_up, vec &val_down ) {
658                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
659                val_down = val_up ( v2v_up );
660        }
661        //! Fill val of "Up" by my pieces
662        void pushup ( vec &val_up, const vec &val ) {
663                bdm_assert_debug ( downsize == val.length(), "Wrong val" );
664                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
665                set_subvector ( val_up, v2v_up, val );
666        }
667        //! access functions
668        int _upsize() {
669                return upsize;
670        }
671        //! access functions
672        int _downsize() {
673                return downsize;
674        }
675};
676
677/*! Extension of datalink to fill only part of Down
678*/
679class datalink_part : public datalink {
680protected:
681        //! indeces of values in vector downsize
682        ivec v2v_down;
683public:
684        void set_connection ( const RV &rv, const RV &rv_up );
685        //! Get val for vector val_down from val of "Up"
686        void filldown ( const vec &val_up, vec &val_down ) {
687                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) );
688        }
689};
690
691/*! \brief Datalink that buffers delayed values - do not forget to call step()
692
693Up is current data, Down is their subset with possibly delayed values
694*/
695class datalink_buffered: public datalink_part {
696protected:
697        //! History, ordered as \f$[Up_{t-1},Up_{t-2}, \ldots]\f$
698        vec history;
699        //! rv of the history
700        RV Hrv;
701        //! h2v : indeces in down
702        ivec h2v_down;
703        //! h2v : indeces in history
704        ivec h2v_hist;
705        //! v2h: indeces of up too be pushed to h
706        ivec v2h_up;
707public:
708
709        datalink_buffered() : datalink_part(), history ( 0 ), h2v_down ( 0 ), h2v_hist ( 0 ) {};
710        //! push current data to history
711        void step ( const vec &val_up ) {
712                if ( v2h_up.length() > 0 ) {
713                        history.shift_right ( 0, v2h_up.length() );
714                  history.set_subvector ( 0, val_up(v2h_up) ); 
715                }
716        }
717        //! Get val for myself from val of "Up"
718        vec pushdown ( const vec &val_up ) {
719                vec tmp ( downsize );
720                filldown ( val_up, tmp );
721                return tmp;
722        }
723
724        void filldown ( const vec &val_up, vec &val_down ) {
725                bdm_assert_debug ( val_down.length() >= downsize, "short val_down" );
726
727                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) ); // copy direct values
728                set_subvector ( val_down, h2v_down, history ( h2v_hist ) ); // copy delayed values
729        }
730
731        void set_connection ( const RV &rv, const RV &rv_up ) {
732                // create link between up and down
733                datalink_part::set_connection ( rv, rv_up );
734
735                // create rvs of history
736                // we can store only what we get in rv_up - everything else is removed
737                ivec valid_ids = rv.findself_ids ( rv_up );
738                RV rv_hist = rv.subselect ( find ( valid_ids >= 0 ) ); // select only rvs that are in rv_up
739          RV rv_hist0 =rv_hist.remove_time();  // these RVs will form history at time =0
740          v2h_up = rv_hist0.dataind(rv_up); // indeces of elements of rv_up to be copied
741          // now we need to know what is needed from Up
742                rv_hist = rv_hist.expand_delayes(); // full regressor - including time 0
743          Hrv=rv_hist.subt(rv_hist0);   // remove time 0
744                history = zeros ( Hrv._dsize() );
745
746                Hrv.dataind ( rv, h2v_hist, h2v_down );
747
748                downsize = v2v_down.length() + h2v_down.length();
749                upsize = v2v_up.length();
750        }
751        //! set history of variable given by \c rv1 to values of \c hist.
752        void set_history(const RV& rv1, const vec &hist0){
753                bdm_assert(rv1._dsize()==hist0.length(),"hist is not compatible with given rv1");
754                ivec ind_H;
755                ivec ind_h0;
756                Hrv.dataind(rv1, ind_H, ind_h0); // find indeces of rv in
757                set_subvector(history, ind_H, hist0(ind_h0)); // copy given hist to appropriate places
758        }
759};
760
761//! buffered datalink from 2 vectors to 1
762class datalink_2to1_buffered {
763protected:
764        datalink_buffered dl1;
765        datalink_buffered dl2;
766public:
767        //! set connection between RVs
768        void set_connection ( const RV &rv, const RV &rv_up1, const RV &rv_up2 ) {
769                dl1.set_connection ( rv, rv_up1 );
770                dl2.set_connection ( rv, rv_up2 );
771        }
772        void filldown ( const vec &val1, const vec &val2, vec &val_down ) {
773                bdm_assert_debug ( val_down.length() >= dl1._downsize() + dl2._downsize(), "short val_down" );
774                dl1.filldown ( val1, val_down );
775                dl2.filldown ( val2, val_down );
776        }
777        void step ( const vec &dt, const vec &ut ) {
778                dl1.step ( dt );
779                dl2.step ( ut );
780        }
781};
782
783
784
785//! Data link with a condition.
786class datalink_m2e: public datalink {
787protected:
788        //! Remember how long cond should be
789        int condsize;
790
791        //!upper_val-to-local_cond link, indices of the upper val
792        ivec v2c_up;
793
794        //!upper_val-to-local_cond link, indices of the local cond
795        ivec v2c_lo;
796
797public:
798        //! Constructor
799        datalink_m2e() : condsize ( 0 ) { }
800
801        //! Set connection between vectors
802        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up );
803
804        //!Construct condition
805        vec get_cond ( const vec &val_up );
806
807        //! Copy corresponding values to Up.condition
808        void pushup_cond ( vec &val_up, const vec &val, const vec &cond );
809};
810
811//!DataLink is a connection between mpdf and its superordinate (Up)
812//! This class links
813class datalink_m2m: public datalink_m2e {
814protected:
815        //!cond-to-cond link, indices of the upper cond
816        ivec c2c_up;
817        //!cond-to-cond link, indices of the local cond
818        ivec c2c_lo;
819
820public:
821        //! Constructor
822        datalink_m2m() {};
823        //! Set connection between the vectors
824        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up ) {
825                datalink_m2e::set_connection ( rv, rvc, rv_up );
826                //establish c2c connection
827                rvc.dataind ( rvc_up, c2c_lo, c2c_up );
828                bdm_assert_debug ( c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given" );
829        }
830
831        //! Get cond for myself from val and cond of "Up"
832        vec get_cond ( const vec &val_up, const vec &cond_up ) {
833                vec tmp ( condsize );
834                set_subvector ( tmp, v2c_lo, val_up ( v2c_up ) );
835                set_subvector ( tmp, c2c_lo, cond_up ( c2c_up ) );
836                return tmp;
837        }
838        //! Fill
839
840};
841
842/*!
843@brief Class for storing results (and semi-results) of an experiment
844
845This class abstracts logging of results from implementation. This class replaces direct logging of results (e.g. to files or to global variables) by calling methods of a logger. Specializations of this abstract class for specific storage method are designed.
846 */
847class logger : public root {
848protected:
849        //! RVs of all logged variables.
850        Array<RV> entries;
851        //! Names of logged quantities, e.g. names of algorithm variants
852        Array<string> names;
853public:
854        //!Default constructor
855        logger() : entries ( 0 ), names ( 0 ) {}
856
857        //! returns an identifier which will be later needed for calling the \c logit() function
858        //! For empty RV it returns -1, this entry will be ignored by \c logit().
859        virtual int add ( const RV &rv, string prefix = "" ) {
860                int id;
861                if ( rv._dsize() > 0 ) {
862                        id = entries.length();
863                        names = concat ( names, prefix ); // diff
864                        entries.set_length ( id + 1, true );
865                        entries ( id ) = rv;
866                } else {
867                        id = -1;
868                }
869                return id; // identifier of the last entry
870        }
871
872        //! log this vector
873        virtual void logit ( int id, const vec &v ) {
874                bdm_error ( "Not implemented" );
875        };
876        //! log this double
877        virtual void logit ( int id, const double &d ) {
878                bdm_error ( "Not implemented" );
879        };
880
881        //! Shifts storage position for another time step.
882        virtual void step() {
883                bdm_error ( "Not implemneted" );
884        };
885
886        //! Finalize storing information
887        virtual void finalize() {};
888
889        //! Initialize the storage
890        virtual void init() {};
891
892};
893
894/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
895
896*/
897class mepdf : public mpdf {
898        //! Internal shared pointer to epdf
899        shared_ptr<epdf> iepdf;
900public:
901        //!Default constructor
902        mepdf() { }
903        //! Set internal shared pointer
904        mepdf ( shared_ptr<epdf> em ) {
905                iepdf = em;
906                set_ep ( *iepdf.get() );
907                dimc = 0;
908        }
909
910        //! empty
911        vec samplecond ( const vec &cond ) {
912                return iepdf->sample();
913        }
914        double evallogcond ( const vec &val, const vec &cond ) {
915                return iepdf->evallog ( val );
916        }
917
918        //! Load from structure with elements:
919        //!  \code
920        //! { class = "mepdf",
921        //!   epdf = {class="epdf_offspring",...}
922        //! }
923        //! \endcode
924        //!@}
925        void from_setting ( const Setting &set );
926};
927UIREGISTER ( mepdf );
928SHAREDPTR ( mepdf );
929
930//! \brief Combines RVs from a list of mpdfs to a single one.
931RV get_composite_rv ( const Array<shared_ptr<mpdf> > &mpdfs, bool checkoverlap = false );
932
933/*! \brief Abstract class for discrete-time sources of data.
934
935The class abstracts operations of:
936\li  data aquisition,
937\li  data-preprocessing, such as  scaling of data,
938\li  data resampling from the task of estimation and control.
939Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
940
941The DataSource has three main data interaction structures:
942\li input, \f$ u_t \f$,
943\li output \f$ y_t \f$,
944\li data, \f$ d_t=[y_t,u_t, \ldots ]\f$ a collection of all inputs and outputs and possibly some internal variables too.
945
946*/
947
948class DS : public root {
949protected:
950                //! size of data returned by \c getdata()
951        int dtsize;
952                //! size of data
953        int utsize;
954                //!size of output
955                int ytsize;
956        //!Description of data returned by \c getdata().
957        RV Drv;
958        //!Description of data witten by by \c write().
959        RV Urv; //
960                //!Description of output data
961                RV Yrv; //
962        //! Remember its own index in Logger L
963        int L_dt, L_ut;
964public:
965        //! default constructors
966                DS() : Drv(), Urv(),Yrv() {};
967
968        //! Returns maximum number of provided data, by default it is set to maximum allowed length, shorter DS should overload this method! See, MemDS.max_length().
969        virtual int max_length() {return std::numeric_limits< int >::max();}
970        //! Returns full vector of observed data=[output, input]
971        virtual void getdata ( vec &dt ) {
972                bdm_error ( "abstract class" );
973        }
974        //! Returns data records at indeces.
975        virtual void getdata ( vec &dt, const ivec &indeces ) {
976                bdm_error ( "abstract class" );
977        }
978
979        //! Accepts action variable and schedule it for application.
980        virtual void write ( vec &ut ) {
981                bdm_error ( "abstract class" );
982        }
983
984        //! Accepts action variables at specific indeces
985        virtual void write ( vec &ut, const ivec &indeces ) {
986                bdm_error ( "abstract class" );
987        }
988
989        //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
990        virtual void step() 
991        {
992                bdm_error ( "abstract class" );
993        }
994
995        //! Register DS for logging into logger L
996        virtual void log_add ( logger &L ) {
997                bdm_assert_debug ( dtsize == Drv._dsize(), "invalid DS: dtsize (" + num2str ( dtsize ) + ") different from Drv " + num2str ( Drv._dsize() ) );
998                bdm_assert_debug ( utsize == Urv._dsize(), "invalid DS: utsize (" + num2str ( utsize ) + ") different from Urv " + num2str ( Urv._dsize() ) );
999
1000                L_dt = L.add ( Drv, "" );
1001                L_ut = L.add ( Urv, "" );
1002        }
1003        //! Register DS for logging into logger L
1004        virtual void logit ( logger &L ) {
1005                vec tmp ( Drv._dsize() + Urv._dsize() );
1006                getdata ( tmp );
1007                // d is first in getdata
1008                L.logit ( L_dt, tmp.left ( Drv._dsize() ) );
1009                // u follows after d in getdata
1010                L.logit ( L_ut, tmp.mid ( Drv._dsize(), Urv._dsize() ) );
1011        }
1012        //!access function
1013        virtual const RV& _drv() const {
1014                //              return concat (Drv, Urv);// why!!!
1015                return Drv;// why!!!
1016        }
1017        //!access function
1018        const RV& _urv() const {
1019                return Urv;
1020        }
1021                //!access function
1022                const RV& _yrv() const {
1023                        return Yrv;
1024                }
1025        //! set random variables
1026                virtual void set_drv (const  RV &yrv, const RV &urv) {
1027                    Yrv = yrv;
1028                        Drv = concat(yrv,urv);
1029                Urv = urv;
1030        }
1031};
1032
1033/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
1034
1035This object represents exact or approximate evaluation of the Bayes rule:
1036\f[
1037f(\theta_t | d_1,\ldots,d_t) = \frac{f(y_t|\theta_t,\cdot) f(\theta_t|d_1,\ldots,d_{t-1})}{f(y_t|d_1,\ldots,d_{t-1})}
1038\f]
1039
1040Access to the resulting posterior density is via function \c posterior().
1041
1042As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
1043It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
1044
1045Alternatively, it can evaluate posterior density conditioned by a known constant, \f$ c_t \f$:
1046\f[
1047f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
1048\f]
1049
1050The value of \f$ c_t \f$ is set by function condition().
1051
1052*/
1053
1054class BM : public root {
1055protected:
1056        //! Random variable of the data (optional)
1057        RV drv;
1058        //!Logarithm of marginalized data likelihood.
1059        double ll;
1060        //!  If true, the filter will compute likelihood of the data record and store it in \c ll . Set to false if you want to save computational time.
1061        bool evalll;
1062public:
1063        //! \name Constructors
1064        //! @{
1065
1066        BM() : ll ( 0 ), evalll ( true ), LIDs ( 4 ), LFlags ( 4 ) {
1067                LIDs = -1;/*empty IDs*/
1068                LFlags = 0;
1069                LFlags ( 0 ) = 1;  /*log only mean*/
1070        };
1071        BM ( const BM &B ) :  drv ( B.drv ), ll ( B.ll ), evalll ( B.evalll ) {}
1072        //! Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
1073        //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
1074        virtual BM* _copy_() const {
1075                return NULL;
1076        };
1077        //!@}
1078
1079        //! \name Mathematical operations
1080        //!@{
1081
1082        /*! \brief Incremental Bayes rule
1083        @param dt vector of input data
1084        */
1085        virtual void bayes ( const vec &dt ) = 0;
1086        //! Batch Bayes rule (columns of Dt are observations)
1087        virtual void bayesB ( const mat &Dt );
1088        //! Evaluates predictive log-likelihood of the given data record
1089        //! I.e. marginal likelihood of the data with the posterior integrated out.
1090        virtual double logpred ( const vec &dt ) const {
1091                bdm_error ( "Not implemented" );
1092                return 0.0;
1093        }
1094
1095        //! Matrix version of logpred
1096        vec logpred_m ( const mat &dt ) const {
1097                vec tmp ( dt.cols() );
1098                for ( int i = 0; i < dt.cols(); i++ ) {
1099                        tmp ( i ) = logpred ( dt.get_col ( i ) );
1100                }
1101                return tmp;
1102        }
1103
1104        //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
1105        virtual epdf* epredictor() const {
1106                bdm_error ( "Not implemented" );
1107                return NULL;
1108        };
1109        //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
1110        virtual mpdf* predictor() const {
1111                bdm_error ( "Not implemented" );
1112                return NULL;
1113        };
1114        //!@}
1115
1116        //! \name Extension to conditional BM
1117        //! This extension is useful e.g. in Marginalized Particle Filter (\ref bdm::MPF).
1118        //! Alternatively, it can be used for automated connection to DS when the condition is observed
1119        //!@{
1120
1121        //! Name of extension variable
1122        RV rvc;
1123        //! access function
1124        const RV& _rvc() const {
1125                return rvc;
1126        }
1127
1128        //! Substitute \c val for \c rvc.
1129        virtual void condition ( const vec &val ) {
1130                bdm_error ( "Not implemented!" );
1131        }
1132
1133        //!@}
1134
1135
1136        //! \name Access to attributes
1137        //!@{
1138
1139        const RV& _drv() const {
1140                return drv;
1141        }
1142        void set_drv ( const RV &rv ) {
1143                drv = rv;
1144        }
1145        void set_rv ( const RV &rv ) {
1146                const_cast<epdf&> ( posterior() ).set_rv ( rv );
1147        }
1148        double _ll() const {
1149                return ll;
1150        }
1151        void set_evalll ( bool evl0 ) {
1152                evalll = evl0;
1153        }
1154        virtual const epdf& posterior() const = 0;
1155        //!@}
1156
1157        //! \name Logging of results
1158        //!@{
1159
1160        //! Set boolean options from a string, recognized are: "logbounds,logll"
1161        virtual void set_options ( const string &opt ) {
1162                LFlags ( 0 ) = 1;
1163                if ( opt.find ( "logbounds" ) != string::npos ) {
1164                        LFlags ( 1 ) = 1;
1165                        LFlags ( 2 ) = 1;
1166                }
1167                if ( opt.find ( "logll" ) != string::npos ) {
1168                        LFlags ( 3 ) = 1;
1169                }
1170        }
1171        //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
1172        ivec LIDs;
1173
1174        //! Flags for logging - same size as LIDs, each entry correspond to the same in LIDs
1175        ivec LFlags;
1176        //! Add all logged variables to a logger
1177        virtual void log_add ( logger &L, const string &name = "" ) {
1178                // internal
1179                RV r;
1180                if ( posterior().isnamed() ) {
1181                        r = posterior()._rv();
1182                } else {
1183                        r = RV ( "est", posterior().dimension() );
1184                };
1185
1186                // Add mean value
1187                if ( LFlags ( 0 ) ) LIDs ( 0 ) = L.add ( r, name + "mean_" );
1188                if ( LFlags ( 1 ) ) LIDs ( 1 ) = L.add ( r, name + "lb_" );
1189                if ( LFlags ( 2 ) ) LIDs ( 2 ) = L.add ( r, name + "ub_" );
1190                if ( LFlags ( 3 ) ) LIDs ( 3 ) = L.add ( RV ( "ll", 1 ), name );    //TODO: "local" RV
1191        }
1192        virtual void logit ( logger &L ) {
1193                L.logit ( LIDs ( 0 ), posterior().mean() );
1194                if ( LFlags ( 1 ) || LFlags ( 2 ) ) {  //if one of them is off, its LID==-1 and will not be stored
1195                        vec ub, lb;
1196                        posterior().qbounds ( lb, ub );
1197                        L.logit ( LIDs ( 1 ), lb );
1198                        L.logit ( LIDs ( 2 ), ub );
1199                }
1200                if ( LFlags ( 3 ) ) L.logit ( LIDs ( 3 ), ll );
1201        }
1202        //!@}
1203        void from_setting ( const Setting &set ) {
1204                shared_ptr<RV> r = UI::build<RV> ( set, "drv", UI::optional );
1205                if ( r ) {
1206                        set_drv ( *r );
1207                }
1208                string opt;
1209                if ( !UI::get ( opt, set, "options", UI::optional ) ) {
1210                        set_options ( opt );
1211                }
1212        }
1213
1214};
1215
1216typedef Array<shared_ptr<epdf> > epdf_array;
1217
1218typedef Array<shared_ptr<mpdf> > mpdf_array;
1219
1220template<class EPDF>
1221vec mpdf_internal<EPDF>::samplecond ( const vec &cond ) {
1222        condition ( cond );
1223        vec temp = iepdf.sample();
1224        return temp;
1225}
1226
1227template<class EPDF>
1228mat mpdf_internal<EPDF>::samplecond_m ( const vec &cond, int N ) {
1229        condition ( cond );
1230        mat temp ( dimension(), N );
1231        vec smp ( dimension() );
1232        for ( int i = 0; i < N; i++ ) {
1233                smp = iepdf.sample();
1234                temp.set_col ( i, smp );
1235        }
1236
1237        return temp;
1238}
1239
1240template<class EPDF>
1241double mpdf_internal<EPDF>::evallogcond ( const vec &dt, const vec &cond ) {
1242        double tmp;
1243        condition ( cond );
1244        tmp = iepdf.evallog ( dt );
1245        return tmp;
1246}
1247
1248template<class EPDF>
1249vec mpdf_internal<EPDF>::evallogcond_m ( const mat &Dt, const vec &cond ) {
1250        condition ( cond );
1251        return iepdf.evallog_m ( Dt );
1252}
1253
1254template<class EPDF>
1255vec mpdf_internal<EPDF>::evallogcond_m ( const Array<vec> &Dt, const vec &cond ) {
1256        condition ( cond );
1257        return iepdf.evallog_m ( Dt );
1258}
1259
1260}; //namespace
1261#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.