MUQ  0.4.3
MIMCMCBox.cpp
Go to the documentation of this file.
5 
6 using namespace muq::SamplingAlgorithms;
7 
8 MIMCMCBox::MIMCMCBox(std::shared_ptr<MIComponentFactory> componentFactory,
9  std::shared_ptr<MultiIndex> boxHighestIndex)
10 : QOIDiff(std::make_shared<MarkovChain>()),
11  componentFactory(componentFactory),
12  boxHighestIndex(boxHighestIndex)
13 {
14  pt::ptree ptChains;
15  ptChains.put("NumSamples", 0); // number of MCMC steps
16  ptChains.put("PrintLevel", 0);
17  pt::ptree ptBlockID;
18  ptBlockID.put("BlockIndex",0);
19 
20  const auto rootIndex = std::make_shared<MultiIndex>(boxHighestIndex->GetLength());
21 
22  // Set up root index sampling
23  auto coarse_problem = componentFactory->SamplingProblem(rootIndex);
24  std::shared_ptr<MultiIndex> coarse_index = rootIndex;
25  auto proposal_coarse = componentFactory->Proposal(rootIndex, coarse_problem);
26 
27  std::vector<std::shared_ptr<TransitionKernel>> coarse_kernels(1);
28  if (componentFactory->IsInverseProblem())
29  coarse_kernels[0] = std::make_shared<MHKernel>(ptBlockID,coarse_problem,proposal_coarse);
30  else
31  coarse_kernels[0] = std::make_shared<DummyKernel>(ptBlockID, coarse_problem, proposal_coarse);
32 
33  Eigen::VectorXd startPtCoarse = componentFactory->StartingPoint(rootIndex);
34  auto coarse_chain = std::make_shared<SingleChainMCMC>(ptChains,coarse_kernels);
35  coarse_chain->SetState(startPtCoarse);
36 
37  // Construct path to lowest index of box
38  boxLowestIndex = MultiIndex::Copy(boxHighestIndex);
39  --(*boxLowestIndex);
40  std::shared_ptr<MultiIndexSet> rootPath = CreateRootPath(boxLowestIndex);
41  for (int i = rootPath->Size()-2; i >= 0; i--) {
42 
43  tailChains.push_back(coarse_chain);
44 
45  std::shared_ptr<MultiIndex> index = (*rootPath)[i];
46 
47  auto problem = componentFactory->SamplingProblem(index);
48  auto proposal = componentFactory->Proposal(index, problem);
49  auto coarse_proposal = componentFactory->CoarseProposal(index, coarse_index, coarse_problem, coarse_chain);
50  auto proposalInterpolation = componentFactory->Interpolation(index);
51  auto startingPoint = componentFactory->StartingPoint(index);
52 
53  std::vector<std::shared_ptr<TransitionKernel>> kernels(1);
54  if (componentFactory->IsInverseProblem())
55  kernels[0] = std::make_shared<MIKernel>(ptBlockID,problem,coarse_problem,proposal,coarse_proposal,proposalInterpolation,coarse_chain);
56  else
57  kernels[0] = std::make_shared<MIDummyKernel>(ptBlockID, problem, proposal, coarse_proposal, proposalInterpolation, coarse_chain);
58 
59  auto chain = std::make_shared<SingleChainMCMC>(ptChains,kernels);
60  chain->SetState(startingPoint);
61 
62  coarse_problem = problem;
63  coarse_index = index;
64  coarse_chain = chain;
65  }
66 
67  finestProblem = coarse_problem;
68 
69  std::shared_ptr<MultiIndex> boxSize = std::make_shared<MultiIndex>(*boxHighestIndex - *boxLowestIndex);
70 
71  // Set up Multiindex box
72  boxIndices = MultiIndexFactory::CreateFullTensor(boxSize->GetVector());
73  boxChains.resize(boxIndices->Size());
74 
75  for (int i = 0; i < boxIndices->Size(); i++) {
76  std::shared_ptr<MultiIndex> boxIndex = (*boxIndices)[i];
77 
78  if (boxIndex->Max() == 0) {
79  boxChains[boxIndices->MultiToIndex(boxIndex)] = coarse_chain;
80  continue;
81  }
82 
83  std::shared_ptr<MultiIndex> index = std::make_shared<MultiIndex>(*boxLowestIndex + *boxIndex);
84 
85  auto problem = componentFactory->SamplingProblem(index);
86  auto proposal = componentFactory->Proposal(index, problem);
87  auto coarse_proposal = componentFactory->CoarseProposal(index, coarse_index, coarse_problem, coarse_chain);
88  auto proposalInterpolation = componentFactory->Interpolation(index);
89  auto startingPoint = componentFactory->StartingPoint(index);
90 
91  std::vector<std::shared_ptr<TransitionKernel>> kernels(1);
92  if (componentFactory->IsInverseProblem())
93  kernels[0] = std::make_shared<MIKernel>(ptBlockID,problem,coarse_problem,proposal,coarse_proposal,proposalInterpolation,coarse_chain);
94  else
95  kernels[0] = std::make_shared<MIDummyKernel>(ptBlockID, problem, proposal, coarse_proposal, proposalInterpolation, coarse_chain);
96 
97  auto chain = std::make_shared<SingleChainMCMC>(ptChains,kernels);
98  chain->SetState(startingPoint);
99 
100  boxChains[boxIndices->MultiToIndex(boxIndex)] = chain;
101 
102  if (*boxIndex == *boxSize)
103  finestProblem = problem;
104  }
105 }
106 
107 std::shared_ptr<MultiIndex> MIMCMCBox::GetHighestIndex() {
108  return MultiIndex::Copy(boxHighestIndex);
109 }
110 
111 std::shared_ptr<MultiIndex> MIMCMCBox::GetLowestIndex() {
112  return MultiIndex::Copy(boxLowestIndex);
113 }
114 
115 std::shared_ptr<AbstractSamplingProblem> MIMCMCBox::GetFinestProblem() {
116  return finestProblem;
117 }
118 
120  // Set up valid sample vector with arbitrary number of components in order to store contribution to telescoping sum
121  const int num_components = GetFinestProblem()->blockSizesQOI.size();
122  std::vector<Eigen::VectorXd> sampDiff(num_components);
123  for (int component = 0; component < num_components; component++) {
124  sampDiff[component] = Eigen::VectorXd::Zero(GetFinestProblem()->blockSizesQOI[component]);
125  }
126 
127  // Advance chains
128  for (unsigned int i = 0; i < boxIndices->Size(); i++) {
129  std::shared_ptr<MultiIndex> boxIndex = (*boxIndices)[i];
130  auto chain = boxChains[boxIndices->MultiToIndex(boxIndex)];
131  chain->AddNumSamps(1);
132  chain->Run();
133  }
134 
135  for (unsigned int i = 0; i < boxIndices->Size(); i++) {
136  std::shared_ptr<MultiIndex> boxIndex = (*boxIndices)[i];
137  auto chain = boxChains[boxIndices->MultiToIndex(boxIndex)];
138 
139  // Add new sample to difference according to chain's position in telescoping sum
140  if (chain->GetQOIs()->size() > 0) {
141  auto new_state = chain->GetQOIs()->at(chain->GetQOIs()->size()-1);
142 
143  std::shared_ptr<MultiIndex> index = std::make_shared<MultiIndex>(*boxLowestIndex + *boxIndex);
144  auto indexDiffFromTop = std::make_shared<MultiIndex>(*boxHighestIndex - *index);
145 
146  if (indexDiffFromTop->Sum() % 2 == 0) {
147  for (int component = 0; component < num_components; component++) {
148  sampDiff[component] += new_state->state[component];
149  }
150  } else {
151  for (int component = 0; component < num_components; component++) {
152  sampDiff[component] -= new_state->state[component];
153  }
154  }
155  }
156  }
157  if (boxChains[0]->GetQOIs()->size() > 0)
158  QOIDiff->Add(std::make_shared<SamplingState>(sampDiff));
159 
160 }
161 
162 void MIMCMCBox::WriteToFile(std::string filename) {
163  for (int i = 0; i < boxIndices->Size(); i++) {
164  std::shared_ptr<MultiIndex> boxIndex = (*boxIndices)[i];
165  auto chain = boxChains[boxIndices->MultiToIndex(boxIndex)];
166  chain->GetSamples()->WriteToFile(filename, "/model_" + boxHighestIndex->ToString() + "_subchain_" + boxIndex->ToString() + "_samples");
167  chain->GetQOIs()->WriteToFile(filename, "/model_" + boxHighestIndex->ToString() + "_subchain_" + boxIndex->ToString() + "_qois");
168  }
169  QOIDiff->WriteToFile(filename, "/model_" + boxHighestIndex->ToString() + "_qoi_diff");
170 }
171 
172 Eigen::VectorXd MIMCMCBox::MeanQOI() {
173  return QOIDiff->Mean();
174 }
175 
176 std::shared_ptr<SampleCollection> MIMCMCBox::GetQOIDiff(){
177  return QOIDiff;
178 }
179 
180 Eigen::VectorXd MIMCMCBox::MeanParam() {
181  Eigen::VectorXd sampMean = Eigen::VectorXd::Zero(GetFinestProblem()->blockSizes.sum());
182 
183  for (int i = 0; i < boxIndices->Size(); i++) {
184  std::shared_ptr<MultiIndex> boxIndex = (*boxIndices)[i];
185  auto chain = boxChains[boxIndices->MultiToIndex(boxIndex)];
186  auto samps = chain->GetSamples();
187 
188  std::shared_ptr<MultiIndex> index = std::make_shared<MultiIndex>(*boxLowestIndex + *boxIndex);
189  auto indexDiffFromTop = std::make_shared<MultiIndex>(*boxHighestIndex - *index);
190 
191  if (indexDiffFromTop->Sum() % 2 == 0) {
192  sampMean += samps->Mean();
193  } else {
194  sampMean -= samps->Mean();
195  }
196  }
197  return sampMean;
198 }
199 
200 
201 void MIMCMCBox::DrawChain(std::shared_ptr<SingleChainMCMC> chain, std::string chainid, std::ofstream& graphfile) const {
202  graphfile << "subgraph cluster_" << chainid << " {" << std::endl;
203  graphfile << "label=\"Chain " << chainid << "\"" << std::endl;
204  for (int s = 0; s < chain->GetSamples()->size(); s++) {
205  std::shared_ptr<SamplingState> sample = chain->GetSamples()->at(s);
206  std::string nodeid = "\"s" + chainid + "node" + std::to_string(s) + "\"";
207  sample->meta["gvizid"] = nodeid;
208 
209  double logTarget = AnyCast(sample->meta["LogTarget"]);
210  graphfile << nodeid << " [label=\""
211  << s << " - " << sample->weight
212  << " (L=" << logTarget << ")";
213 
214  if (sample->HasMeta("QOI"))
215  graphfile << " QOI";
216 
217  graphfile << "\"]" << std::endl;
218  }
219  graphfile << "}" << std::endl;
220  for (int s = 0; s < chain->GetSamples()->size(); s++) {
221  std::shared_ptr<SamplingState> sample = chain->GetSamples()->at(s);
222  std::string nodeid = "\"s" + chainid + "node" + std::to_string(s) + "\"";
223 
224  if (s < chain->GetSamples()->size() - 1)
225  graphfile << nodeid << " -> " << "\"s" << chainid << "node" << s+1 << "\"" << std::endl;
226 
227  if (sample->HasMeta("coarseSample")) {
228  std::shared_ptr<SamplingState> coarseSample = AnyCast(sample->meta["coarseSample"]);
229  if (coarseSample->HasMeta("gvizid")) {
230  std::string coarseid = AnyCast(coarseSample->meta["gvizid"]);
231  graphfile << nodeid << " -> " << coarseid << std::endl;
232  } else {
233  std::cout << "no gvizid!" << std::endl;
234  }
235  }
236  }
237 }
238 
239 void MIMCMCBox::Draw(std::ofstream& graphfile, bool drawSamples) const {
240 
241  if (drawSamples) {
242  for (int i = 0; i < tailChains.size(); i++) {
243  std::string chainid = "box" + boxHighestIndex->ToString() + "_tail" + std::to_string(i) + "";
244 
245  DrawChain (tailChains[i], chainid, graphfile);
246  }
247 
248  for (int i = 0; i < boxIndices->Size(); i++) {
249  std::shared_ptr<MultiIndex> boxIndex = (*boxIndices)[i];
250  std::shared_ptr<SingleChainMCMC> singleChain = boxChains[boxIndices->MultiToIndex(boxIndex)];
251 
252  std::string chainid = "box" + boxHighestIndex->ToString() + "_node" + boxIndex->ToString() + "";
253  DrawChain (singleChain, chainid, graphfile);
254  }
255  } else {
256  std::string previd = "";
257  for (int i = 0; i < tailChains.size(); i++) {
258  std::string chainid = "\"box" + boxHighestIndex->ToString() + "_tail" + std::to_string(i) + "\"";
259  if (i > 0)
260  graphfile << chainid << " -> " << previd << std::endl;
261  else
262  graphfile << chainid << std::endl;
263  previd = chainid;
264  }
265 
266  for (int i = 0; i < boxIndices->Size(); i++) {
267  std::shared_ptr<MultiIndex> boxIndex = (*boxIndices)[i];
268  std::shared_ptr<SingleChainMCMC> singleChain = boxChains[boxIndices->MultiToIndex(boxIndex)];
269 
270  std::string chainid = "\"box" + boxHighestIndex->ToString() + "_node" + boxIndex->ToString() + "\"";
271 
272  if (previd != "")
273  graphfile << chainid << " -> " << previd << std::endl;
274  else
275  graphfile << chainid << std::endl;
276  if (i == 0)
277  previd = chainid;
278  }
279  }
280 }
281 
282 std::shared_ptr<SingleChainMCMC> MIMCMCBox::FinestChain() {
283  std::shared_ptr<MultiIndex> boxSize = std::make_shared<MultiIndex>(*boxHighestIndex - *boxLowestIndex);
284  return boxChains[boxIndices->MultiToIndex(boxSize)];
285 }
286 
287 std::shared_ptr<MultiIndexSet> MIMCMCBox::GetBoxIndices() {
288  return boxIndices;
289 }
290 
291 std::shared_ptr<SingleChainMCMC> MIMCMCBox::GetChain(std::shared_ptr<MultiIndex> boxIndex) {
292  int index = boxIndices->MultiToIndex(boxIndex);
293  if (index < 0)
294  return nullptr;
295  return boxChains[index];
296 }
297 
298 std::shared_ptr<MultiIndexSet> MIMCMCBox::CreateRootPath(std::shared_ptr<MultiIndex> index) {
299 
300  // create an empy multiindex set
301  std::shared_ptr<MultiIndexLimiter> limiter = std::make_shared<NoLimiter>();
302  std::shared_ptr<MultiIndexSet> output = std::make_shared<MultiIndexSet>(index->GetLength(),limiter);
303 
304  // Always go down one step in direction of largest index value until reaching root index
305  std::shared_ptr<MultiIndex> currentIndex = index;
306  output->AddActive(currentIndex);
307 
308  while (true) {
309 
310  int maxCoeffId;
311  int maxEntry = currentIndex->GetVector().maxCoeff(&maxCoeffId);
312  if (maxEntry == 0)
313  break;
314 
315  std::shared_ptr<MultiIndex> nextIndex = MultiIndex::Copy(currentIndex);
316  nextIndex->SetValue(maxCoeffId, maxEntry - 1);
317  output->AddActive(nextIndex);
318 
319  currentIndex = nextIndex;
320  }
321 
322  return output;
323 }
std::shared_ptr< SingleChainMCMC > FinestChain()
Definition: MIMCMCBox.cpp:282
void Draw(std::ofstream &graphfile, bool drawSamples=true) const
Definition: MIMCMCBox.cpp:239
void DrawChain(std::shared_ptr< SingleChainMCMC > chain, std::string chainid, std::ofstream &graphfile) const
Definition: MIMCMCBox.cpp:201
std::shared_ptr< SampleCollection > QOIDiff
Definition: MIMCMCBox.h:65
MIMCMCBox(std::shared_ptr< MIComponentFactory > componentFactory, std::shared_ptr< MultiIndex > boxHighestIndex)
Definition: MIMCMCBox.cpp:8
std::shared_ptr< AbstractSamplingProblem > finestProblem
Definition: MIMCMCBox.h:73
std::shared_ptr< MultiIndexSet > boxIndices
Definition: MIMCMCBox.h:70
std::shared_ptr< MultiIndex > boxHighestIndex
Definition: MIMCMCBox.h:68
std::shared_ptr< AbstractSamplingProblem > GetFinestProblem()
Definition: MIMCMCBox.cpp:115
std::shared_ptr< MultiIndex > GetLowestIndex()
Definition: MIMCMCBox.cpp:111
std::shared_ptr< MIComponentFactory > componentFactory
Definition: MIMCMCBox.h:67
std::vector< std::shared_ptr< SingleChainMCMC > > tailChains
Definition: MIMCMCBox.h:72
std::shared_ptr< MultiIndexSet > CreateRootPath(std::shared_ptr< MultiIndex > index)
Definition: MIMCMCBox.cpp:298
std::shared_ptr< MultiIndexSet > GetBoxIndices()
Definition: MIMCMCBox.cpp:287
std::vector< std::shared_ptr< SingleChainMCMC > > boxChains
Definition: MIMCMCBox.h:71
std::shared_ptr< MultiIndex > GetHighestIndex()
Definition: MIMCMCBox.cpp:107
void WriteToFile(std::string filename)
Definition: MIMCMCBox.cpp:162
std::shared_ptr< SingleChainMCMC > GetChain(std::shared_ptr< MultiIndex > index)
Definition: MIMCMCBox.cpp:291
std::shared_ptr< SampleCollection > GetQOIDiff()
Definition: MIMCMCBox.cpp:176
std::shared_ptr< MultiIndex > boxLowestIndex
Definition: MIMCMCBox.h:69
A class for storing and working with the results of Markov chain Monte Carlo algorithms.
Definition: MarkovChain.h:20
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25172