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

Revision 895, 33.7 kB (checked in by smidl, 14 years ago)

get rid of Yrv in DS

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