MUQ  0.4.3
MultiIndexEstimator.cpp
Go to the documentation of this file.
3 
4 using namespace muq::SamplingAlgorithms;
5 
6 
7 MultiIndexEstimator::MultiIndexEstimator(std::vector<std::shared_ptr<MIMCMCBox>> const& boxesIn,
8  bool useQoisIn) : boxes(boxesIn),
9  blockSizes(useQoisIn ? boxesIn.at(0)->GetFinestProblem()->blockSizesQOI : boxesIn.at(0)->GetFinestProblem()->blockSizes),
10  useQois(useQoisIn)
11 {
12 
13 }
14 
15 unsigned int MultiIndexEstimator::BlockSize(int blockInd) const
16 {
17  if(blockInd<0){
18  return blockSizes.sum();
19  }else{
20  return blockSizes(blockInd);
21  }
22 }
23 
24 
25 unsigned int MultiIndexEstimator::NumBlocks() const
26 {
27  return blockSizes.size();
28 }
29 
30 Eigen::VectorXd MultiIndexEstimator::StandardError(int blockDim, std::string const& method) const
31 {
32  // Construct Markov chain objects for each term in the telescoping series
33  std::vector<std::shared_ptr<MarkovChain>> chains = GetDiffChains();
34 
35  Eigen::VectorXd estVar = chains.at(0)->StandardError(blockDim, method).array().square();
36  for(unsigned int i=1; i<chains.size(); ++i)
37  estVar += chains.at(i)->StandardError(blockDim, method).array().square().matrix();
38 
39  return estVar.array().sqrt();
40 }
41 
42 
43 Eigen::VectorXd MultiIndexEstimator::ESS(int blockDim, std::string const& method) const
44 {
45  return Variance(blockDim).array() / StandardError(blockDim, method).array().square();
46 }
47 
48 
49 
50 std::vector<std::shared_ptr<MarkovChain>> MultiIndexEstimator::GetDiffChains(int blockInd, std::shared_ptr<muq::Modeling::ModPiece> const& f) const
51 {
52  // Chains to hold the summand for each term in the multi-index telescoping series
53  std::vector<std::shared_ptr<MarkovChain>> diffChains(boxes.size());
54 
55  unsigned int dim;
56  if(useQois){
57  dim = boxes.at(0)->FinestChain()->GetQOIs()->BlockSize(blockInd);
58  }else{
59  dim = boxes.at(0)->FinestChain()->GetSamples()->BlockSize(blockInd);
60  }
61 
62  // Extract information from each box
63  for(unsigned int boxInd = 0; boxInd<boxes.size(); ++boxInd){
64 
65  diffChains.at(boxInd) = std::make_shared<MarkovChain>();
66 
67  auto& box = boxes.at(boxInd);
68  auto boxIndices = box->GetBoxIndices();
69 
70  unsigned int numSamps;
71  if(useQois){
72  numSamps = box->FinestChain()->GetQOIs()->size();
73  }else{
74  numSamps = box->FinestChain()->GetSamples()->size();
75  }
76 
77  Eigen::VectorXd diff;
78  for(unsigned int sampInd =0; sampInd < numSamps; ++sampInd)
79  {
80  // Compute the difference for one term and one sample in the telescoping series
81  diff = Eigen::VectorXd::Zero(dim);
82 
83  for (int i = 0; i < boxIndices->Size(); i++) {
84 
85  std::shared_ptr<MultiIndex> boxIndex = (*boxIndices)[i];
86  auto chain = box->GetChain(boxIndex);
87  std::shared_ptr<MarkovChain> samps;
88  if(useQois){
89  samps = chain->GetQOIs();
90  }else{
91  samps = chain->GetSamples();
92  }
93 
94  MultiIndex index = *(box->GetLowestIndex()) + *boxIndex;
95  MultiIndex indexDiffFromTop = *(box->GetHighestIndex()) - index;
96 
97  double mult = (indexDiffFromTop.Sum() % 2 == 0) ? 1.0 : -1.0;
98 
99  if(f){
100  diff += mult * f->Evaluate(samps->at(sampInd)->state).at(0);
101  }else{
102  diff += mult * samps->at(sampInd)->ToVector(blockInd);
103  }
104 
105  }
106 
107  diffChains.at(boxInd)->Add(std::make_shared<SamplingState>(diff));
108  }
109  }
110 
111  return diffChains;
112 }
113 
114 
115 Eigen::VectorXd MultiIndexEstimator::ExpectedValue(std::shared_ptr<muq::Modeling::ModPiece> const& f,
116  std::vector<std::string> const& metains) const
117 {
118  assert(f->outputSizes.size()==1);
119 
120  Eigen::VectorXd telescopingSum = Eigen::VectorXd::Zero(f->outputSizes(0));
121 
122  // Add up the telescoping series of MI boxes
123  for (auto& box : boxes) {
124 
125  // Compute the expected difference for one term in the telescoping series
126  Eigen::VectorXd diffMean = Eigen::VectorXd::Zero(f->outputSizes(0));
127 
128  auto boxIndices = box->GetBoxIndices();
129  for (int i = 0; i < boxIndices->Size(); i++) {
130 
131  std::shared_ptr<MultiIndex> boxIndex = (*boxIndices)[i];
132  auto chain = box->GetChain(boxIndex);
133  std::shared_ptr<MarkovChain> samps;
134  if(useQois){
135  samps = chain->GetQOIs();
136  }else{
137  samps = chain->GetSamples();
138  }
139 
140  MultiIndex index = *(box->GetLowestIndex()) + *boxIndex;
141  MultiIndex indexDiffFromTop = *(box->GetHighestIndex()) - index;
142 
143  if (indexDiffFromTop.Sum() % 2 == 0) {
144  diffMean += samps->ExpectedValue(f,metains);
145  } else {
146  diffMean -= samps->ExpectedValue(f,metains);
147  }
148  }
149 
150  // Add this term of the series to the running total
151  telescopingSum += diffMean;
152  }
153 
154  return telescopingSum;
155 }
156 
157 Eigen::MatrixXd MultiIndexEstimator::Covariance(Eigen::VectorXd const& mean,
158  int blockInd) const
159 {
160  Eigen::MatrixXd telescopingSum = Eigen::MatrixXd::Zero(BlockSize(blockInd),BlockSize(blockInd));
161 
162  // Add up the telescoping series of MI boxes
163  for (auto& box : boxes) {
164 
165  // Compute the expected difference for one term in the telescoping series
166  Eigen::MatrixXd diffMean = Eigen::MatrixXd::Zero(BlockSize(blockInd),BlockSize(blockInd));
167 
168  auto boxIndices = box->GetBoxIndices();
169  for (int i = 0; i < boxIndices->Size(); i++) {
170 
171  std::shared_ptr<MultiIndex> boxIndex = (*boxIndices)[i];
172  auto chain = box->GetChain(boxIndex);
173  std::shared_ptr<MarkovChain> samps;
174  if(useQois){
175  samps = chain->GetQOIs();
176  }else{
177  samps = chain->GetSamples();
178  }
179 
180  MultiIndex index = *(box->GetLowestIndex()) + *boxIndex;
181  MultiIndex indexDiffFromTop = *(box->GetHighestIndex()) - index;
182 
183  if (indexDiffFromTop.Sum() % 2 == 0) {
184  diffMean += samps->Covariance(mean);
185  } else {
186  diffMean -= samps->Covariance(mean);
187  }
188  }
189 
190  // Add this term of the series to the running total
191  telescopingSum += diffMean;
192  }
193 
194  return 0.5*(telescopingSum + telescopingSum.transpose());
195 }
virtual unsigned int BlockSize(int blockInd) const override
std::vector< std::shared_ptr< MarkovChain > > GetDiffChains(int blockInd=-1, std::shared_ptr< muq::Modeling::ModPiece > const &f=nullptr) const
MultiIndexEstimator(std::vector< std::shared_ptr< MIMCMCBox >> const &boxesIn, bool useQoisIn=false)
virtual unsigned int NumBlocks() const override
virtual Eigen::MatrixXd Covariance(int blockInd=-1) const override
virtual Eigen::VectorXd ExpectedValue(std::shared_ptr< muq::Modeling::ModPiece > const &f, std::vector< std::string > const &metains=std::vector< std::string >()) const override
virtual Eigen::VectorXd ESS(std::string const &method="Batch") const override
virtual Eigen::VectorXd StandardError(int blockDim, std::string const &method) const override
std::vector< std::shared_ptr< MarkovChain > > diffChains
std::vector< std::shared_ptr< MIMCMCBox > > boxes
virtual Eigen::VectorXd Variance(int blockInd=-1) const