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

Revision 864, 33.4 kB (checked in by smidl, 14 years ago)

log_level fixes + abstract fixes

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