root/library/bdm/stat/exp_family.h @ 621

Revision 621, 36.8 kB (checked in by smidl, 15 years ago)

doc - new pattern for from_setting for pdfs

  • Property svn:eol-style set to native
Line 
1/*!
2  \file
3  \brief Probability distributions for Exponential Family models.
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 EF_H
14#define EF_H
15
16
17#include "../shared_ptr.h"
18#include "../base/bdmbase.h"
19#include "../math/chmat.h"
20
21namespace bdm
22{
23
24
25//! Global Uniform_RNG
26extern Uniform_RNG UniRNG;
27//! Global Normal_RNG
28extern Normal_RNG NorRNG;
29//! Global Gamma_RNG
30extern Gamma_RNG GamRNG;
31
32/*!
33* \brief General conjugate exponential family posterior density.
34
35* More?...
36*/
37
38class eEF : public epdf
39{
40        public:
41//      eEF() :epdf() {};
42                //! default constructor
43                eEF () : epdf () {};
44                //! logarithm of the normalizing constant, \f$\mathcal{I}\f$
45                virtual double lognc() const = 0;
46
47                //!Evaluate normalized log-probability
48                virtual double evallog_nn (const vec &val) const {
49                        bdm_error ("Not implemented");
50                        return 0.0;
51                }
52
53                //!Evaluate normalized log-probability
54                virtual double evallog (const vec &val) const {
55                        double tmp;
56                        tmp = evallog_nn (val) - lognc();
57                        return tmp;
58                }
59                //!Evaluate normalized log-probability for many samples
60                virtual vec evallog_m (const mat &Val) const {
61                        vec x (Val.cols());
62                        for (int i = 0;i < Val.cols();i++) {x (i) = evallog_nn (Val.get_col (i)) ;}
63                        return x -lognc();
64                }
65                //!Evaluate normalized log-probability for many samples
66                virtual vec evallog_m (const Array<vec> &Val) const {
67                        vec x (Val.length());
68                        for (int i = 0;i < Val.length();i++) {x (i) = evallog_nn (Val (i)) ;}
69                        return x -lognc();
70                }
71
72                //!Power of the density, used e.g. to flatten the density
73                virtual void pow (double p) {
74                        bdm_error ("Not implemented");
75                }
76};
77
78
79//! Estimator for Exponential family
80class BMEF : public BM
81{
82        protected:
83                //! forgetting factor
84                double frg;
85                //! cached value of lognc() in the previous step (used in evaluation of \c ll )
86                double last_lognc;
87        public:
88                //! Default constructor (=empty constructor)
89                BMEF (double frg0 = 1.0) : BM (), frg (frg0) {}
90                //! Copy constructor
91                BMEF (const BMEF &B) : BM (B), frg (B.frg), last_lognc (B.last_lognc) {}
92                //!get statistics from another model
93                virtual void set_statistics (const BMEF* BM0) {
94                        bdm_error ("Not implemented");
95                }
96
97                //! Weighted update of sufficient statistics (Bayes rule)
98                virtual void bayes (const vec &data, const double w) {};
99                //original Bayes
100                void bayes (const vec &dt);
101
102                //!Flatten the posterior according to the given BMEF (of the same type!)
103                virtual void flatten (const BMEF * B) {
104                        bdm_error ("Not implemented");
105                }
106
107                BMEF* _copy_ () const {
108                        bdm_error ("function _copy_ not implemented for this BM");
109                        return NULL;
110                }
111};
112
113template<class sq_T, template <typename> class TEpdf>
114class mlnorm;
115
116/*!
117* \brief Gaussian density with positive definite (decomposed) covariance matrix.
118
119* More?...
120*/
121template<class sq_T>
122class enorm : public eEF
123{
124        protected:
125                //! mean value
126                vec mu;
127                //! Covariance matrix in decomposed form
128                sq_T R;
129        public:
130                //!\name Constructors
131                //!@{
132
133                enorm () : eEF (), mu (), R () {};
134                enorm (const vec &mu, const sq_T &R) {set_parameters (mu, R);}
135                void set_parameters (const vec &mu, const sq_T &R);
136                /*! Create Normal density
137                \f[ f(rv) = N(\mu, R) \f]
138                from structure
139                \code
140                class = 'enorm<ldmat>', (OR) 'enorm<chmat>', (OR) 'enorm<fsqmat>';
141                mu    = [];                  // mean value
142                R     = [];                  // variance, square matrix of appropriate dimension
143                \endcode
144                */
145                void from_setting (const Setting &root);
146                void validate() {
147                        bdm_assert (mu.length() == R.rows(), "mu and R parameters do not match");
148                        dim = mu.length();
149                }
150                //!@}
151
152                //! \name Mathematical operations
153                //!@{
154
155                //! dupdate in exponential form (not really handy)
156                void dupdate (mat &v, double nu = 1.0);
157
158                vec sample() const;
159
160                double evallog_nn (const vec &val) const;
161                double lognc () const;
162                vec mean() const {return mu;}
163                vec variance() const {return diag (R.to_mat());}
164//      mlnorm<sq_T>* condition ( const RV &rvn ) const ; <=========== fails to cmpile. Why?
165                shared_ptr<mpdf> condition ( const RV &rvn ) const;
166
167                // target not typed to mlnorm<sq_T, enorm<sq_T> > &
168                // because that doesn't compile (perhaps because we
169                // haven't finished defining enorm yet), but the type
170                // is required
171                void condition ( const RV &rvn, mpdf &target ) const;
172
173                shared_ptr<epdf> marginal (const RV &rvn ) const;
174                void marginal ( const RV &rvn, enorm<sq_T> &target ) const;
175                //!@}
176
177                //! \name Access to attributes
178                //!@{
179
180                vec& _mu() {return mu;}
181                const vec& _mu() const {return mu;}
182                void set_mu (const vec mu0) { mu = mu0;}
183                sq_T& _R() {return R;}
184                const sq_T& _R() const {return R;}
185                //!@}
186
187};
188UIREGISTER2 (enorm, chmat);
189SHAREDPTR2 ( enorm, chmat );
190UIREGISTER2 (enorm, ldmat);
191SHAREDPTR2 ( enorm, ldmat );
192UIREGISTER2 (enorm, fsqmat);
193SHAREDPTR2 ( enorm, fsqmat );
194
195
196/*!
197* \brief Gauss-inverse-Wishart density stored in LD form
198
199* For \f$p\f$-variate densities, given rv.count() should be \f$p\times\f$ V.rows().
200*
201*/
202class egiw : public eEF
203{
204        protected:
205                //! Extended information matrix of sufficient statistics
206                ldmat V;
207                //! Number of data records (degrees of freedom) of sufficient statistics
208                double nu;
209                //! Dimension of the output
210                int dimx;
211                //! Dimension of the regressor
212                int nPsi;
213        public:
214                //!\name Constructors
215                //!@{
216                egiw() : eEF() {};
217                egiw (int dimx0, ldmat V0, double nu0 = -1.0) : eEF() {set_parameters (dimx0, V0, nu0);};
218
219                void set_parameters (int dimx0, ldmat V0, double nu0 = -1.0) {
220                        dimx = dimx0;
221                        nPsi = V0.rows() - dimx;
222                        dim = dimx * (dimx + nPsi); // size(R) + size(Theta)
223
224                        V = V0;
225                        if (nu0 < 0) {
226                                nu = 0.1 + nPsi + 2 * dimx + 2; // +2 assures finite expected value of R
227                                // terms before that are sufficient for finite normalization
228                        } else {
229                                nu = nu0;
230                        }
231                }
232                //!@}
233
234                vec sample() const;
235                vec mean() const;
236                vec variance() const;
237
238                //! LS estimate of \f$\theta\f$
239                vec est_theta() const;
240
241                //! Covariance of the LS estimate
242                ldmat est_theta_cov() const;
243
244                //! expected values of the linear coefficient and the covariance matrix are written to \c M and \c R , respectively
245                void mean_mat (mat &M, mat&R) const;
246                //! In this instance, val= [theta, r]. For multivariate instances, it is stored columnwise val = [theta_1 theta_2 ... r_1 r_2 ]
247                double evallog_nn (const vec &val) const;
248                double lognc () const;
249                void pow (double p) {V *= p;nu *= p;};
250
251                //! \name Access attributes
252                //!@{
253
254                ldmat& _V() {return V;}
255                const ldmat& _V() const {return V;}
256                double& _nu()  {return nu;}
257                const double& _nu() const {return nu;}
258                /*! Create Gauss-inverse-Wishart density
259                \f[ f(rv) = GiW(V,\nu) \f]
260                from structure
261                \code
262                class = 'egiw';
263                V     = [];               // square matrix
264                nu    = [];               // scalar \nu ((almost) degrees of freedom)
265                                                                  // when missing, it will be computed to obtain proper pdf
266                dimx  = [];               // dimension of the wishart part
267                rv = RV({'name'})         // description of RV
268                rvc = RV({'name'})        // description of RV in condition
269                \endcode
270                */
271               
272                void from_setting (const Setting &set) {
273                        epdf::from_setting(set);
274                        if (!UI::get (nu, set, "nu", UI::compulsory)) {nu=-1;}
275                        UI::get (dimx, set, "dimx", UI::compulsory);
276                        mat V;
277                        UI::get (V, set, "V", UI::compulsory);
278                        set_parameters (dimx, V, nu);
279                }
280                //!@}
281};
282UIREGISTER ( egiw );
283SHAREDPTR ( egiw );
284
285/*! \brief Dirichlet posterior density
286
287Continuous Dirichlet density of \f$n\f$-dimensional variable \f$x\f$
288\f[
289f(x|\beta) = \frac{\Gamma[\gamma]}{\prod_{i=1}^{n}\Gamma(\beta_i)} \prod_{i=1}^{n}x_i^{\beta_i-1}
290\f]
291where \f$\gamma=\sum_i \beta_i\f$.
292*/
293class eDirich: public eEF
294{
295        protected:
296                //!sufficient statistics
297                vec beta;
298        public:
299                //!\name Constructors
300                //!@{
301
302                eDirich () : eEF () {};
303                eDirich (const eDirich &D0) : eEF () {set_parameters (D0.beta);};
304                eDirich (const vec &beta0) {set_parameters (beta0);};
305                void set_parameters (const vec &beta0) {
306                        beta = beta0;
307                        dim = beta.length();
308                }
309                //!@}
310
311                vec sample() const {
312                        bdm_error ("Not implemented");
313                        return vec();
314                }
315
316                vec mean() const {return beta / sum (beta);};
317                vec variance() const {double gamma = sum (beta); return elem_mult (beta, (beta + 1)) / (gamma* (gamma + 1));}
318                //! In this instance, val is ...
319                double evallog_nn (const vec &val) const {
320                        double tmp; tmp = (beta - 1) * log (val);
321                        return tmp;
322                }
323
324                double lognc () const {
325                        double tmp;
326                        double gam = sum (beta);
327                        double lgb = 0.0;
328                        for (int i = 0;i < beta.length();i++) {lgb += lgamma (beta (i));}
329                        tmp = lgb - lgamma (gam);
330                        return tmp;
331                }
332
333                //!access function
334                vec& _beta()  {return beta;}
335                //!Set internal parameters
336};
337
338//! \brief Estimator for Multinomial density
339class multiBM : public BMEF
340{
341        protected:
342                //! Conjugate prior and posterior
343                eDirich est;
344                //! Pointer inside est to sufficient statistics
345                vec &beta;
346        public:
347                //!Default constructor
348                multiBM () : BMEF (), est (), beta (est._beta()) {
349                        if (beta.length() > 0) {last_lognc = est.lognc();}
350                        else{last_lognc = 0.0;}
351                }
352                //!Copy constructor
353                multiBM (const multiBM &B) : BMEF (B), est (B.est), beta (est._beta()) {}
354                //! Sets sufficient statistics to match that of givefrom mB0
355                void set_statistics (const BM* mB0) {const multiBM* mB = dynamic_cast<const multiBM*> (mB0); beta = mB->beta;}
356                void bayes (const vec &dt) {
357                        if (frg < 1.0) {beta *= frg;last_lognc = est.lognc();}
358                        beta += dt;
359                        if (evalll) {ll = est.lognc() - last_lognc;}
360                }
361                double logpred (const vec &dt) const {
362                        eDirich pred (est);
363                        vec &beta = pred._beta();
364
365                        double lll;
366                        if (frg < 1.0)
367                                {beta *= frg;lll = pred.lognc();}
368                        else
369                                if (evalll) {lll = last_lognc;}
370                                else{lll = pred.lognc();}
371
372                        beta += dt;
373                        return pred.lognc() - lll;
374                }
375                void flatten (const BMEF* B) {
376                        const multiBM* E = dynamic_cast<const multiBM*> (B);
377                        // sum(beta) should be equal to sum(B.beta)
378                        const vec &Eb = E->beta;//const_cast<multiBM*> ( E )->_beta();
379                        beta *= (sum (Eb) / sum (beta));
380                        if (evalll) {last_lognc = est.lognc();}
381                }
382                //! reimplemnetation of BM::posterior()
383                const eDirich& posterior() const {return est;};
384                //! constructor function               
385                void set_parameters (const vec &beta0) {
386                        est.set_parameters (beta0);
387                        if (evalll) {last_lognc = est.lognc();}
388                }
389};
390
391/*!
392 \brief Gamma posterior density
393
394 Multivariate Gamma density as product of independent univariate densities.
395 \f[
396 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
397 \f]
398*/
399
400class egamma : public eEF
401{
402        protected:
403                //! Vector \f$\alpha\f$
404                vec alpha;
405                //! Vector \f$\beta\f$
406                vec beta;
407        public :
408                //! \name Constructors
409                //!@{
410                egamma () : eEF (), alpha (0), beta (0) {};
411                egamma (const vec &a, const vec &b) {set_parameters (a, b);};
412                void set_parameters (const vec &a, const vec &b) {alpha = a, beta = b;dim = alpha.length();};
413                //!@}
414
415                vec sample() const;
416                double evallog (const vec &val) const;
417                double lognc () const;
418                //! Returns pointer to internal alpha. Potentially dengerous: use with care!
419                vec& _alpha() {return alpha;}
420                //! Returns pointer to internal beta. Potentially dengerous: use with care!
421                vec& _beta() {return beta;}
422                vec mean() const {return elem_div (alpha, beta);}
423                vec variance() const {return elem_div (alpha, elem_mult (beta, beta)); }
424
425                /*! Create Gamma density
426                \f[ f(rv|rvc) = \Gamma(\alpha, \beta) \f]
427                from structure
428                \code
429                class = 'egamma';
430                alpha = [...];         // vector of alpha
431                beta = [...];          // vector of beta
432                rv = RV({'name'})      // description of RV
433                \endcode
434                */
435                void from_setting (const Setting &set) {
436                        epdf::from_setting (set); // reads rv
437                        UI::get (alpha, set, "alpha", UI::compulsory);
438                        UI::get (beta, set, "beta", UI::compulsory);
439                        validate();
440                }
441                void validate() {
442                        bdm_assert (alpha.length() == beta.length(), "parameters do not match");
443                        dim = alpha.length();
444                }
445};
446UIREGISTER (egamma);
447SHAREDPTR ( egamma );
448
449/*!
450 \brief Inverse-Gamma posterior density
451
452 Multivariate inverse-Gamma density as product of independent univariate densities.
453 \f[
454 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
455 \f]
456
457Vector \f$\beta\f$ has different meaning (in fact it is 1/beta as used in definition of iG)
458
459 Inverse Gamma can be converted to Gamma using \f[
460 x\sim iG(a,b) => 1/x\sim G(a,1/b)
461\f]
462This relation is used in sampling.
463 */
464
465class eigamma : public egamma
466{
467        protected:
468        public :
469                //! \name Constructors
470                //! All constructors are inherited
471                //!@{
472                //!@}
473
474                vec sample() const {return 1.0 / egamma::sample();};
475                //! Returns poiter to alpha and beta. Potentially dangerous: use with care!
476                vec mean() const {return elem_div (beta, alpha - 1);}
477                vec variance() const {vec mea = mean(); return elem_div (elem_mult (mea, mea), alpha - 2);}
478};
479/*
480//! Weighted mixture of epdfs with external owned components.
481class emix : public epdf {
482protected:
483        int n;
484        vec &w;
485        Array<epdf*> Coms;
486public:
487//! Default constructor
488        emix ( const RV &rv, vec &w0): epdf(rv), n(w0.length()), w(w0), Coms(n) {};
489        void set_parameters( int &i, double wi, epdf* ep){w(i)=wi;Coms(i)=ep;}
490        vec mean(){vec pom; for(int i=0;i<n;i++){pom+=Coms(i)->mean()*w(i);} return pom;};
491};
492*/
493
494//!  Uniform distributed density on a rectangular support
495
496class euni: public epdf
497{
498        protected:
499//! lower bound on support
500                vec low;
501//! upper bound on support
502                vec high;
503//! internal
504                vec distance;
505//! normalizing coefficients
506                double nk;
507//! cache of log( \c nk )
508                double lnk;
509        public:
510                //! \name Constructors
511                //!@{
512                euni () : epdf () {}
513                euni (const vec &low0, const vec &high0) {set_parameters (low0, high0);}
514                void set_parameters (const vec &low0, const vec &high0) {
515                        distance = high0 - low0;
516                        low = low0;
517                        high = high0;
518                        nk = prod (1.0 / distance);
519                        lnk = log (nk);
520                        dim = low.length();
521                }
522                //!@}
523
524                double evallog (const vec &val) const  {
525                        if (any (val < low) && any (val > high)) {return inf;}
526                        else return lnk;
527                }
528                vec sample() const {
529                        vec smp (dim);
530#pragma omp critical
531                        UniRNG.sample_vector (dim , smp);
532                        return low + elem_mult (distance, smp);
533                }
534                //! set values of \c low and \c high
535                vec mean() const {return (high -low) / 2.0;}
536                vec variance() const {return (pow (high, 2) + pow (low, 2) + elem_mult (high, low)) / 3.0;}
537                /*! Create Uniform density
538                \f[ f(rv) = U(low,high) \f]
539                from structure
540                 \code
541                 class = 'euni'
542                 high = [...];          // vector of upper bounds
543                 low = [...];           // vector of lower bounds
544                 rv = RV({'name'});     // description of RV
545                 \endcode
546                 */
547                void from_setting (const Setting &set) {
548                        epdf::from_setting (set); // reads rv and rvc
549
550                        UI::get (high, set, "high", UI::compulsory);
551                        UI::get (low, set, "low", UI::compulsory);
552                        set_parameters(low,high);
553                        validate();
554                }
555                void validate() {
556                        bdm_assert(high.length()==low.length(), "Incompatible high and low vectors");
557                        dim = high.length();
558                        bdm_assert (min (distance) > 0.0, "bad support");
559                }
560};
561UIREGISTER(euni);
562
563/*!
564 \brief Normal distributed linear function with linear function of mean value;
565
566 Mean value \f$ \mu=A*\mbox{rvc}+\mu_0 \f$.
567*/
568template < class sq_T, template <typename> class TEpdf = enorm >
569class mlnorm : public mpdf_internal< TEpdf<sq_T> >
570{
571        protected:
572                //! Internal epdf that arise by conditioning on \c rvc
573                mat A;
574                //! Constant additive term
575                vec mu_const;
576//                      vec& _mu; //cached epdf.mu; !!!!!! WHY NOT?
577        public:
578                //! \name Constructors
579                //!@{
580                mlnorm() : mpdf_internal< TEpdf<sq_T> >() {};
581                mlnorm (const mat &A, const vec &mu0, const sq_T &R) : mpdf_internal< TEpdf<sq_T> >() {
582                        set_parameters (A, mu0, R);
583                }
584
585                //! Set \c A and \c R
586                void set_parameters (const  mat &A0, const vec &mu0, const sq_T &R0) { 
587                        this->iepdf.set_parameters (zeros (A0.rows()), R0);
588                        A = A0;
589                        mu_const = mu0;
590                        this->dimc = A0.cols();
591                }
592                //!@}
593                //! Set value of \c rvc . Result of this operation is stored in \c epdf use function \c _ep to access it.
594                void condition (const vec &cond) {
595                        this->iepdf._mu() = A * cond + mu_const;
596//R is already assigned;
597                }
598
599                //!access function
600                const vec& _mu_const() const {return mu_const;}
601                //!access function
602                const mat& _A() const {return A;}
603                //!access function
604                mat _R() const { return this->iepdf._R().to_mat(); }
605
606                //! Debug stream
607                template<typename sq_M>
608                friend std::ostream &operator<< (std::ostream &os,  mlnorm<sq_M, enorm> &ml);
609
610                /*! Create Normal density with linear function of mean value
611                 \f[ f(rv|rvc) = N(A*rvc+const, R) \f]
612                from structure
613                \code
614                class = 'mlnorm<ldmat>', (OR) 'mlnorm<chmat>', (OR) 'mlnorm<fsqmat>';
615                A     = [];                  // matrix or vector of appropriate dimension
616                const = [];                  // vector of constant term
617                R     = [];                  // square matrix of appropriate dimension
618                \endcode
619                */
620                void from_setting (const Setting &set) {
621                        mpdf::from_setting (set);
622
623                        UI::get (A, set, "A", UI::compulsory);
624                        UI::get (mu_const, set, "const", UI::compulsory);
625                        mat R0;
626                        UI::get (R0, set, "R", UI::compulsory);
627                        set_parameters (A, mu_const, R0);
628                        validate();
629                };
630                void validate() {
631                        bdm_assert (A.rows() == mu_const.length(), "mlnorm: A vs. mu mismatch");
632                        bdm_assert (A.rows() == _R().rows(), "mlnorm: A vs. R mismatch");
633                       
634                }
635};
636UIREGISTER2 (mlnorm,ldmat);
637SHAREDPTR2 ( mlnorm, ldmat );
638UIREGISTER2 (mlnorm,fsqmat);
639SHAREDPTR2 ( mlnorm, fsqmat );
640UIREGISTER2 (mlnorm, chmat);
641SHAREDPTR2 ( mlnorm, chmat );
642
643//! Mpdf with general function for mean value
644template<class sq_T>
645class mgnorm : public mpdf_internal< enorm< sq_T > >
646{
647        private:
648//                      vec &mu; WHY NOT?
649                shared_ptr<fnc> g;
650
651        public:
652                //!default constructor
653                mgnorm() : mpdf_internal<enorm<sq_T> >() { }
654                //!set mean function
655                inline void set_parameters (const shared_ptr<fnc> &g0, const sq_T &R0);
656                inline void condition (const vec &cond);
657
658
659                /*! Create Normal density with given function of mean value
660                \f[ f(rv|rvc) = N( g(rvc), R) \f]
661                from structure
662                \code
663                class = 'mgnorm';
664                g.class =  'fnc';      // function for mean value evolution
665                g._fields_of_fnc = ...;
666
667                R = [1, 0;             // covariance matrix
668                        0, 1];
669                        --OR --
670                dR = [1, 1];           // diagonal of cavariance matrix
671
672                rv = RV({'name'})      // description of RV
673                rvc = RV({'name'})     // description of RV in condition
674                \endcode
675                */
676
677                void from_setting (const Setting &set) {
678                        mpdf::from_setting(set);
679                        shared_ptr<fnc> g = UI::build<fnc> (set, "g", UI::compulsory);
680
681                        mat R;
682                        vec dR;
683                        if (UI::get (dR, set, "dR"))
684                                R = diag (dR);
685                        else
686                                UI::get (R, set, "R", UI::compulsory);
687
688                        set_parameters (g, R);
689                        validate();
690                }
691                void validate() {
692                        bdm_assert(g->dimension()==this->dimension(),"incompatible function");
693                }
694};
695
696UIREGISTER2 (mgnorm, chmat);
697SHAREDPTR2 ( mgnorm, chmat );
698
699
700/*! (Approximate) Student t density with linear function of mean value
701
702The internal epdf of this class is of the type of a Gaussian (enorm).
703However, each conditioning is trying to assure the best possible approximation by taking into account the zeta function. See [] for reference.
704
705Perhaps a moment-matching technique?
706*/
707class mlstudent : public mlnorm<ldmat, enorm>
708{
709        protected:
710                //! Variable \f$ \Lambda \f$ from theory
711                ldmat Lambda;
712                //! Reference to variable \f$ R \f$
713                ldmat &_R;
714                //! Variable \f$ R_e \f$
715                ldmat Re;
716        public:
717                mlstudent () : mlnorm<ldmat, enorm> (),
718                                Lambda (),      _R (iepdf._R()) {}
719                //! constructor function
720                void set_parameters (const mat &A0, const vec &mu0, const ldmat &R0, const ldmat& Lambda0) {
721                        iepdf.set_parameters (mu0, R0);// was Lambda, why?
722                        A = A0;
723                        mu_const = mu0;
724                        Re = R0;
725                        Lambda = Lambda0;
726                }
727                void condition (const vec &cond) {
728                        iepdf._mu() = A * cond + mu_const;
729                        double zeta;
730                        //ugly hack!
731                        if ( (cond.length() + 1) == Lambda.rows()) {
732                                zeta = Lambda.invqform (concat (cond, vec_1 (1.0)));
733                        } else {
734                                zeta = Lambda.invqform (cond);
735                        }
736                        _R = Re;
737                        _R *= (1 + zeta);// / ( nu ); << nu is in Re!!!!!!
738                };
739
740                void validate() {
741                        bdm_assert (A.rows() == mu_const.length(), "mlstudent: A vs. mu mismatch");
742                        bdm_assert (_R.rows() == A.rows(), "mlstudent: A vs. R mismatch");
743                       
744                }
745};
746/*!
747\brief  Gamma random walk
748
749Mean value, \f$\mu\f$, of this density is given by \c rvc .
750Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
751This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
752
753The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
754*/
755class mgamma : public mpdf_internal<egamma>
756{
757        protected:
758
759                //! Constant \f$k\f$
760                double k;
761
762                //! cache of iepdf.beta
763                vec &_beta;
764
765        public:
766                //! Constructor
767                mgamma() : mpdf_internal<egamma>(), k (0),
768                                _beta (iepdf._beta()) {
769                }
770
771                //! Set value of \c k
772                void set_parameters (double k, const vec &beta0);
773
774                void condition (const vec &val) {_beta = k / val;};
775                /*! Create Gamma density with conditional mean value
776                \f[ f(rv|rvc) = \Gamma(k, k/rvc) \f]
777                from structure
778                \code
779                  class = 'mgamma';
780                  beta = [...];          // vector of initial alpha
781                  k = 1.1;               // multiplicative constant k
782                  rv = RV({'name'})      // description of RV
783                  rvc = RV({'name'})     // description of RV in condition
784                 \endcode
785                */
786                void from_setting (const Setting &set) {
787                        mpdf::from_setting (set); // reads rv and rvc
788                        vec betatmp; // ugly but necessary
789                        UI::get (betatmp, set, "beta", UI::compulsory);
790                        UI::get (k, set, "k", UI::compulsory);
791                        set_parameters (k, betatmp);
792                }
793};
794UIREGISTER (mgamma);
795SHAREDPTR (mgamma);
796
797/*!
798\brief  Inverse-Gamma random walk
799
800Mean value, \f$ \mu \f$, of this density is given by \c rvc .
801Standard deviation of the random walk is proportional to one \f$ k \f$-th the mean.
802This is achieved by setting \f$ \alpha=\mu/k^2+2 \f$ and \f$ \beta=\mu(\alpha-1)\f$.
803
804The standard deviation of the walk is then: \f$ \mu/\sqrt(k)\f$.
805 */
806class migamma : public mpdf_internal<eigamma>
807{
808        protected:
809                //! Constant \f$k\f$
810                double k;
811
812                //! cache of iepdf.alpha
813                vec &_alpha;
814
815                //! cache of iepdf.beta
816                vec &_beta;
817
818        public:
819                //! \name Constructors
820                //!@{
821                migamma() : mpdf_internal<eigamma>(),
822                                k (0),
823                                _alpha (iepdf._alpha()),
824                                _beta (iepdf._beta()) {
825                }
826
827                migamma (const migamma &m) : mpdf_internal<eigamma>(),
828                                k (0),
829                                _alpha (iepdf._alpha()),
830                                _beta (iepdf._beta()) {
831                }
832                //!@}
833
834                //! Set value of \c k
835                void set_parameters (int len, double k0) {
836                        k = k0;
837                        iepdf.set_parameters ( (1.0 / (k*k) + 2.0) *ones (len) /*alpha*/, ones (len) /*beta*/);
838                        dimc = dimension();
839                };
840                void condition (const vec &val) {
841                        _beta = elem_mult (val, (_alpha - 1.0));
842                };
843};
844
845
846/*!
847\brief  Gamma random walk around a fixed point
848
849Mean value, \f$\mu\f$, of this density is given by a geometric combination of \c rvc and given fixed point, \f$p\f$. \f$l\f$ is the coefficient of the geometric combimation
850\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
851
852Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
853This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
854
855The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
856*/
857class mgamma_fix : public mgamma
858{
859        protected:
860                //! parameter l
861                double l;
862                //! reference vector
863                vec refl;
864        public:
865                //! Constructor
866                mgamma_fix () : mgamma (), refl () {};
867                //! Set value of \c k
868                void set_parameters (double k0 , vec ref0, double l0) {
869                        mgamma::set_parameters (k0, ref0);
870                        refl = pow (ref0, 1.0 - l0);l = l0;
871                        dimc = dimension();
872                };
873
874                void condition (const vec &val) {vec mean = elem_mult (refl, pow (val, l)); _beta = k / mean;};
875};
876
877
878/*!
879\brief  Inverse-Gamma random walk around a fixed point
880
881Mean value, \f$\mu\f$, of this density is given by a geometric combination of \c rvc and given fixed point, \f$p\f$. \f$l\f$ is the coefficient of the geometric combimation
882\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
883
884==== Check == vv =
885Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
886This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
887
888The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
889 */
890class migamma_ref : public migamma
891{
892        protected:
893                //! parameter l
894                double l;
895                //! reference vector
896                vec refl;
897        public:
898                //! Constructor
899                migamma_ref () : migamma (), refl () {};
900                //! Set value of \c k
901                void set_parameters (double k0 , vec ref0, double l0) {
902                        migamma::set_parameters (ref0.length(), k0);
903                        refl = pow (ref0, 1.0 - l0);
904                        l = l0;
905                        dimc = dimension();
906                };
907
908                void condition (const vec &val) {
909                        vec mean = elem_mult (refl, pow (val, l));
910                        migamma::condition (mean);
911                };
912
913
914                /*! Create inverse-Gamma density with conditional mean value
915                \f[ f(rv|rvc) = i\Gamma(k, k/(rvc^l \circ ref^{(1-l)}) \f]
916                from structure
917                \code
918                class = 'migamma_ref';
919                ref = [1e-5; 1e-5; 1e-2 1e-3];            // reference vector
920                l = 0.999;                                // constant l
921                k = 0.1;                                  // constant k
922                rv = RV({'name'})                         // description of RV
923                rvc = RV({'name'})                        // description of RV in condition
924                \endcode
925                 */
926                void from_setting (const Setting &set);
927
928                // TODO dodelat void to_setting( Setting &set ) const;
929};
930
931
932UIREGISTER (migamma_ref);
933SHAREDPTR (migamma_ref);
934
935/*! Log-Normal probability density
936 only allow diagonal covariances!
937
938Density of the form \f$ \log(x)\sim \mathcal{N}(\mu,\sigma^2) \f$ , i.e.
939\f[
940x \sim \frac{1}{x\sigma\sqrt{2\pi}}\exp{-\frac{1}{2\sigma^2}(\log(x)-\mu)}
941\f]
942
943Function from_setting loads mu and R in the same way as it does for enorm<>!
944*/
945class elognorm: public enorm<ldmat>
946{
947        public:
948                vec sample() const {return exp (enorm<ldmat>::sample());};
949                vec mean() const {vec var = enorm<ldmat>::variance();return exp (mu - 0.5*var);};
950
951};
952
953/*!
954\brief  Log-Normal random walk
955
956Mean value, \f$\mu\f$, is...
957
958 */
959class mlognorm : public mpdf_internal<elognorm>
960{
961        protected:
962                //! parameter 1/2*sigma^2
963                double sig2;
964
965                //! access
966                vec &mu;
967        public:
968                //! Constructor
969                mlognorm() : mpdf_internal<elognorm>(),
970                                sig2 (0),
971                                mu (iepdf._mu()) {
972                }
973
974                //! Set value of \c k
975                void set_parameters (int size, double k) {
976                        sig2 = 0.5 * log (k * k + 1);
977                        iepdf.set_parameters (zeros (size), 2*sig2*eye (size));
978
979                        dimc = size;
980                };
981
982                void condition (const vec &val) {
983                        mu = log (val) - sig2;//elem_mult ( refl,pow ( val,l ) );
984                };
985
986                /*! Create logNormal random Walk
987                \f[ f(rv|rvc) = log\mathcal{N}( \log(rvc)-0.5\log(k^2+1), k I) \f]
988                from structure
989                \code
990                class = 'mlognorm';
991                k   = 0.1;               // "variance" k
992                mu0 = 0.1;               // Initial value of mean
993                rv  = RV({'name'})       // description of RV
994                rvc = RV({'name'})       // description of RV in condition
995                \endcode
996                */
997                void from_setting (const Setting &set);
998
999                // TODO dodelat void to_setting( Setting &set ) const;
1000
1001};
1002
1003UIREGISTER (mlognorm);
1004SHAREDPTR (mlognorm);
1005
1006/*! inverse Wishart density defined on Choleski decomposition
1007
1008*/
1009class eWishartCh : public epdf
1010{
1011        protected:
1012                //! Upper-Triagle of Choleski decomposition of \f$ \Psi \f$
1013                chmat Y;
1014                //! dimension of matrix  \f$ \Psi \f$
1015                int p;
1016                //! degrees of freedom  \f$ \nu \f$
1017                double delta;
1018        public:
1019                //! Set internal structures
1020                void set_parameters (const mat &Y0, const double delta0) {Y = chmat (Y0);delta = delta0; p = Y.rows(); dim = p * p; }
1021                //! Sample matrix argument
1022                mat sample_mat() const {
1023                        mat X = zeros (p, p);
1024
1025                        //sample diagonal
1026                        for (int i = 0;i < p;i++) {
1027                                GamRNG.setup (0.5* (delta - i) , 0.5);   // no +1 !! index if from 0
1028#pragma omp critical
1029                                X (i, i) = sqrt (GamRNG());
1030                        }
1031                        //do the rest
1032                        for (int i = 0;i < p;i++) {
1033                                for (int j = i + 1;j < p;j++) {
1034#pragma omp critical
1035                                        X (i, j) = NorRNG.sample();
1036                                }
1037                        }
1038                        return X*Y._Ch();// return upper triangular part of the decomposition
1039                }
1040                vec sample () const {
1041                        return vec (sample_mat()._data(), p*p);
1042                }
1043                //! fast access function y0 will be copied into Y.Ch.
1044                void setY (const mat &Ch0) {copy_vector (dim, Ch0._data(), Y._Ch()._data());}
1045                //! fast access function y0 will be copied into Y.Ch.
1046                void _setY (const vec &ch0) {copy_vector (dim, ch0._data(), Y._Ch()._data()); }
1047                //! access function
1048                const chmat& getY() const {return Y;}
1049};
1050
1051//! Inverse Wishart on Choleski decomposition
1052/*! Being computed by conversion from `standard' Wishart
1053*/
1054class eiWishartCh: public epdf
1055{
1056        protected:
1057                //! Internal instance of Wishart density
1058                eWishartCh W;
1059                //! size of Ch
1060                int p;
1061                //! parameter delta
1062                double delta;
1063        public:
1064                //! constructor function
1065                void set_parameters (const mat &Y0, const double delta0) {
1066                        delta = delta0;
1067                        W.set_parameters (inv (Y0), delta0);
1068                        dim = W.dimension(); p = Y0.rows();
1069                }
1070                vec sample() const {mat iCh; iCh = inv (W.sample_mat()); return vec (iCh._data(), dim);}
1071                //! access function
1072                void _setY (const vec &y0) {
1073                        mat Ch (p, p);
1074                        mat iCh (p, p);
1075                        copy_vector (dim, y0._data(), Ch._data());
1076
1077                        iCh = inv (Ch);
1078                        W.setY (iCh);
1079                }
1080                virtual double evallog (const vec &val) const {
1081                        chmat X (p);
1082                        const chmat& Y = W.getY();
1083
1084                        copy_vector (p*p, val._data(), X._Ch()._data());
1085                        chmat iX (p);X.inv (iX);
1086                        // compute
1087//                              \frac{ |\Psi|^{m/2}|X|^{-(m+p+1)/2}e^{-tr(\Psi X^{-1})/2} }{ 2^{mp/2}\Gamma_p(m/2)},
1088                        mat M = Y.to_mat() * iX.to_mat();
1089
1090                        double log1 = 0.5 * p * (2 * Y.logdet()) - 0.5 * (delta + p + 1) * (2 * X.logdet()) - 0.5 * trace (M);
1091                        //Fixme! Multivariate gamma omitted!! it is ok for sampling, but not otherwise!!
1092
1093                        /*                              if (0) {
1094                                                                mat XX=X.to_mat();
1095                                                                mat YY=Y.to_mat();
1096
1097                                                                double log2 = 0.5*p*log(det(YY))-0.5*(delta+p+1)*log(det(XX))-0.5*trace(YY*inv(XX));
1098                                                                cout << log1 << "," << log2 << endl;
1099                                                        }*/
1100                        return log1;
1101                };
1102
1103};
1104
1105//! Random Walk on inverse Wishart
1106class rwiWishartCh : public mpdf_internal<eiWishartCh>
1107{
1108        protected:
1109                //!square root of \f$ \nu-p-1 \f$ - needed for computation of \f$ \Psi \f$ from conditions
1110                double sqd;
1111                //!reference point for diagonal
1112                vec refl;
1113                //! power of the reference
1114                double l;
1115                //! dimension
1116                int p;
1117
1118        public:
1119                rwiWishartCh() : sqd (0), l (0), p (0) {}
1120                //! constructor function
1121                void set_parameters (int p0, double k, vec ref0, double l0) {
1122                        p = p0;
1123                        double delta = 2 / (k * k) + p + 3;
1124                        sqd = sqrt (delta - p - 1);
1125                        l = l0;
1126                        refl = pow (ref0, 1 - l);
1127
1128                        iepdf.set_parameters (eye (p), delta);
1129                        dimc = iepdf.dimension();
1130                }
1131                void condition (const vec &c) {
1132                        vec z = c;
1133                        int ri = 0;
1134                        for (int i = 0;i < p*p;i += (p + 1)) {//trace diagonal element
1135                                z (i) = pow (z (i), l) * refl (ri);
1136                                ri++;
1137                        }
1138
1139                        iepdf._setY (sqd*z);
1140                }
1141};
1142
1143//! Switch between various resampling methods.
1144enum RESAMPLING_METHOD { MULTINOMIAL = 0, STRATIFIED = 1, SYSTEMATIC = 3 };
1145/*!
1146\brief Weighted empirical density
1147
1148Used e.g. in particle filters.
1149*/
1150class eEmp: public epdf
1151{
1152        protected :
1153                //! Number of particles
1154                int n;
1155                //! Sample weights \f$w\f$
1156                vec w;
1157                //! Samples \f$x^{(i)}, i=1..n\f$
1158                Array<vec> samples;
1159        public:
1160                //! \name Constructors
1161                //!@{
1162                eEmp () : epdf (), w (), samples () {};
1163                //! copy constructor
1164                eEmp (const eEmp &e) : epdf (e), w (e.w), samples (e.samples) {};
1165                //!@}
1166
1167                //! Set samples and weights
1168                void set_statistics (const vec &w0, const epdf &pdf0);
1169                //! Set samples and weights
1170                void set_statistics (const epdf &pdf0 , int n) {set_statistics (ones (n) / n, pdf0);};
1171                //! Set sample
1172                void set_samples (const epdf* pdf0);
1173                //! Set sample
1174                void set_parameters (int n0, bool copy = true) {n = n0; w.set_size (n0, copy);samples.set_size (n0, copy);};
1175                //! Set samples
1176                void set_parameters (const Array<vec> &Av) {
1177                        bdm_assert(Av.size()>0,"Empty samples"); 
1178                        n = Av.size(); 
1179                        epdf::set_parameters(Av(0).length());
1180                        w=1/n*ones(n);
1181                        samples=Av;
1182                };
1183                //! Potentially dangerous, use with care.
1184                vec& _w()  {return w;};
1185                //! Potentially dangerous, use with care.
1186                const vec& _w() const {return w;};
1187                //! access function
1188                Array<vec>& _samples() {return samples;};
1189                //! access function
1190                const Array<vec>& _samples() const {return samples;};
1191                //! Function performs resampling, i.e. removal of low-weight samples and duplication of high-weight samples such that the new samples represent the same density.
1192                ivec resample (RESAMPLING_METHOD method = SYSTEMATIC);
1193
1194                //! inherited operation : NOT implemented
1195                vec sample() const {
1196                        bdm_error ("Not implemented");
1197                        return vec();
1198                }
1199
1200                //! inherited operation : NOT implemented
1201                double evallog (const vec &val) const {
1202                        bdm_error ("Not implemented");
1203                        return 0.0;
1204                }
1205
1206                vec mean() const {
1207                        vec pom = zeros (dim);
1208                        for (int i = 0;i < n;i++) {pom += samples (i) * w (i);}
1209                        return pom;
1210                }
1211                vec variance() const {
1212                        vec pom = zeros (dim);
1213                        for (int i = 0;i < n;i++) {pom += pow (samples (i), 2) * w (i);}
1214                        return pom -pow (mean(), 2);
1215                }
1216                //! For this class, qbounds are minimum and maximum value of the population!
1217                void qbounds (vec &lb, vec &ub, double perc = 0.95) const {
1218                        // lb in inf so than it will be pushed below;
1219                        lb.set_size (dim);
1220                        ub.set_size (dim);
1221                        lb = std::numeric_limits<double>::infinity();
1222                        ub = -std::numeric_limits<double>::infinity();
1223                        int j;
1224                        for (int i = 0;i < n;i++) {
1225                                for (j = 0;j < dim; j++) {
1226                                        if (samples (i) (j) < lb (j)) {lb (j) = samples (i) (j);}
1227                                        if (samples (i) (j) > ub (j)) {ub (j) = samples (i) (j);}
1228                                }
1229                        }
1230                }
1231};
1232
1233
1234////////////////////////
1235
1236template<class sq_T>
1237void enorm<sq_T>::set_parameters (const vec &mu0, const sq_T &R0)
1238{
1239//Fixme test dimensions of mu0 and R0;
1240        mu = mu0;
1241        R = R0;
1242        validate();
1243};
1244
1245template<class sq_T>
1246void enorm<sq_T>::from_setting (const Setting &set)
1247{
1248        epdf::from_setting (set); //reads rv
1249
1250        UI::get (mu, set, "mu", UI::compulsory);
1251        mat Rtmp;// necessary for conversion
1252        UI::get (Rtmp, set, "R", UI::compulsory);
1253        R = Rtmp; // conversion
1254        validate();
1255}
1256
1257template<class sq_T>
1258void enorm<sq_T>::dupdate (mat &v, double nu)
1259{
1260        //
1261};
1262
1263// template<class sq_T>
1264// void enorm<sq_T>::tupdate ( double phi, mat &vbar, double nubar ) {
1265//      //
1266// };
1267
1268template<class sq_T>
1269vec enorm<sq_T>::sample() const
1270{
1271        vec x (dim);
1272#pragma omp critical
1273        NorRNG.sample_vector (dim, x);
1274        vec smp = R.sqrt_mult (x);
1275
1276        smp += mu;
1277        return smp;
1278};
1279
1280// template<class sq_T>
1281// double enorm<sq_T>::eval ( const vec &val ) const {
1282//      double pdfl,e;
1283//      pdfl = evallog ( val );
1284//      e = exp ( pdfl );
1285//      return e;
1286// };
1287
1288template<class sq_T>
1289double enorm<sq_T>::evallog_nn (const vec &val) const
1290{
1291        // 1.83787706640935 = log(2pi)
1292        double tmp = -0.5 * (R.invqform (mu - val));// - lognc();
1293        return  tmp;
1294};
1295
1296template<class sq_T>
1297inline double enorm<sq_T>::lognc () const
1298{
1299        // 1.83787706640935 = log(2pi)
1300        double tmp = 0.5 * (R.cols() * 1.83787706640935 + R.logdet());
1301        return tmp;
1302};
1303
1304
1305// template<class sq_T>
1306// vec mlnorm<sq_T>::samplecond (const  vec &cond, double &lik ) {
1307//      this->condition ( cond );
1308//      vec smp = epdf.sample();
1309//      lik = epdf.eval ( smp );
1310//      return smp;
1311// }
1312
1313// template<class sq_T>
1314// mat mlnorm<sq_T>::samplecond (const vec &cond, vec &lik, int n ) {
1315//      int i;
1316//      int dim = rv.count();
1317//      mat Smp ( dim,n );
1318//      vec smp ( dim );
1319//      this->condition ( cond );
1320//
1321//      for ( i=0; i<n; i++ ) {
1322//              smp = epdf.sample();
1323//              lik ( i ) = epdf.eval ( smp );
1324//              Smp.set_col ( i ,smp );
1325//      }
1326//
1327//      return Smp;
1328// }
1329
1330
1331template<class sq_T>
1332shared_ptr<epdf> enorm<sq_T>::marginal ( const RV &rvn ) const
1333{
1334        enorm<sq_T> *tmp = new enorm<sq_T> ();
1335        shared_ptr<epdf> narrow(tmp);
1336        marginal ( rvn, *tmp );
1337        return narrow;
1338}
1339
1340template<class sq_T>
1341void enorm<sq_T>::marginal ( const RV &rvn, enorm<sq_T> &target ) const
1342{
1343        bdm_assert (isnamed(), "rv description is not assigned");
1344        ivec irvn = rvn.dataind (rv);
1345
1346        sq_T Rn (R, irvn);  // select rows and columns of R
1347
1348        target.set_rv ( rvn );
1349        target.set_parameters (mu (irvn), Rn);
1350}
1351
1352template<class sq_T>
1353shared_ptr<mpdf> enorm<sq_T>::condition ( const RV &rvn ) const
1354{
1355        mlnorm<sq_T> *tmp = new mlnorm<sq_T> ();
1356        shared_ptr<mpdf> narrow(tmp);
1357        condition ( rvn, *tmp );
1358        return narrow;
1359}
1360
1361template<class sq_T>
1362void enorm<sq_T>::condition ( const RV &rvn, mpdf &target ) const
1363{
1364        typedef mlnorm<sq_T> TMlnorm;
1365
1366        bdm_assert (isnamed(), "rvs are not assigned");
1367        TMlnorm &uptarget = dynamic_cast<TMlnorm &>(target);
1368
1369        RV rvc = rv.subt (rvn);
1370        bdm_assert ( (rvc._dsize() + rvn._dsize() == rv._dsize()), "wrong rvn");
1371        //Permutation vector of the new R
1372        ivec irvn = rvn.dataind (rv);
1373        ivec irvc = rvc.dataind (rv);
1374        ivec perm = concat (irvn , irvc);
1375        sq_T Rn (R, perm);
1376
1377        //fixme - could this be done in general for all sq_T?
1378        mat S = Rn.to_mat();
1379        //fixme
1380        int n = rvn._dsize() - 1;
1381        int end = R.rows() - 1;
1382        mat S11 = S.get (0, n, 0, n);
1383        mat S12 = S.get (0, n , rvn._dsize(), end);
1384        mat S22 = S.get (rvn._dsize(), end, rvn._dsize(), end);
1385
1386        vec mu1 = mu (irvn);
1387        vec mu2 = mu (irvc);
1388        mat A = S12 * inv (S22);
1389        sq_T R_n (S11 - A *S12.T());
1390
1391        uptarget.set_rv (rvn);
1392        uptarget.set_rvc (rvc);
1393        uptarget.set_parameters (A, mu1 - A*mu2, R_n);
1394}
1395
1396////
1397///////
1398template<class sq_T>
1399void mgnorm<sq_T >::set_parameters (const shared_ptr<fnc> &g0, const sq_T &R0) {
1400        g = g0;
1401        this->iepdf.set_parameters (zeros (g->dimension()), R0);
1402}
1403
1404template<class sq_T>
1405void mgnorm<sq_T >::condition (const vec &cond) {this->iepdf._mu() = g->eval (cond);};
1406
1407//! \todo unify this stuff with to_string()
1408template<class sq_T>
1409std::ostream &operator<< (std::ostream &os,  mlnorm<sq_T> &ml)
1410{
1411        os << "A:" << ml.A << endl;
1412        os << "mu:" << ml.mu_const << endl;
1413        os << "R:" << ml._R() << endl;
1414        return os;
1415};
1416
1417}
1418#endif //EF_H
Note: See TracBrowser for help on using the browser.