root/library/bdm/stat/merger.h @ 1077

Revision 1072, 9.9 kB (checked in by smidl, 14 years ago)

new merger

  • Property svn:eol-style set to native
Line 
1/*!
2  \file
3  \brief Mergers for combination of pdfs
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 MERGER_H
14#define MERGER_H
15
16
17#include "../estim/mixtures.h"
18#include "discrete.h"
19
20namespace bdm {
21using std::string;
22
23//!Merging methods
24enum MERGER_METHOD {ARITHMETIC = 1, GEOMETRIC = 2, LOGNORMAL = 3};
25
26/*!  Abstract common class for mergers
27
28It defines only common interface of access to sources and operation merge(); The result of merging is available via function epdf()
29*/
30class MergerBase: public root{
31        public:         
32                //! weights of the sources -- no restrictions
33                vec w;
34                //! get ith source
35                Array<shared_ptr<epdf> > sources;
36                //! merge
37                void merge() NOT_IMPLEMENTED_VOID;
38                //!
39                //! check if all epdfs are on the same support
40                void validate() {
41                        int n=sources.length();
42                       
43                        bdm_assert(n>0,"merger has no sources to merge");
44                        // check if weights are ok
45                        if (w.length()!=n) {
46                                w = ones(n)/n;
47                        }
48                       
49                        // check compatibility of sources -- no types are needed
50                        int dim0 = sources(0)->dimension();
51                        for (int i=0; i<n; i++){
52                                bdm_assert(sources(i)->dimension()==dim0, "Merger: Incompatible dimensions of sources");
53                                if (sources(i)->isnamed()){
54                                        //check if rv match
55                                }
56                        }
57                }
58                //! return the result of merging
59                virtual const epdf& merger()=0;
60};
61
62//! Merger into normal density, max entropy approximator for 2 moments (mean+variance)
63template<class sq_T>
64class ENormMerger: public MergerBase{
65        protected:
66                //!internal epdf
67                enorm<sq_T> iepdf;
68        public:
69                ENormMerger():method(GEOMETRIC){};
70                MERGER_METHOD method;
71                void merge(){
72                        int n = sources.length();
73                        int dim = sources(0)->dimension();
74                        sq_T Var(zeros(dim));
75                        vec mea=zeros(dim);
76                        // go through all sources
77                        for (int i=0; i<n; i++){
78                                sq_T Ci = sources(i)->covariance();
79                                sq_T wCi = Ci; wCi*=w(i);
80                                vec mi = sources(i)->mean();
81                                switch (method) {
82                                        case ARITHMETIC:{
83                                                Var += wCi;
84                                                Var.opupdt(mi,w(i)); // + mean * mean'
85                                                mea += w(i)*mi;
86                                                break;
87                                        }
88                                        case GEOMETRIC:{
89                                                Var += wCi;
90                                                sq_T iCi;
91                                                Ci.inv(iCi);
92                                                mea += iCi.to_mat()*w(i)*mi;
93                                                break;
94                                        }
95                                        default:
96                                                bdm_error("Method not implemneted");
97                                }
98                        }
99                        // post pocessing
100                        switch (method) {
101                                case ARITHMETIC:
102                                        iepdf._R()=Var;
103                                        iepdf._R().opupdt(mea,-1.0); // Var - mean * mean'
104                                        iepdf._mu()=mea;
105                                        break;
106                                case GEOMETRIC:
107                                        iepdf._R()=Var;
108                                        iepdf._mu() = Var.to_mat()*mea; // mean=sqrt(Var)*mea
109                                        break;
110                                default:
111                                        bdm_error("Method not implemneted");
112                        }
113                }
114                //! access function
115                const epdf& merger(){return iepdf;}
116};
117
118/*!
119@brief Base class (interface) for for general combination of pdfs on discrete support
120
121Mixtures of Gaussian densities are used internally. Switching to other densities should be trivial.
122
123The merged pdfs are expected to be of the form:
124 \f[ f(x_i|y_i),  i=1..n \f]
125where the resulting merger is a density on \f$ \cup [x_i,y_i] \f$ .
126Note that all variables will be joined.
127
128As a result of this feature, each source must be extended to common support
129\f[ f(z_i|y_i,x_i) f(x_i|y_i) f(y_i)  i=1..n \f]
130where \f$ z_i \f$ accumulate variables that were not in the original source.
131These extensions are calculated on-the-fly.
132
133However, these operations can not be performed in general. Hence, this class merges only sources on common support, \f$ y_i={}, z_i={}, \forall i \f$.
134For merging of more general cases, use offsprings merger_mix and merger_grid.
135*/
136class merger_base : public epdf {
137protected:
138    //! Elements of composition
139    Array<shared_ptr<pdf> > pdfs;
140
141    //! Data link for each pdf in pdfs
142    Array<datalink_m2e*> dls;
143
144    //! Array of rvs that are not modelled by pdfs at all, \f$ z_i \f$
145    Array<RV> rvzs;
146
147    //! Data Links for extension \f$ f(z_i|x_i,y_i) \f$
148    Array<datalink_m2e*> zdls;
149
150    //! number of support points
151    int Npoints;
152
153    //! number of sources
154    int Nsources;
155
156    //! switch of the methoh used for merging
157    MERGER_METHOD METHOD;
158    //! Default for METHOD
159    static const MERGER_METHOD DFLT_METHOD;
160
161    //!Prior on the log-normal merging model
162    double beta;
163    //! default for beta
164    static const double DFLT_beta;
165
166    //! Projection to empirical density (could also be piece-wise linear)
167    eEmp eSmp;
168
169    //! debug or not debug
170    bool DBG;
171
172    //! debugging file
173    it_file* dbg_file;
174public:
175    //! \name Constructors
176    //! @{
177
178    //! Default constructor
179    merger_base () : Npoints ( 0 ), Nsources ( 0 ), DBG ( false ), dbg_file ( 0 ) {
180    }
181
182    //!Constructor from sources
183    merger_base ( const Array<shared_ptr<pdf> > &S );
184
185    //! Function setting the main internal structures
186    void set_sources ( const Array<shared_ptr<pdf> > &Sources );
187
188    //! Set support points from rectangular grid
189    void set_support ( rectangular_support &Sup );
190
191    //! Set support points from dicrete grid
192    void set_support ( discrete_support &Sup ) {
193        Npoints = Sup.points();
194        eSmp.set_parameters ( Sup._Spoints() );
195        eSmp.validate();
196    }
197
198
199    //! set debug file
200    void set_debug_file ( const string fname ) {
201        if ( DBG ) delete dbg_file;
202        dbg_file = new it_file ( fname );
203        DBG = ( dbg_file != 0 );
204    }
205
206    //! Set internal parameters used in approximation
207    void set_method ( MERGER_METHOD MTH = DFLT_METHOD, double beta0 = DFLT_beta ) {
208        METHOD = MTH;
209        beta = beta0;
210    }
211    //! Set support points from a pdf by drawing N samples
212    void set_support ( const epdf &overall, int N ) {
213        eSmp.set_statistics ( overall, N );
214        Npoints = N;
215    }
216
217    //! Destructor
218    virtual ~merger_base() {
219        for ( int i = 0; i < Nsources; i++ ) {
220            delete dls ( i );
221            delete zdls ( i );
222        }
223        if ( DBG ) delete dbg_file;
224    };
225    //!@}
226
227    //! \name Mathematical operations
228    //!@{
229
230    //!Merge given sources in given points
231    virtual void merge ();
232
233    //! Merge log-likelihood values in points using method specified by parameter METHOD
234    vec merge_points ( mat &lW );
235
236
237    //! sample from merged density
238//! weight w is a
239    vec mean() const;
240
241    mat covariance() const;
242
243    vec variance() const;
244
245    //! Compute log-probability of argument \c val
246    virtual double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);
247
248    //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
249    virtual vec sample() const NOT_IMPLEMENTED(0);
250
251    //!@}
252
253    //! \name Access to attributes
254    //! @{
255
256    //! Access function
257    eEmp& _Smp() {
258        return eSmp;
259    }
260
261    /*! Create object from the following structure
262
263    \code
264    class = 'merger_base';
265    method = 'arithmetic' or 'geometric' or 'lognormal';   % name of the model used for merging
266    --- compulsory only for lognormal merging model ---
267    beta = x;                                              % scalar prior on the log-normal merging model
268    --- optional fields ---
269    dbg_file = '...';                                      % name of the file to store debug informations
270    --- inherited fields ---
271    bdm::epdf::from_setting
272    \endcode
273    */
274    void from_setting ( const Setting& set );
275
276    void to_setting  (Setting  &set) const ;
277
278    void validate() ;
279    //!@}
280};
281UIREGISTER ( merger_base );
282SHAREDPTR ( merger_base );
283
284//! \brief Merger using importance sampling with mixture proposal density
285class merger_mix : public merger_base {
286protected:
287    //!Internal mixture of EF models
288    MixEF Mix;
289    //!Number of components in a mixture
290    int Ncoms;
291    //! coefficient of resampling [0,1]
292    double effss_coef;
293    //! stop after niter iterations
294    int stop_niter;
295
296    //! default value for Ncoms
297    static const int DFLT_Ncoms;
298    //! default value for efss_coef;
299    static const double DFLT_effss_coef;
300
301public:
302    //!\name Constructors
303    //!@{
304    merger_mix () : Ncoms ( 0 ), effss_coef ( 0 ), stop_niter ( 0 ) { }
305
306    merger_mix ( const Array<shared_ptr<pdf> > &S ) :
307        Ncoms ( 0 ), effss_coef ( 0 ), stop_niter ( 0 ) {
308        set_sources ( S );
309    }
310
311    //! Set sources and prepare all internal structures
312    void set_sources ( const Array<shared_ptr<pdf> > &S ) {
313        merger_base::set_sources ( S );
314        //Nsources = S.length();
315    }
316
317    //! Set internal parameters used in approximation
318    void set_parameters ( int Ncoms0 = DFLT_Ncoms, double effss_coef0 = DFLT_effss_coef ) {
319        Ncoms = Ncoms0;
320        effss_coef = effss_coef0;
321    }
322    //!@}
323
324    //! \name Mathematical operations
325    //!@{
326
327    //!Merge values using mixture approximation
328    void merge ();
329
330    //! sample from the approximating mixture
331    vec sample () const {
332        return Mix.posterior().sample();
333    }
334    //! loglikelihood computed on mixture models
335    double evallog ( const vec &yt ) const {
336        vec dtf = ones ( yt.length() + 1 );
337        dtf.set_subvector ( 0, yt );
338        return Mix.logpred ( dtf, vec(0) );
339    }
340    //!@}
341
342    //!\name Access functions
343    //!@{
344//! Access function
345    MixEF& _Mix() {
346        return Mix;
347    }
348    //! Access function
349    emix* proposal() {
350        emix* tmp = Mix.epredictor();
351        tmp->set_rv ( rv );
352        return tmp;
353    }
354    /*! Create object from the following structure
355
356    \code
357    class = 'merger_mix';
358    --- optional fields ---
359    ncoms = [];        % number of components in a mixture
360    effss_coef = [];   % coefficient of resampling from interval [0,1]
361    stop_niter = [];   % number of interations
362    --- inherited fields ---
363    bdm::merger_base::from_setting
364    \endcode   
365    If the optional fields are not given, they will be filled as follows:
366    \code
367    ncoms = 10;       
368    effss_coef = 0.9; 
369    stop_niter = 10; 
370    \endcode
371
372    */
373    void from_setting ( const Setting& set );
374
375    void to_setting  (Setting  &set) const;
376    void validate();
377
378    //! @}
379};
380UIREGISTER ( merger_mix );
381SHAREDPTR ( merger_mix );
382
383}
384
385#endif // MER_H
Note: See TracBrowser for help on using the browser.