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

Revision 660, 34.9 kB (checked in by smidl, 15 years ago)

doc - doxygen warnings

  • 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},\ldots  rv_{max_delay}]\f$
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        //! link 1st vector to down
767        datalink_buffered dl1;
768        //! link 2nd vector to down
769        datalink_buffered dl2;
770public:
771        //! set connection between RVs
772        void set_connection ( const RV &rv, const RV &rv_up1, const RV &rv_up2 ) {
773                dl1.set_connection ( rv, rv_up1 );
774                dl2.set_connection ( rv, rv_up2 );
775        }
776        //! fill values of down from the values of the two up vectors
777        void filldown ( const vec &val1, const vec &val2, vec &val_down ) {
778                bdm_assert_debug ( val_down.length() >= dl1._downsize() + dl2._downsize(), "short val_down" );
779                dl1.filldown ( val1, val_down );
780                dl2.filldown ( val2, val_down );
781        }
782        //! update buffer
783        void step ( const vec &dt, const vec &ut ) {
784                dl1.step ( dt );
785                dl2.step ( ut );
786        }
787};
788
789
790
791//! Data link with a condition.
792class datalink_m2e: public datalink {
793protected:
794        //! Remember how long cond should be
795        int condsize;
796
797        //!upper_val-to-local_cond link, indices of the upper val
798        ivec v2c_up;
799
800        //!upper_val-to-local_cond link, indices of the local cond
801        ivec v2c_lo;
802
803public:
804        //! Constructor
805        datalink_m2e() : condsize ( 0 ) { }
806
807        //! Set connection between vectors
808        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up );
809
810        //!Construct condition
811        vec get_cond ( const vec &val_up );
812
813        //! Copy corresponding values to Up.condition
814        void pushup_cond ( vec &val_up, const vec &val, const vec &cond );
815};
816
817//!DataLink is a connection between mpdf and its superordinate (Up)
818//! This class links
819class datalink_m2m: public datalink_m2e {
820protected:
821        //!cond-to-cond link, indices of the upper cond
822        ivec c2c_up;
823        //!cond-to-cond link, indices of the local cond
824        ivec c2c_lo;
825
826public:
827        //! Constructor
828        datalink_m2m() {};
829        //! Set connection between the vectors
830        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up ) {
831                datalink_m2e::set_connection ( rv, rvc, rv_up );
832                //establish c2c connection
833                rvc.dataind ( rvc_up, c2c_lo, c2c_up );
834                bdm_assert_debug ( c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given" );
835        }
836
837        //! Get cond for myself from val and cond of "Up"
838        vec get_cond ( const vec &val_up, const vec &cond_up ) {
839                vec tmp ( condsize );
840                set_subvector ( tmp, v2c_lo, val_up ( v2c_up ) );
841                set_subvector ( tmp, c2c_lo, cond_up ( c2c_up ) );
842                return tmp;
843        }
844        //! Fill
845
846};
847
848/*!
849@brief Class for storing results (and semi-results) of an experiment
850
851This 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.
852 */
853class logger : public root {
854protected:
855        //! RVs of all logged variables.
856        Array<RV> entries;
857        //! Names of logged quantities, e.g. names of algorithm variants
858        Array<string> names;
859public:
860        //!Default constructor
861        logger() : entries ( 0 ), names ( 0 ) {}
862
863        //! returns an identifier which will be later needed for calling the \c logit() function
864        //! For empty RV it returns -1, this entry will be ignored by \c logit().
865        virtual int add ( const RV &rv, string prefix = "" ) {
866                int id;
867                if ( rv._dsize() > 0 ) {
868                        id = entries.length();
869                        names = concat ( names, prefix ); // diff
870                        entries.set_length ( id + 1, true );
871                        entries ( id ) = rv;
872                } else {
873                        id = -1;
874                }
875                return id; // identifier of the last entry
876        }
877
878        //! log this vector
879        virtual void logit ( int id, const vec &v ) {
880                bdm_error ( "Not implemented" );
881        };
882        //! log this double
883        virtual void logit ( int id, const double &d ) {
884                bdm_error ( "Not implemented" );
885        };
886
887        //! Shifts storage position for another time step.
888        virtual void step() {
889                bdm_error ( "Not implemneted" );
890        };
891
892        //! Finalize storing information
893        virtual void finalize() {};
894
895        //! Initialize the storage
896        virtual void init() {};
897
898};
899
900/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
901
902*/
903class mepdf : public mpdf {
904        //! Internal shared pointer to epdf
905        shared_ptr<epdf> iepdf;
906public:
907        //!Default constructor
908        mepdf() { }
909        //! Set internal shared pointer
910        mepdf ( shared_ptr<epdf> em ) {
911                iepdf = em;
912                set_ep ( *iepdf.get() );
913                dimc = 0;
914        }
915
916        //! empty
917        vec samplecond ( const vec &cond ) {
918                return iepdf->sample();
919        }
920        double evallogcond ( const vec &val, const vec &cond ) {
921                return iepdf->evallog ( val );
922        }
923
924        //! Load from structure with elements:
925        //!  \code
926        //! { class = "mepdf",
927        //!   epdf = {class="epdf_offspring",...}
928        //! }
929        //! \endcode
930        //!@}
931        void from_setting ( const Setting &set );
932};
933UIREGISTER ( mepdf );
934SHAREDPTR ( mepdf );
935
936//! \brief Combines RVs from a list of mpdfs to a single one.
937RV get_composite_rv ( const Array<shared_ptr<mpdf> > &mpdfs, bool checkoverlap = false );
938
939/*! \brief Abstract class for discrete-time sources of data.
940
941The class abstracts operations of:
942\li  data aquisition,
943\li  data-preprocessing, such as  scaling of data,
944\li  data resampling from the task of estimation and control.
945Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
946
947The DataSource has three main data interaction structures:
948\li input, \f$ u_t \f$,
949\li output \f$ y_t \f$,
950\li data, \f$ d_t=[y_t,u_t, \ldots ]\f$ a collection of all inputs and outputs and possibly some internal variables too.
951
952*/
953
954class DS : public root {
955protected:
956                //! size of data returned by \c getdata()
957        int dtsize;
958                //! size of data
959        int utsize;
960                //!size of output
961                int ytsize;
962        //!Description of data returned by \c getdata().
963        RV Drv;
964        //!Description of data witten by by \c write().
965        RV Urv; //
966                //!Description of output data
967                RV Yrv; //
968        //! Remember its own index in Logger L, [0=dt, 1=ut]
969        ivec LIDs;
970public:
971        //! default constructors
972                DS() : Drv(), Urv(),Yrv(), LIDs(2) {};
973
974        //! 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().
975        virtual int max_length() {return std::numeric_limits< int >::max();}
976        //! Returns full vector of observed data=[output, input]
977        virtual void getdata ( vec &dt ) {
978                bdm_error ( "abstract class" );
979        }
980        //! Returns data records at indeces.
981        virtual void getdata ( vec &dt, const ivec &indeces ) {
982                bdm_error ( "abstract class" );
983        }
984
985        //! Accepts action variable and schedule it for application.
986        virtual void write (const vec &ut ) {
987                bdm_error ( "abstract class" );
988        }
989
990        //! Accepts action variables at specific indeces
991        virtual void write (const vec &ut, const ivec &indeces ) {
992                bdm_error ( "abstract class" );
993        }
994
995        //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
996        virtual void step() 
997        {
998                bdm_error ( "abstract class" );
999        }
1000
1001        //! Register DS for logging into logger L
1002        virtual void log_add ( logger &L ) {
1003                bdm_assert ( dtsize == Drv._dsize(), "invalid DS: dtsize (" + num2str ( dtsize ) + ") different from Drv " + num2str ( Drv._dsize() ) );
1004                bdm_assert ( utsize == Urv._dsize(), "invalid DS: utsize (" + num2str ( utsize ) + ") different from Urv " + num2str ( Urv._dsize() ) );
1005
1006                LIDs(0) = L.add ( Drv, "" );
1007                LIDs(1) = L.add ( Urv, "" );
1008        }
1009        //! Register DS for logging into logger L
1010        virtual void logit ( logger &L ) {
1011                vec tmp ( Drv._dsize() + Urv._dsize() );
1012                getdata ( tmp );
1013                // d is first in getdata
1014                L.logit ( LIDs(0), tmp.left ( Drv._dsize() ) );
1015                // u follows after d in getdata
1016                L.logit ( LIDs(1), tmp.mid ( Drv._dsize(), Urv._dsize() ) );
1017        }
1018        //!access function
1019        virtual const RV& _drv() const {
1020                //              return concat (Drv, Urv);// why!!!
1021                return Drv;// why!!!
1022        }
1023        //!access function
1024        const RV& _urv() const {
1025                return Urv;
1026        }
1027                //!access function
1028                const RV& _yrv() const {
1029                        return Yrv;
1030                }
1031        //! set random variables
1032                virtual void set_drv (const  RV &yrv, const RV &urv) {
1033                    Yrv = yrv;
1034                        Drv = concat(yrv,urv);
1035                Urv = urv;
1036        }
1037};
1038
1039/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
1040
1041This object represents exact or approximate evaluation of the Bayes rule:
1042\f[
1043f(\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})}
1044\f]
1045
1046Access to the resulting posterior density is via function \c posterior().
1047
1048As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
1049It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
1050
1051Alternatively, it can evaluate posterior density conditioned by a known constant, \f$ c_t \f$:
1052\f[
1053f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
1054\f]
1055
1056The value of \f$ c_t \f$ is set by function condition().
1057
1058*/
1059
1060class BM : public root {
1061protected:
1062        //! Random variable of the data (optional)
1063        RV drv;
1064        //!Logarithm of marginalized data likelihood.
1065        double ll;
1066        //!  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.
1067        bool evalll;
1068public:
1069        //! \name Constructors
1070        //! @{
1071
1072        BM() : ll ( 0 ), evalll ( true ), LIDs ( 4 ), LFlags ( 4 ) {
1073                LIDs = -1;/*empty IDs*/
1074                LFlags = 0;
1075                LFlags ( 0 ) = 1;  /*log only mean*/
1076        };
1077        BM ( const BM &B ) :  drv ( B.drv ), ll ( B.ll ), evalll ( B.evalll ) {}
1078        //! \brief Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
1079        //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
1080        virtual BM* _copy_() const {
1081                return NULL;
1082        };
1083        //!@}
1084
1085        //! \name Mathematical operations
1086        //!@{
1087
1088        /*! \brief Incremental Bayes rule
1089        @param dt vector of input data
1090        */
1091        virtual void bayes ( const vec &dt ) = 0;
1092        //! Batch Bayes rule (columns of Dt are observations)
1093        virtual void bayesB ( const mat &Dt );
1094        //! Evaluates predictive log-likelihood of the given data record
1095        //! I.e. marginal likelihood of the data with the posterior integrated out.
1096        virtual double logpred ( const vec &dt ) const {
1097                bdm_error ( "Not implemented" );
1098                return 0.0;
1099        }
1100
1101        //! Matrix version of logpred
1102        vec logpred_m ( const mat &dt ) const {
1103                vec tmp ( dt.cols() );
1104                for ( int i = 0; i < dt.cols(); i++ ) {
1105                        tmp ( i ) = logpred ( dt.get_col ( i ) );
1106                }
1107                return tmp;
1108        }
1109
1110        //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
1111        virtual epdf* epredictor() const {
1112                bdm_error ( "Not implemented" );
1113                return NULL;
1114        };
1115        //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
1116        virtual mpdf* predictor() const {
1117                bdm_error ( "Not implemented" );
1118                return NULL;
1119        };
1120        //!@}
1121
1122        //! \name Extension to conditional BM
1123        //! This extension is useful e.g. in Marginalized Particle Filter (\ref bdm::MPF).
1124        //! Alternatively, it can be used for automated connection to DS when the condition is observed
1125        //!@{
1126
1127        //! Name of extension variable
1128        RV rvc;
1129        //! access function
1130        const RV& _rvc() const {
1131                return rvc;
1132        }
1133
1134        //! Substitute \c val for \c rvc.
1135        virtual void condition ( const vec &val ) {
1136                bdm_error ( "Not implemented!" );
1137        }
1138
1139        //!@}
1140
1141
1142        //! \name Access to attributes
1143        //!@{
1144        //! access function
1145        const RV& _drv() const {
1146                return drv;
1147        }
1148        //! access function
1149        void set_drv ( const RV &rv ) {
1150                drv = rv;
1151        }
1152        //! access to rv of the posterior
1153        void set_rv ( const RV &rv ) {
1154                const_cast<epdf&> ( posterior() ).set_rv ( rv );
1155        }
1156        //! return internal log-likelihood of the last data vector
1157        double _ll() const {
1158                return ll;
1159        }
1160        //! switch evaluation of log-likelihood on/off
1161        void set_evalll ( bool evl0 ) {
1162                evalll = evl0;
1163        }
1164        //! return posterior density
1165        virtual const epdf& posterior() const = 0;
1166        //!@}
1167
1168        //! \name Logging of results
1169        //!@{
1170
1171        //! Set boolean options from a string, recognized are: "logbounds,logll"
1172        virtual void set_options ( const string &opt ) {
1173                LFlags ( 0 ) = 1;
1174                if ( opt.find ( "logbounds" ) != string::npos ) {
1175                        LFlags ( 1 ) = 1;
1176                        LFlags ( 2 ) = 1;
1177                }
1178                if ( opt.find ( "logll" ) != string::npos ) {
1179                        LFlags ( 3 ) = 1;
1180                }
1181        }
1182        //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
1183        ivec LIDs;
1184
1185        //! Flags for logging - same size as LIDs, each entry correspond to the same in LIDs
1186        ivec LFlags;
1187        //! Add all logged variables to a logger
1188        virtual void log_add ( logger &L, const string &name = "" ) {
1189                // internal
1190                RV r;
1191                if ( posterior().isnamed() ) {
1192                        r = posterior()._rv();
1193                } else {
1194                        r = RV ( "est", posterior().dimension() );
1195                };
1196
1197                // Add mean value
1198                if ( LFlags ( 0 ) ) LIDs ( 0 ) = L.add ( r, name + "mean_" );
1199                if ( LFlags ( 1 ) ) LIDs ( 1 ) = L.add ( r, name + "lb_" );
1200                if ( LFlags ( 2 ) ) LIDs ( 2 ) = L.add ( r, name + "ub_" );
1201                if ( LFlags ( 3 ) ) LIDs ( 3 ) = L.add ( RV ( "ll", 1 ), name );    //TODO: "local" RV
1202        }
1203        //! Save results to the given logger, details of what is stored is configured by \c LIDs and \c options
1204        virtual void logit ( logger &L ) {
1205                L.logit ( LIDs ( 0 ), posterior().mean() );
1206                if ( LFlags ( 1 ) || LFlags ( 2 ) ) {  //if one of them is off, its LID==-1 and will not be stored
1207                        vec ub, lb;
1208                        posterior().qbounds ( lb, ub );
1209                        L.logit ( LIDs ( 1 ), lb );
1210                        L.logit ( LIDs ( 2 ), ub );
1211                }
1212                if ( LFlags ( 3 ) ) L.logit ( LIDs ( 3 ), ll );
1213        }
1214        //!@}
1215        void from_setting ( const Setting &set ) {
1216                shared_ptr<RV> r = UI::build<RV> ( set, "drv", UI::optional );
1217                if ( r ) {
1218                        set_drv ( *r );
1219                }
1220                string opt;
1221                if ( !UI::get ( opt, set, "options", UI::optional ) ) {
1222                        set_options ( opt );
1223                }
1224        }
1225
1226};
1227//! array of pointers to epdf
1228typedef Array<shared_ptr<epdf> > epdf_array;
1229//! array of pointers to mpdf
1230typedef Array<shared_ptr<mpdf> > mpdf_array;
1231
1232template<class EPDF>
1233vec mpdf_internal<EPDF>::samplecond ( const vec &cond ) {
1234        condition ( cond );
1235        vec temp = iepdf.sample();
1236        return temp;
1237}
1238
1239template<class EPDF>
1240mat mpdf_internal<EPDF>::samplecond_m ( const vec &cond, int N ) {
1241        condition ( cond );
1242        mat temp ( dimension(), N );
1243        vec smp ( dimension() );
1244        for ( int i = 0; i < N; i++ ) {
1245                smp = iepdf.sample();
1246                temp.set_col ( i, smp );
1247        }
1248
1249        return temp;
1250}
1251
1252template<class EPDF>
1253double mpdf_internal<EPDF>::evallogcond ( const vec &dt, const vec &cond ) {
1254        double tmp;
1255        condition ( cond );
1256        tmp = iepdf.evallog ( dt );
1257        return tmp;
1258}
1259
1260template<class EPDF>
1261vec mpdf_internal<EPDF>::evallogcond_m ( const mat &Dt, const vec &cond ) {
1262        condition ( cond );
1263        return iepdf.evallog_m ( Dt );
1264}
1265
1266template<class EPDF>
1267vec mpdf_internal<EPDF>::evallogcond_m ( const Array<vec> &Dt, const vec &cond ) {
1268        condition ( cond );
1269        return iepdf.evallog_m ( Dt );
1270}
1271
1272}; //namespace
1273#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.