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

Revision 760, 33.4 kB (checked in by smidl, 14 years ago)

cleanups & stuff for SYSID like estimation

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