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

Revision 675, 34.1 kB (checked in by mido, 15 years ago)

experiment: epdf as a descendat of mpdf

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