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

Revision 652, 34.4 kB (checked in by smidl, 15 years ago)

doc corrections

  • Property svn:eol-style set to native
Line 
1/*!
2  \file
3  \brief Basic structures of probability calculus: random variables, probability densities, Bayes rule
4  \author Vaclav Smidl.
5
6  -----------------------------------
7  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8
9  Using IT++ for numerical operations
10  -----------------------------------
11*/
12
13#ifndef BDMBASE_H
14#define BDMBASE_H
15
16#include <map>
17
18#include "../itpp_ext.h"
19#include "../bdmroot.h"
20#include "../shared_ptr.h"
21#include "user_info.h"
22
23using namespace libconfig;
24using namespace itpp;
25using namespace std;
26
27namespace bdm {
28//! Structure of RV, i.e. RVs expanded into a flat list of IDs, used for debugging.
29class str {
30public:
31        //! vector id ids (non-unique!)
32        ivec ids;
33        //! vector of times
34        ivec times;
35        //!Default constructor
36        str ( ivec ids0, ivec times0 ) : ids ( ids0 ), times ( times0 ) {
37                bdm_assert ( times0.length() == ids0.length(), "Incompatible input" );
38        };
39};
40
41/*!
42* \brief Class representing variables, most often random variables
43
44The purpose of this class is to decribe a vector of data. Such description is used for connecting various vectors between each other, see class datalink.
45
46The class is implemented using global variables to assure uniqueness of description:
47
48 In is a vector
49\dot
50digraph datalink {
51rankdir=LR;
52subgraph cluster0 {
53node [shape=record];
54label = "MAP \n std::map<string,int>";
55map [label="{{\"a\"| \"b\" | \"c\"} | {<3> 3 |<1> 1|<2> 2}}"];
56color = "white"
57}
58subgraph cluster1{
59node [shape=record];
60label = "NAMES";
61names [label="{<1> \"b\" | <2> \"c\" | <3>\"a\" }"];
62color = "white"
63}
64subgraph cluster2{
65node [shape=record];
66label = "SIZES";
67labelloc = b;
68sizes [label="{<1>1 |<2> 4 |<3> 1}"];
69color = "white"
70}
71map:1 -> names:1;
72map:1 -> sizes:1;
73map:3 -> names:3;
74map:3 -> sizes:3;
75}
76\enddot
77*/
78
79class RV : public root {
80private:
81        typedef std::map<string, int> str2int_map;
82
83        //! Internal global variable storing sizes of RVs
84        static ivec SIZES;
85        //! Internal global variable storing names of RVs
86        static Array<string> NAMES;
87
88        //! TODO
89        const static int BUFFER_STEP;
90
91        //! TODO
92        static str2int_map MAP;
93
94public:
95
96protected:
97        //! size of the data vector
98        int dsize;
99        //! number of individual rvs
100        int len;
101        //! Vector of unique IDs
102        ivec ids;
103        //! Vector of shifts from current time
104        ivec times;
105
106private:
107        enum enum_dummy {dummy};
108
109        //! auxiliary function used in constructor
110        void init ( const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times );
111        int init ( const string &name, int size );
112        //! Private constructor from IDs, potentially dangerous since all ids must be valid!
113        //! dummy is there to prevent confusion with RV(" string");
114        explicit RV ( const ivec &ids0, enum_dummy dum ) : dsize ( 0 ), len ( ids0.length() ), ids ( ids0 ), times ( zeros_i ( ids0.length() ) ) {
115                dsize = countsize();
116        }
117public:
118        //! \name Constructors
119        //!@{
120
121        //! Full constructor
122        RV ( const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times ) {
123                init ( in_names, in_sizes, in_times );
124        }
125
126        //! Constructor with times=0
127        RV ( const Array<std::string> &in_names, const ivec &in_sizes ) {
128                init ( in_names, in_sizes, zeros_i ( in_names.length() ) );
129        }
130
131        //! Constructor with sizes=1, times=0
132        RV ( const Array<std::string> &in_names ) {
133                init ( in_names, ones_i ( in_names.length() ), zeros_i ( in_names.length() ) );
134        }
135
136        //! Constructor of empty RV
137        RV() : dsize ( 0 ), len ( 0 ), ids ( 0 ), times ( 0 ) {}
138
139        //! Constructor of a single RV with given id
140        RV ( string name, int sz, int tm = 0 );
141
142        // compiler-generated copy constructor is used
143        //!@}
144
145        //! \name Access functions
146        //!@{
147
148        //! State output, e.g. for debugging.
149        friend std::ostream &operator<< ( std::ostream &os, const RV &rv );
150
151        string to_string() {ostringstream o; o << this; return o.str();}
152       
153        //! total size of a random variable
154        int _dsize() const {
155                return dsize;
156        }
157
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;
165        //! Vector of cumulative sizes of RV
166        ivec cumsizes() const;
167        //! Number of named parts
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        //! 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 {
185                bdm_assert(scalat<dsize,"Wrong input index");
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        }
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.
226        void t_plus ( int delta );
227        //!@}
228
229        //! @{ \name Time manipulation functions
230        //! returns rvs with time set to 0 and removed duplicates
231        RV remove_time() const {
232                return RV ( unique ( ids ), dummy );
233        }
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        }
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-- ) {
246                        rvt.t_plus ( -1 );
247                        tmp.add ( rvt ); //shift u1
248                }
249                return tmp;
250        }
251        //!@}
252
253        //!\name Relation to vectors
254        //!@{
255
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 {
268                        return times.length()>0 ? min (times) : 0;
269        }
270        //!@}
271
272        /*! \brief UI for class RV (description of data vectors)
273
274        \code
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()
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();
290        //! function for debugging RV related stuff
291        string show_all();
292
293};
294UIREGISTER ( RV );
295SHAREDPTR ( RV );
296
297//! Concat two random variables
298RV concat ( const RV &rv1, const RV &rv2 );
299
300//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
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        };
312
313        //! function substitutes given value into an appropriate position
314        virtual void condition ( const vec &val ) {};
315
316        //! access function
317        int dimension() const {
318                return dimy;
319        }
320};
321
322class mpdf;
323
324//! Probability density function with numerical statistics, e.g. posterior density.
325
326class epdf : public root {
327protected:
328        //! dimension of the random variable
329        int dim;
330        //! Description of the random variable
331        RV rv;
332
333public:
334        /*! \name Constructors
335         Construction of each epdf should support two types of constructors:
336        \li empty constructor,
337        \li copy constructor,
338
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()
342
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        //!@}
354
355        //! \name Matematical Operations
356        //!@{
357
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        }
363
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;
366
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        }
373
374        //! Compute log-probability of multiple values argument \c val
375        virtual vec evallog_m ( const mat &Val ) const;
376
377        //! Compute log-probability of multiple values argument \c val
378        virtual vec evallog_m ( const Array<vec> &Avec ) const;
379
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;
382
383        //! Return marginal density on the given RV, the remainig rvs are intergrated out
384        virtual shared_ptr<epdf> marginal ( const RV &rv ) const;
385
386        //! return expected value
387        virtual vec mean() const {
388                bdm_error ( "not implemneted" );
389                return vec();
390        }
391
392        //! return expected variance (not covariance!)
393        virtual vec variance() const {
394                bdm_error ( "not implemneted" );
395                return vec();
396        }
397
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        //!@}
406
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        //! @{
412
413        //!Name its rv
414        void set_rv ( const RV &rv0 ) {
415                rv = rv0;
416        }
417
418        //! True if rv is assigned
419        bool isnamed() const {
420                bool b = ( dim == rv._dsize() );
421                return b;
422        }
423
424        //! Return name (fails when isnamed is false)
425        const RV& _rv() const {
426                //bdm_assert_debug ( isnamed(), "" );
427                return rv;
428        }
429        //!@}
430
431        //! \name Access to attributes
432        //! @{
433
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 );
449                }
450        }
451
452};
453SHAREDPTR ( epdf );
454
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.
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;
465
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        }
475
476public:
477        //! \name Constructors
478        //! @{
479
480        mpdf() : dimc ( 0 ), rvc(), ep ( NULL ) { }
481
482        mpdf ( const mpdf &m ) : dimc ( m.dimc ), rvc ( m.rvc ), ep ( m.ep ) { }
483        //!@}
484
485        //! \name Matematical operations
486        //!@{
487
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        }
493
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 );
496
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        }
502
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 );
508                }
509                return v;
510        }
511
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        }
517
518        //! \name Access to attributes
519        //! @{
520
521        const RV& _rv() const {
522                return ep->_rv();
523        }
524        const RV& _rvc() const {
525                return rvc;
526        }
527
528        int dimension() const {
529                return ep->dimension();
530        }
531        int dimensionc() {
532                return dimc;
533        }
534
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        //!@}
546
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        //!@}
559};
560SHAREDPTR ( mpdf );
561
562//! Mpdf with internal epdf that is modified by function \c condition
563template <class EPDF>
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        }
573
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        }
579
580        //!access function to iepdf
581        EPDF& e() {
582                return iepdf;
583        }
584
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 );
595};
596
597/*! \brief DataLink is a connection between two data vectors Up and Down
598
599Up can be longer than Down. Down must be fully present in Up (TODO optional)
600See chart:
601\dot
602digraph datalink {
603  node [shape=record];
604  subgraph cluster0 {
605    label = "Up";
606      up [label="<1>|<2>|<3>|<4>|<5>"];
607    color = "white"
608}
609  subgraph cluster1{
610    label = "Down";
611    labelloc = b;
612      down [label="<1>|<2>|<3>"];
613    color = "white"
614}
615    up:1 -> down:1;
616    up:3 -> down:2;
617    up:5 -> down:3;
618}
619\enddot
620
621*/
622class datalink {
623protected:
624        //! Remember how long val should be
625        int downsize;
626
627        //! Remember how long val of "Up" should be
628        int upsize;
629
630        //! val-to-val link, indices of the upper val
631        ivec v2v_up;
632
633public:
634        //! Constructor
635        datalink() : downsize ( 0 ), upsize ( 0 ) { }
636
637        //! Convenience constructor
638        datalink ( const RV &rv, const RV &rv_up ) {
639                set_connection ( rv, rv_up );
640        }
641
642        //! set connection, rv must be fully present in rv_up
643        virtual void set_connection ( const RV &rv, const RV &rv_up );
644
645        //! set connection using indices
646        virtual void set_connection ( int ds, int us, const ivec &upind );
647
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"
655        virtual void filldown ( const vec &val_up, vec &val_down ) {
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
660        virtual void pushup ( vec &val_up, const vec &val ) {
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        }
673};
674
675/*! Extension of datalink to fill only part of Down
676*/
677class datalink_part : public datalink {
678protected:
679        //! indeces of values in vector downsize
680        ivec v2v_down;
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        }
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*/
693class datalink_buffered: public datalink_part {
694protected:
695        //! History, ordered as \f$[Up_{t-1},Up_{t-2}, \ldots]\f$
696        vec history;
697        //! rv of the history
698        RV Hrv;
699        //! h2v : indeces in down
700        ivec h2v_down;
701        //! h2v : indeces in history
702        ivec h2v_hist;
703        //! v2h: indeces of up too be pushed to h
704        ivec v2h_up;
705public:
706
707        datalink_buffered() : datalink_part(), history ( 0 ), h2v_down ( 0 ), h2v_hist ( 0 ) {};
708        //! push current data to history
709        void step ( const vec &val_up ) {
710                if ( v2h_up.length() > 0 ) {
711                        history.shift_right ( 0, v2h_up.length() );
712                  history.set_subvector ( 0, val_up(v2h_up) ); 
713                }
714        }
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;
720        }
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
727        }
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
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
739                rv_hist = rv_hist.expand_delayes(); // full regressor - including time 0
740                Hrv=rv_hist.subt(rv_hist0);   // remove time 0
741                history = zeros ( Hrv._dsize() );
742
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               
748                Hrv.dataind ( rv, h2v_hist, h2v_down );
749
750                downsize = v2v_down.length() + h2v_down.length();
751                upsize = v2v_up.length();
752        }
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        }
761};
762
763//! buffered datalink from 2 vectors to 1
764class datalink_2to1_buffered {
765protected:
766        datalink_buffered dl1;
767        datalink_buffered dl2;
768public:
769        //! set connection between RVs
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 );
773        }
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 );
778        }
779        void step ( const vec &dt, const vec &ut ) {
780                dl1.step ( dt );
781                dl2.step ( ut );
782        }
783};
784
785
786
787//! Data link with a condition.
788class datalink_m2e: public datalink {
789protected:
790        //! Remember how long cond should be
791        int condsize;
792
793        //!upper_val-to-local_cond link, indices of the upper val
794        ivec v2c_up;
795
796        //!upper_val-to-local_cond link, indices of the local cond
797        ivec v2c_lo;
798
799public:
800        //! Constructor
801        datalink_m2e() : condsize ( 0 ) { }
802
803        //! Set connection between vectors
804        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up );
805
806        //!Construct condition
807        vec get_cond ( const vec &val_up );
808
809        //! Copy corresponding values to Up.condition
810        void pushup_cond ( vec &val_up, const vec &val, const vec &cond );
811};
812
813//!DataLink is a connection between mpdf and its superordinate (Up)
814//! This class links
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;
821
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        }
832
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
841
842};
843
844/*!
845@brief Class for storing results (and semi-results) of an experiment
846
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 */
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 ) {}
858
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;
870                }
871                return id; // identifier of the last entry
872        }
873
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        };
882
883        //! Shifts storage position for another time step.
884        virtual void step() {
885                bdm_error ( "Not implemneted" );
886        };
887
888        //! Finalize storing information
889        virtual void finalize() {};
890
891        //! Initialize the storage
892        virtual void init() {};
893
894};
895
896/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
897
898*/
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        }
911
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        }
919
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 );
928};
929UIREGISTER ( mepdf );
930SHAREDPTR ( mepdf );
931
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 );
934
935/*! \brief Abstract class for discrete-time sources of data.
936
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.
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).
942
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
948*/
949
950class DS : public root {
951protected:
952                //! size of data returned by \c getdata()
953        int dtsize;
954                //! size of data
955        int utsize;
956                //!size of output
957                int ytsize;
958        //!Description of data returned by \c getdata().
959        RV Drv;
960        //!Description of data witten by by \c write().
961        RV Urv; //
962                //!Description of output data
963                RV Yrv; //
964        //! Remember its own index in Logger L
965        int L_dt, L_ut;
966public:
967        //! default constructors
968                DS() : Drv(), Urv(),Yrv() {};
969
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();}
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        }
980
981        //! Accepts action variable and schedule it for application.
982        virtual void write ( vec &ut ) {
983                bdm_error ( "abstract class" );
984        }
985
986        //! Accepts action variables at specific indeces
987        virtual void write ( vec &ut, const ivec &indeces ) {
988                bdm_error ( "abstract class" );
989        }
990
991        //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
992        virtual void step() 
993        {
994                bdm_error ( "abstract class" );
995        }
996
997        //! Register DS for logging into logger L
998        virtual void log_add ( logger &L ) {
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() ) );
1001
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        }
1023                //!access function
1024                const RV& _yrv() const {
1025                        return Yrv;
1026                }
1027        //! set random variables
1028                virtual void set_drv (const  RV &yrv, const RV &urv) {
1029                    Yrv = yrv;
1030                        Drv = concat(yrv,urv);
1031                Urv = urv;
1032        }
1033};
1034
1035/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
1036
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
1054*/
1055
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        //! @{
1067
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        //!@}
1080
1081        //! \name Mathematical operations
1082        //!@{
1083
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        }
1096
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 ) );
1102                }
1103                return tmp;
1104        }
1105
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        //!@}
1117
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        //!@{
1122
1123        //! Name of extension variable
1124        RV rvc;
1125        //! access function
1126        const RV& _rvc() const {
1127                return rvc;
1128        }
1129
1130        //! Substitute \c val for \c rvc.
1131        virtual void condition ( const vec &val ) {
1132                bdm_error ( "Not implemented!" );
1133        }
1134
1135        //!@}
1136
1137
1138        //! \name Access to attributes
1139        //!@{
1140
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        //!@}
1158
1159        //! \name Logging of results
1160        //!@{
1161
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;
1168                }
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;
1175
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                };
1187
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        //! Save results to the given logger, details of what is stored is configured by \c LIDs and \c options
1195        virtual void logit ( logger &L ) {
1196                L.logit ( LIDs ( 0 ), posterior().mean() );
1197                if ( LFlags ( 1 ) || LFlags ( 2 ) ) {  //if one of them is off, its LID==-1 and will not be stored
1198                        vec ub, lb;
1199                        posterior().qbounds ( lb, ub );
1200                        L.logit ( LIDs ( 1 ), lb );
1201                        L.logit ( LIDs ( 2 ), ub );
1202                }
1203                if ( LFlags ( 3 ) ) L.logit ( LIDs ( 3 ), ll );
1204        }
1205        //!@}
1206        void from_setting ( const Setting &set ) {
1207                shared_ptr<RV> r = UI::build<RV> ( set, "drv", UI::optional );
1208                if ( r ) {
1209                        set_drv ( *r );
1210                }
1211                string opt;
1212                if ( !UI::get ( opt, set, "options", UI::optional ) ) {
1213                        set_options ( opt );
1214                }
1215        }
1216
1217};
1218
1219typedef Array<shared_ptr<epdf> > epdf_array;
1220
1221typedef Array<shared_ptr<mpdf> > mpdf_array;
1222
1223template<class EPDF>
1224vec mpdf_internal<EPDF>::samplecond ( const vec &cond ) {
1225        condition ( cond );
1226        vec temp = iepdf.sample();
1227        return temp;
1228}
1229
1230template<class EPDF>
1231mat mpdf_internal<EPDF>::samplecond_m ( const vec &cond, int N ) {
1232        condition ( cond );
1233        mat temp ( dimension(), N );
1234        vec smp ( dimension() );
1235        for ( int i = 0; i < N; i++ ) {
1236                smp = iepdf.sample();
1237                temp.set_col ( i, smp );
1238        }
1239
1240        return temp;
1241}
1242
1243template<class EPDF>
1244double mpdf_internal<EPDF>::evallogcond ( const vec &dt, const vec &cond ) {
1245        double tmp;
1246        condition ( cond );
1247        tmp = iepdf.evallog ( dt );
1248        return tmp;
1249}
1250
1251template<class EPDF>
1252vec mpdf_internal<EPDF>::evallogcond_m ( const mat &Dt, const vec &cond ) {
1253        condition ( cond );
1254        return iepdf.evallog_m ( Dt );
1255}
1256
1257template<class EPDF>
1258vec mpdf_internal<EPDF>::evallogcond_m ( const Array<vec> &Dt, const vec &cond ) {
1259        condition ( cond );
1260        return iepdf.evallog_m ( Dt );
1261}
1262
1263}; //namespace
1264#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.