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

Revision 728, 36.9 kB (checked in by smidl, 15 years ago)

logger now has ability to store settings - used in estimator. New mexfunction epdf_mean

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