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

Revision 797, 32.5 kB (checked in by smidl, 14 years ago)

new objects: mgdirac + mexFnc

  • 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
112        //! auxiliary function assigning unique integer index related to the passed name and size of the random variable
113        int assign_id( const string &name, int size );
114
115        //! Private constructor from IDs, potentially dangerous since all ids must be valid!
116        //! dummy is there to prevent confusion with RV(" string");
117        explicit RV ( const ivec &ids0, enum_dummy dum ) : dsize ( 0 ), len ( ids0.length() ), ids ( ids0 ), times ( zeros_i ( ids0.length() ) ) {
118                dsize = countsize();
119        }
120public:
121        //! \name Constructors
122        //!@{
123
124        //! Full constructor
125        RV ( const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times ) {
126                init ( in_names, in_sizes, in_times );
127        }
128
129        //! Constructor with times=0
130        RV ( const Array<std::string> &in_names, const ivec &in_sizes ) {
131                init ( in_names, in_sizes, zeros_i ( in_names.length() ) );
132        }
133
134        //! Constructor with sizes=1, times=0
135        RV ( const Array<std::string> &in_names ) {
136                init ( in_names, ones_i ( in_names.length() ), zeros_i ( in_names.length() ) );
137        }
138
139        //! Constructor of empty RV
140        RV() : dsize ( 0 ), len ( 0 ), ids ( 0 ), times ( 0 ) {}
141
142        //! Constructor of a single RV with given id
143        RV ( string name, int sz, int tm = 0 );
144
145        // compiler-generated copy constructor is used
146        //!@}
147
148        //! \name Access functions
149        //!@{
150
151        //! State output, e.g. for debugging.
152        friend std::ostream &operator<< ( std::ostream &os, const RV &rv );
153
154        string to_string() const {
155                ostringstream o;
156                o << *this;
157                return o.str();
158        }
159
160        //! total size of a random variable
161        int _dsize() const {
162                return dsize;
163        }
164
165        //! access function
166        const ivec& _ids() const {
167                return ids;
168        }
169
170        //! Recount size of the corresponding data vector
171        int countsize() const;
172        //! Vector of cumulative sizes of RV
173        ivec cumsizes() const;
174        //! Number of named parts
175        int length() const {
176                return len;
177        }
178        int id ( int at ) const {
179                return ids ( at );
180        }
181        int size ( int at ) const {
182                return SIZES ( ids ( at ) );
183        }
184        int time ( int at ) const {
185                return times ( at );
186        }
187        std::string name ( int at ) const {
188                return NAMES ( ids ( at ) );
189        }
190        //! 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
191        std::string scalarname ( int scalat ) const;
192
193        void set_time ( int at, int time0 ) {
194                times ( at ) = time0;
195        }
196        //!@}
197
198        //! \name Algebra on Random Variables
199        //!@{
200
201        //! Find indices of self in another rv, \return ivec of the same size as self.
202        ivec findself ( const RV &rv2 ) const;
203        //! Find indices of self in another rv, ignore time, \return ivec of the same size as self.
204        ivec findself_ids ( const RV &rv2 ) const;
205        //! Compare if \c rv2 is identical to this \c RV
206        bool equal ( const RV &rv2 ) const;
207        //! Add (concat) another variable to the current one, \return true if all rv2 were added, false if rv2 is in conflict
208        bool add ( const RV &rv2 );
209        //! Subtract  another variable from the current one
210        RV subt ( const RV &rv2 ) const;
211        //! Select only variables at indices ind
212        RV subselect ( const ivec &ind ) const;
213
214        //! Select only variables at indices ind
215        RV operator() ( const ivec &ind ) const {
216                return subselect ( ind );
217        }
218
219        //! Select from data vector starting at di1 to di2
220        RV operator() ( int di1, int di2 ) const;
221
222        //! Shift \c time by delta.
223        void t_plus ( int delta );
224        //!@}
225
226        //! @{ \name Time manipulation functions
227        //! returns rvs with time set to 0 and removed duplicates
228        RV remove_time() const {
229                return RV ( unique ( ids ), dummy );
230        }
231        //! create new RV from the current one with time shifted by given value
232        RV copy_t ( int dt ) const {
233                RV tmp = *this;
234                tmp.t_plus ( dt );
235                return tmp;
236        }
237        //! return rvs with expanded delayes and sorted in the order of: \f$ [ rv_{0}, rv_{-1},\ldots  rv_{max_delay}]\f$
238        RV expand_delayes() const;
239        //!@}
240
241        //!\name Relation to vectors
242        //!@{
243
244        //! generate \c str from rv, by expanding sizes
245        str tostr() const;
246        //! when this rv is a part of bigger rv, this function returns indices of self in the data vector of the bigger crv.
247        //! Then, data can be copied via: data_of_this = cdata(ind);
248        ivec dataind ( const RV &crv ) const;
249        //! same as dataind but this time crv should not be complete supperset of rv.
250        ivec dataind_part ( const RV &crv ) const;
251        //! generate mutual indices when copying data between self and crv.
252        //! Data are copied via: data_of_this(selfi) = data_of_rv2(rv2i)
253        void dataind ( const RV &rv2, ivec &selfi, ivec &rv2i ) const;
254        //! Minimum time-offset
255        int mint() const {
256                return times.length() > 0 ? min ( times ) : 0;
257        }
258        //! Minimum time-offset of ids of given RVs
259        int mint ( const RV &rv ) const {
260                bvec belong = zeros_b ( len );
261                for ( int r = 0; r < rv.length(); r++ ) {
262                        belong = belong | ( ids == rv.id ( r ) );
263                }
264                return times.length() > 0 ? min ( get_from_bvec ( times, belong ) ) : 0;
265        }
266        //!@}
267
268        /*! \brief UI for class RV (description of data vectors)
269
270        \code
271        class = 'RV';
272        names = {'a', 'b', 'c', ...};   // UNIQUE IDENTIFIER same names = same variable
273                                                                        // names are also used when storing results
274        --- optional ---
275        sizes = [1, 2, 3, ...];         // size of each name. default = ones()
276                                                                        // if size = -1, it is found out from previous instances of the same name
277        times = [-1, -2, 0, ...];       // time shifts with respect to current time, default = zeros()
278        \endcode
279        */
280        void from_setting ( const Setting &set );
281
282        void to_setting ( Setting &set ) const;
283
284        //! Invalidate all named RVs. Use before initializing any RV instances, with care...
285        static void clear_all();
286        //! function for debugging RV related stuff
287        string show_all();
288
289};
290UIREGISTER ( RV );
291SHAREDPTR ( RV );
292
293//! Concat two random variables
294RV concat ( const RV &rv1, const RV &rv2 );
295
296/*!
297@brief Class for storing results (and semi-results) of an experiment
298
299This 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.
300*/
301class logger : public root {
302protected:
303        //! RVs of all logged variables.
304        Array<RV> entries;
305        //! Names of logged quantities, e.g. names of algorithm variants
306        Array<string> names;
307        //!separator of prefixes of entries
308        const string separator;
309        //! Root Setting for storing Settings
310        Config setting_conf;
311        //! list of Settings for specific ids
312        Array<Setting*> settings;
313public:
314        //!Default constructor
315        logger ( const string separator0 ) : entries ( 0 ), names ( 0 ), separator ( separator0 ) {}
316
317        //! returns an identifier which will be later needed for calling the \c logit() function
318        //! For empty RV it returns -1, this entry will be ignored by \c logit().
319        virtual int add_vector ( const RV &rv, string prefix = "" );
320
321        virtual int add_setting ( const string &prefix );
322
323        //! log this vector
324        virtual void log_vector ( int id, const vec &v ) = 0;
325
326        virtual Setting & log_to_setting ( int id ) {
327                return settings ( id )->add ( Setting::TypeGroup );
328        }
329        //! log this double
330        virtual void logit ( int id, const double &d ) = 0;
331
332        //! Shifts storage position for another time step.
333        virtual void step() = 0;
334
335        //! Finalize storing information
336        virtual void finalize() {};
337
338        //! Initialize the storage
339        virtual void init() {};
340
341        //!separator of prefixes for this logger
342        const string& prefix_sep() {
343                return separator;
344        }
345};
346
347
348//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
349class fnc : public root {
350protected:
351        //! Length of the output vector
352        int dimy;
353        //! Length of the input vector
354        int dimc;
355public:
356        //!default constructor
357        fnc() {};
358        //! function evaluates numerical value of \f$f(x)\f$ at \f$x=\f$ \c cond
359        virtual vec eval ( const vec &cond ) {
360                return vec ( 0 );
361        };
362
363        //! access function
364        int dimension() const {
365                return dimy;
366        }
367        //! access function
368        int dimensionc() const {
369                return dimc;
370        }
371        void from_setting(const Setting &set){
372                UI::get(dimy, set, "dim", UI::optional);
373                UI::get(dimc, set, "dimc", UI::optional);
374        }
375};
376
377class epdf;
378
379//! 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.
380class pdf : public root {
381protected:
382        //!dimension of the condition
383        int dimc;
384
385        //! random variable in condition
386        RV rvc;
387
388        //! dimension of random variable
389        int dim;
390
391        //! random variable
392        RV rv;
393
394public:
395        //! \name Constructors
396        //! @{
397
398        pdf() : dimc ( 0 ), rvc(), dim ( 0 ), rv() { }
399
400        pdf ( const pdf &m ) : dimc ( m.dimc ), rvc ( m.rvc ), dim ( m.dim ), rv ( m.rv ) { }
401
402        //!@}
403
404        //! \name Matematical operations
405        //!@{
406
407        //! 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
408        virtual vec samplecond ( const vec &cond ) = 0;
409
410        //! 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
411        virtual mat samplecond_mat ( const vec &cond, int N );
412
413        //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
414        virtual double evallogcond ( const vec &yt, const vec &cond ) = 0;
415
416        //! Matrix version of evallogcond
417        virtual vec evallogcond_mat ( const mat &Yt, const vec &cond ) {
418                vec v ( Yt.cols() );
419                for ( int i = 0; i < Yt.cols(); i++ ) {
420                        v ( i ) = evallogcond ( Yt.get_col ( i ), cond );
421                }
422                return v;
423        }
424
425        //! Array<vec> version of evallogcond
426        virtual vec evallogcond_mat ( const Array<vec> &Yt, const vec &cond ) {
427                vec v ( Yt.length() );
428                for ( int i = 0; i < Yt.length(); i++ ) {
429                        v ( i ) = evallogcond ( Yt( i ), cond );
430                }
431                return v;
432        }
433
434        //! \name Access to attributes
435        //! @{
436
437        const RV& _rv() const {
438                return rv;
439        }
440        const RV& _rvc() const {
441                return rvc;
442        }
443
444        int dimension() const {
445                return dim;
446        }
447        int dimensionc() {
448                return dimc;
449        }
450
451        //! access function
452        void set_dim ( int d ) {
453                dim = d;
454        }
455        //! access function
456        void set_dimc ( int d ) {
457                dimc = d;
458        }
459        //! Load from structure with elements:
460        //!  \code
461        //! { class = "pdf_offspring",
462        //!   rv = {class="RV", names=(...),}; // RV describing meaning of random variable
463        //!   rvc= {class="RV", names=(...),}; // RV describing meaning of random variable in condition
464        //!   // elements of offsprings
465        //! }
466        //! \endcode
467        //!@}
468        void from_setting ( const Setting &set );
469
470        void to_setting ( Setting &set ) const;
471        //!@}
472
473        //! \name Connection to other objects
474        //!@{
475        void set_rvc ( const RV &rvc0 ) {
476                rvc = rvc0;
477        }
478        void set_rv ( const RV &rv0 ) {
479                rv = rv0;
480        }
481
482        //! Names of variables stored in RV are considered to be valid only if their size match size of the parameters (dim).
483        bool isnamed() const {
484                return ( dim == rv._dsize() ) && ( dimc == rvc._dsize() );
485        }
486        //!@}
487};
488SHAREDPTR ( pdf );
489
490//! Probability density function with numerical statistics, e.g. posterior density.
491class epdf : public pdf {
492
493public:
494        /*! \name Constructors
495         Construction of each epdf should support two types of constructors:
496        \li empty constructor,
497        \li copy constructor,
498
499        The following constructors should be supported for convenience:
500        \li constructor followed by calling \c set_parameters()
501        \li constructor accepting random variables calling \c set_rv()
502
503         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.
504        @{*/
505        epdf() {};
506        epdf ( const epdf &e ) : pdf ( e ) {};
507               
508        //!@}
509
510        //! \name Matematical Operations
511        //!@{
512
513        //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
514        virtual vec sample() const = 0;
515
516        //! Returns N samples, \f$ [x_1 , x_2 , \ldots \ \f$  from density \f$ f_x(rv)\f$
517        virtual mat sample_mat ( int N ) const;
518
519        //! Compute log-probability of argument \c val
520        //! In case the argument is out of suport return -Infinity
521        virtual double evallog ( const vec &val ) const = 0;
522       
523        //! Compute log-probability of multiple values argument \c val
524        virtual vec evallog_mat ( const mat &Val ) const;
525
526        //! Compute log-probability of multiple values argument \c val
527        virtual vec evallog_mat ( const Array<vec> &Avec ) const;
528
529        //! Return conditional density on the given RV, the remaining rvs will be in conditioning
530        virtual shared_ptr<pdf> condition ( const RV &rv ) const;
531
532        //! Return marginal density on the given RV, the remainig rvs are intergrated out
533        virtual shared_ptr<epdf> marginal ( const RV &rv ) const;
534
535        virtual vec mean() const = 0;
536
537        //! return expected variance (not covariance!)
538        virtual vec variance() const = 0;
539
540        //! Lower and upper bounds of \c percentage % quantile, returns mean-2*sigma as default
541        virtual void qbounds ( vec &lb, vec &ub, double percentage = 0.95 ) const {
542                vec mea = mean();
543                vec std = sqrt ( variance() );
544                lb = mea - 2 * std;
545                ub = mea + 2 * std;
546        };
547        //!@}
548
549        //! \name Connection to other classes
550        //! Description of the random quantity via attribute \c rv is optional.
551        //! For operations such as sampling \c rv does not need to be set. However, for \c marginalization
552        //! and \c conditioning \c rv has to be set. NB:
553        //! @{
554
555        //! store values of the epdf on the following levels:
556        //!  #1 mean
557        //!  #2 mean + lower & upper bound
558        void log_register ( logger &L, const string &prefix );
559
560        void log_write() const;
561        //!@}
562
563        //! \name Access to attributes
564        //! @{
565
566        //! Load from structure with elements:
567        //!  \code
568        //! { rv = {class="RV", names=(...),}; // RV describing meaning of random variable
569        //!   // elements of offsprings
570        //! }
571        //! \endcode
572        //!@}
573        void from_setting ( const Setting &set ) {
574                shared_ptr<RV> r = UI::build<RV> ( set, "rv", UI::optional );
575                if ( r ) {
576                        set_rv ( *r );
577                }
578        }
579
580        void to_setting ( Setting &set ) const {
581                // we do not want to store rvc, therfore, pdf::to_setting( set ) is omitted
582                root::to_setting(set);
583
584                UI::save( &rv, set, "rv" );
585        }
586
587        vec samplecond ( const vec &cond ) {
588                return sample();
589        }
590        double evallogcond ( const vec &val, const vec &cond ) {
591                return evallog ( val );
592        }
593};
594SHAREDPTR ( epdf );
595
596//! pdf with internal epdf that is modified by function \c condition
597template <class EPDF>
598class pdf_internal: public pdf {
599protected :
600        //! Internal epdf used for sampling
601        EPDF iepdf;
602public:
603        //! constructor
604        pdf_internal() : pdf(), iepdf() {
605        }
606
607        //! Update \c iepdf so that it represents this pdf conditioned on \c rvc = cond
608        //! This function provides convenient reimplementation in offsprings
609        virtual void condition ( const vec &cond ) = 0;
610
611        //!access function to iepdf
612        EPDF& e() {
613                return iepdf;
614        }
615
616        //! Reimplements samplecond using \c condition()
617        vec samplecond ( const vec &cond );
618        //! Reimplements evallogcond using \c condition()
619        double evallogcond ( const vec &val, const vec &cond );
620        //! Efficient version of evallogcond for matrices
621        virtual vec evallogcond_mat ( const mat &Dt, const vec &cond );
622        //! Efficient version of evallogcond for Array<vec>
623        virtual vec evallogcond_mat ( const Array<vec> &Dt, const vec &cond );
624        //! Efficient version of samplecond
625        virtual mat samplecond_mat ( const vec &cond, int N );
626
627        void validate() {
628                iepdf.validate();
629                if ( rv._dsize() < iepdf._rv()._dsize() ) {
630                        rv = iepdf._rv();
631                };
632                dim = iepdf.dimension();
633        }
634};
635
636/*! \brief DataLink is a connection between two data vectors Up and Down
637
638Up can be longer than Down. Down must be fully present in Up (TODO optional)
639See chart:
640\dot
641digraph datalink {
642  node [shape=record];
643  subgraph cluster0 {
644    label = "Up";
645      up [label="<1>|<2>|<3>|<4>|<5>"];
646    color = "white"
647}
648  subgraph cluster1{
649    label = "Down";
650    labelloc = b;
651      down [label="<1>|<2>|<3>"];
652    color = "white"
653}
654    up:1 -> down:1;
655    up:3 -> down:2;
656    up:5 -> down:3;
657}
658\enddot
659
660*/
661class datalink {
662protected:
663        //! Remember how long val should be
664        int downsize;
665
666        //! Remember how long val of "Up" should be
667        int upsize;
668
669        //! val-to-val link, indices of the upper val
670        ivec v2v_up;
671
672public:
673        //! Constructor
674        datalink() : downsize ( 0 ), upsize ( 0 ) { }
675
676        //! Convenience constructor
677        datalink ( const RV &rv, const RV &rv_up ) {
678                set_connection ( rv, rv_up );
679        }
680
681        //! set connection, rv must be fully present in rv_up
682        virtual void set_connection ( const RV &rv, const RV &rv_up );
683
684        //! set connection using indices
685        virtual void set_connection ( int ds, int us, const ivec &upind );
686
687        //! Get val for myself from val of "Up"
688        vec pushdown ( const vec &val_up ) {
689                vec tmp ( downsize );
690                filldown ( val_up, tmp );
691                return tmp;
692        }
693        //! Get val for vector val_down from val of "Up"
694        virtual void filldown ( const vec &val_up, vec &val_down ) {
695                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
696                val_down = val_up ( v2v_up );
697        }
698        //! Fill val of "Up" by my pieces
699        virtual void pushup ( vec &val_up, const vec &val ) {
700                bdm_assert_debug ( downsize == val.length(), "Wrong val" );
701                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
702                set_subvector ( val_up, v2v_up, val );
703        }
704        //! access functions
705        int _upsize() {
706                return upsize;
707        }
708        //! access functions
709        int _downsize() {
710                return downsize;
711        }
712        //! for future use
713        virtual ~datalink() {}
714};
715
716/*! Extension of datalink to fill only part of Down
717*/
718class datalink_part : public datalink {
719protected:
720        //! indeces of values in vector downsize
721        ivec v2v_down;
722public:
723        void set_connection ( const RV &rv, const RV &rv_up );
724        //! Get val for vector val_down from val of "Up"
725        void filldown ( const vec &val_up, vec &val_down ) {
726                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) );
727        }
728};
729
730/*! \brief Datalink that buffers delayed values - do not forget to call step()
731
732Up is current data, Down is their subset with possibly delayed values
733*/
734class datalink_buffered: public datalink_part {
735protected:
736        //! History, ordered as \f$[Up_{t-1},Up_{t-2}, \ldots]\f$
737        vec history;
738        //! rv of the history
739        RV Hrv;
740        //! h2v : indeces in down
741        ivec h2v_down;
742        //! h2v : indeces in history
743        ivec h2v_hist;
744        //! v2h: indeces of up too be pushed to h
745        ivec v2h_up;
746public:
747
748        datalink_buffered() : datalink_part(), history ( 0 ), h2v_down ( 0 ), h2v_hist ( 0 ) {};
749        //! push current data to history
750        void store_data ( const vec &val_up ) {
751                if ( v2h_up.length() > 0 ) {
752                        history.shift_right ( 0, v2h_up.length() );
753                        history.set_subvector ( 0, val_up ( v2h_up ) );
754                }
755        }
756        //! Get val for myself from val of "Up"
757        vec pushdown ( const vec &val_up ) {
758                vec tmp ( downsize );
759                filldown ( val_up, tmp );
760                return tmp;
761        }
762
763        void filldown ( const vec &val_up, vec &val_down ) {
764                bdm_assert_debug ( val_down.length() >= downsize, "short val_down" );
765
766                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) ); // copy direct values
767                set_subvector ( val_down, h2v_down, history ( h2v_hist ) ); // copy delayed values
768        }
769
770        void set_connection ( const RV &rv, const RV &rv_up );
771       
772        //! set history of variable given by \c rv1 to values of \c hist.
773        void set_history ( const RV& rv1, const vec &hist0 );
774};
775
776//! buffered datalink from 2 vectors to 1
777class datalink_2to1_buffered {
778protected:
779        //! link 1st vector to down
780        datalink_buffered dl1;
781        //! link 2nd vector to down
782        datalink_buffered dl2;
783public:
784        //! set connection between RVs
785        void set_connection ( const RV &rv, const RV &rv_up1, const RV &rv_up2 ) {
786                dl1.set_connection ( rv, rv_up1 );
787                dl2.set_connection ( rv, rv_up2 );
788        }
789        //! fill values of down from the values of the two up vectors
790        void filldown ( const vec &val1, const vec &val2, vec &val_down ) {
791                bdm_assert_debug ( val_down.length() >= dl1._downsize() + dl2._downsize(), "short val_down" );
792                dl1.filldown ( val1, val_down );
793                dl2.filldown ( val2, val_down );
794        }
795        //! update buffer
796        void step ( const vec &dt, const vec &ut ) {
797                dl1.store_data ( dt );
798                dl2.store_data ( ut );
799        }
800};
801
802
803
804//! Data link with a condition.
805class datalink_m2e: public datalink {
806protected:
807        //! Remember how long cond should be
808        int condsize;
809
810        //!upper_val-to-local_cond link, indices of the upper val
811        ivec v2c_up;
812
813        //!upper_val-to-local_cond link, indices of the local cond
814        ivec v2c_lo;
815
816public:
817        //! Constructor
818        datalink_m2e() : condsize ( 0 ) { }
819
820        //! Set connection between vectors
821        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up );
822
823        //!Construct condition
824        vec get_cond ( const vec &val_up );
825
826        //! Copy corresponding values to Up.condition
827        void pushup_cond ( vec &val_up, const vec &val, const vec &cond );
828};
829
830//!DataLink is a connection between pdf and its superordinate (Up)
831//! This class links
832class datalink_m2m: public datalink_m2e {
833protected:
834        //!cond-to-cond link, indices of the upper cond
835        ivec c2c_up;
836        //!cond-to-cond link, indices of the local cond
837        ivec c2c_lo;
838
839public:
840        //! Constructor
841        datalink_m2m() {};
842        //! Set connection between the vectors
843        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up ) {
844                datalink_m2e::set_connection ( rv, rvc, rv_up );
845                //establish c2c connection
846                rvc.dataind ( rvc_up, c2c_lo, c2c_up );
847//              bdm_assert_debug ( c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given" );
848        }
849
850        //! Get cond for myself from val and cond of "Up"
851        vec get_cond ( const vec &val_up, const vec &cond_up ) {
852                vec tmp ( condsize );
853                fill_cond ( val_up, cond_up, tmp );
854                return tmp;
855        }
856        //! fill condition
857        void fill_cond ( const vec &val_up, const vec &cond_up, vec& cond_out ) {
858                bdm_assert_debug ( cond_out.length() >= condsize, "dl.fill_cond: cond_out is too small" );
859                set_subvector ( cond_out, v2c_lo, val_up ( v2c_up ) );
860                set_subvector ( cond_out, c2c_lo, cond_up ( c2c_up ) );
861        }
862        //! Fill
863
864};
865
866
867//! \brief Combines RVs from a list of pdfs to a single one.
868RV get_composite_rv ( const Array<shared_ptr<pdf> > &pdfs, bool checkoverlap = false );
869
870/*! \brief Abstract class for discrete-time sources of data.
871
872The class abstracts operations of:
873\li  data aquisition,
874\li  data-preprocessing, such as  scaling of data,
875\li  data resampling from the task of estimation and control.
876Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
877
878The DataSource has three main data interaction structures:
879\li input, \f$ u_t \f$,
880\li output \f$ y_t \f$,
881\li data, \f$ d_t=[y_t,u_t, \ldots ]\f$ a collection of all inputs and outputs and possibly some internal variables too.
882
883*/
884
885class DS : public root {
886protected:
887        //! size of data returned by \c getdata()
888        int dtsize;
889        //! size of data
890        int utsize;
891        //!size of output
892        int ytsize;
893        //!Description of data returned by \c getdata().
894        RV Drv;
895        //!Description of data witten by by \c write().
896        RV Urv; //
897        //!Description of output data
898        RV Yrv; //
899public:
900        //! default constructors
901        DS() : dtsize ( 0 ), utsize ( 0 ), ytsize ( 0 ), Drv(), Urv(), Yrv() {
902                log_level = 1;
903        };
904
905        //! 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().
906        virtual int max_length() {
907                return std::numeric_limits< int >::max();
908        }
909        //! Returns full vector of observed data=[output, input]
910        virtual void getdata ( vec &dt ) const = 0;
911
912        //! Returns data records at indeces.
913        virtual void getdata ( vec &dt, const ivec &indeces ) = 0;
914
915        //! Accepts action variable and schedule it for application.   
916        virtual void write ( const vec &ut ) = 0;
917
918        //! Accepts action variables at specific indeces
919        virtual void write ( const vec &ut, const ivec &indeces ) = 0;
920
921        //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
922        virtual void step() = 0;
923
924        //! Register DS for logging into logger L
925        virtual void log_register ( logger &L,  const string &prefix );
926        //! Register DS for logging into logger L
927        virtual void log_write ( ) const;
928        //!access function
929        virtual const RV& _drv() const {
930                return Drv;
931        }
932        //!access function
933        const RV& _urv() const {
934                return Urv;
935        }
936        //!access function
937        const RV& _yrv() const {
938                return Yrv;
939        }
940        //! set random variables
941        virtual void set_drv ( const  RV &yrv, const RV &urv ) {
942                Yrv = yrv;
943                Drv = concat ( yrv, urv );
944                Urv = urv;
945        }
946};
947
948/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
949
950This object represents exact or approximate evaluation of the Bayes rule:
951\f[
952f(\theta_t | y_1,\ldots,y_t, u_1,\ldots,u_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})}
953\f]
954where:
955 * \f$ y_t \f$ is the variable
956Access to the resulting posterior density is via function \c posterior().
957
958As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
959It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
960
961Alternatively, it can evaluate posterior density with rvc replaced by the given values, \f$ c_t \f$:
962\f[
963f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
964\f]
965
966
967*/
968
969class BM : public root {
970protected:
971        //! Random variable of the data (optional)
972        RV yrv;
973        //! size of the data record
974        int dimy;
975        //! Name of extension variable
976        RV rvc;
977        //! size of the conditioning vector
978        int dimc;
979
980        //!Logarithm of marginalized data likelihood.
981        double ll;
982        //!  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.
983        bool evalll;
984
985public:
986        //! \name Constructors
987        //! @{
988
989        BM() : yrv(), dimy ( 0 ), rvc(), dimc ( 0 ), ll ( 0 ), evalll ( true ) { };
990//      BM ( const BM &B ) :  yrv ( B.yrv ), dimy(B.dimy), rvc ( B.rvc ),dimc(B.dimc), ll ( B.ll ), evalll ( B.evalll ) {}
991        //! \brief Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
992        //! Prototype: \code BM* _copy() const {return new BM(*this);} \endcode
993        virtual BM* _copy() const {             return NULL;    }; // TODO NEBUDE TU TAKY LEPSI BDM_ERROR??!
994        //!@}
995
996        //! \name Mathematical operations
997        //!@{
998
999        /*! \brief Incremental Bayes rule
1000        @param dt vector of input data
1001        */
1002        virtual void bayes ( const vec &yt, const vec &cond = empty_vec ) = 0;
1003        //! Batch Bayes rule (columns of Dt are observations)
1004        virtual void bayes_batch ( const mat &Dt, const vec &cond = empty_vec );
1005        //! Batch Bayes rule (columns of Dt are observations, columns of Cond are conditions)
1006        virtual void bayes_batch ( const mat &Dt, const mat &Cond );
1007        //! Evaluates predictive log-likelihood of the given data record
1008        //! I.e. marginal likelihood of the data with the posterior integrated out.
1009        //! This function evaluates only \f$ y_t \f$, condition is assumed to be the last used in bayes().
1010        //! See bdm::BM::predictor for conditional version.
1011        virtual double logpred ( const vec &yt ) const = 0;
1012
1013        //! Matrix version of logpred
1014        vec logpred_mat ( const mat &Yt ) const {
1015                vec tmp ( Yt.cols() );
1016                for ( int i = 0; i < Yt.cols(); i++ ) {
1017                        tmp ( i ) = logpred ( Yt.get_col ( i ) );
1018                }
1019                return tmp;
1020        }
1021
1022        //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
1023        virtual epdf* epredictor() const = 0;
1024
1025        //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
1026        virtual pdf* predictor() const = 0;
1027
1028        //!@}
1029
1030
1031        //! \name Access to attributes
1032        //!@{
1033        //! access function
1034        const RV& _rvc() const {
1035                return rvc;
1036        }
1037        //! access function
1038        int dimensionc() const {
1039                return dimc;
1040        }
1041        //! access function
1042        int dimensiony() const {
1043                return dimy;
1044        }
1045        //! access function
1046        int dimension() const {
1047                return posterior().dimension();
1048        }
1049        //! access function
1050        const RV& _yrv() const {
1051                return yrv;
1052        }
1053        //! access function
1054        void set_yrv ( const RV &rv ) {
1055                yrv = rv;
1056        }
1057        //! access function
1058        void set_rvc ( const RV &rv ) {
1059                rvc = rv;
1060        }
1061        //! access to rv of the posterior
1062        void set_rv ( const RV &rv ) {
1063                const_cast<epdf&> ( posterior() ).set_rv ( rv );
1064        }
1065        //! access function
1066        void set_dim ( int dim ) {
1067                const_cast<epdf&> ( posterior() ).set_dim ( dim );
1068        }
1069        //! return internal log-likelihood of the last data vector
1070        double _ll() const {
1071                return ll;
1072        }
1073        //! switch evaluation of log-likelihood on/off
1074        void set_evalll ( bool evl0 ) {
1075                evalll = evl0;
1076        }
1077        //! return posterior density
1078        virtual const epdf& posterior() const = 0;
1079        //!@}
1080
1081        //! \name Logging of results
1082        //!@{
1083
1084        //! Set boolean options from a string, recognized are: "logbounds,logll"
1085        virtual void set_options ( const string &opt );
1086
1087        //! Add all logged variables to a logger
1088        //! Log levels two digits: xy where
1089        //!  * y = 0/1 log-likelihood is to be logged
1090        //!  * x = level of the posterior (typically 0/1/2 for nothing/mean/bounds)
1091        virtual void log_register ( logger &L, const string &prefix = "" );
1092
1093        //! Save results to the given logger, details of what is stored is configured by \c LIDs and \c options
1094        virtual void log_write ( ) const;
1095
1096        //!@}
1097        void from_setting ( const Setting &set ) {
1098                shared_ptr<RV> r = UI::build<RV> ( set, "yrv", UI::optional );
1099                if ( r ) {
1100                        set_yrv ( *r );
1101                }
1102                shared_ptr<RV> r2 = UI::build<RV> ( set, "rvc", UI::optional );
1103                if ( r2 ) {
1104                        rvc =   *r2;
1105                }
1106                shared_ptr<RV> r3 = UI::build<RV> ( set, "rv", UI::optional );
1107                if ( r3 ) {
1108                        set_rv ( *r3 );
1109                }
1110
1111                string opt;
1112                if ( UI::get ( opt, set, "options", UI::optional ) ) {
1113                        set_options ( opt );
1114                }
1115        }
1116
1117        void to_setting ( Setting &set ) const {
1118                root::to_setting( set );
1119                UI::save( &yrv, set, "yrv" );
1120                UI::save( &rvc, set, "rvc" );           
1121                UI::save( &posterior()._rv(), set, "rv" );
1122
1123                string opt;
1124                switch( posterior()._log_level() )
1125                {
1126                case 2:
1127                        opt = "logbounds ";
1128                        break;
1129                case 10:
1130                        opt = "logfull ";
1131                        break;
1132                default:
1133                        opt = "";
1134                        break;
1135                }
1136                if( log_level == 1 ) opt = opt + "logll";
1137                if( !opt.empty() )
1138                        UI::save( opt, set, "options" );
1139        }
1140};
1141
1142//! array of pointers to epdf
1143typedef Array<shared_ptr<epdf> > epdf_array;
1144//! array of pointers to pdf
1145typedef Array<shared_ptr<pdf> > pdf_array;
1146
1147template<class EPDF>
1148vec pdf_internal<EPDF>::samplecond ( const vec &cond ) {
1149        condition ( cond );
1150        vec temp = iepdf.sample();
1151        return temp;
1152}
1153
1154template<class EPDF>
1155mat pdf_internal<EPDF>::samplecond_mat ( const vec &cond, int N ) {
1156        condition ( cond );
1157        mat temp ( dimension(), N );
1158        vec smp ( dimension() );
1159        for ( int i = 0; i < N; i++ ) {
1160                smp = iepdf.sample();
1161                temp.set_col ( i, smp );
1162        }
1163
1164        return temp;
1165}
1166
1167template<class EPDF>
1168double pdf_internal<EPDF>::evallogcond ( const vec &yt, const vec &cond ) {
1169        double tmp;
1170        condition ( cond );
1171        tmp = iepdf.evallog ( yt );
1172        return tmp;
1173}
1174
1175template<class EPDF>
1176vec pdf_internal<EPDF>::evallogcond_mat ( const mat &Yt, const vec &cond ) {
1177        condition ( cond );
1178        return iepdf.evallog_mat ( Yt );
1179}
1180
1181template<class EPDF>
1182vec pdf_internal<EPDF>::evallogcond_mat ( const Array<vec> &Yt, const vec &cond ) {
1183        condition ( cond );
1184        return iepdf.evallog_mat ( Yt );
1185}
1186
1187}; //namespace
1188#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.