// @(#)root/roostats:$Id$
// Authors: Kevin Belasco        17/06/2009
// Authors: Kyle Cranmer         17/06/2009
/*************************************************************************
 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//_________________________________________________
/*
BEGIN_HTML
<p>
PdfProposal is a concrete implementation of the ProposalFunction interface.
It proposes points across the parameter space in the distribution of the
given PDF.
</p>
<p>
To make Propose(xPrime, x) dependent on x, configure with
PdfProposal::AddMapping(varToUpdate, valueToUse).  For example, suppose we have:
</p>

<p>
// our parameter
RooRealVar p("p", "p", 5, 0, 10);

// create mean and sigma for gaussian proposal function
RooRealVar meanP("meanP", "meanP", 0, 10);
RooRealVar sigma("sigma", "sigma", 1, 0, 5);
RooGaussian pGaussian("pGaussian", "pGaussian", p, meanP, sigma);

// configure proposal function
PdfProposal pdfProposal(pGaussian);
pdfProposal.AddMapping(meanP, p); // each call of Propose(xPrime, x), meanP in
                                  // the proposal function will be updated to
                                  // the value of p in x.  this will center the
                                  // proposal function about x's p when
                                  // proposing for xPrime

// To improve performance, PdfProposal has the ability to cache a specified
// number of proposals. If you don't call this function, the default cache size
// is 1, which can be slow.
pdfProposal.SetCacheSize(desiredCacheSize);
</p>

<p>
PdfProposal currently uses a fixed cache size. Adaptive caching methods are in the works
for future versions.
</p>

END_HTML
*/
//_________________________________________________

#ifndef ROOT_Rtypes
#include "Rtypes.h"
#endif

#ifndef ROOSTATS_PdfProposal
#include "RooStats/PdfProposal.h"
#endif
#ifndef RooStats_RooStatsUtils
#include "RooStats/RooStatsUtils.h"
#endif
#ifndef ROO_ARG_SET
#include "RooArgSet.h"
#endif
#ifndef ROO_DATA_SET
#include "RooDataSet.h"
#endif
#ifndef ROO_ABS_PDF
#include "RooAbsPdf.h"
#endif
#ifndef ROO_MSG_SERVICE
#include "RooMsgService.h"
#endif
#ifndef ROO_REAL_VAR
#include "RooRealVar.h"
#endif
#ifndef ROOT_TIterator
#include "TIterator.h"
#endif

#include <map>

ClassImp(RooStats::PdfProposal);

using namespace RooFit;
using namespace RooStats;
using namespace std;

// By default, PdfProposal does NOT own the PDF that serves as the
// proposal density function
PdfProposal::PdfProposal() : ProposalFunction()
{
   fPdf = NULL;
   fOwnsPdf = kFALSE;
   fCacheSize = 1;
   fCachePosition = 0;
   fCache = NULL;
}

// By default, PdfProposal does NOT own the PDF that serves as the
// proposal density function
PdfProposal::PdfProposal(RooAbsPdf& pdf) : ProposalFunction()
{
   fPdf = &pdf;
   fOwnsPdf = kFALSE;
   fCacheSize = 1;
   fCachePosition = 0;
   fCache = NULL;
}

Bool_t PdfProposal::Equals(RooArgSet& x1, RooArgSet& x2)
{
   if (x1.equals(x2)) {
      TIterator* it = x1.createIterator();
      RooRealVar* r;
      while ((r = (RooRealVar*)it->Next()) != NULL)
         if (r->getVal() != x2.getRealValue(r->GetName())) {
            delete it;
            return kFALSE;
         }
      delete it;
      return kTRUE;
   }
   return kFALSE;
}

// Populate xPrime with a new proposed point
void PdfProposal::Propose(RooArgSet& xPrime, RooArgSet& x)
{
   if (fLastX.getSize() == 0) {
      // fLastX not yet initialized
      fLastX.addClone(x);
      // generate initial cache
      RooStats::SetParameters(&x, &fMaster);
      if (fMap.size() > 0) {
         for (fIt = fMap.begin(); fIt != fMap.end(); fIt++)
            fIt->first->setVal(fIt->second->getVal(&x));
      }
      fCache = fPdf->generate(xPrime, fCacheSize);
   }

   Bool_t moved = false;
   if (fMap.size() > 0) {
      moved = !Equals(fLastX, x);

      // if we've moved, set the values of the variables in the PDF to the
      // corresponding values of the variables in x, according to the
      // mappings (i.e. let the variables in x set the given values for the
      // PDF that will generate xPrime)
      if (moved) {
         // update the pdf parameters
         RooStats::SetParameters(&x, &fMaster);

         for (fIt = fMap.begin(); fIt != fMap.end(); fIt++)
            fIt->first->setVal(fIt->second->getVal(&x));

         // save the new x in fLastX
         RooStats::SetParameters(&x, &fLastX);
      }
   }

   // generate new cache if necessary
   if (moved || fCachePosition >= fCacheSize) {
      delete fCache;
      fCache = fPdf->generate(xPrime, fCacheSize);
      fCachePosition = 0;
   }

   const RooArgSet* proposal = fCache->get(fCachePosition);
   fCachePosition++;
   RooStats::SetParameters(proposal, &xPrime);
}

// Determine whether or not the proposal density is symmetric for
// points x1 and x2 - that is, whether the probabilty of reaching x2
// from x1 is equal to the probability of reaching x1 from x2
Bool_t PdfProposal::IsSymmetric(RooArgSet& /* x1 */, RooArgSet& /* x2 */)
{
   // kbelasco: is there a better way to do this?
   return false;
}

// Return the probability of proposing the point x1 given the starting
// point x2
Double_t PdfProposal::GetProposalDensity(RooArgSet& x1, RooArgSet& x2)
{
   RooStats::SetParameters(&x2, &fMaster);
   for (fIt = fMap.begin(); fIt != fMap.end(); fIt++)
      fIt->first->setVal(fIt->second->getVal(&x2));
   RooArgSet* temp = fPdf->getObservables(x1);
   RooStats::SetParameters(&x1, temp);
   delete temp;
   return fPdf->getVal(&x1); // could just as well use x2
}

void PdfProposal::AddMapping(RooRealVar& proposalParam, RooAbsReal& update)
{
   fMaster.add(*update.getParameters((RooAbsData*)NULL));
   if (update.getParameters((RooAbsData*)NULL)->getSize() == 0)
      fMaster.add(update);
   fMap.insert(pair<RooRealVar*, RooAbsReal*>(&proposalParam, &update));
}
 PdfProposal.cxx:1
 PdfProposal.cxx:2
 PdfProposal.cxx:3
 PdfProposal.cxx:4
 PdfProposal.cxx:5
 PdfProposal.cxx:6
 PdfProposal.cxx:7
 PdfProposal.cxx:8
 PdfProposal.cxx:9
 PdfProposal.cxx:10
 PdfProposal.cxx:11
 PdfProposal.cxx:12
 PdfProposal.cxx:13
 PdfProposal.cxx:14
 PdfProposal.cxx:15
 PdfProposal.cxx:16
 PdfProposal.cxx:17
 PdfProposal.cxx:18
 PdfProposal.cxx:19
 PdfProposal.cxx:20
 PdfProposal.cxx:21
 PdfProposal.cxx:22
 PdfProposal.cxx:23
 PdfProposal.cxx:24
 PdfProposal.cxx:25
 PdfProposal.cxx:26
 PdfProposal.cxx:27
 PdfProposal.cxx:28
 PdfProposal.cxx:29
 PdfProposal.cxx:30
 PdfProposal.cxx:31
 PdfProposal.cxx:32
 PdfProposal.cxx:33
 PdfProposal.cxx:34
 PdfProposal.cxx:35
 PdfProposal.cxx:36
 PdfProposal.cxx:37
 PdfProposal.cxx:38
 PdfProposal.cxx:39
 PdfProposal.cxx:40
 PdfProposal.cxx:41
 PdfProposal.cxx:42
 PdfProposal.cxx:43
 PdfProposal.cxx:44
 PdfProposal.cxx:45
 PdfProposal.cxx:46
 PdfProposal.cxx:47
 PdfProposal.cxx:48
 PdfProposal.cxx:49
 PdfProposal.cxx:50
 PdfProposal.cxx:51
 PdfProposal.cxx:52
 PdfProposal.cxx:53
 PdfProposal.cxx:54
 PdfProposal.cxx:55
 PdfProposal.cxx:56
 PdfProposal.cxx:57
 PdfProposal.cxx:58
 PdfProposal.cxx:59
 PdfProposal.cxx:60
 PdfProposal.cxx:61
 PdfProposal.cxx:62
 PdfProposal.cxx:63
 PdfProposal.cxx:64
 PdfProposal.cxx:65
 PdfProposal.cxx:66
 PdfProposal.cxx:67
 PdfProposal.cxx:68
 PdfProposal.cxx:69
 PdfProposal.cxx:70
 PdfProposal.cxx:71
 PdfProposal.cxx:72
 PdfProposal.cxx:73
 PdfProposal.cxx:74
 PdfProposal.cxx:75
 PdfProposal.cxx:76
 PdfProposal.cxx:77
 PdfProposal.cxx:78
 PdfProposal.cxx:79
 PdfProposal.cxx:80
 PdfProposal.cxx:81
 PdfProposal.cxx:82
 PdfProposal.cxx:83
 PdfProposal.cxx:84
 PdfProposal.cxx:85
 PdfProposal.cxx:86
 PdfProposal.cxx:87
 PdfProposal.cxx:88
 PdfProposal.cxx:89
 PdfProposal.cxx:90
 PdfProposal.cxx:91
 PdfProposal.cxx:92
 PdfProposal.cxx:93
 PdfProposal.cxx:94
 PdfProposal.cxx:95
 PdfProposal.cxx:96
 PdfProposal.cxx:97
 PdfProposal.cxx:98
 PdfProposal.cxx:99
 PdfProposal.cxx:100
 PdfProposal.cxx:101
 PdfProposal.cxx:102
 PdfProposal.cxx:103
 PdfProposal.cxx:104
 PdfProposal.cxx:105
 PdfProposal.cxx:106
 PdfProposal.cxx:107
 PdfProposal.cxx:108
 PdfProposal.cxx:109
 PdfProposal.cxx:110
 PdfProposal.cxx:111
 PdfProposal.cxx:112
 PdfProposal.cxx:113
 PdfProposal.cxx:114
 PdfProposal.cxx:115
 PdfProposal.cxx:116
 PdfProposal.cxx:117
 PdfProposal.cxx:118
 PdfProposal.cxx:119
 PdfProposal.cxx:120
 PdfProposal.cxx:121
 PdfProposal.cxx:122
 PdfProposal.cxx:123
 PdfProposal.cxx:124
 PdfProposal.cxx:125
 PdfProposal.cxx:126
 PdfProposal.cxx:127
 PdfProposal.cxx:128
 PdfProposal.cxx:129
 PdfProposal.cxx:130
 PdfProposal.cxx:131
 PdfProposal.cxx:132
 PdfProposal.cxx:133
 PdfProposal.cxx:134
 PdfProposal.cxx:135
 PdfProposal.cxx:136
 PdfProposal.cxx:137
 PdfProposal.cxx:138
 PdfProposal.cxx:139
 PdfProposal.cxx:140
 PdfProposal.cxx:141
 PdfProposal.cxx:142
 PdfProposal.cxx:143
 PdfProposal.cxx:144
 PdfProposal.cxx:145
 PdfProposal.cxx:146
 PdfProposal.cxx:147
 PdfProposal.cxx:148
 PdfProposal.cxx:149
 PdfProposal.cxx:150
 PdfProposal.cxx:151
 PdfProposal.cxx:152
 PdfProposal.cxx:153
 PdfProposal.cxx:154
 PdfProposal.cxx:155
 PdfProposal.cxx:156
 PdfProposal.cxx:157
 PdfProposal.cxx:158
 PdfProposal.cxx:159
 PdfProposal.cxx:160
 PdfProposal.cxx:161
 PdfProposal.cxx:162
 PdfProposal.cxx:163
 PdfProposal.cxx:164
 PdfProposal.cxx:165
 PdfProposal.cxx:166
 PdfProposal.cxx:167
 PdfProposal.cxx:168
 PdfProposal.cxx:169
 PdfProposal.cxx:170
 PdfProposal.cxx:171
 PdfProposal.cxx:172
 PdfProposal.cxx:173
 PdfProposal.cxx:174
 PdfProposal.cxx:175
 PdfProposal.cxx:176
 PdfProposal.cxx:177
 PdfProposal.cxx:178
 PdfProposal.cxx:179
 PdfProposal.cxx:180
 PdfProposal.cxx:181
 PdfProposal.cxx:182
 PdfProposal.cxx:183
 PdfProposal.cxx:184
 PdfProposal.cxx:185
 PdfProposal.cxx:186
 PdfProposal.cxx:187
 PdfProposal.cxx:188
 PdfProposal.cxx:189
 PdfProposal.cxx:190
 PdfProposal.cxx:191
 PdfProposal.cxx:192
 PdfProposal.cxx:193
 PdfProposal.cxx:194
 PdfProposal.cxx:195
 PdfProposal.cxx:196
 PdfProposal.cxx:197
 PdfProposal.cxx:198
 PdfProposal.cxx:199
 PdfProposal.cxx:200
 PdfProposal.cxx:201
 PdfProposal.cxx:202
 PdfProposal.cxx:203
 PdfProposal.cxx:204
 PdfProposal.cxx:205
 PdfProposal.cxx:206
 PdfProposal.cxx:207