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

Revision 635, 34.3 kB (checked in by smidl, 15 years ago)

changes in base classes

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