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

Revision 795, 32.4 kB (checked in by mido, 14 years ago)

validate() finally included into UI::build mechanism and removed from some from_setting methods,
from that point StateDS test does not pass, I do not understand why

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