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

Revision 741, 32.5 kB (checked in by smidl, 14 years ago)

Stress tests are passing now. Missing validate calls are filled...

  • 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
483        //! \name Connection to other objects
484        //!@{
485        void set_rvc ( const RV &rvc0 ) {
486                rvc = rvc0;
487        }
488        void set_rv ( const RV &rv0 ) {
489                rv = rv0;
490        }
491
492        bool isnamed() const {
493                return ( dim == rv._dsize() ) && ( dimc == rvc._dsize() );
494        }
495        //!@}
496};
497SHAREDPTR ( pdf );
498
499//! Probability density function with numerical statistics, e.g. posterior density.
500class epdf : public pdf {
501
502public:
503        /*! \name Constructors
504         Construction of each epdf should support two types of constructors:
505        \li empty constructor,
506        \li copy constructor,
507
508        The following constructors should be supported for convenience:
509        \li constructor followed by calling \c set_parameters()
510        \li constructor accepting random variables calling \c set_rv()
511
512         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.
513        @{*/
514        epdf() {};
515        epdf ( const epdf &e ) : pdf ( e ) {};
516        void set_parameters ( int dim0 ) {
517                dim = dim0;
518        }
519        epdf* _copy_() const {
520                return new epdf ( *this );
521        }
522        //!@}
523
524        //! \name Matematical Operations
525        //!@{
526
527        //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
528        virtual vec sample() const {
529                bdm_error ( "not implemented" );
530                return vec();
531        }
532
533        //! Returns N samples, \f$ [x_1 , x_2 , \ldots \ \f$  from density \f$ f_x(rv)\f$
534        virtual mat sample_mat ( int N ) const;
535
536        //! Compute log-probability of argument \c val
537        //! In case the argument is out of suport return -Infinity
538        virtual double evallog ( const vec &val ) const {
539                bdm_error ( "not implemented" );
540                return 0.0;
541        }
542
543        //! Compute log-probability of multiple values argument \c val
544        virtual vec evallog_mat ( const mat &Val ) const;
545
546        //! Compute log-probability of multiple values argument \c val
547        virtual vec evallog_mat ( const Array<vec> &Avec ) const;
548
549        //! Return conditional density on the given RV, the remaining rvs will be in conditioning
550        virtual shared_ptr<pdf> condition ( const RV &rv ) const;
551
552        //! Return marginal density on the given RV, the remainig rvs are intergrated out
553        virtual shared_ptr<epdf> marginal ( const RV &rv ) const;
554
555        //! return expected value
556        virtual vec mean() const {
557                bdm_error ( "not implemneted" );
558                return vec();
559        }
560
561        //! return expected variance (not covariance!)
562        virtual vec variance() const {
563                bdm_error ( "not implemneted" );
564                return vec();
565        }
566
567        //! Lower and upper bounds of \c percentage % quantile, returns mean-2*sigma as default
568        virtual void qbounds ( vec &lb, vec &ub, double percentage = 0.95 ) const {
569                vec mea = mean();
570                vec std = sqrt ( variance() );
571                lb = mea - 2 * std;
572                ub = mea + 2 * std;
573        };
574        //!@}
575
576        //! \name Connection to other classes
577        //! Description of the random quantity via attribute \c rv is optional.
578        //! For operations such as sampling \c rv does not need to be set. However, for \c marginalization
579        //! and \c conditioning \c rv has to be set. NB:
580        //! @{
581
582        //! store values of the epdf on the following levels:
583        //!  #1 mean
584        //!  #2 mean + lower & upper bound
585        void log_register ( logger &L, const string &prefix );
586
587        void log_write() const;
588        //!@}
589
590        //! \name Access to attributes
591        //! @{
592
593        //! Load from structure with elements:
594        //!  \code
595        //! { rv = {class="RV", names=(...),}; // RV describing meaning of random variable
596        //!   // elements of offsprings
597        //! }
598        //! \endcode
599        //!@}
600        void from_setting ( const Setting &set ) {
601                shared_ptr<RV> r = UI::build<RV> ( set, "rv", UI::optional );
602                if ( r ) {
603                        set_rv ( *r );
604                }
605        }
606
607        vec samplecond ( const vec &cond ) {
608                return sample();
609        }
610        double evallogcond ( const vec &val, const vec &cond ) {
611                return evallog ( val );
612        }
613};
614SHAREDPTR ( epdf );
615
616//! pdf with internal epdf that is modified by function \c condition
617template <class EPDF>
618class pdf_internal: public pdf {
619protected :
620        //! Internal epdf used for sampling
621        EPDF iepdf;
622public:
623        //! constructor
624        pdf_internal() : pdf(), iepdf() {
625//              set_ep ( iepdf ); TODO!
626        }
627
628        //! Update \c iepdf so that it represents this pdf conditioned on \c rvc = cond
629        //! This function provides convenient reimplementation in offsprings
630        virtual void condition ( const vec &cond ) {
631                bdm_error ( "Not implemented" );
632        }
633
634        //!access function to iepdf
635        EPDF& e() {
636                return iepdf;
637        }
638
639        //! Reimplements samplecond using \c condition()
640        vec samplecond ( const vec &cond );
641        //! Reimplements evallogcond using \c condition()
642        double evallogcond ( const vec &val, const vec &cond );
643        //! Efficient version of evallogcond for matrices
644        virtual vec evallogcond_mat ( const mat &Dt, const vec &cond );
645        //! Efficient version of evallogcond for Array<vec>
646        virtual vec evallogcond_mat ( const Array<vec> &Dt, const vec &cond );
647        //! Efficient version of samplecond
648        virtual mat samplecond_mat ( const vec &cond, int N );
649
650        void validate() {
651                iepdf.validate();
652                if ( rv._dsize() < iepdf._rv()._dsize() ) {
653                        rv = iepdf._rv();
654                };
655                dim = iepdf.dimension();
656        }
657};
658
659/*! \brief DataLink is a connection between two data vectors Up and Down
660
661Up can be longer than Down. Down must be fully present in Up (TODO optional)
662See chart:
663\dot
664digraph datalink {
665  node [shape=record];
666  subgraph cluster0 {
667    label = "Up";
668      up [label="<1>|<2>|<3>|<4>|<5>"];
669    color = "white"
670}
671  subgraph cluster1{
672    label = "Down";
673    labelloc = b;
674      down [label="<1>|<2>|<3>"];
675    color = "white"
676}
677    up:1 -> down:1;
678    up:3 -> down:2;
679    up:5 -> down:3;
680}
681\enddot
682
683*/
684class datalink {
685protected:
686        //! Remember how long val should be
687        int downsize;
688
689        //! Remember how long val of "Up" should be
690        int upsize;
691
692        //! val-to-val link, indices of the upper val
693        ivec v2v_up;
694
695public:
696        //! Constructor
697        datalink() : downsize ( 0 ), upsize ( 0 ) { }
698
699        //! Convenience constructor
700        datalink ( const RV &rv, const RV &rv_up ) {
701                set_connection ( rv, rv_up );
702        }
703
704        //! set connection, rv must be fully present in rv_up
705        virtual void set_connection ( const RV &rv, const RV &rv_up );
706
707        //! set connection using indices
708        virtual void set_connection ( int ds, int us, const ivec &upind );
709
710        //! Get val for myself from val of "Up"
711        vec pushdown ( const vec &val_up ) {
712                vec tmp ( downsize );
713                filldown ( val_up, tmp );
714                return tmp;
715        }
716        //! Get val for vector val_down from val of "Up"
717        virtual void filldown ( const vec &val_up, vec &val_down ) {
718                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
719                val_down = val_up ( v2v_up );
720        }
721        //! Fill val of "Up" by my pieces
722        virtual void pushup ( vec &val_up, const vec &val ) {
723                bdm_assert_debug ( downsize == val.length(), "Wrong val" );
724                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
725                set_subvector ( val_up, v2v_up, val );
726        }
727        //! access functions
728        int _upsize() {
729                return upsize;
730        }
731        //! access functions
732        int _downsize() {
733                return downsize;
734        }
735        //! for future use
736        virtual ~datalink() {}
737};
738
739/*! Extension of datalink to fill only part of Down
740*/
741class datalink_part : public datalink {
742protected:
743        //! indeces of values in vector downsize
744        ivec v2v_down;
745public:
746        void set_connection ( const RV &rv, const RV &rv_up );
747        //! Get val for vector val_down from val of "Up"
748        void filldown ( const vec &val_up, vec &val_down ) {
749                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) );
750        }
751};
752
753/*! \brief Datalink that buffers delayed values - do not forget to call step()
754
755Up is current data, Down is their subset with possibly delayed values
756*/
757class datalink_buffered: public datalink_part {
758protected:
759        //! History, ordered as \f$[Up_{t-1},Up_{t-2}, \ldots]\f$
760        vec history;
761        //! rv of the history
762        RV Hrv;
763        //! h2v : indeces in down
764        ivec h2v_down;
765        //! h2v : indeces in history
766        ivec h2v_hist;
767        //! v2h: indeces of up too be pushed to h
768        ivec v2h_up;
769public:
770
771        datalink_buffered() : datalink_part(), history ( 0 ), h2v_down ( 0 ), h2v_hist ( 0 ) {};
772        //! push current data to history
773        void store_data ( const vec &val_up ) {
774                if ( v2h_up.length() > 0 ) {
775                        history.shift_right ( 0, v2h_up.length() );
776                        history.set_subvector ( 0, val_up ( v2h_up ) );
777                }
778        }
779        //! Get val for myself from val of "Up"
780        vec pushdown ( const vec &val_up ) {
781                vec tmp ( downsize );
782                filldown ( val_up, tmp );
783                return tmp;
784        }
785
786        void filldown ( const vec &val_up, vec &val_down ) {
787                bdm_assert_debug ( val_down.length() >= downsize, "short val_down" );
788
789                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) ); // copy direct values
790                set_subvector ( val_down, h2v_down, history ( h2v_hist ) ); // copy delayed values
791        }
792
793        void set_connection ( const RV &rv, const RV &rv_up );
794       
795        //! set history of variable given by \c rv1 to values of \c hist.
796        void set_history ( const RV& rv1, const vec &hist0 );
797};
798
799//! buffered datalink from 2 vectors to 1
800class datalink_2to1_buffered {
801protected:
802        //! link 1st vector to down
803        datalink_buffered dl1;
804        //! link 2nd vector to down
805        datalink_buffered dl2;
806public:
807        //! set connection between RVs
808        void set_connection ( const RV &rv, const RV &rv_up1, const RV &rv_up2 ) {
809                dl1.set_connection ( rv, rv_up1 );
810                dl2.set_connection ( rv, rv_up2 );
811        }
812        //! fill values of down from the values of the two up vectors
813        void filldown ( const vec &val1, const vec &val2, vec &val_down ) {
814                bdm_assert_debug ( val_down.length() >= dl1._downsize() + dl2._downsize(), "short val_down" );
815                dl1.filldown ( val1, val_down );
816                dl2.filldown ( val2, val_down );
817        }
818        //! update buffer
819        void step ( const vec &dt, const vec &ut ) {
820                dl1.store_data ( dt );
821                dl2.store_data ( ut );
822        }
823};
824
825
826
827//! Data link with a condition.
828class datalink_m2e: public datalink {
829protected:
830        //! Remember how long cond should be
831        int condsize;
832
833        //!upper_val-to-local_cond link, indices of the upper val
834        ivec v2c_up;
835
836        //!upper_val-to-local_cond link, indices of the local cond
837        ivec v2c_lo;
838
839public:
840        //! Constructor
841        datalink_m2e() : condsize ( 0 ) { }
842
843        //! Set connection between vectors
844        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up );
845
846        //!Construct condition
847        vec get_cond ( const vec &val_up );
848
849        //! Copy corresponding values to Up.condition
850        void pushup_cond ( vec &val_up, const vec &val, const vec &cond );
851};
852
853//!DataLink is a connection between pdf and its superordinate (Up)
854//! This class links
855class datalink_m2m: public datalink_m2e {
856protected:
857        //!cond-to-cond link, indices of the upper cond
858        ivec c2c_up;
859        //!cond-to-cond link, indices of the local cond
860        ivec c2c_lo;
861
862public:
863        //! Constructor
864        datalink_m2m() {};
865        //! Set connection between the vectors
866        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up ) {
867                datalink_m2e::set_connection ( rv, rvc, rv_up );
868                //establish c2c connection
869                rvc.dataind ( rvc_up, c2c_lo, c2c_up );
870//              bdm_assert_debug ( c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given" );
871        }
872
873        //! Get cond for myself from val and cond of "Up"
874        vec get_cond ( const vec &val_up, const vec &cond_up ) {
875                vec tmp ( condsize );
876                fill_cond ( val_up, cond_up, tmp );
877                return tmp;
878        }
879        //! fill condition
880        void fill_cond ( const vec &val_up, const vec &cond_up, vec& cond_out ) {
881                bdm_assert_debug ( cond_out.length() >= condsize, "dl.fill_cond: cond_out is too small" );
882                set_subvector ( cond_out, v2c_lo, val_up ( v2c_up ) );
883                set_subvector ( cond_out, c2c_lo, cond_up ( c2c_up ) );
884        }
885        //! Fill
886
887};
888
889
890//! \brief Combines RVs from a list of pdfs to a single one.
891RV get_composite_rv ( const Array<shared_ptr<pdf> > &pdfs, bool checkoverlap = false );
892
893/*! \brief Abstract class for discrete-time sources of data.
894
895The class abstracts operations of:
896\li  data aquisition,
897\li  data-preprocessing, such as  scaling of data,
898\li  data resampling from the task of estimation and control.
899Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
900
901The DataSource has three main data interaction structures:
902\li input, \f$ u_t \f$,
903\li output \f$ y_t \f$,
904\li data, \f$ d_t=[y_t,u_t, \ldots ]\f$ a collection of all inputs and outputs and possibly some internal variables too.
905
906*/
907
908class DS : public root {
909protected:
910        //! size of data returned by \c getdata()
911        int dtsize;
912        //! size of data
913        int utsize;
914        //!size of output
915        int ytsize;
916        //!Description of data returned by \c getdata().
917        RV Drv;
918        //!Description of data witten by by \c write().
919        RV Urv; //
920        //!Description of output data
921        RV Yrv; //
922public:
923        //! default constructors
924        DS() : dtsize ( 0 ), utsize ( 0 ), ytsize ( 0 ), Drv(), Urv(), Yrv() {
925                log_level = 1;
926        };
927
928        //! 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().
929        virtual int max_length() {
930                return std::numeric_limits< int >::max();
931        }
932        //! Returns full vector of observed data=[output, input]
933        virtual void getdata ( vec &dt ) const {
934                bdm_error ( "abstract class" );
935        }
936        //! Returns data records at indeces.
937        virtual void getdata ( vec &dt, const ivec &indeces ) {
938                bdm_error ( "abstract class" );
939        }
940
941        //! Accepts action variable and schedule it for application.
942        virtual void write ( const vec &ut ) {
943                bdm_error ( "abstract class" );
944        }
945
946        //! Accepts action variables at specific indeces
947        virtual void write ( const vec &ut, const ivec &indeces ) {
948                bdm_error ( "abstract class" );
949        }
950
951        //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
952        virtual void step() {
953                bdm_error ( "abstract class" );
954        }
955
956        //! Register DS for logging into logger L
957        virtual void log_register ( logger &L,  const string &prefix );
958        //! Register DS for logging into logger L
959        virtual void log_write ( ) const;
960        //!access function
961        virtual const RV& _drv() const {
962                return Drv;
963        }
964        //!access function
965        const RV& _urv() const {
966                return Urv;
967        }
968        //!access function
969        const RV& _yrv() const {
970                return Yrv;
971        }
972        //! set random variables
973        virtual void set_drv ( const  RV &yrv, const RV &urv ) {
974                Yrv = yrv;
975                Drv = concat ( yrv, urv );
976                Urv = urv;
977        }
978};
979
980/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
981
982This object represents exact or approximate evaluation of the Bayes rule:
983\f[
984f(\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})}
985\f]
986where:
987 * \f$ y_t \f$ is the variable
988Access to the resulting posterior density is via function \c posterior().
989
990As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
991It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
992
993Alternatively, it can evaluate posterior density with rvc replaced by the given values, \f$ c_t \f$:
994\f[
995f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
996\f]
997
998
999*/
1000
1001class BM : public root {
1002protected:
1003        //! Random variable of the data (optional)
1004        RV yrv;
1005        //! size of the data record
1006        int dimy;
1007        //! Name of extension variable
1008        RV rvc;
1009        //! size of the conditioning vector
1010        int dimc;
1011
1012        //!Logarithm of marginalized data likelihood.
1013        double ll;
1014        //!  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.
1015        bool evalll;
1016
1017public:
1018        //! \name Constructors
1019        //! @{
1020
1021        BM() : yrv(), dimy ( 0 ), rvc(), dimc ( 0 ), ll ( 0 ), evalll ( true ) { };
1022//      BM ( const BM &B ) :  yrv ( B.yrv ), dimy(B.dimy), rvc ( B.rvc ),dimc(B.dimc), ll ( B.ll ), evalll ( B.evalll ) {}
1023        //! \brief Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
1024        //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
1025        virtual BM* _copy_() const {
1026                return NULL;
1027        };
1028        //!@}
1029
1030        //! \name Mathematical operations
1031        //!@{
1032
1033        /*! \brief Incremental Bayes rule
1034        @param dt vector of input data
1035        */
1036        virtual void bayes ( const vec &yt, const vec &cond = empty_vec ) = 0;
1037        //! Batch Bayes rule (columns of Dt are observations)
1038        virtual void bayes_batch ( const mat &Dt, const vec &cond = empty_vec );
1039        //! Batch Bayes rule (columns of Dt are observations, columns of Cond are conditions)
1040        virtual void bayes_batch ( const mat &Dt, const mat &Cond );
1041        //! Evaluates predictive log-likelihood of the given data record
1042        //! I.e. marginal likelihood of the data with the posterior integrated out.
1043        //! This function evaluates only \f$ y_t \f$, condition is assumed to be the last used in bayes().
1044        //! See bdm::BM::predictor for conditional version.
1045        virtual double logpred ( const vec &yt ) const {
1046                bdm_error ( "Not implemented" );
1047                return 0.0;
1048        }
1049
1050        //! Matrix version of logpred
1051        vec logpred_mat ( const mat &Yt ) const {
1052                vec tmp ( Yt.cols() );
1053                for ( int i = 0; i < Yt.cols(); i++ ) {
1054                        tmp ( i ) = logpred ( Yt.get_col ( i ) );
1055                }
1056                return tmp;
1057        }
1058
1059        //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
1060        virtual epdf* epredictor() const {
1061                bdm_error ( "Not implemented" );
1062                return NULL;
1063        };
1064        //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
1065        virtual pdf* predictor() const {
1066                bdm_error ( "Not implemented" );
1067                return NULL;
1068        };
1069        //!@}
1070
1071
1072        //! \name Access to attributes
1073        //!@{
1074        //! access function
1075        const RV& _rvc() const {
1076                return rvc;
1077        }
1078        //! access function
1079        int dimensionc() const {
1080                return dimc;
1081        }
1082        //! access function
1083        int dimensiony() const {
1084                return dimy;
1085        }
1086        //! access function
1087        int dimension() const {
1088                return posterior().dimension();
1089        }
1090        //! access function
1091        const RV& _yrv() const {
1092                return yrv;
1093        }
1094        //! access function
1095        void set_yrv ( const RV &rv ) {
1096                yrv = rv;
1097        }
1098        //! access to rv of the posterior
1099        void set_rv ( const RV &rv ) {
1100                const_cast<epdf&> ( posterior() ).set_rv ( rv );
1101        }
1102        //! access function
1103        void set_dim ( int dim ) {
1104                const_cast<epdf&> ( posterior() ).set_dim ( dim );
1105        }
1106        //! return internal log-likelihood of the last data vector
1107        double _ll() const {
1108                return ll;
1109        }
1110        //! switch evaluation of log-likelihood on/off
1111        void set_evalll ( bool evl0 ) {
1112                evalll = evl0;
1113        }
1114        //! return posterior density
1115        virtual const epdf& posterior() const = 0;
1116        //!@}
1117
1118        //! \name Logging of results
1119        //!@{
1120
1121        //! Set boolean options from a string, recognized are: "logbounds,logll"
1122        virtual void set_options ( const string &opt );
1123
1124        //! Add all logged variables to a logger
1125        //! Log levels two digits: xy where
1126        //!  * y = 0/1 log-likelihood is to be logged
1127        //!  * x = level of the posterior (typically 0/1/2 for nothing/mean/bounds)
1128        virtual void log_register ( logger &L, const string &prefix = "" );
1129
1130        //! Save results to the given logger, details of what is stored is configured by \c LIDs and \c options
1131        virtual void log_write ( ) const;
1132
1133        //!@}
1134        void from_setting ( const Setting &set ) {
1135                shared_ptr<RV> r = UI::build<RV> ( set, "yrv", UI::optional );
1136                if ( r ) {
1137                        set_yrv ( *r );
1138                }
1139                shared_ptr<RV> r2 = UI::build<RV> ( set, "rvc", UI::optional );
1140                if ( r2 ) {
1141                        rvc =   *r2;
1142                }
1143                shared_ptr<RV> r3 = UI::build<RV> ( set, "rv", UI::optional );
1144                if ( r3 ) {
1145                        set_rv ( *r3 );
1146                }
1147
1148                string opt;
1149                if ( UI::get ( opt, set, "options", UI::optional ) ) {
1150                        set_options ( opt );
1151                }
1152        }
1153
1154};
1155//! array of pointers to epdf
1156typedef Array<shared_ptr<epdf> > epdf_array;
1157//! array of pointers to pdf
1158typedef Array<shared_ptr<pdf> > pdf_array;
1159
1160template<class EPDF>
1161vec pdf_internal<EPDF>::samplecond ( const vec &cond ) {
1162        condition ( cond );
1163        vec temp = iepdf.sample();
1164        return temp;
1165}
1166
1167template<class EPDF>
1168mat pdf_internal<EPDF>::samplecond_mat ( const vec &cond, int N ) {
1169        condition ( cond );
1170        mat temp ( dimension(), N );
1171        vec smp ( dimension() );
1172        for ( int i = 0; i < N; i++ ) {
1173                smp = iepdf.sample();
1174                temp.set_col ( i, smp );
1175        }
1176
1177        return temp;
1178}
1179
1180template<class EPDF>
1181double pdf_internal<EPDF>::evallogcond ( const vec &yt, const vec &cond ) {
1182        double tmp;
1183        condition ( cond );
1184        tmp = iepdf.evallog ( yt );
1185        return tmp;
1186}
1187
1188template<class EPDF>
1189vec pdf_internal<EPDF>::evallogcond_mat ( const mat &Yt, const vec &cond ) {
1190        condition ( cond );
1191        return iepdf.evallog_mat ( Yt );
1192}
1193
1194template<class EPDF>
1195vec pdf_internal<EPDF>::evallogcond_mat ( const Array<vec> &Yt, const vec &cond ) {
1196        condition ( cond );
1197        return iepdf.evallog_mat ( Yt );
1198}
1199
1200}; //namespace
1201#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.