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

Revision 665, 35.0 kB (checked in by smidl, 15 years ago)

Compilation and minor extensions

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