MUQ  0.4.3
SampleCollection.cpp
Go to the documentation of this file.
2 
4 
6 
7 
8 using namespace muq::SamplingAlgorithms;
9 using namespace muq::Utilities;
10 
11 ExpectedModPieceValue::ExpectedModPieceValue(std::shared_ptr<muq::Modeling::ModPiece> const& f, std::vector<std::string> const& metains) : f(f), metains(metains) {
12  assert(f->numOutputs==1);
13 }
14 
15 void ExpectedValueInputs(SamplingState const& a, std::vector<std::string> const& metains, std::vector<Eigen::VectorXd>& ins) {
16  ins = a.state;
17 
18  for( auto metain : metains ) {
19  auto it = a.meta.find(metain);
20  assert(it!=a.meta.end());
21 
22  if( it->second.type()==typeid(Eigen::Vector2d) ) {
23  ins.push_back(boost::any_cast<Eigen::Vector2d const&>(it->second));
24  continue;
25  }
26  if( it->second.type()==typeid(Eigen::Vector3d) ) {
27  ins.push_back(boost::any_cast<Eigen::Vector3d const&>(it->second));
28  continue;
29  }
30  if( it->second.type()==typeid(Eigen::Vector4d) ) {
31  ins.push_back(boost::any_cast<Eigen::Vector4d const&>(it->second));
32  continue;
33  }
34  if( it->second.type()==typeid(Eigen::VectorXd) ) {
35  ins.push_back(boost::any_cast<Eigen::VectorXd const&>(it->second));
36  continue;
37  }
38  if( it->second.type()==typeid(double) ) {
39  ins.push_back(Eigen::VectorXd::Constant(1, boost::any_cast<double const>(it->second)));
40  continue;
41  }
42  if( it->second.type()==typeid(float) ) {
43  ins.push_back(Eigen::VectorXd::Constant(1, boost::any_cast<float const>(it->second)));
44  continue;
45  }
46  if( it->second.type()==typeid(int) ) {
47  ins.push_back(Eigen::VectorXd::Constant(1, boost::any_cast<int const>(it->second)));
48  continue;
49  }
50  if( it->second.type()==typeid(unsigned int) ) {
51  ins.push_back(Eigen::VectorXd::Constant(1, boost::any_cast<unsigned int const>(it->second)));
52  continue;
53  }
54  }
55 }
56 
57 Eigen::VectorXd const& ExpectedModPieceValue::operator()(SamplingState const& a) {
58  assert(f->numInputs==a.state.size()+metains.size());
59  for( unsigned int i=0; i<a.state.size(); ++i ) { assert(a.state[i].size()==f->inputSizes(i)); }
60 
61  std::vector<Eigen::VectorXd> ins;
63 
64  return f->Evaluate(ins) [0];
65 }
66 
67 Eigen::VectorXd const& SamplingStateIdentity::operator()(SamplingState const& a)
68 {
69  if(blockInd<0){
70  const int totalSize = a.TotalDim();
71  const int numBlocks = a.state.size();
72 
73  output.resize(totalSize);
74  int currInd = 0;
75  for(int i=0; i<numBlocks; ++i){
76  output.segment(currInd,a.state.at(i).size()) = a.state.at(i);
77  currInd += a.state.at(i).size();
78  }
79  return output;
80 
81  }else{
82  output.resize(0);
83  return a.state.at(blockInd);
84  }
85 }
86 
87 Eigen::VectorXd const& SamplingStatePartialMoment::operator()(SamplingState const& a)
88 {
89  if(blockInd<0){
90  const int totalSize = a.TotalDim();
91  const int numBlocks = a.state.size();
92 
93  output.resize(totalSize);
94  int currInd = 0;
95  for(int i=0; i<numBlocks; ++i){
96  output.segment(currInd,a.state.at(i).size()) = (a.state.at(i)-mu.segment(currInd,a.state.at(i).size())).array().pow(momentPower).matrix();
97  currInd += a.state.at(i).size();
98  }
99  return output;
100 
101  }else{
102  output = (a.state.at(blockInd)-mu).array().pow(momentPower).matrix();
103  return output;
104  }
105 }
106 
107 void SampleCollection::Add(std::shared_ptr<SamplingState> newSamp)
108 {
109  // copy the sample pointer
110  samples.push_back(newSamp);//std::make_shared<SamplingState>(*newSamp));
111 }
112 
113 std::shared_ptr<SamplingState> SampleCollection::at(unsigned i)
114 {
115  return samples.at(i);
116 }
117 const std::shared_ptr<SamplingState> SampleCollection::at(unsigned i) const
118 {
119  return samples.at(i);
120 }
121 
122 std::shared_ptr<SampleCollection> SampleCollection::segment(unsigned int startInd, unsigned int length, unsigned int skipBy) const
123 {
124  assert(startInd<size());
125  assert(startInd+length<=size());
126 
127  std::shared_ptr<SampleCollection> output = std::make_shared<SampleCollection>();
128  for(unsigned int i=startInd; i<startInd+length; i+=skipBy)
129  output->Add(at(i));
130 
131  return output;
132 }
133 
134 const std::shared_ptr<SamplingState> SampleCollection::back() const {
135  return samples.back();
136 }
137 
138 
139 Eigen::VectorXd SampleCollection::CentralMoment(unsigned order, Eigen::VectorXd const& mean, int blockNum) const {
140  SamplingStatePartialMoment op(blockNum, order, mean);
141 
142  Eigen::VectorXd stateSum;
143  double weightSum;
144 
145  std::tie(weightSum, stateSum) = RecursiveSum(samples.begin(), samples.end(), op);
146  return (stateSum / weightSum).eval();
147 }
148 
149 Eigen::VectorXd SampleCollection::Mean(int blockNum) const
150 {
151  SamplingStateIdentity op(blockNum);
152 
153  Eigen::VectorXd stateSum;
154  double weightSum;
155 
156  std::tie(weightSum, stateSum) = RecursiveSum(samples.begin(), samples.end(), op);
157  return (stateSum / weightSum).eval();
158 }
159 
160 
161 Eigen::MatrixXd SampleCollection::Covariance(Eigen::VectorXd const& mean, int blockInd) const {
162  const int numSamps = samples.size();
163  Eigen::MatrixXd samps;
164  Eigen::VectorXd weights(numSamps);
165 
166  if(blockInd<0){
167 
168  const int totalSize = samples.at(0)->TotalDim();
169  const int numBlocks = samples.at(0)->state.size();
170 
171  samps.resize(totalSize, numSamps);
172 
173  for(int i=0; i<numSamps; ++i){
174  weights(i) = samples.at(i)->weight;
175 
176  int currInd = 0;
177  for(int block = 0; block<numBlocks; ++block){
178  samps.col(i).segment(currInd, samples.at(i)->state.at(block).size()) = samples.at(i)->state.at(block);
179  currInd += samples.at(i)->state.at(block).size();
180  }
181 
182  }
183 
184  }else{
185 
186  const int blockSize = samples.at(0)->state.at(blockInd).size();
187 
188  samps.resize(blockSize, numSamps);
189 
190  for(int i=0; i<numSamps; ++i){
191  weights(i) = samples.at(i)->weight;
192  samps.col(i) = samples.at(i)->state.at(blockInd);
193  }
194  }
195 
196  return (samps.colwise() - mean) * weights.asDiagonal() * (samps.colwise()-mean).transpose() / weights.sum();
197 }
198 
199 std::vector<Eigen::MatrixXd> SampleCollection::RunningCovariance(int blockInd) const {
200  return RunningCovariance(Mean(blockInd), blockInd);
201 }
202 
203 std::vector<Eigen::MatrixXd> SampleCollection::RunningCovariance(Eigen::VectorXd const& mean, int blockInd) const {
204  const int numSamps = size();
205  std::vector<Eigen::MatrixXd> runCov(numSamps);
206 
207  if(blockInd<0){
208  std::shared_ptr<SamplingState> s = at(0);
209 
210  const int totalSize = s->TotalDim();
211  const int numBlocks = s->state.size();
212  double totWeight = s->weight;
213 
214  Eigen::VectorXd samp(totalSize);
215 
216  int currInd = 0;
217  for(int block = 0; block<numBlocks; ++block){
218  samp.segment(currInd, s->state.at(block).size()) = s->state.at(block);
219  currInd += s->state.at(block).size();
220  }
221 
222  samp -= mean;
223  runCov[0] = totWeight*samp*samp.transpose();
224 
225  for(int i=1; i<numSamps; ++i){
226  s = at(i);
227 
228  int currInd = 0;
229  for(int block = 0; block<numBlocks; ++block){
230  samp.segment(currInd, s->state.at(block).size()) = s->state.at(block);
231  currInd += s->state.at(block).size();
232  }
233 
234  totWeight += s->weight;
235  samp -= mean;
236  runCov[i] = ((totWeight-s->weight)*runCov[i-1] + s->weight*samp*samp.transpose())/totWeight;
237  }
238 
239  }else{
240  std::shared_ptr<SamplingState> s = at(0);
241 
242  const int blockSize = s->state.at(blockInd).size();
243  double totWeight = s->weight;
244 
245  Eigen::VectorXd samp = s->state.at(blockInd)-mean;
246  runCov[0] = totWeight*samp*samp.transpose();
247 
248  for(int i=1; i<numSamps; ++i){
249  s = at(i);
250  totWeight += s->weight;
251  samp = s->state.at(blockInd);
252  runCov[i] = ((totWeight-s->weight)*runCov[i-1] + s->weight*samp*samp.transpose())/totWeight;
253  }
254  }
255 
256  return runCov;
257 }
258 
259 std::pair<double,double> SampleCollection::RecursiveWeightSum(std::vector<std::shared_ptr<SamplingState>>::const_iterator start,
260  std::vector<std::shared_ptr<SamplingState>>::const_iterator end)
261 {
262  int numSamps = std::distance(start,end);
263  const int maxSamps = 20;
264 
265  // If the number of samples is small enough, we can safely add them up directly
266  if(numSamps<maxSamps){
267 
268  double weightSquareSum = (*start)->weight * (*start)->weight;
269  double weightSum = (*start)->weight;
270 
271  for(auto it=start+1; it!=end; ++it){
272  weightSquareSum += (*it)->weight * (*it)->weight;
273  weightSum += (*it)->weight;
274  }
275  return std::make_pair(weightSum, weightSquareSum);
276 
277  }else{
278  int halfDist = std::floor(0.5*numSamps);
279  double weight1, weight2, squaredSum1, squaredSum2;
280  std::tie(weight1,squaredSum1) = RecursiveWeightSum(start, start+halfDist);
281  std::tie(weight2,squaredSum2) = RecursiveWeightSum(start+halfDist, end);
282 
283  return std::make_pair(weight1+weight2, squaredSum1+squaredSum2);
284  }
285 }
286 
287 
288 Eigen::VectorXd SampleCollection::ESS(int blockInd, std::string const& method) const
289 {
290  if(method=="Batch"){
291  return BatchESS(blockInd);
292  }else if(method=="MultiBatch"){
293  return MultiBatchESS(blockInd)*Eigen::VectorXd::Ones(1);
294  }else{
295  std::stringstream msg;
296  msg << "Invalid method (" << method << ") passed to SampleCollection::ESS. Valid options are \"Batch\" and \"MultiBatch\".";
297  throw std::runtime_error(msg.str());
298  return Eigen::VectorXd();
299  }
300 }
301 
302 
303 double SampleCollection::MultiBatchESS(int blockInd, int batchSize, int overlap) const
304 {
305  double numSamps = size();
306 
307  // If the blocksize wasn't given explicitly, use n^{1/3}
308  if(batchSize<1)
309  batchSize = std::min( std::floor(numSamps/(BlockSize(blockInd)+1)), std::round(std::pow(numSamps, 1.0/2.0)));
310 
311  // If the overlap wasn't given explicitly, use 10% of the batchSize
312  if(overlap<1)
313  overlap = std::floor(0.75*batchSize);
314 
315  // The total number of overlapping batches in the chain
316  unsigned int numBatches = std::floor( (numSamps-batchSize)/(batchSize-overlap) );
317 
318  // The number of non-overlapping batches that we could fit in this chain
319  unsigned int numNonOverlapBatches = std::floor( (numSamps / batchSize) - 1 );
320 
321  // If the batch size and overlap do not result in enough batches, throw an error
322  if(numNonOverlapBatches < BlockSize(blockInd)){
323 
324  std::stringstream msg;
325  msg << "ERROR in SampleCollection::MultiBatchError. Batch size of " << batchSize;
326  msg << " results in " << numNonOverlapBatches << " non-overlapping batches, which";
327  msg << " is less than the parameter dimension " << BlockSize(blockInd);
328  msg << " and will result in a singular estimator covariance matrix.";
329  throw std::runtime_error(msg.str());
330  }
331 
332  // Number of non-overlapping variance estimators
333  unsigned int numEstimators = std::floor( (numSamps - numNonOverlapBatches*batchSize)/double(batchSize-overlap) );
334 
335  // Sample mean
336  Eigen::VectorXd mean = Mean(blockInd);
337 
338  // The covariance of batch estimators
339  Eigen::MatrixXd estCov = Eigen::MatrixXd::Zero(BlockSize(blockInd), BlockSize(blockInd));
340 
341  // Compute the estimator covariance
342  for(unsigned int estInd=0; estInd<numEstimators; ++estInd){
343  for(unsigned int batchInd=0; batchInd<numNonOverlapBatches; ++batchInd){
344  Eigen::VectorXd diff = segment(estInd*(batchSize-overlap) + batchInd*batchSize, batchSize)->Mean(blockInd) - mean;
345  estCov += diff * diff.transpose();
346  }
347  }
348  estCov /= (numNonOverlapBatches-1.0)*numEstimators; // <- Estimate of the size b_n estimator variance
349  estCov *= double(batchSize); // <-Estimate of the size n estimator variance
350 
351  double covDet = Covariance(mean).determinant();
352 
353  return std::min(numSamps, numSamps*std::pow(covDet / estCov.determinant(), 1.0/BlockSize(blockInd)) );
354 }
355 
356 Eigen::VectorXd SampleCollection::BatchESS(int blockInd, int batchSize, int overlap) const
357 {
358  double numSamps = size();
359 
360  Eigen::VectorXd avgEstVar = BatchError(blockInd, batchSize, overlap).array().square();
361 
362  Eigen::VectorXd ess = Variance(blockInd).array() / avgEstVar.array();
363  for(int i=0; i<ess.size(); ++i)
364  ess(i) = std::min(ess(i), numSamps);
365 
366  return ess;
367 }
368 
369 Eigen::VectorXd SampleCollection::StandardError(int blockInd,
370  std::string const& method) const
371 {
372  if(method=="Batch"){
373  return BatchError(blockInd);
374  }else if(method=="MultiBatch"){
375  return MultiBatchError(blockInd);
376  }else{
377  std::stringstream msg;
378  msg << "Invalid method (" << method << ") passed to SampleCollection::StandardError. Valid options are \"Batch\" and \"MultiBatch\".";
379  throw std::runtime_error(msg.str());
380  return Eigen::VectorXd();
381  }
382 }
383 
384 Eigen::VectorXd SampleCollection::BatchError(int blockInd, int batchSize, int overlap) const
385 {
386  double numSamps = size();
387 
388  // If the blocksize wasn't given explicitly, use n^{1/2}
389  if(batchSize<1)
390  batchSize = std::round(std::pow(numSamps, 1.0/2.0));
391 
392  // If the overlap wasn't given explicitly, use 10% of the batchSize
393  if(overlap<1)
394  overlap = std::floor(0.75*batchSize);
395 
396  // The total number of overlapping batches in the chain
397  unsigned int numBatches = std::floor( (numSamps-batchSize)/(batchSize-overlap) );
398 
399  // The number of non-overlapping batches that we could fit in this chain
400  unsigned int numNonOverlapBatches = std::floor( (numSamps / batchSize) - 1 );
401 
402  // Number of non-overlapping variance estimators
403  unsigned int numEstimators = std::floor( (numSamps - numNonOverlapBatches*batchSize)/double(batchSize-overlap) );
404 
405  Eigen::VectorXd mean = Mean(blockInd);
406 
407  // Vector to hold the mean (over non-overlapping estimators) estimator variance.
408  Eigen::VectorXd avgEstVar = Eigen::VectorXd::Zero(BlockSize(blockInd));
409  for(unsigned int estInd=0; estInd<numEstimators; ++estInd){
410  for(unsigned int batchInd=0; batchInd<numNonOverlapBatches; ++batchInd){
411  avgEstVar += (1.0/(numNonOverlapBatches-1.0)) * (segment(estInd*(batchSize-overlap) + batchInd*batchSize, batchSize)->Mean(blockInd) - mean).array().square().matrix();
412  }
413  }
414  avgEstVar /= numEstimators; // <- Estimate of the size b_n estimator variance
415  avgEstVar *= (double(batchSize)/double(size())); // <-Estimate of the size n estimator variance
416 
417  return avgEstVar.cwiseSqrt();
418 }
419 
420 Eigen::VectorXd SampleCollection::MultiBatchError(int blockInd, int batchSize, int overlap) const
421 {
422  double ess = MultiBatchESS(blockInd, batchSize, overlap);
423  return (Variance() / ess).array().sqrt();
424 }
425 
426 
427 std::shared_ptr<SampleCollection> SampleCollection::FromMatrix(Eigen::MatrixXd const& samps)
428 {
429  const unsigned int numSamps = samps.cols();
430 
431  std::shared_ptr<SampleCollection> output = std::make_shared<SampleCollection>();
432  for(unsigned int col=0; col<numSamps; ++col)
433  output->Add( std::make_shared<SamplingState>(samps.col(col)));
434 
435  return output;
436 }
437 
438 Eigen::MatrixXd SampleCollection::AsMatrix(int blockDim) const
439 {
440  if(samples.size()==0)
441  return Eigen::MatrixXd();
442 
443  if(blockDim<0){
444 
445  Eigen::MatrixXd output(samples.at(0)->TotalDim(), samples.size());
446  for(int i=0; i<samples.size(); ++i){
447  int startInd = 0;
448 
449  for(int block=0; block<samples.at(0)->state.size(); ++block){
450  int blockSize = samples.at(0)->state.at(block).size();
451  output.col(i).segment(startInd, blockSize) = samples.at(i)->state.at(block);
452  startInd += blockSize;
453  }
454  }
455 
456  return output;
457 
458  }else{
459  Eigen::MatrixXd output(samples.at(0)->state.at(blockDim).size(), samples.size());
460  for(int i=0; i<samples.size(); ++i)
461  output.col(i) = samples.at(0)->state.at(blockDim);
462  return output;
463  }
464 }
465 
466 Eigen::VectorXd SampleCollection::Weights() const
467 {
468  Eigen::VectorXd output(samples.size());
469  for(int i=0; i<samples.size(); ++i)
470  output(i) = samples.at(i)->weight;
471  return output;
472 }
473 
474 bool SampleCollection::CreateDataset(std::shared_ptr<muq::Utilities::HDF5File> hdf5file, std::string const& dataname, int const dataSize, int const totSamps) const {
475  if( !hdf5file->IsDataSet(dataname) ) { return true; }
476 
477  Eigen::VectorXi size = hdf5file->GetDataSetSize(dataname);
478  if( size(0)!=dataSize || size(1)!=totSamps ) { return true; }
479 
480  return false;
481 }
482 
483 void SampleCollection::WriteToFile(std::string const& filename, std::string const& dataset) const {
484  if( size()==0 ) { return; }
485 
486  // open the hdf5 file
487  auto hdf5file = std::make_shared<HDF5File>(filename);
488 
489  // write the sample matrix and weights
490  hdf5file->WriteMatrix(dataset+"/samples", AsMatrix());
491  hdf5file->WriteMatrix(dataset+"/weights", (Eigen::RowVectorXd)Weights());
492 
493  // meta data
494  const std::unordered_map<std::string, Eigen::MatrixXd>& meta = GetMeta();
495 
496  // write meta data to file
497  for( const auto& data : meta ) { hdf5file->WriteMatrix(dataset+"/"+data.first, data.second); }
498 
499  hdf5file->Close();
500 }
501 
502 unsigned SampleCollection::size() const { return samples.size(); }
503 
504 
505 std::set<std::string> SampleCollection::ListMeta(bool requireAll) const{
506 
507  std::set<std::string> output;
508 
509  // Add all of the metadata from the first sample
510  for(auto& metaPair : at(0)->meta)
511  output.insert(metaPair.first);
512 
513  // Loop through the rest of the samples
514  for(unsigned int i=1; i<size(); ++i) {
515  if(requireAll){
516 
517  // Make a list of any keys that we don't have already
518  std::vector<std::string> eraseElements;
519  for(auto& key : output){
520  if( !at(i)->HasMeta(key) ){
521  eraseElements.push_back(key);
522  }
523  }
524 
525  // Erase any key that we didn't find in this sample
526  for(auto& key : eraseElements){
527  output.erase(key);
528  }
529 
530  }else{
531  for(auto& metaPair : at(i)->meta)
532  output.insert(metaPair.first);
533  }
534  }
535 
536  return output;
537 }
538 
539 
540 Eigen::MatrixXd SampleCollection::GetMeta(std::string const& name) const {
541 
542  Eigen::MatrixXd meta;
543 
544  // for each sample
545  for( unsigned int i=0; i<size(); ++i ) {
546  // get the meta data for that sample
547  auto it = at(i)->meta.find(name);
548  if( it==at(i)->meta.end() ) { continue; }
549 
550  if( it->second.type()==typeid(Eigen::Vector2d) ) {
551  // create a matrix for the meta data
552  if( meta.size()==0 ) {
553  meta = Eigen::MatrixXd::Constant(2, size(), std::numeric_limits<double>::quiet_NaN());
554  }
555  meta.col(i) = boost::any_cast<Eigen::Vector2d const&>(it->second);
556 
557  continue;
558  }
559 
560  if( it->second.type()==typeid(Eigen::Vector3d) ) {
561  // create a matrix for the meta data
562  if( meta.size()==0 ) {
563  meta = Eigen::MatrixXd::Constant(3, size(), std::numeric_limits<double>::quiet_NaN());
564  }
565  meta.col(i) = boost::any_cast<Eigen::Vector3d const&>(it->second);
566 
567  continue;
568  }
569 
570  if( it->second.type()==typeid(Eigen::Vector4d) ) {
571  // create a matrix for the meta data
572  if( meta.size()==0 ) {
573  meta = Eigen::MatrixXd::Constant(4, size(), std::numeric_limits<double>::quiet_NaN());
574  }
575  meta.col(i) = boost::any_cast<Eigen::Vector4d const&>(it->second);
576 
577  continue;
578  }
579 
580  if( it->second.type()==typeid(Eigen::VectorXd) ) {
581  // create a matrix for the meta data
582  if( meta.size()==0 ) {
583  meta = Eigen::MatrixXd::Constant(boost::any_cast<Eigen::VectorXd const&>(it->second).size(), size(), std::numeric_limits<double>::quiet_NaN());
584  }
585 
586  meta.col(i) = boost::any_cast<Eigen::VectorXd const&>(it->second);
587 
588  continue;
589  }
590 
591  // create a matrix, assuming scalar type, for the meta data
592  if( meta.size()==0 ) {
593  meta = Eigen::MatrixXd::Constant(1, size(), std::numeric_limits<double>::quiet_NaN());
594  }
595 
596  if( it->second.type()==typeid(double) ) { // doubles
597  meta(i) = boost::any_cast<double const>(it->second);
598  continue;
599  }
600 
601  if( it->second.type()==typeid(float) ) { // floats
602  meta(i) = boost::any_cast<float const>(it->second);
603  continue;
604  }
605 
606  if( it->second.type()==typeid(int) ) { // ints
607  meta(i) = boost::any_cast<int const>(it->second);
608  continue;
609  }
610 
611  if( it->second.type()==typeid(unsigned int) ) { // unsigned ints
612  meta(i) = boost::any_cast<unsigned int const>(it->second);
613  continue;
614  }
615  }
616 
617  return meta;
618 }
619 
620 std::unordered_map<std::string, Eigen::MatrixXd> SampleCollection::GetMeta() const {
621  std::unordered_map<std::string, Eigen::MatrixXd> meta;
622  for( unsigned int i=0; i<size(); ++i ) { // loop through the samples
623  // loop through all meta data for this sample
624  for( auto it = at(i)->meta.begin(); it!=at(i)->meta.end(); ++it ) {
625  // if we have not yet gotten this meta information
626  auto mat = meta.find(it->first);
627  if( mat==meta.end() ) {
628  meta[it->first] = GetMeta(it->first);
629  }
630  }
631  }
632 
633  return meta;
634 }
635 
636 Eigen::VectorXd SampleCollection::ExpectedValue(std::shared_ptr<muq::Modeling::ModPiece> const& f, std::vector<std::string> const& metains) const {
637  ExpectedModPieceValue op(f, metains);
638 
639  Eigen::VectorXd val;
640  double weight;
641 
642  std::tie(weight, val) = RecursiveSum(samples.begin(), samples.end(), op);
643  return (val / weight).eval();
644 }
645 
646 std::vector<Eigen::VectorXd> SampleCollection::RunningExpectedValue(std::shared_ptr<muq::Modeling::ModPiece> const& f, std::vector<std::string> const& metains) const {
647  const unsigned int numSamps = size();
648  std::vector<Eigen::VectorXd> runningExpected(numSamps);
649 
650  std::shared_ptr<SamplingState> s = at(0);
651  double totWeight = s->weight;
652 
653  std::vector<Eigen::VectorXd> ins;
654  ExpectedValueInputs(*s, metains, ins);
655 
656  runningExpected[0] = totWeight*f->Evaluate(ins) [0];
657  for( unsigned int i=1; i<numSamps; ++i ) {
658  s = at(i);
659  ExpectedValueInputs(*s, metains, ins);
660  totWeight += s->weight;
661 
662  runningExpected[i] = ((totWeight-s->weight)*runningExpected[i-1] + s->weight*f->Evaluate(ins) [0])/totWeight;
663  }
664 
665  return runningExpected;
666 }
667 
668 
669 unsigned int SampleCollection::BlockSize(int blockInd) const
670 {
671  if(blockInd<0){
672  return samples.at(0)->TotalDim();
673  }else{
674  return samples.at(0)->state.at(blockInd).size();
675  }
676 }
677 
678 unsigned int SampleCollection::NumBlocks() const
679 {
680  return samples.at(0)->state.size();
681 }
682 
683 
684 Eigen::VectorXd SampleCollection::Rhat(int blockDim,
685  unsigned int numSegments,
686  boost::property_tree::ptree options) const
687 {
688  std::vector<std::shared_ptr<const SampleCollection>> chains;
689  chains.push_back( shared_from_this());
690 
691  return Diagnostics::Rhat(Diagnostics::SplitChains(chains, numSegments), options);
692 }
void ExpectedValueInputs(SamplingState const &a, std::vector< std::string > const &metains, std::vector< Eigen::VectorXd > &ins)
Eigen::VectorXd const & operator()(SamplingState const &a)
ExpectedModPieceValue(std::shared_ptr< muq::Modeling::ModPiece > const &f, std::vector< std::string > const &metains)
const std::vector< std::string > metains
std::shared_ptr< muq::Modeling::ModPiece > f
virtual std::shared_ptr< SamplingState > at(unsigned i)
std::unordered_map< std::string, Eigen::MatrixXd > GetMeta() const
double MultiBatchESS(int blockInd=-1, int batchSize=-1, int overlap=-1) const
virtual Eigen::VectorXd ESS(std::string const &method="Batch") const override
Returns the effective sample size of the samples.
virtual Eigen::VectorXd MultiBatchError(int blockInd=-1, int batchSize=-1, int overlap=-1) const
virtual std::vector< Eigen::MatrixXd > RunningCovariance(int blockInd=-1) const
std::vector< std::shared_ptr< SamplingState > > samples
virtual Eigen::VectorXd CentralMoment(unsigned order, Eigen::VectorXd const &mean, int blockNum=-1) const override
Computes the componentwise central moments (e.g., variance, skewness, kurtosis, etc....
virtual std::shared_ptr< SampleCollection > segment(unsigned int startInd, unsigned int length, unsigned int skipBy=1) const
virtual void Add(std::shared_ptr< SamplingState > newSamp)
virtual Eigen::MatrixXd AsMatrix(int blockDim=-1) const
static std::pair< double, double > RecursiveWeightSum(std::vector< std::shared_ptr< SamplingState >>::const_iterator start, std::vector< std::shared_ptr< SamplingState >>::const_iterator end)
bool CreateDataset(std::shared_ptr< muq::Utilities::HDF5File > hdf5file, std::string const &dataname, int const dataSize, int const totSamps) const
virtual Eigen::VectorXd Rhat(int blockDim, unsigned int numSegments=4, boost::property_tree::ptree options=boost::property_tree::ptree()) const
Eigen::VectorXd BatchESS(int blockInd=-1, int batchSize=-1, int overlap=-1) const
virtual Eigen::VectorXd Mean(int blockInd=-1) const override
virtual Eigen::VectorXd Weights() const
virtual Eigen::VectorXd StandardError(int blockInd, std::string const &method) const override
virtual Eigen::MatrixXd Covariance(int blockInd=-1) const override
static std::shared_ptr< SampleCollection > FromMatrix(Eigen::MatrixXd const &samps)
static std::pair< double, Eigen::VectorXd > RecursiveSum(std::vector< std::shared_ptr< SamplingState >>::const_iterator start, std::vector< std::shared_ptr< SamplingState >>::const_iterator end, FuncType &f)
virtual const std::shared_ptr< SamplingState > back() const
virtual Eigen::VectorXd BatchError(int blockInd=-1, int batchSize=-1, int overlap=-1) const
virtual unsigned int BlockSize(int blockInd) const =0
virtual Eigen::VectorXd ExpectedValue(std::shared_ptr< muq::Modeling::ModPiece > const &f, std::vector< std::string > const &metains=std::vector< std::string >()) const =0
virtual Eigen::VectorXd Variance(int blockInd=-1) const
virtual unsigned int NumBlocks() const =0
Eigen::VectorXd const & operator()(SamplingState const &a)
Eigen::VectorXd const & operator()(SamplingState const &a)
Each state is one sample generated by a sampling algorithm.
Definition: SamplingState.h:31
int TotalDim() const
The total number of parameters in the state, i.e., the sum of state[i].size()
std::unordered_map< std::string, boost::any > meta
A map containing extra information like the target density, run time, forward model output,...
Definition: SamplingState.h:72
std::vector< Eigen::VectorXd > state
The state variables.
Definition: SamplingState.h:48