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

Revision 953, 41.7 kB (checked in by smidl, 14 years ago)

RV are now through UI::get

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