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

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

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

  • Property svn:eol-style set to native
RevLine 
[2]1/*!
[5]2  \file
[508]3  \brief Basic structures of probability calculus: random variables, probability densities, Bayes rule
[5]4  \author Vaclav Smidl.
[2]5
[5]6  -----------------------------------
7  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8
9  Using IT++ for numerical operations
10  -----------------------------------
11*/
12
[384]13#ifndef BDMBASE_H
14#define BDMBASE_H
[2]15
[351]16#include <map>
[263]17
[190]18#include "../itpp_ext.h"
[357]19#include "../bdmroot.h"
[461]20#include "../shared_ptr.h"
[384]21#include "user_info.h"
[2]22
[340]23using namespace libconfig;
[270]24using namespace itpp;
25using namespace std;
[2]26
[600]27namespace bdm {
[422]28//! Structure of RV, i.e. RVs expanded into a flat list of IDs, used for debugging.
[600]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 ) {
[620]37                bdm_assert ( times0.length() == ids0.length(), "Incompatible input" );
[600]38        };
[270]39};
[145]40
[270]41/*!
42* \brief Class representing variables, most often random variables
[5]43
[270]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.
[32]45
[270]46The class is implemented using global variables to assure uniqueness of description:
[2]47
[270]48 In is a vector
49\dot
50digraph datalink {
51rankdir=LR;
52subgraph cluster0 {
53node [shape=record];
[600]54label = "MAP \n std::map<string,int>";
[270]55map [label="{{\"a\"| \"b\" | \"c\"} | {<3> 3 |<1> 1|<2> 2}}"];
56color = "white"
57}
58subgraph cluster1{
59node [shape=record];
[600]60label = "NAMES";
[270]61names [label="{<1> \"b\" | <2> \"c\" | <3>\"a\" }"];
62color = "white"
63}
64subgraph cluster2{
65node [shape=record];
[600]66label = "SIZES";
[270]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*/
[32]78
[600]79class RV : public root {
80private:
81        typedef std::map<string, int> str2int_map;
[5]82
[600]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;
[271]87
[600]88        //! TODO
89        const static int BUFFER_STEP;
[422]90
[600]91        //! TODO
92        static str2int_map MAP;
[422]93
[600]94public:
[422]95
[600]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;
[532]105
[600]106private:
107        enum enum_dummy {dummy};
[532]108
[600]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        //!@{
[271]120
[600]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        }
[271]125
[600]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        }
[422]130
[600]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        }
[422]135
[600]136        //! Constructor of empty RV
137        RV() : dsize ( 0 ), len ( 0 ), ids ( 0 ), times ( 0 ) {}
[271]138
[600]139        //! Constructor of a single RV with given id
140        RV ( string name, int sz, int tm = 0 );
[271]141
[600]142        // compiler-generated copy constructor is used
143        //!@}
[422]144
[600]145        //! \name Access functions
146        //!@{
[422]147
[600]148        //! State output, e.g. for debugging.
149        friend std::ostream &operator<< ( std::ostream &os, const RV &rv );
[422]150
[737]151        string to_string() const {
152                ostringstream o;
153                o << *this;
154                return o.str();
155        }
156
[604]157        //! total size of a random variable
[600]158        int _dsize() const {
159                return dsize;
160        }
[271]161
[600]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;
[604]169        //! Vector of cumulative sizes of RV
[600]170        ivec cumsizes() const;
[604]171        //! Number of named parts
[600]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        }
[610]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
[738]188        std::string scalarname ( int scalat ) const;
[610]189
[600]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.
[604]220        void t_plus ( int delta );
[600]221        //!@}
222
[604]223        //! @{ \name Time manipulation functions
[600]224        //! returns rvs with time set to 0 and removed duplicates
225        RV remove_time() const {
226                return RV ( unique ( ids ), dummy );
227        }
[604]228        //! create new RV from the current one with time shifted by given value
[737]229        RV copy_t ( int dt ) const {
230                RV tmp = *this;
231                tmp.t_plus ( dt );
[604]232                return tmp;
233        }
[660]234        //! return rvs with expanded delayes and sorted in the order of: \f$ [ rv_{0}, rv_{-1},\ldots  rv_{max_delay}]\f$
[738]235        RV expand_delayes() const;
[600]236        //!@}
[271]237
[600]238        //!\name Relation to vectors
239        //!@{
[271]240
[600]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 {
[737]253                return times.length() > 0 ? min ( times ) : 0;
[600]254        }
[700]255        //! Minimum time-offset of ids of given RVs
[737]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 ) );
[700]260                }
[737]261                return times.length() > 0 ? min ( get_from_bvec ( times, belong ) ) : 0;
[700]262        }
[600]263        //!@}
[357]264
[600]265        /*! \brief UI for class RV (description of data vectors)
[357]266
[600]267        \code
[737]268        class = 'RV';
[624]269        names = {'a', 'b', 'c', ...};   // UNIQUE IDENTIFIER same names = same variable
[737]270                                                                        // names are also used when storing results
[624]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()
[600]275        \endcode
276        */
277        void from_setting ( const Setting &set );
278
[737]279        void to_setting ( Setting &set ) const;
[600]280
281        //! Invalidate all named RVs. Use before initializing any RV instances, with care...
282        static void clear_all();
[604]283        //! function for debugging RV related stuff
284        string show_all();
285
[270]286};
[600]287UIREGISTER ( RV );
288SHAREDPTR ( RV );
[32]289
[145]290//! Concat two random variables
[600]291RV concat ( const RV &rv1, const RV &rv2 );
[2]292
[676]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 {
[737]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().
[738]316        virtual int add_vector ( const RV &rv, string prefix = "" );
[737]317
[738]318        virtual int add_setting ( const string &prefix );
319
[737]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        }
[676]349};
350
351
[85]352//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
[600]353class fnc : public root {
354protected:
355        //! Length of the output vector
356        int dimy;
[665]357        //! Length of the input vector
358        int dimc;
[600]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        };
[2]366
[600]367        //! function substitutes given value into an appropriate position
368        virtual void condition ( const vec &val ) {};
[27]369
[600]370        //! access function
371        int dimension() const {
372                return dimy;
373        }
[665]374        //! access function
375        int dimensionc() const {
376                return dimc;
377        }
[270]378};
[2]379
[675]380class epdf;
[7]381
[675]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.
[693]383class pdf : public root {
[675]384protected:
385        //!dimension of the condition
386        int dimc;
387        //! random variable in condition
388        RV rvc;
[32]389
[678]390        //! dimension of random variable
[675]391        int dim;
392
[678]393        //! random variable
[675]394        RV rv;
395
396public:
397        //! \name Constructors
398        //! @{
399
[737]400        pdf() : dimc ( 0 ), rvc(), dim ( 0 ), rv() { }
[675]401
[737]402        pdf ( const pdf &m ) : dimc ( m.dimc ), rvc ( m.rvc ), dim ( m.dim ), rv ( m.rv ) { }
403
[679]404        //! copy of the current object - make sure to implement
[737]405        virtual pdf* _copy_() const {
406                return new pdf ( *this );
407        }
[675]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
[713]420        virtual mat samplecond_mat ( const vec &cond, int N );
[675]421
422        //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
[679]423        virtual double evallogcond ( const vec &yt, const vec &cond ) {
[675]424                bdm_error ( "Not implemented" );
425                return 0.0;
426        }
427
428        //! Matrix version of evallogcond
[713]429        virtual vec evallogcond_mat ( const mat &Yt, const vec &cond ) {
[679]430                vec v ( Yt.cols() );
431                for ( int i = 0; i < Yt.cols(); i++ ) {
432                        v ( i ) = evallogcond ( Yt.get_col ( i ), cond );
[675]433                }
434                return v;
435        }
436
437        //! Array<vec> version of evallogcond
[713]438        virtual vec evallogcond_mat ( const Array<vec> &Yt, const vec &cond ) {
[741]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;
[675]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
[679]463        //! access function
[737]464        void set_dim ( int d ) {
465                dim = d;
466        }
[679]467        //! access function
[737]468        void set_dimc ( int d ) {
469                dimc = d;
470        }
[675]471        //! Load from structure with elements:
472        //!  \code
[693]473        //! { class = "pdf_offspring",
[675]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
[678]492        bool isnamed() const {
[675]493                return ( dim == rv._dsize() ) && ( dimc == rvc._dsize() );
494        }
495        //!@}
496};
[693]497SHAREDPTR ( pdf );
[675]498
499//! Probability density function with numerical statistics, e.g. posterior density.
[693]500class epdf : public pdf {
[32]501
[600]502public:
503        /*! \name Constructors
504         Construction of each epdf should support two types of constructors:
505        \li empty constructor,
506        \li copy constructor,
[271]507
[600]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()
[271]511
[600]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        @{*/
[678]514        epdf() {};
[737]515        epdf ( const epdf &e ) : pdf ( e ) {};
[600]516        void set_parameters ( int dim0 ) {
517                dim = dim0;
518        }
[737]519        epdf* _copy_() const {
520                return new epdf ( *this );
521        }
[600]522        //!@}
[271]523
[600]524        //! \name Matematical Operations
525        //!@{
[271]526
[600]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        }
[502]532
[600]533        //! Returns N samples, \f$ [x_1 , x_2 , \ldots \ \f$  from density \f$ f_x(rv)\f$
[713]534        virtual mat sample_mat ( int N ) const;
[502]535
[600]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        }
[502]542
[600]543        //! Compute log-probability of multiple values argument \c val
[713]544        virtual vec evallog_mat ( const mat &Val ) const;
[502]545
[600]546        //! Compute log-probability of multiple values argument \c val
[713]547        virtual vec evallog_mat ( const Array<vec> &Avec ) const;
[502]548
[600]549        //! Return conditional density on the given RV, the remaining rvs will be in conditioning
[693]550        virtual shared_ptr<pdf> condition ( const RV &rv ) const;
[271]551
[600]552        //! Return marginal density on the given RV, the remainig rvs are intergrated out
553        virtual shared_ptr<epdf> marginal ( const RV &rv ) const;
[271]554
[600]555        //! return expected value
556        virtual vec mean() const {
557                bdm_error ( "not implemneted" );
558                return vec();
559        }
[271]560
[600]561        //! return expected variance (not covariance!)
562        virtual vec variance() const {
563                bdm_error ( "not implemneted" );
564                return vec();
565        }
[565]566
[600]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        //!@}
[271]575
[600]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        //! @{
[271]581
[676]582        //! store values of the epdf on the following levels:
583        //!  #1 mean
584        //!  #2 mean + lower & upper bound
[738]585        void log_register ( logger &L, const string &prefix );
[737]586
[738]587        void log_write() const;
[600]588        //!@}
[377]589
[600]590        //! \name Access to attributes
591        //! @{
[377]592
[600]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 );
[477]604                }
[600]605        }
[377]606
[675]607        vec samplecond ( const vec &cond ) {
608                return sample();
[600]609        }
[675]610        double evallogcond ( const vec &val, const vec &cond ) {
611                return evallog ( val );
[600]612        }
[270]613};
[675]614SHAREDPTR ( epdf );
[32]615
[693]616//! pdf with internal epdf that is modified by function \c condition
[487]617template <class EPDF>
[693]618class pdf_internal: public pdf {
[600]619protected :
620        //! Internal epdf used for sampling
621        EPDF iepdf;
622public:
623        //! constructor
[693]624        pdf_internal() : pdf(), iepdf() {
[675]625//              set_ep ( iepdf ); TODO!
[600]626        }
[565]627
[693]628        //! Update \c iepdf so that it represents this pdf conditioned on \c rvc = cond
[600]629        //! This function provides convenient reimplementation in offsprings
630        virtual void condition ( const vec &cond ) {
631                bdm_error ( "Not implemented" );
632        }
[565]633
[600]634        //!access function to iepdf
635        EPDF& e() {
636                return iepdf;
637        }
[488]638
[600]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
[713]644        virtual vec evallogcond_mat ( const mat &Dt, const vec &cond );
[600]645        //! Efficient version of evallogcond for Array<vec>
[713]646        virtual vec evallogcond_mat ( const Array<vec> &Dt, const vec &cond );
[600]647        //! Efficient version of samplecond
[713]648        virtual mat samplecond_mat ( const vec &cond, int N );
[737]649
[678]650        void validate() {
651                iepdf.validate();
[737]652                if ( rv._dsize() < iepdf._rv()._dsize() ) {
653                        rv = iepdf._rv();
654                };
[678]655                dim = iepdf.dimension();
656        }
[487]657};
658
[270]659/*! \brief DataLink is a connection between two data vectors Up and Down
[2]660
[270]661Up can be longer than Down. Down must be fully present in Up (TODO optional)
662See chart:
663\dot
664digraph datalink {
[377]665  node [shape=record];
666  subgraph cluster0 {
667    label = "Up";
668      up [label="<1>|<2>|<3>|<4>|<5>"];
669    color = "white"
[270]670}
[377]671  subgraph cluster1{
672    label = "Down";
673    labelloc = b;
674      down [label="<1>|<2>|<3>"];
675    color = "white"
[270]676}
677    up:1 -> down:1;
678    up:3 -> down:2;
679    up:5 -> down:3;
680}
681\enddot
[263]682
[270]683*/
[600]684class datalink {
685protected:
686        //! Remember how long val should be
687        int downsize;
[424]688
[600]689        //! Remember how long val of "Up" should be
690        int upsize;
[424]691
[600]692        //! val-to-val link, indices of the upper val
693        ivec v2v_up;
[545]694
[600]695public:
696        //! Constructor
697        datalink() : downsize ( 0 ), upsize ( 0 ) { }
[424]698
[600]699        //! Convenience constructor
700        datalink ( const RV &rv, const RV &rv_up ) {
701                set_connection ( rv, rv_up );
702        }
[271]703
[600]704        //! set connection, rv must be fully present in rv_up
[628]705        virtual void set_connection ( const RV &rv, const RV &rv_up );
[286]706
[600]707        //! set connection using indices
[628]708        virtual void set_connection ( int ds, int us, const ivec &upind );
[424]709
[600]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"
[628]717        virtual void filldown ( const vec &val_up, vec &val_down ) {
[600]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
[628]722        virtual void pushup ( vec &val_up, const vec &val ) {
[600]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        }
[665]735        //! for future use
[737]736        virtual ~datalink() {}
[270]737};
[115]738
[598]739/*! Extension of datalink to fill only part of Down
740*/
[600]741class datalink_part : public datalink {
742protected:
[598]743        //! indeces of values in vector downsize
744        ivec v2v_down;
[600]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        }
[598]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*/
[600]757class datalink_buffered: public datalink_part {
758protected:
[598]759        //! History, ordered as \f$[Up_{t-1},Up_{t-2}, \ldots]\f$
760        vec history;
761        //! rv of the history
762        RV Hrv;
[600]763        //! h2v : indeces in down
[598]764        ivec h2v_down;
765        //! h2v : indeces in history
766        ivec h2v_hist;
[603]767        //! v2h: indeces of up too be pushed to h
768        ivec v2h_up;
[600]769public:
770
771        datalink_buffered() : datalink_part(), history ( 0 ), h2v_down ( 0 ), h2v_hist ( 0 ) {};
[598]772        //! push current data to history
[723]773        void store_data ( const vec &val_up ) {
[613]774                if ( v2h_up.length() > 0 ) {
775                        history.shift_right ( 0, v2h_up.length() );
[737]776                        history.set_subvector ( 0, val_up ( v2h_up ) );
[598]777                }
778        }
[600]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;
[598]784        }
[600]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
[598]791        }
[600]792
[738]793        void set_connection ( const RV &rv, const RV &rv_up );
794       
[613]795        //! set history of variable given by \c rv1 to values of \c hist.
[738]796        void set_history ( const RV& rv1, const vec &hist0 );
[598]797};
798
799//! buffered datalink from 2 vectors to 1
[600]800class datalink_2to1_buffered {
801protected:
[660]802        //! link 1st vector to down
[598]803        datalink_buffered dl1;
[660]804        //! link 2nd vector to down
[598]805        datalink_buffered dl2;
[600]806public:
[598]807        //! set connection between RVs
[600]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 );
[598]811        }
[660]812        //! fill values of down from the values of the two up vectors
[600]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 );
[598]817        }
[660]818        //! update buffer
[600]819        void step ( const vec &dt, const vec &ut ) {
[723]820                dl1.store_data ( dt );
821                dl2.store_data ( ut );
[600]822        }
[598]823};
824
[600]825
826
[424]827//! Data link with a condition.
[600]828class datalink_m2e: public datalink {
829protected:
830        //! Remember how long cond should be
831        int condsize;
[424]832
[600]833        //!upper_val-to-local_cond link, indices of the upper val
834        ivec v2c_up;
[424]835
[600]836        //!upper_val-to-local_cond link, indices of the local cond
837        ivec v2c_lo;
[192]838
[600]839public:
840        //! Constructor
841        datalink_m2e() : condsize ( 0 ) { }
[545]842
[600]843        //! Set connection between vectors
844        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up );
[424]845
[600]846        //!Construct condition
847        vec get_cond ( const vec &val_up );
[545]848
[600]849        //! Copy corresponding values to Up.condition
850        void pushup_cond ( vec &val_up, const vec &val, const vec &cond );
[270]851};
[424]852
[693]853//!DataLink is a connection between pdf and its superordinate (Up)
[192]854//! This class links
[600]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;
[424]861
[600]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 );
[700]870//              bdm_assert_debug ( c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given" );
[600]871        }
[424]872
[600]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 );
[737]876                fill_cond ( val_up, cond_up, tmp );
[600]877                return tmp;
878        }
[737]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" );
[700]882                set_subvector ( cond_out, v2c_lo, val_up ( v2c_up ) );
883                set_subvector ( cond_out, c2c_lo, cond_up ( c2c_up ) );
884        }
[600]885        //! Fill
[190]886
[270]887};
[190]888
[267]889
[693]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 );
[175]892
[270]893/*! \brief Abstract class for discrete-time sources of data.
[12]894
[737]895The class abstracts operations of:
896\li  data aquisition,
897\li  data-preprocessing, such as  scaling of data,
[603]898\li  data resampling from the task of estimation and control.
[270]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).
[12]900
[603]901The DataSource has three main data interaction structures:
[737]902\li input, \f$ u_t \f$,
[603]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
[270]906*/
[32]907
[600]908class DS : public root {
909protected:
[737]910        //! size of data returned by \c getdata()
[600]911        int dtsize;
[737]912        //! size of data
[600]913        int utsize;
[737]914        //!size of output
915        int ytsize;
[600]916        //!Description of data returned by \c getdata().
917        RV Drv;
918        //!Description of data witten by by \c write().
919        RV Urv; //
[737]920        //!Description of output data
921        RV Yrv; //
[600]922public:
923        //! default constructors
[737]924        DS() : dtsize ( 0 ), utsize ( 0 ), ytsize ( 0 ), Drv(), Urv(), Yrv() {
925                log_level = 1;
926        };
[565]927
[609]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().
[737]929        virtual int max_length() {
930                return std::numeric_limits< int >::max();
931        }
[600]932        //! Returns full vector of observed data=[output, input]
[676]933        virtual void getdata ( vec &dt ) const {
[600]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        }
[565]940
[600]941        //! Accepts action variable and schedule it for application.
[737]942        virtual void write ( const vec &ut ) {
[600]943                bdm_error ( "abstract class" );
944        }
[565]945
[600]946        //! Accepts action variables at specific indeces
[737]947        virtual void write ( const vec &ut, const ivec &indeces ) {
[600]948                bdm_error ( "abstract class" );
949        }
[32]950
[600]951        //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
[737]952        virtual void step() {
[619]953                bdm_error ( "abstract class" );
954        }
[32]955
[600]956        //! Register DS for logging into logger L
[738]957        virtual void log_register ( logger &L,  const string &prefix );
[600]958        //! Register DS for logging into logger L
[738]959        virtual void log_write ( ) const;
[600]960        //!access function
961        virtual const RV& _drv() const {
[676]962                return Drv;
[600]963        }
964        //!access function
965        const RV& _urv() const {
966                return Urv;
967        }
[676]968        //!access function
969        const RV& _yrv() const {
970                return Yrv;
971        }
[600]972        //! set random variables
[737]973        virtual void set_drv ( const  RV &yrv, const RV &urv ) {
[676]974                Yrv = yrv;
[737]975                Drv = concat ( yrv, urv );
[600]976                Urv = urv;
977        }
[270]978};
[18]979
[270]980/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
[32]981
[283]982This object represents exact or approximate evaluation of the Bayes rule:
983\f[
[679]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})}
[283]985\f]
[679]986where:
[737]987 * \f$ y_t \f$ is the variable
[283]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
[679]993Alternatively, it can evaluate posterior density with rvc replaced by the given values, \f$ c_t \f$:
[283]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
[270]999*/
[32]1000
[600]1001class BM : public root {
1002protected:
1003        //! Random variable of the data (optional)
[679]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;
[737]1011
[600]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;
[679]1016
[600]1017public:
1018        //! \name Constructors
1019        //! @{
[271]1020
[737]1021        BM() : yrv(), dimy ( 0 ), rvc(), dimc ( 0 ), ll ( 0 ), evalll ( true ) { };
[700]1022//      BM ( const BM &B ) :  yrv ( B.yrv ), dimy(B.dimy), rvc ( B.rvc ),dimc(B.dimc), ll ( B.ll ), evalll ( B.evalll ) {}
[660]1023        //! \brief Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
[600]1024        //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
[737]1025        virtual BM* _copy_() const {
1026                return NULL;
1027        };
[600]1028        //!@}
[18]1029
[600]1030        //! \name Mathematical operations
1031        //!@{
[271]1032
[600]1033        /*! \brief Incremental Bayes rule
1034        @param dt vector of input data
1035        */
[737]1036        virtual void bayes ( const vec &yt, const vec &cond = empty_vec ) = 0;
[600]1037        //! Batch Bayes rule (columns of Dt are observations)
[737]1038        virtual void bayes_batch ( const mat &Dt, const vec &cond = empty_vec );
[690]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 );
[600]1041        //! Evaluates predictive log-likelihood of the given data record
[737]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().
[679]1044        //! See bdm::BM::predictor for conditional version.
1045        virtual double logpred ( const vec &yt ) const {
[600]1046                bdm_error ( "Not implemented" );
1047                return 0.0;
1048        }
[565]1049
[600]1050        //! Matrix version of logpred
[713]1051        vec logpred_mat ( const mat &Yt ) const {
[679]1052                vec tmp ( Yt.cols() );
1053                for ( int i = 0; i < Yt.cols(); i++ ) {
1054                        tmp ( i ) = logpred ( Yt.get_col ( i ) );
[488]1055                }
[600]1056                return tmp;
1057        }
[32]1058
[600]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$
[693]1065        virtual pdf* predictor() const {
[600]1066                bdm_error ( "Not implemented" );
1067                return NULL;
1068        };
1069        //!@}
[271]1070
[283]1071
[600]1072        //! \name Access to attributes
1073        //!@{
[737]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
[679]1091        const RV& _yrv() const {
1092                return yrv;
[600]1093        }
[660]1094        //! access function
[679]1095        void set_yrv ( const RV &rv ) {
1096                yrv = rv;
[600]1097        }
[660]1098        //! access to rv of the posterior
[600]1099        void set_rv ( const RV &rv ) {
[737]1100                const_cast<epdf&> ( posterior() ).set_rv ( rv );
[600]1101        }
[679]1102        //! access function
1103        void set_dim ( int dim ) {
[737]1104                const_cast<epdf&> ( posterior() ).set_dim ( dim );
[679]1105        }
[660]1106        //! return internal log-likelihood of the last data vector
[600]1107        double _ll() const {
1108                return ll;
1109        }
[660]1110        //! switch evaluation of log-likelihood on/off
[600]1111        void set_evalll ( bool evl0 ) {
1112                evalll = evl0;
1113        }
[660]1114        //! return posterior density
[600]1115        virtual const epdf& posterior() const = 0;
1116        //!@}
[28]1117
[600]1118        //! \name Logging of results
1119        //!@{
[200]1120
[600]1121        //! Set boolean options from a string, recognized are: "logbounds,logll"
[738]1122        virtual void set_options ( const string &opt );
[190]1123
[600]1124        //! Add all logged variables to a logger
[676]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)
[738]1128        virtual void log_register ( logger &L, const string &prefix = "" );
[190]1129
[676]1130        //! Save results to the given logger, details of what is stored is configured by \c LIDs and \c options
[738]1131        virtual void log_write ( ) const;
1132
[600]1133        //!@}
1134        void from_setting ( const Setting &set ) {
[685]1135                shared_ptr<RV> r = UI::build<RV> ( set, "yrv", UI::optional );
[600]1136                if ( r ) {
[679]1137                        set_yrv ( *r );
[488]1138                }
[685]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 ) {
[737]1145                        set_rv ( *r3 );
[685]1146                }
[737]1147
[600]1148                string opt;
[665]1149                if ( UI::get ( opt, set, "options", UI::optional ) ) {
[600]1150                        set_options ( opt );
[573]1151                }
[600]1152        }
[573]1153
[270]1154};
[660]1155//! array of pointers to epdf
[529]1156typedef Array<shared_ptr<epdf> > epdf_array;
[693]1157//! array of pointers to pdf
1158typedef Array<shared_ptr<pdf> > pdf_array;
[529]1159
[488]1160template<class EPDF>
[693]1161vec pdf_internal<EPDF>::samplecond ( const vec &cond ) {
[600]1162        condition ( cond );
[488]1163        vec temp = iepdf.sample();
1164        return temp;
1165}
[339]1166
[488]1167template<class EPDF>
[713]1168mat pdf_internal<EPDF>::samplecond_mat ( const vec &cond, int N ) {
[600]1169        condition ( cond );
1170        mat temp ( dimension(), N );
1171        vec smp ( dimension() );
1172        for ( int i = 0; i < N; i++ ) {
[488]1173                smp = iepdf.sample();
[600]1174                temp.set_col ( i, smp );
[488]1175        }
1176
1177        return temp;
1178}
1179
1180template<class EPDF>
[693]1181double pdf_internal<EPDF>::evallogcond ( const vec &yt, const vec &cond ) {
[488]1182        double tmp;
[600]1183        condition ( cond );
[679]1184        tmp = iepdf.evallog ( yt );
[488]1185        return tmp;
1186}
1187
1188template<class EPDF>
[713]1189vec pdf_internal<EPDF>::evallogcond_mat ( const mat &Yt, const vec &cond ) {
[600]1190        condition ( cond );
[713]1191        return iepdf.evallog_mat ( Yt );
[488]1192}
1193
1194template<class EPDF>
[713]1195vec pdf_internal<EPDF>::evallogcond_mat ( const Array<vec> &Yt, const vec &cond ) {
[600]1196        condition ( cond );
[713]1197        return iepdf.evallog_mat ( Yt );
[488]1198}
1199
[254]1200}; //namespace
[384]1201#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.