File indexing completed on 2026-08-06 09:24:21
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef EXSAMPLE_SimpleCellGrid_hpp_included
0010 #define EXSAMPLE_SimpleCellGrid_hpp_included
0011
0012 #include "CellGrid.h"
0013 #include <cmath>
0014
0015 namespace ExSample {
0016
0017
0018
0019
0020
0021
0022 class SimpleCellGrid
0023 : public CellGrid {
0024
0025 public:
0026
0027
0028
0029
0030 SimpleCellGrid()
0031 : CellGrid() {}
0032
0033
0034
0035
0036 SimpleCellGrid(const std::vector<double>& newLowerLeft,
0037 const std::vector<double>& newUpperRight,
0038 bool keepWeightInformation = true,
0039 double newWeight = 0.0);
0040
0041
0042
0043
0044 virtual CellGrid* makeInstance() const;
0045
0046
0047
0048
0049 virtual CellGrid* makeInstance(const std::vector<double>& newLowerLeft,
0050 const std::vector<double>& newUpperRight,
0051 double newWeight = 0.0) const;
0052
0053
0054
0055
0056
0057 virtual void split(std::size_t newSplitDimension, double newSplitCoordinate);
0058
0059
0060 virtual void splitter(size_t dim, int rat);
0061
0062 public:
0063
0064
0065
0066
0067 const SimpleCellGrid& firstChild() const {
0068 return dynamic_cast<const SimpleCellGrid&>(CellGrid::firstChild());
0069 }
0070
0071
0072
0073
0074 SimpleCellGrid& firstChild() {
0075 return dynamic_cast<SimpleCellGrid&>(CellGrid::firstChild());
0076 }
0077
0078
0079
0080
0081 const SimpleCellGrid& secondChild() const {
0082 return dynamic_cast<const SimpleCellGrid&>(CellGrid::secondChild());
0083 }
0084
0085
0086
0087
0088 SimpleCellGrid& secondChild() {
0089 return dynamic_cast<SimpleCellGrid&>(CellGrid::secondChild());
0090 }
0091
0092 public:
0093
0094
0095
0096
0097 struct Counter {
0098
0099
0100
0101
0102 Counter()
0103 : nPoints(0.0), sumOfWeights(0.0),
0104 sumOfSquaredWeights(0.0),
0105 maxWeight(0.0) {}
0106
0107
0108
0109
0110 double nPoints;
0111
0112
0113
0114
0115 double sumOfWeights;
0116
0117
0118
0119
0120 double sumOfSquaredWeights;
0121
0122
0123
0124
0125 double maxWeight;
0126
0127
0128
0129
0130 void book(double weight) {
0131 nPoints += 1.0;
0132 sumOfWeights += std::abs(weight);
0133 sumOfSquaredWeights += sqr(weight);
0134 maxWeight = std::max(std::abs(weight),maxWeight);
0135 }
0136
0137
0138
0139
0140 double averageWeight() const { return nPoints != 0.0 ? sumOfWeights/nPoints : 0.0; }
0141
0142
0143
0144
0145 double varianceOfAverage() const {
0146 return
0147 nPoints > 1.0 ?
0148 fabs(sumOfSquaredWeights/nPoints - sqr(sumOfWeights/nPoints))/(nPoints-1) : 0.0;
0149 }
0150
0151 };
0152
0153
0154
0155
0156 const std::vector<std::pair<Counter,Counter> >& weightInformation() const { return theWeightInformation; }
0157
0158
0159
0160
0161 std::vector<std::pair<Counter,Counter> >& weightInformation() { return theWeightInformation; }
0162
0163
0164
0165
0166 virtual void updateWeightInformation(const std::vector<double>& p,
0167 double w);
0168
0169
0170
0171
0172 void adjustReferenceWeight(double w) {
0173 theReferenceWeight = std::max(theReferenceWeight,std::abs(w));
0174 }
0175
0176
0177
0178
0179 double getReferenceWeight() const {
0180 return theReferenceWeight;
0181 }
0182
0183
0184
0185
0186
0187
0188 virtual void adapt(double gain, double epsilon,
0189 std::set<SimpleCellGrid*>& newCells);
0190
0191
0192
0193
0194
0195 virtual void setWeights();
0196
0197 public:
0198
0199
0200
0201
0202 template<class RndGenerator>
0203 void sampleFlatPoint(std::vector<double>& p,
0204 RndGenerator& rnd) const {
0205 assert(p.size() == lowerLeft().size());
0206 for ( size_t k = 0; k < p.size(); ++k ) {
0207 p[k] = lowerLeft()[k] + rnd.rnd()*(upperRight()[k]-lowerLeft()[k]);
0208 }
0209 }
0210
0211
0212
0213
0214 template<class RndGenerator>
0215 void sampleFlatPoint(std::vector<double>& p,
0216 const std::vector<bool>& parameterFlags,
0217 RndGenerator& rnd) const {
0218 assert(p.size() == lowerLeft().size());
0219 for ( size_t k = 0; k < p.size(); ++k ) {
0220 if ( parameterFlags[k] )
0221 continue;
0222 p[k] = lowerLeft()[k] + rnd.rnd()*(upperRight()[k]-lowerLeft()[k]);
0223 }
0224 }
0225
0226
0227
0228
0229
0230
0231
0232 template<class RndGenerator, class Function>
0233 void explore(std::size_t nPoints,
0234 RndGenerator& rnd,
0235 Function& f,
0236 std::set<SimpleCellGrid*>& newCells,
0237 std::ostream& warn) {
0238 unsigned long nanPoints = 0;
0239 if ( !isLeaf() ) {
0240 firstChild().explore(nPoints,rnd,f,newCells,warn);
0241 secondChild().explore(nPoints,rnd,f,newCells,warn);
0242 return;
0243 }
0244 if ( !newCells.empty() ) {
0245 if ( newCells.find(this) == newCells.end() )
0246 return;
0247 }
0248 std::vector<double> point(lowerLeft().size());
0249 for ( std::size_t k = 0; k < nPoints; ++k ) {
0250 sampleFlatPoint(point,rnd);
0251 double w = f.evaluate(point);
0252 if ( ! std::isfinite(w) ) {
0253 ++nanPoints;
0254 continue;
0255 }
0256 updateWeightInformation(point,std::abs(w));
0257 }
0258 if ( nanPoints ) {
0259 warn << "Warning: " << nanPoints << " out of "
0260 << nPoints << " points with nan or inf weight encountered while "
0261 << "exploring a cell.\n" << std::flush;
0262 }
0263 }
0264
0265
0266
0267
0268 template<class RndGenerator>
0269 SimpleCellGrid* selectCell(RndGenerator& rnd) {
0270 if ( isLeaf() )
0271 return this;
0272 if ( firstChild().active() &&
0273 secondChild().active() ) {
0274 double p = firstChild().integral()/integral();
0275 if ( rnd.rnd() <= p )
0276 return firstChild().selectCell(rnd);
0277 else
0278 return secondChild().selectCell(rnd);
0279 }
0280 if ( firstChild().active() &&
0281 !secondChild().active() )
0282 return firstChild().selectCell(rnd);
0283 else
0284 return secondChild().selectCell(rnd);
0285 }
0286
0287
0288
0289
0290 template<class RndGenerator, class Function>
0291 double sample(RndGenerator& rnd,
0292 Function& f,
0293 std::vector<double>& p,
0294 bool unweight,
0295 bool adjustReference) {
0296 SimpleCellGrid* selected = selectCell(rnd);
0297 selected->sampleFlatPoint(p,rnd);
0298 double w = f.evaluate(p);
0299 selected->updateWeightInformation(p,w);
0300 double xw = integral()*w/selected->weight();
0301 if ( adjustReference ) {
0302 selected->adjustReferenceWeight(xw);
0303 }
0304 if ( unweight ) {
0305 double r = selected->getReferenceWeight();
0306 if ( r == 0. )
0307 return xw;
0308 double p = std::min(std::abs(xw),r)/r;
0309 double sign = xw >= 0. ? 1. : -1.;
0310 if ( p < 1 && rnd.rnd() > p )
0311 xw = 0.;
0312 else
0313 xw = sign*std::max(std::abs(xw),r);
0314 }
0315 return xw;
0316 }
0317
0318
0319
0320
0321 template<class RndGenerator, class Function>
0322 std::pair<double,double> generate(RndGenerator& rnd,
0323 Function& f,
0324 std::vector<double>& p) {
0325 SimpleCellGrid* selected = selectCell(rnd);
0326 selected->sampleFlatPoint(p,rnd);
0327 double w = f.evaluate(p);
0328 selected->updateWeightInformation(p,w);
0329 return std::make_pair(w,selected->weight());
0330 }
0331
0332
0333
0334
0335 template<class RndGenerator, class Function>
0336 std::pair<double,double> generate(RndGenerator& rnd,
0337 Function& f,
0338 std::vector<double>& p,
0339 const std::vector<bool>& parameterFlags) {
0340 SimpleCellGrid* selected = selectCell(rnd);
0341 selected->sampleFlatPoint(p,parameterFlags,rnd);
0342 double w = f.evaluate(p);
0343 selected->updateWeightInformation(p,w);
0344 return std::make_pair(w,selected->weight());
0345 }
0346
0347 public:
0348
0349
0350
0351
0352 virtual void fromXML(const XML::Element&);
0353
0354
0355
0356
0357 virtual XML::Element toXML() const;
0358
0359 private:
0360
0361
0362
0363
0364 std::vector<std::pair<Counter,Counter> > theWeightInformation;
0365
0366
0367
0368
0369 double theReferenceWeight;
0370
0371 };
0372
0373 }
0374
0375 #endif
0376