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

Revision 609, 33.2 kB (checked in by smidl, 15 years ago)

remove "delays" from memory DS, check length of datasource

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