MultipleImportanceSampler.h
Go to the documentation of this file.00001 /**<!--------------------------------------------------------------------> 00002 @class MultipleImportanceSampler 00003 @author Travis Fischer (fisch0920@gmail.com) 00004 @author Matthew Jacobs (jacobs.mh@gmail.com) 00005 @date Fall 2008 00006 00007 @brief 00008 "Optimally" combines samples taken from multiple sampling distributions 00009 with respect to a function, 'f', whose value we are trying to integate 00010 over a given domain,'D'. D is assumed to be the union of the domains of 00011 the individual underlying distributions. 00012 00013 The goal of importance sampling is to reduce variance while 00014 approximating the integral of f over D by drawing random samples across D 00015 according to some probability density function p which is proportional to 00016 f. By drawing more samples from the regions where f is large (concentrating 00017 our sampling effort on the "important" regions of the domain), and similarly 00018 drawing less samples from the regions where f is small (focusing less effort 00019 in the "unimportant" regions of the domain), the variance of our estimate 00020 overall is reduced, as long as we compensate for our uneven sampling rate 00021 by weighting each sample by the inverse probability with which it was 00022 sampled. 00023 Think of importance sampling this way: if we have only one shot at 00024 sampling f (only one sample because of very limited 'resources'), we would 00025 like to concentrate that one sample in the region of the domain that will 00026 contribute the most to the value of the integral we are ultimately trying 00027 to approximate. By biasing our sampling technique to weigh "important", 00028 "large" regions of the domain with respect to f, we get more bang for our 00029 buck and correspondingly end up with a much lower variance estimator. If 00030 we were to instead naively sample uniformly across the domain, D, there's 00031 a good chance that our one, precious sample would be wasted by sampling 00032 a location, x, that is unimportant, where f(x) is relatively small. 00033 A perfect estimator would take samples from a distribution p, across D, 00034 whose probabilities were distributed directly proportional to f. This is, 00035 however, unreasonable, since if we knew the exact values of f across D, 00036 we wouldn't have to approximate the integral of f over D in the first place. 00037 We can, however, still greatly reduce variance by using knowledge about 00038 f to guide our sampling process and instead, sample according to either 00039 an approximation of f, or possibly according to some factorization of f 00040 into separate functions f1, f2, etc, some of which may be easier to draw 00041 samples from. As long as our sampling process attempts to draw samples 00042 from areas in D where f is "known" to be large and avoids regions in D 00043 where f is "known" to be small, our sampler will be more efficient and 00044 our overall variance will be reduced. 00045 00046 Multiple importance sampling generalizes this one step further. Say 00047 we have n different sampling distributions p1,p2,...,pn, and our function 00048 f, may be separated or factored into several functions, f1,f2,...fm. By 00049 designing different sampling distributions to focus on one or more of the 00050 simpler functions, fi, we can combine samples from the different sampling 00051 distributions, each of which may be better at estimating some important 00052 component (subfunction) of f, we can gain a much better final sampling 00053 distribution, p, which captures all of the relevant aspects of f in an 00054 intuitive, modularized manner (where each pi can be tuned towards 00055 capturing a different fi). How to go about combining samples from n 00056 distributions, all or some of which may be good or bad estimators of f, 00057 is a very difficult problem in this generic of a setting. 00058 Veach and Guibas (1995) showed several provably good ways of optimally 00059 combining sampling techniques for Monte Carlo integration. This class 00060 implements their multiple importance sampling model, including several 00061 heuristics they gave which attempt to combine samples in slightly 00062 different ways that may work better in one situation versus another. 00063 These include the balance, cutoff, power, and maximum heuristics. 00064 00065 @note for more information and theoretical details, see 00066 Veach and Guibas. Optimally Combining Sampling Techniques for Monte 00067 Carlo Rendering. In Proceedings of the 22nd Annual Conference on 00068 Computer Graphics and interactive Techniques S.G. Mair and R. Cook, 00069 Eds. SIGGRAPH '95. ACM, New York, NY, 419-428. 00070 00071 @see http://www-graphics.stanford.edu/papers/combine/ 00072 <!-------------------------------------------------------------------->**/ 00073 00074 #ifndef MULTIPLE_IMPORTANCE_SAMPLER_H_ 00075 #define MULTIPLE_IMPORTANCE_SAMPLER_H_ 00076 00077 #include <stats/WeightedEvent.h> 00078 #include <utils/PropertyMap.h> 00079 00080 class Sampler; 00081 00082 DECLARE_STL_TYPEDEF(std::vector<Sampler*>, SamplerList); 00083 DECLARE_STL_TYPEDEF(std::vector<unsigned>, IntList); 00084 00085 class MultipleImportanceSampler : public PropertyMap { 00086 /// @note ni, n, and N use the same notation from Veach and Guibas' paper 00087 00088 public: 00089 ///@name Constructors 00090 //@{----------------------------------------------------------------- 00091 00092 /** 00093 * @param ni is the constant number of samples to take per sampler 00094 */ 00095 inline MultipleImportanceSampler(const SamplerList &samplers, 00096 unsigned ni = 1) 00097 : m_samplers(samplers), m_N(samplers.size()), m_n(m_N * ni), 00098 m_ni(m_N, ni), m_computeWeightFunc(NULL) 00099 { } 00100 00101 /** 00102 * @param ni holds the variable number of samples to take per sampler 00103 */ 00104 inline MultipleImportanceSampler(const SamplerList &samplers, 00105 const IntList &ni) 00106 : m_samplers(samplers), m_N(samplers.size()), m_n(0), m_ni(ni), 00107 m_computeWeightFunc(NULL) 00108 { 00109 ASSERT(m_N == m_ni.size()); 00110 00111 FOREACH(IntListConstIter, m_ni, iter) { 00112 m_n += *iter; 00113 } 00114 } 00115 00116 virtual ~MultipleImportanceSampler() 00117 { } 00118 00119 00120 //@}----------------------------------------------------------------- 00121 ///@name Initialization 00122 //@{----------------------------------------------------------------- 00123 00124 /** 00125 * @brief 00126 * Initializes the weight computation function based on this 00127 * class' PropertyMap 00128 * 00129 * @note defaults to balance heuristic 00130 */ 00131 virtual void init(); 00132 00133 00134 //@}----------------------------------------------------------------- 00135 ///@name Main usage interface 00136 //@{----------------------------------------------------------------- 00137 00138 /** 00139 * @brief 00140 * Generates ni samples from each sampler pi in { p1,p1,...,pn }, 00141 * along with sample weights, and stores the N weighted events in 00142 * the out parameter @p results 00143 * 00144 * @note 'results' is first cleared before adding any samples 00145 */ 00146 virtual void sample(WeightedEventList &results); 00147 00148 00149 //@}----------------------------------------------------------------- 00150 00151 protected: 00152 typedef void (MultipleImportanceSampler::*ComputeWeightFunc) 00153 (WeightedEvent &event, unsigned i); 00154 00155 // weighting heuristics 00156 virtual void _computeWeightBalance(WeightedEvent &event, unsigned i); 00157 virtual void _computeWeightCutoff (WeightedEvent &event, unsigned i); 00158 virtual void _computeWeightPower (WeightedEvent &event, unsigned i); 00159 virtual void _computeWeightMaximum(WeightedEvent &event, unsigned i); 00160 00161 protected: 00162 /// list of distributions from which to draw samples from 00163 SamplerList m_samplers; 00164 00165 /// number of sampling distributions in m_samplers 00166 unsigned m_N; 00167 00168 /// total number of samples 00169 unsigned m_n; 00170 00171 /// sampler-by-sampler breakdown of number of samples 00172 IntList m_ni; 00173 00174 /// weight computation for individual samples (see init()) 00175 ComputeWeightFunc m_computeWeightFunc; 00176 00177 union { 00178 /// input to power heuristic 00179 real_t m_beta; 00180 00181 /// input to alpha heuristic 00182 real_t m_alpha; 00183 }; 00184 }; 00185 00186 #endif // MULTIPLE_IMPORTANCE_SAMPLER_H_ 00187
Generated on 28 Feb 2009 for Milton by
1.5.6