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

Revision 685, 35.2 kB (checked in by smidl, 15 years ago)

mex tutorial cleanup + working mexDS

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