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

Revision 956, 41.5 kB (checked in by sarka, 14 years ago)

to_setting

  • 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        void to_setting ( Setting &set ) const;
765
766        vec samplecond ( const vec &cond ) {
767                return sample();
768        }
769        double evallogcond ( const vec &val, const vec &cond ) {
770                return evallog ( val );
771        }
772};
773SHAREDPTR ( epdf );
774
775//! pdf with internal epdf that is modified by function \c condition
776template <class EPDF>
777class pdf_internal: public pdf {
778protected :
779        //! Internal epdf used for sampling
780        EPDF iepdf;
781public:
782        //! constructor
783        pdf_internal() : pdf(), iepdf() {
784        }
785
786        //! Update \c iepdf so that it represents this pdf conditioned on \c rvc = cond
787        //! This function provides convenient reimplementation in offsprings
788        virtual void condition ( const vec &cond ) = 0;
789
790        //!access function to iepdf
791        EPDF& e() {
792                return iepdf;
793        }
794
795        //! Reimplements samplecond using \c condition()
796        vec samplecond ( const vec &cond );
797        //! Reimplements evallogcond using \c condition()
798        double evallogcond ( const vec &val, const vec &cond );
799        //! Efficient version of evallogcond for matrices
800        virtual vec evallogcond_mat ( const mat &Dt, const vec &cond );
801        //! Efficient version of evallogcond for Array<vec>
802        virtual vec evallogcond_mat ( const Array<vec> &Dt, const vec &cond );
803        //! Efficient version of samplecond
804        virtual mat samplecond_mat ( const vec &cond, int N );
805
806        void validate() {
807                pdf::validate();
808                iepdf.validate();
809                if ( rv._dsize() < iepdf._rv()._dsize() ) {
810                        rv = iepdf._rv();
811                };
812                dim = iepdf.dimension();
813        }
814};
815
816/*! \brief DataLink is a connection between two data vectors Up and Down
817
818Up can be longer than Down. Down must be fully present in Up (TODO optional)
819See chart:
820\dot
821digraph datalink {
822  node [shape=record];
823  subgraph cluster0 {
824    label = "Up";
825      up [label="<1>|<2>|<3>|<4>|<5>"];
826    color = "white"
827}
828  subgraph cluster1{
829    label = "Down";
830    labelloc = b;
831      down [label="<1>|<2>|<3>"];
832    color = "white"
833}
834    up:1 -> down:1;
835    up:3 -> down:2;
836    up:5 -> down:3;
837}
838\enddot
839
840*/
841class datalink {
842protected:
843        //! Remember how long val should be
844        int downsize;
845
846        //! Remember how long val of "Up" should be
847        int upsize;
848
849        //! val-to-val link, indices of the upper val
850        ivec v2v_up;
851
852public:
853        //! Constructor
854        datalink() : downsize ( 0 ), upsize ( 0 ) { }
855
856        //! Convenience constructor
857        datalink ( const RV &rv, const RV &rv_up ) {
858                set_connection ( rv, rv_up );
859        }
860
861        //! set connection, rv must be fully present in rv_up
862        virtual void set_connection ( const RV &rv, const RV &rv_up );
863
864        //! set connection using indices
865        virtual void set_connection ( int ds, int us, const ivec &upind );
866
867        //! Get val for myself from val of "Up"
868        vec pushdown ( const vec &val_up ) {
869                vec tmp ( downsize );
870                filldown ( val_up, tmp );
871                return tmp;
872        }
873        //! Get val for vector val_down from val of "Up"
874        virtual void filldown ( const vec &val_up, vec &val_down ) {
875                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
876                val_down = val_up ( v2v_up );
877        }
878        //! Fill val of "Up" by my pieces
879        virtual void pushup ( vec &val_up, const vec &val ) {
880                bdm_assert_debug ( downsize == val.length(), "Wrong val" );
881                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
882                set_subvector ( val_up, v2v_up, val );
883        }
884        //! access functions
885        int _upsize() {
886                return upsize;
887        }
888        //! access functions
889        int _downsize() {
890                return downsize;
891        }
892        //! for future use
893        virtual ~datalink() {}
894};
895
896/*! Extension of datalink to fill only part of Down
897*/
898class datalink_part : public datalink {
899protected:
900        //! indices of values in vector downsize
901        ivec v2v_down;
902public:
903        void set_connection ( const RV &rv, const RV &rv_up );
904        //! Get val for vector val_down from val of "Up"
905        void filldown ( const vec &val_up, vec &val_down ) {
906                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) );
907        }
908};
909
910/*! \brief Datalink that buffers delayed values - do not forget to call step()
911
912Up is current data, Down is their subset with possibly delayed values
913*/
914class datalink_buffered: public datalink_part {
915protected:
916        //! History, ordered as \f$[Up_{t-1},Up_{t-2}, \ldots]\f$
917        vec history;
918        //! rv of the history
919        RV Hrv;
920        //! h2v : indices in down
921        ivec h2v_down;
922        //! h2v : indices in history
923        ivec h2v_hist;
924        //! v2h: indices of up too be pushed to h
925        ivec v2h_up;
926public:
927
928        datalink_buffered() : datalink_part(), history ( 0 ), h2v_down ( 0 ), h2v_hist ( 0 ) {};
929        //! push current data to history
930        void store_data ( const vec &val_up ) {
931                if ( v2h_up.length() > 0 ) {
932                        history.shift_right ( 0, v2h_up.length() );
933                        history.set_subvector ( 0, val_up ( v2h_up ) );
934                }
935        }
936        //! Get val for myself from val of "Up"
937        vec pushdown ( const vec &val_up ) {
938                vec tmp ( downsize );
939                filldown ( val_up, tmp );
940                return tmp;
941        }
942
943        void filldown ( const vec &val_up, vec &val_down ) {
944                bdm_assert_debug ( val_down.length() >= downsize, "short val_down" );
945
946                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) ); // copy direct values
947                set_subvector ( val_down, h2v_down, history ( h2v_hist ) ); // copy delayed values
948        }
949
950        void set_connection ( const RV &rv, const RV &rv_up );
951       
952        //! set history of variable given by \c rv1 to values of \c hist.
953        void set_history ( const RV& rv1, const vec &hist0 );
954};
955
956//! buffered datalink from 2 vectors to 1
957class datalink_2to1_buffered {
958protected:
959        //! link 1st vector to down
960        datalink_buffered dl1;
961        //! link 2nd vector to down
962        datalink_buffered dl2;
963public:
964        //! set connection between RVs
965        void set_connection ( const RV &rv, const RV &rv_up1, const RV &rv_up2 ) {
966                dl1.set_connection ( rv, rv_up1 );
967                dl2.set_connection ( rv, rv_up2 );
968        }
969        //! fill values of down from the values of the two up vectors
970        void filldown ( const vec &val1, const vec &val2, vec &val_down ) {
971                bdm_assert_debug ( val_down.length() >= dl1._downsize() + dl2._downsize(), "short val_down" );
972                dl1.filldown ( val1, val_down );
973                dl2.filldown ( val2, val_down );
974        }
975        //! update buffer
976        void step ( const vec &dt, const vec &ut ) {
977                dl1.store_data ( dt );
978                dl2.store_data ( ut );
979        }
980};
981
982
983
984//! Data link with a condition.
985class datalink_m2e: public datalink {
986protected:
987        //! Remember how long cond should be
988        int condsize;
989
990        //!upper_val-to-local_cond link, indices of the upper val
991        ivec v2c_up;
992
993        //!upper_val-to-local_cond link, indices of the local cond
994        ivec v2c_lo;
995
996public:
997        //! Constructor
998        datalink_m2e() : condsize ( 0 ) { }
999
1000        //! Set connection between vectors
1001        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up );
1002
1003        //!Construct condition
1004        vec get_cond ( const vec &val_up );
1005
1006        //! Copy corresponding values to Up.condition
1007        void pushup_cond ( vec &val_up, const vec &val, const vec &cond );
1008};
1009
1010//!DataLink is a connection between pdf and its superordinate (Up)
1011//! This class links
1012class datalink_m2m: public datalink_m2e {
1013protected:
1014        //!cond-to-cond link, indices of the upper cond
1015        ivec c2c_up;
1016        //!cond-to-cond link, indices of the local cond
1017        ivec c2c_lo;
1018
1019public:
1020        //! Constructor
1021        datalink_m2m() {};
1022        //! Set connection between the vectors
1023        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up ) {
1024                datalink_m2e::set_connection ( rv, rvc, rv_up );
1025                //establish c2c connection
1026                rvc.dataind ( rvc_up, c2c_lo, c2c_up );
1027//              bdm_assert_debug ( c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given" );
1028        }
1029
1030        //! Get cond for myself from val and cond of "Up"
1031        vec get_cond ( const vec &val_up, const vec &cond_up ) {
1032                vec tmp ( condsize );
1033                fill_cond ( val_up, cond_up, tmp );
1034                return tmp;
1035        }
1036        //! fill condition
1037        void fill_cond ( const vec &val_up, const vec &cond_up, vec& cond_out ) {
1038                bdm_assert_debug ( cond_out.length() >= condsize, "dl.fill_cond: cond_out is too small" );
1039                set_subvector ( cond_out, v2c_lo, val_up ( v2c_up ) );
1040                set_subvector ( cond_out, c2c_lo, cond_up ( c2c_up ) );
1041        }
1042        //! Fill
1043
1044};
1045
1046
1047//! \brief Combines RVs from a list of pdfs to a single one.
1048RV get_composite_rv ( const Array<shared_ptr<pdf> > &pdfs, bool checkoverlap = false );
1049
1050/*! \brief Abstract class for discrete-time sources of data.
1051
1052The class abstracts operations of:
1053\li  data aquisition,
1054\li  data-preprocessing, such as  scaling of data,
1055\li  data resampling from the task of estimation and control.
1056Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
1057
1058The DataSource has three main data interaction structures:
1059\li input, \f$ u_t \f$,
1060\li output \f$ d_t \f$,
1061In simulators, d_t may contain "hidden" variables as well.
1062*/
1063
1064class DS : public root {
1065        //! \var log_level_enums logdt
1066        //! log all outputs
1067
1068        //! \var log_level_enums logut
1069        //! log all inputs
1070        LOG_LEVEL(DS,logdt,logut);
1071
1072protected:
1073        //! size of data returned by \c getdata()
1074        int dtsize;
1075        //! size of data
1076        int utsize;
1077        //!Description of data returned by \c getdata().
1078        RV Drv;
1079        //!Description of data witten by by \c write().
1080        RV Urv; //
1081public:
1082        //! default constructors
1083        DS() : dtsize ( 0 ), utsize ( 0 ), Drv(), Urv(){
1084                log_level[logdt] = true;
1085                log_level[logut] = true;
1086        };
1087
1088        //! 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().
1089        virtual int max_length() {
1090                return std::numeric_limits< int >::max();
1091        }
1092        //! Returns full vector of observed data=[output, input]
1093        virtual void getdata ( vec &dt ) const = 0;
1094
1095        //! Returns data records at indices. Default is inefficent.
1096        virtual void getdata ( vec &dt, const ivec &indices ) {
1097                vec tmp(dtsize);
1098                getdata(tmp);
1099                dt = tmp(indices);
1100        };
1101
1102        //! Accepts action variable and schedule it for application.   
1103        virtual void write ( const vec &ut ) NOT_IMPLEMENTED_VOID;
1104
1105        //! Accepts action variables at specific indices
1106        virtual void write ( const vec &ut, const ivec &indices ) NOT_IMPLEMENTED_VOID;
1107
1108        //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
1109        virtual void step() = 0;
1110
1111        //! Register DS for logging into logger L
1112        virtual void log_register ( logger &L,  const string &prefix );
1113        //! Register DS for logging into logger L
1114        virtual void log_write ( ) const;
1115        //!access function
1116        virtual const RV& _drv() const {
1117                return Drv;
1118        }
1119        //!access function
1120        const RV& _urv() const {
1121                return Urv;
1122        }
1123
1124        //! set random variables
1125        virtual void set_drv ( const  RV &drv, const RV &urv) {
1126                Drv = drv;
1127                Urv = urv;
1128        }
1129
1130        void from_setting ( const Setting &set );
1131
1132        void validate();
1133};
1134
1135/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
1136
1137This object represents exact or approximate evaluation of the Bayes rule:
1138\f[
1139f(\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})}
1140\f]
1141where:
1142 * \f$ y_t \f$ is the variable
1143Access to the resulting posterior density is via function \c posterior().
1144
1145As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
1146It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
1147
1148Alternatively, it can evaluate posterior density with rvc replaced by the given values, \f$ c_t \f$:
1149\f[
1150f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
1151\f]
1152
1153*/
1154
1155class BM : public root {
1156        //! \var log_level_enums logfull
1157        //! TODO DOPLNIT
1158
1159        //! \var log_level_enums logevidence
1160        //! TODO DOPLNIT
1161       
1162        //! \var log_level_enums logbounds
1163        //! TODO DOPLNIT       
1164        LOG_LEVEL(BM,logfull,logevidence,logbounds);
1165
1166protected:
1167        //! Random variable of the data (optional)
1168        RV yrv;
1169        //! size of the data record
1170        int dimy;
1171        //! Name of extension variable
1172        RV rvc;
1173        //! size of the conditioning vector
1174        int dimc;
1175
1176        //!Logarithm of marginalized data likelihood.
1177        double ll;
1178        //!  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.
1179        bool evalll;
1180
1181public:
1182        //! \name Constructors
1183        //! @{
1184
1185        BM() : yrv(), dimy ( 0 ), rvc(), dimc ( 0 ), ll ( 0 ), evalll ( true ) { };
1186        //      BM ( const BM &B ) :  yrv ( B.yrv ), dimy(B.dimy), rvc ( B.rvc ),dimc(B.dimc), ll ( B.ll ), evalll ( B.evalll ) {}
1187        //! \brief Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
1188        //! Prototype: \code BM* _copy() const {return new BM(*this);} \endcode
1189        virtual BM* _copy() const NOT_IMPLEMENTED(NULL);
1190        //!@}
1191
1192        //! \name Mathematical operations
1193        //!@{
1194
1195        /*! \brief Incremental Bayes rule
1196        @param dt vector of input data
1197        */
1198        virtual void bayes ( const vec &yt, const vec &cond = empty_vec ) = 0;
1199        //! Batch Bayes rule (columns of Dt are observations)
1200        virtual void bayes_batch ( const mat &Dt, const vec &cond = empty_vec );
1201        //! Batch Bayes rule (columns of Dt are observations, columns of Cond are conditions)
1202        virtual void bayes_batch ( const mat &Dt, const mat &Cond );
1203        //! Evaluates predictive log-likelihood of the given data record
1204        //! I.e. marginal likelihood of the data with the posterior integrated out.
1205        //! This function evaluates only \f$ y_t \f$, condition is assumed to be the last used in bayes().
1206        //! See bdm::BM::predictor for conditional version.
1207        virtual double logpred ( const vec &yt ) const NOT_IMPLEMENTED(0.0);
1208
1209        //! Matrix version of logpred
1210        vec logpred_mat ( const mat &Yt ) const {
1211                vec tmp ( Yt.cols() );
1212                for ( int i = 0; i < Yt.cols(); i++ ) {
1213                        tmp ( i ) = logpred ( Yt.get_col ( i ) );
1214                }
1215                return tmp;
1216        }
1217
1218        //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
1219        virtual epdf* epredictor(const vec &cond=vec()) const NOT_IMPLEMENTED(NULL);
1220
1221        //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
1222        virtual pdf* predictor() const NOT_IMPLEMENTED(NULL);
1223
1224        //!@}
1225
1226
1227        //! \name Access to attributes
1228        //!@{
1229        //! access function
1230        const RV& _rvc() const {
1231                return rvc;
1232        }
1233        //! access function
1234        int dimensionc() const {
1235                return dimc;
1236        }
1237        //! access function
1238        int dimensiony() const {
1239                return dimy;
1240        }
1241        //! access function
1242        int dimension() const {
1243                return posterior().dimension();
1244        }
1245        //! access function
1246        const RV& _rv() const {
1247                return posterior()._rv();
1248        }
1249        //! access function
1250        const RV& _yrv() const {
1251                return yrv;
1252        }
1253        //! access function
1254        void set_yrv ( const RV &rv ) {
1255                yrv = rv;
1256        }
1257        //! access function
1258        void set_rvc ( const RV &rv ) {
1259                rvc = rv;
1260        }
1261        //! access to rv of the posterior
1262        void set_rv ( const RV &rv ) {
1263                const_cast<epdf&> ( posterior() ).set_rv ( rv );
1264        }
1265        //! access function
1266        void set_dim ( int dim ) {
1267                const_cast<epdf&> ( posterior() ).set_dim ( dim );
1268        }
1269        //! return internal log-likelihood of the last data vector
1270        double _ll() const {
1271                return ll;
1272        }
1273        //! switch evaluation of log-likelihood on/off
1274        void set_evalll ( bool evl0 ) {
1275                evalll = evl0;
1276        }
1277        //! return posterior density
1278        virtual const epdf& posterior() const = 0;
1279       
1280        epdf& prior() {return const_cast<epdf&>(posterior());}
1281        //! set prior density -- same as posterior but writable
1282        virtual void set_prior(const epdf *pdf0) NOT_IMPLEMENTED_VOID;
1283       
1284        //!@}
1285
1286        //! \name Logging of results
1287        //!@{
1288
1289        //! Add all logged variables to a logger
1290        //! Log levels two digits: xy where
1291        //!  * y = 0/1 log-likelihood is to be logged
1292        //!  * x = level of the posterior (typically 0/1/2 for nothing/mean/bounds)
1293        virtual void log_register ( logger &L, const string &prefix = "" );
1294
1295        //! Save results to the given logger, details of what is stored is configured by \c LIDs and \c options
1296        virtual void log_write ( ) const;
1297
1298        //!@}
1299        void from_setting ( const Setting &set ) {
1300                UI::get(yrv, set, "yrv", UI::optional );
1301                UI::get(rvc, set, "rvc", UI::optional );
1302                RV r;
1303                UI::get(r, set, "rv", UI::optional );
1304                set_rv ( r );
1305
1306                UI::get ( log_level, set, "log_level", UI::optional );
1307        }
1308
1309        void to_setting ( Setting &set ) const {
1310                root::to_setting( set );
1311                UI::save( &yrv, set, "yrv" );
1312                UI::save( &rvc, set, "rvc" );           
1313                UI::save( &posterior()._rv(), set, "rv" );
1314                UI::save( log_level, set );
1315        }
1316
1317        void validate()
1318        {
1319                if ( log_level[logbounds] ) {
1320                        const_cast<epdf&> ( posterior() ).log_level[epdf::loglbound] = true;
1321                } else {
1322                        const_cast<epdf&> ( posterior() ).log_level[epdf::logmean] = true;;
1323                }
1324        }
1325};
1326
1327//! array of pointers to epdf
1328typedef Array<shared_ptr<epdf> > epdf_array;
1329//! array of pointers to pdf
1330typedef Array<shared_ptr<pdf> > pdf_array;
1331
1332template<class EPDF>
1333vec pdf_internal<EPDF>::samplecond ( const vec &cond ) {
1334        condition ( cond );
1335        vec temp = iepdf.sample();
1336        return temp;
1337}
1338
1339template<class EPDF>
1340mat pdf_internal<EPDF>::samplecond_mat ( const vec &cond, int N ) {
1341        condition ( cond );
1342        mat temp ( dimension(), N );
1343        vec smp ( dimension() );
1344        for ( int i = 0; i < N; i++ ) {
1345                smp = iepdf.sample();
1346                temp.set_col ( i, smp );
1347        }
1348
1349        return temp;
1350}
1351
1352template<class EPDF>
1353double pdf_internal<EPDF>::evallogcond ( const vec &yt, const vec &cond ) {
1354        double tmp;
1355        condition ( cond );
1356        tmp = iepdf.evallog ( yt );
1357        return tmp;
1358}
1359
1360template<class EPDF>
1361vec pdf_internal<EPDF>::evallogcond_mat ( const mat &Yt, const vec &cond ) {
1362        condition ( cond );
1363        return iepdf.evallog_mat ( Yt );
1364}
1365
1366template<class EPDF>
1367vec pdf_internal<EPDF>::evallogcond_mat ( const Array<vec> &Yt, const vec &cond ) {
1368        condition ( cond );
1369        return iepdf.evallog_mat ( Yt );
1370}
1371
1372}; //namespace
1373#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.