MUQ  0.4.3
DILIKernel.cpp
Go to the documentation of this file.
2 
11 #include "MUQ/Modeling/WorkGraph.h"
13 
14 using namespace muq::SamplingAlgorithms;
15 using namespace muq::Modeling;
16 
17 AverageHessian::AverageHessian(unsigned int numOldSamps,
18  std::shared_ptr<Eigen::ColPivHouseholderQR<Eigen::MatrixXd>> const& uQRIn,
19  std::shared_ptr<Eigen::MatrixXd> const& oldWIn,
20  std::shared_ptr<Eigen::VectorXd> const& oldValsIn,
21  std::shared_ptr<muq::Modeling::LinearOperator> const& newHessIn) : LinearOperator(newHessIn->rows(), newHessIn->cols()),
22  numSamps(numOldSamps),
23  uQR(uQRIn),
24  oldW(oldWIn),
25  oldEigVals(oldValsIn),
26  newHess(newHessIn)
27 {
28  assert(oldW->rows()>0);
29  assert(oldW->cols()>0);
30  assert(oldEigVals->size()==oldW->cols());
31 
32  thinQ = uQR->householderQ().setLength(uQR->nonzeroPivots()) * Eigen::MatrixXd::Identity(oldW->rows(), uQR->rank());
33 }
34 
35 Eigen::MatrixXd AverageHessian::Apply(Eigen::Ref<const Eigen::MatrixXd> const& x)
36 {
37  Eigen::MatrixXd result = newHess->Apply(x) / (numSamps+1.0);
38  result += (numSamps/(numSamps+1.0)) * ((*oldW) * oldEigVals->asDiagonal()* uQR->colsPermutation() * uQR->matrixR().topLeftCorner(uQR->rank(), uQR->rank()).template triangularView<Eigen::Upper>().solve(thinQ.transpose() * x));
39 
40  return result;
41 }
42 
43 Eigen::MatrixXd AverageHessian::ApplyTranspose(Eigen::Ref<const Eigen::MatrixXd> const& x)
44 {
45  return Apply(x);
46 }
47 
48 
49 Eigen::MatrixXd CSProjector::Apply(Eigen::Ref<const Eigen::MatrixXd> const& x)
50 {
51  return x - U->leftCols(lisDim)*W->leftCols(lisDim).transpose() * x;
52 }
53 
54 Eigen::MatrixXd CSProjector::ApplyTranspose(Eigen::Ref<const Eigen::MatrixXd> const& x)
55 {
56  return x - W->leftCols(lisDim)*U->leftCols(lisDim).transpose() * x;
57 }
58 
59 Eigen::MatrixXd LIS2Full::Apply(Eigen::Ref<const Eigen::MatrixXd> const& x)
60 {
61  return U->leftCols(lisDim) * L->asDiagonal() * x;
62 }
63 
64 Eigen::MatrixXd LIS2Full::ApplyTranspose(Eigen::Ref<const Eigen::MatrixXd> const& x)
65 {
66  return L->asDiagonal() * U->leftCols(lisDim).transpose() * x;
67 }
68 
69 
70 
71 DILIKernel::DILIKernel(boost::property_tree::ptree const& pt,
72  std::shared_ptr<AbstractSamplingProblem> problem) : DILIKernel(pt,
73  problem,
74  ExtractPrior(problem, pt.get("Prior Node", "Prior")),
75  ExtractLikelihood(problem,pt.get("Likelihood Node", "Likelihood")))
76 {
77 }
78 
79 DILIKernel::DILIKernel(boost::property_tree::ptree const& pt,
80  std::shared_ptr<AbstractSamplingProblem> problem,
81  Eigen::VectorXd const& genEigVals,
82  Eigen::MatrixXd const& genEigVecs) : DILIKernel(pt,
83  problem,
84  ExtractPrior(problem, pt.get("Prior Node", "Prior")),
85  ExtractLikelihood(problem,pt.get("Likelihood Node", "Likelihood")),
86  genEigVals,
87  genEigVecs)
88 {
89 }
90 
91 
92 DILIKernel::DILIKernel(boost::property_tree::ptree const& pt,
93  std::shared_ptr<AbstractSamplingProblem> problem,
94  std::shared_ptr<muq::Modeling::GaussianBase> const& priorIn,
95  std::shared_ptr<muq::Modeling::ModPiece> const& noiseModelIn,
96  std::shared_ptr<muq::Modeling::ModPiece> const& forwardModelIn) : TransitionKernel(pt,problem),
97  lisKernelOpts(pt.get_child(pt.get<std::string>("LIS Block"))),
98  csKernelOpts(pt.get_child(pt.get<std::string>("CS Block"))),
99  logLikelihood(CreateLikelihood(forwardModelIn,noiseModelIn)),
100  prior(priorIn),
101  forwardModel(forwardModelIn),
102  noiseDensity(noiseModelIn),
103  hessType(pt.get("HessianType","GaussNewton")),
104  updateInterval(pt.get("Adapt Interval",-1)),
105  adaptStart(pt.get("Adapt Start",1)),
106  adaptEnd(pt.get("Adapt End", -1)),
107  initialHessSamps(pt.get("Initial Weight",100)),
108  hessValTol(pt.get("Hessian Tolerance",1e-4)),
109  lisValTol(pt.get("LIS Tolerance", 0.1))
110 {
111  try{
112  std::string blockName = pt.get<std::string>("Eigensolver Block");
113  eigOpts = pt.get_child(blockName);
114  }catch(const boost::property_tree::ptree_bad_path&){
115  // Do nothing, just leave the solver options ptree empty
116  }
117 }
118 
119 DILIKernel::DILIKernel(boost::property_tree::ptree const& pt,
120  std::shared_ptr<AbstractSamplingProblem> problem,
121  std::shared_ptr<muq::Modeling::GaussianBase> const& priorIn,
122  std::shared_ptr<muq::Modeling::ModPiece> const& noiseModelIn,
123  std::shared_ptr<muq::Modeling::ModPiece> const& forwardModelIn,
124  Eigen::VectorXd const& genEigVals,
125  Eigen::MatrixXd const& genEigVecs) : TransitionKernel(pt,problem),
126  lisKernelOpts(pt.get_child(pt.get<std::string>("LIS Block"))),
127  csKernelOpts(pt.get_child(pt.get<std::string>("CS Block"))),
128  logLikelihood(CreateLikelihood(forwardModelIn,noiseModelIn)),
129  prior(priorIn),
130  forwardModel(forwardModelIn),
131  noiseDensity(noiseModelIn),
132  hessType(pt.get("HessianType","GaussNewton")),
133  updateInterval(pt.get("Adapt Interval",-1)),
134  adaptStart(pt.get("Adapt Start",1)),
135  adaptEnd(pt.get("Adapt End", -1)),
136  initialHessSamps(pt.get("Initial Weight",100)),
137  hessValTol(pt.get("Hessian Tolerance",1e-4)),
138  lisValTol(pt.get("LIS Tolerance", 0.1))
139 {
140  try{
141  std::string blockName = pt.get<std::string>("Eigensolver Block");
142  eigOpts = pt.get_child(blockName);
143  }catch(const boost::property_tree::ptree_bad_path&){
144  // Do nothing, just leave the solver options ptree empty
145  }
146 
147  SetLIS(genEigVals, genEigVecs);
148 }
149 
150 DILIKernel::DILIKernel(boost::property_tree::ptree const& pt,
151  std::shared_ptr<AbstractSamplingProblem> problem,
152  std::shared_ptr<muq::Modeling::GaussianBase> const& priorIn,
153  std::shared_ptr<muq::Modeling::ModPiece> const& likelihoodIn) : TransitionKernel(pt,problem),
154  lisKernelOpts(pt.get_child(pt.get<std::string>("LIS Block"))),
155  csKernelOpts(pt.get_child(pt.get<std::string>("CS Block"))),
156  logLikelihood(likelihoodIn),
157  prior(priorIn),
158  forwardModel(ExtractForwardModel(likelihoodIn)),
159  noiseDensity(ExtractNoiseModel(likelihoodIn)),
160  hessType(pt.get("HessianType","GaussNewton")),
161  updateInterval(pt.get("Adapt Interval",-1)),
162  adaptStart(pt.get("Adapt Start",1)),
163  adaptEnd(pt.get("Adapt End", -1)),
164  initialHessSamps(pt.get("Initial Weight",100)),
165  hessValTol(pt.get("Hessian Tolerance",1e-4)),
166  lisValTol(pt.get("LIS Tolerance", 0.1))
167 {
168  try{
169  std::string blockName = pt.get<std::string>("Eigensolver Block");
170  eigOpts = pt.get_child(blockName);
171  }catch(const boost::property_tree::ptree_bad_path&){
172  // Do nothing, just leave the solver options ptree empty
173  }
174 }
175 
176 DILIKernel::DILIKernel(boost::property_tree::ptree const& pt,
177  std::shared_ptr<AbstractSamplingProblem> problem,
178  std::shared_ptr<muq::Modeling::GaussianBase> const& priorIn,
179  std::shared_ptr<muq::Modeling::ModPiece> const& likelihoodIn,
180  Eigen::VectorXd const& genEigVals,
181  Eigen::MatrixXd const& genEigVecs) : TransitionKernel(pt,problem),
182  lisKernelOpts(pt.get_child(pt.get<std::string>("LIS Block"))),
183  csKernelOpts(pt.get_child(pt.get<std::string>("CS Block"))),
184  logLikelihood(likelihoodIn),
185  prior(priorIn),
186  forwardModel(ExtractForwardModel(likelihoodIn)),
187  noiseDensity(ExtractNoiseModel(likelihoodIn)),
188  hessType(pt.get("HessianType","GaussNewton")),
189  updateInterval(pt.get("Adapt Interval",-1)),
190  adaptStart(pt.get("Adapt Start",1)),
191  adaptEnd(pt.get("Adapt End", -1)),
192  initialHessSamps(pt.get("Initial Weight",100)),
193  hessValTol(pt.get("Hessian Tolerance",1e-4)),
194  lisValTol(pt.get("LIS Tolerance", 0.1))
195 {
196  try{
197  std::string blockName = pt.get<std::string>("Eigensolver Block");
198  eigOpts = pt.get_child(blockName);
199  }catch(const boost::property_tree::ptree_bad_path&){
200  // Do nothing, just leave the solver options ptree empty
201  }
202 
203  SetLIS(genEigVals, genEigVecs);
204 }
205 
206 void DILIKernel::PostStep(unsigned int const t,
207  std::vector<std::shared_ptr<SamplingState>> const& state)
208 {
209  if((updateInterval>0)&&((t%updateInterval)<=state.size())&&(t>=adaptStart)&&((t<adaptEnd)||(adaptEnd<0))){
210  numLisUpdates++;
211  UpdateLIS(numLisUpdates, state.at(state.size()-1)->state);
212  }
213 }
214 
215 Eigen::VectorXd DILIKernel::ToLIS(Eigen::VectorXd const& x) const
216 {
217  return lisL->array().inverse().matrix().asDiagonal() * hessW->leftCols(lisDim).transpose()*x;
218 }
219 
223 Eigen::VectorXd DILIKernel::FromLIS(Eigen::VectorXd const& r) const
224 {
225  assert(lisDim>0);
226  return hessU->leftCols(lisDim)*lisL->asDiagonal()*r;
227 }
228 
229 Eigen::VectorXd DILIKernel::ToCS(Eigen::VectorXd const& x) const
230 {
231  return x - hessU->leftCols(lisDim) * hessW->leftCols(lisDim).transpose() * x;
232 }
233 
234 
235 std::vector<std::shared_ptr<SamplingState>> DILIKernel::Step(unsigned int const t,
236  std::shared_ptr<SamplingState> prevState)
237 {
238  if(hessU==nullptr){
239  CreateLIS(prevState->state);
240  }
241 
242  std::vector<Eigen::VectorXd> splitVec(2);
243  // Special handling of case when no LIS exists
244  if(lisDim==0){
245  splitVec.at(1) = prevState->state.at(blockInd);
246  std::shared_ptr<SamplingState> splitState = std::make_shared<SamplingState>(splitVec);
247  splitState->meta = prevState->meta;
248 
249  auto nextSteps = csKernel->Step(t, splitState);
250 
251  std::vector<std::shared_ptr<SamplingState>> output(nextSteps.size());
252  for(unsigned int i=0; i<nextSteps.size(); ++i){
253  output.at(i) = std::make_shared<SamplingState>(prevState->state);
254  output.at(i)->state.at(blockInd) = nextSteps.at(i)->state.at(1);
255  output.at(i)->meta = nextSteps.at(i)->meta;
256  }
257 
258  return output;
259  }
260 
261 
262  splitVec.at(0) = ToLIS(prevState->state.at(blockInd) );
263  splitVec.at(1) = prevState->state.at(blockInd);
264 
265  std::shared_ptr<SamplingState> splitState = std::make_shared<SamplingState>(splitVec);
266  splitState->meta = prevState->meta;
267 
268  // Take the alternating Metropolis-in-Gibbs steps for the LIS and CS
269  std::vector<std::shared_ptr<SamplingState>> nextSteps = lisKernel->Step(t, splitState);
270  std::vector<std::shared_ptr<SamplingState>> nextSteps2 = csKernel->Step(t+nextSteps.size(), nextSteps.back());
271 
272  // Combine the states and return the results
273  std::vector<std::shared_ptr<SamplingState>> output(nextSteps.size() + nextSteps2.size());
274  Eigen::VectorXd x;
275  for(unsigned int i=0; i<nextSteps.size(); ++i){
276  x = FromLIS( nextSteps.at(i)->state.at(0) );
277  x += ToCS(nextSteps.at(i)->state.at(1));
278 
279  output.at(i) = std::make_shared<SamplingState>(prevState->state);
280  output.at(i)->state.at(blockInd) = x;
281  //output.at(i)->meta = nextSteps.at(i)->meta;
282  }
283 
284  for(unsigned int i=0; i<nextSteps2.size(); ++i){
285  x = FromLIS( nextSteps2.at(i)->state.at(0) );
286  x += ToCS( nextSteps2.at(i)->state.at(1) );
287  output.at(i+nextSteps.size()) = std::make_shared<SamplingState>(prevState->state);
288  output.at(i+nextSteps.size())->state.at(blockInd) = x;
289  //output.at(i+nextSteps.size())->meta = nextSteps2.at(i)->meta;
290  }
291 
292  return output;
293 }
294 
295 void DILIKernel::PrintStatus(std::string prefix) const
296 {
297  std::stringstream lisStream;
298  lisStream << prefix << " LIS (dim=" << lisDim << "): ";
299  std::string newPrefix = lisStream.str();
300  lisKernel->PrintStatus(newPrefix);
301  newPrefix = prefix + " CS: ";
302  csKernel->PrintStatus(newPrefix);
303 }
304 
305 void DILIKernel::SetLIS(Eigen::VectorXd const& eigVals, Eigen::MatrixXd const& eigVecs)
306 {
307  bool subDimChange = false;
308  if(hessU==nullptr)
309  subDimChange = true;
310 
311  assert(eigVals(1)<eigVals(0));
312 
313  hessU = std::make_shared<Eigen::MatrixXd>(eigVecs);
314  hessUQR = std::make_shared<Eigen::ColPivHouseholderQR<Eigen::MatrixXd>>(eigVecs);
315 
316  hessW = std::make_shared<Eigen::MatrixXd>(prior->ApplyPrecision(eigVecs));
317  hessEigVals = std::make_shared<Eigen::VectorXd>(eigVals);
318 
319  // Figure out the dimension of the LIS
320  int oldLisDim = lisDim;
321  for(lisDim=0; lisDim<eigVals.size(); ++lisDim){
322  if(eigVals(lisDim)<lisValTol)
323  break;
324  }
325 
326  if(oldLisDim!=lisDim)
327  subDimChange = true;
328 
329  // Estimate the subspace covariance based on the posterior Hessian
330  Eigen::VectorXd deltaVec = eigVals.head(lisDim).array()/(1.0+eigVals.head(lisDim).array());
331  lisL = std::make_shared<Eigen::VectorXd>((Eigen::VectorXd::Ones(lisDim) - deltaVec).array().sqrt());
332 
333  // If the dimension of the subspace has changed, we need to recreate the transition kernels
334  if(subDimChange)
335  UpdateKernels();
336 }
337 
338 std::pair<Eigen::MatrixXd, Eigen::VectorXd> DILIKernel::ComputeLocalLIS(std::vector<Eigen::VectorXd> const& currState)
339 {
340  // First, set up the hessian operator for the log-likelihood
341  std::shared_ptr<LinearOperator> hessOp;
342  if(hessType=="Exact"){
343  assert(logLikelihood);
344  hessOp = std::make_shared<HessianOperator>(logLikelihood, currState, 0, blockInd, blockInd, Eigen::VectorXd::Ones(1), -1.0, 0.0);
345 
346  }else if(hessType=="GaussNewton"){
347  assert(forwardModel);
348  assert(noiseDensity);
349  hessOp = std::make_shared<GaussNewtonOperator>(forwardModel, noiseDensity, currState, blockInd, -1.0, 0.0);
350 
351  }else{
352  std::cerr << "\nERROR: Unrecognized Hessian type. Options are \"Exact\" or \"GaussNewton\".\n\n";
353  }
354 
355  // Set up the prior precision operator
356  std::shared_ptr<LinearOperator> precOp = std::make_shared<GaussianOperator>(prior, Gaussian::Precision);
357  std::shared_ptr<LinearOperator> covOp = std::make_shared<GaussianOperator>(prior, Gaussian::Covariance);
358 
359  // Solve the generalized Eigenvalue problem using StochasticEigenSolver
360  eigOpts.put("AbsoluteTolerance", lisValTol); // <- We are computing the local LIS, so use the local tolerance
361  if(lisDim>0){
362  eigOpts.put("ExpectedRank", lisDim);
363  eigOpts.put("NumEigs", 2*lisDim);
364  }
365 
367  solver.compute(hessOp, precOp, covOp);
368 
369  return std::make_pair(solver.eigenvectors(), solver.eigenvalues());
370 }
371 
372 void DILIKernel::CreateLIS(std::vector<Eigen::VectorXd> const& currState)
373 {
374  numLisUpdates = 0;
375 
376  Eigen::MatrixXd vecs;
377  Eigen::VectorXd vals;
378  std::tie(vecs,vals) = ComputeLocalLIS(currState);
379 
380  SetLIS(vals, vecs);
381 }
382 
384 {
385  lisToFull = std::make_shared<LIS2Full>(hessU,lisL);
386  fullToCS = std::make_shared<CSProjector>(hessU, hessW, lisDim);
387 
388  // Create a new graph for the split likelihood
389  std::shared_ptr<WorkGraph> graph = std::make_shared<WorkGraph>();
390  graph->AddNode(std::make_shared<SumPiece>(prior->Dimension(), 2), "Parameters");
391  graph->AddNode(lisToFull, "Informed Parameters");
392  graph->AddNode(fullToCS, "Complementary Parameters");
393  graph->AddNode(logLikelihood, "Likelihood");
394  graph->AddNode(prior->AsDensity(), "Prior");
395  graph->AddNode(std::make_shared<DensityProduct>(2), "Posterior");
396  graph->AddEdge("Informed Parameters",0, "Parameters",0);
397  graph->AddEdge("Complementary Parameters",0, "Parameters",1);
398  graph->AddEdge("Parameters",0,"Prior",0);
399  graph->AddEdge("Parameters",0,"Likelihood",0);
400  graph->AddEdge("Prior",0,"Posterior",0);
401  graph->AddEdge("Likelihood",0,"Posterior",1);
402 
403  auto prob = std::make_shared<SamplingProblem>(graph->CreateModPiece("Posterior"));
404 
405  lisKernelOpts.put("BlockIndex",0);
407 
408  csKernelOpts.put("BlockIndex",1);
410 
411 }
412 
413 void DILIKernel::UpdateLIS(unsigned int numSamps,
414  std::vector<Eigen::VectorXd> const& currState)
415 {
416  std::shared_ptr<LinearOperator> hessOp, newOp, precOp, covOp;
417  if(hessType=="Exact"){
418  newOp = std::make_shared<HessianOperator>(logLikelihood, currState, 0, blockInd, blockInd, Eigen::VectorXd::Ones(1), -1.0, 0.0);
419  }else if(hessType=="GaussNewton"){
420  newOp = std::make_shared<GaussNewtonOperator>(forwardModel, noiseDensity, currState, blockInd, -1.0, 0.0);
421  }else{
422  std::cerr << "\nERROR: Unrecognized Hessian type. Options are \"Exact\" or \"GaussNewton\".\n\n";
423  }
424 
425  hessOp = std::make_shared<AverageHessian>(numSamps+initialHessSamps, hessUQR, hessW, hessEigVals, newOp);
426  precOp = std::make_shared<GaussianOperator>(prior, Gaussian::Precision);
427  covOp = std::make_shared<GaussianOperator>(prior, Gaussian::Covariance);
428 
429  eigOpts.put("AbsoluteTolerance", hessValTol);
430  if(hessEigVals!=nullptr){
431  eigOpts.put("ExpectedRank", hessEigVals->size());
432  eigOpts.put("NumEigs", 2*hessEigVals->size());
433  }
434 
436  solver.compute(hessOp, precOp, covOp);
437 
438  SetLIS(solver.eigenvalues(), solver.eigenvectors());
439 }
440 
441 std::shared_ptr<muq::Modeling::GaussianBase> DILIKernel::ExtractPrior(std::shared_ptr<AbstractSamplingProblem> const& problem,
442  std::string const& nodeName)
443 {
444  // First, try to cast the abstract problem to a regular sampling problem
445  auto regProb = std::dynamic_pointer_cast<SamplingProblem>(problem);
446  if(!regProb){
447  throw std::runtime_error("In DILIKernel::ExtractPrior: Could not cast AbstractSamplingProblem instance into SamplingProblem.");
448  }
449 
450  // Try to pull out the ModGraphPiece from the sampling problem and try to cast as ModGraphPiece
451  auto postPiece = regProb->GetDistribution();
452  auto postGraphPiece = std::dynamic_pointer_cast<ModGraphPiece>(postPiece);
453  if(!postGraphPiece){
454  throw std::runtime_error("In DILIKernel::ExtractPrior: Could not cast Posterior ModPiece to ModGraphPiece.");
455  }
456 
457  std::shared_ptr<muq::Modeling::WorkPiece> priorWork = postGraphPiece->GetGraph()->GetPiece(nodeName);
458  std::shared_ptr<muq::Modeling::Density> priorDens = std::dynamic_pointer_cast<Density>(priorWork);
459  if(!priorDens){
460  throw std::runtime_error("In DILIKernel::ExtractPrior: Could not cast prior WorkPiece to Density.");
461  }
462 
463  std::shared_ptr<muq::Modeling::GaussianBase> output = std::dynamic_pointer_cast<GaussianBase>(priorDens->GetDistribution());
464  if(!output){
465  throw std::runtime_error("In DILIKernel::ExtractPrior: Could not cast prior distribution to GaussianBase.");
466  }
467 
468  return output;
469 }
470 
471 std::shared_ptr<muq::Modeling::ModPiece> DILIKernel::ExtractNoiseModel(std::shared_ptr<muq::Modeling::ModPiece> const& likelihood)
472 {
473  auto likelyGraphPiece = std::dynamic_pointer_cast<ModGraphPiece>(likelihood);
474  if(!likelyGraphPiece){
475  throw std::runtime_error("In DILIKernel::ExtractNoiseModel: Could not cast likelihood ModPiece to ModGraphPiece.");
476  }
477 
478  return likelyGraphPiece->GetOutputPiece();
479 }
480 
481 std::shared_ptr<muq::Modeling::ModPiece> DILIKernel::ExtractForwardModel(std::shared_ptr<muq::Modeling::ModPiece> const& likelihoodIn)
482 {
483  if(likelihoodIn->inputSizes.size()!=1)
484  throw std::runtime_error("In DILIKernel::ExtractForwardModel: Could not detect forward model because likelihood piece has more than one input.");
485 
486  auto likelyGraphPiece = std::dynamic_pointer_cast<ModGraphPiece>(likelihoodIn);
487  if(!likelyGraphPiece){
488  throw std::runtime_error("In DILIKernel::ExtractForwardModel: Could not cast likelihood ModPiece to ModGraphPiece.");
489  }
490 
491  // Get the name of the output node
492  auto graph = likelyGraphPiece->GetGraph();
493  std::vector<std::string> modelNames = graph->GetParents(likelyGraphPiece->GetOutputName());
494 
495  return likelyGraphPiece->GetSubModel(modelNames.at(0));
496 }
497 
498 std::shared_ptr<muq::Modeling::ModPiece> DILIKernel::ExtractLikelihood(std::shared_ptr<AbstractSamplingProblem> const& problem,
499  std::string const& nodeName)
500 {
501  // First, try to cast the abstract problem to a regular sampling problem
502  auto regProb = std::dynamic_pointer_cast<SamplingProblem>(problem);
503  if(!regProb){
504  throw std::runtime_error("In DILIKernel::ExtractLikelihood: Could not cast AbstractSamplingProblem instance into SamplingProblem.");
505  }
506 
507  // Try to pull out the ModGraphPiece from the sampling problem and try to cast as ModGraphPiece
508  auto postPiece = regProb->GetDistribution();
509  auto postGraphPiece = std::dynamic_pointer_cast<ModGraphPiece>(postPiece);
510  if(!postGraphPiece){
511  throw std::runtime_error("In DILIKernel::ExtractLikelihood: Could not cast Posterior ModPiece to ModGraphPiece.");
512  }
513 
514  std::shared_ptr<muq::Modeling::ModPiece> likelihood = postGraphPiece->GetSubModel(nodeName);
515 
516  return likelihood;
517 }
518 
519 std::shared_ptr<muq::Modeling::ModPiece> DILIKernel::CreateLikelihood(std::shared_ptr<muq::Modeling::ModPiece> const& forwardModel,
520  std::shared_ptr<muq::Modeling::ModPiece> const& noiseDensity)
521 {
522  WorkGraph graph;
523  graph.AddNode(forwardModel, "Forward Model");
524  graph.AddNode(noiseDensity, "Likelihood");
525  graph.AddEdge("Forward Model", 0, "Likelihood",0);
526  return graph.CreateModPiece("Likelihood");
527 }
Eigen::VectorXd const & eigenvalues() const
Eigen::MatrixXd const & eigenvectors() const
Generic linear operator base class.
Two-pass stochastic algorithm for computing generalized eigenvalues from matrix products.
virtual StochasticEigenSolver & compute(std::shared_ptr< LinearOperator > const &A, std::shared_ptr< LinearOperator > B=nullptr, std::shared_ptr< LinearOperator > Binv=nullptr)
A graph of connected muq::Modeling::WorkPiece's.
Definition: WorkGraph.h:20
void AddNode(std::shared_ptr< WorkPiece > input, std::string const &name)
Add a new node to the graph.
Definition: WorkGraph.cpp:195
void AddEdge(std::string const &nameFrom, unsigned int const outputDim, std::string const &nameTo, unsigned int const inputDim)
Add a new edge to the graph.
Definition: WorkGraph.cpp:206
std::shared_ptr< ModGraphPiece > CreateModPiece(std::string const &node, std::vector< std::string > const &inNames=std::vector< std::string >()) const
Create a muq::Modeling::ModPiece whose output matches a given node.
Definition: WorkGraph.cpp:591
virtual Eigen::MatrixXd Apply(Eigen::Ref< const Eigen::MatrixXd > const &x) override
Definition: DILIKernel.cpp:35
AverageHessian(unsigned int numOldSamps, std::shared_ptr< Eigen::ColPivHouseholderQR< Eigen::MatrixXd >> const &uQRIn, std::shared_ptr< Eigen::MatrixXd > const &oldWIn, std::shared_ptr< Eigen::VectorXd > const &oldValsIn, std::shared_ptr< muq::Modeling::LinearOperator > const &newHess)
Definition: DILIKernel.cpp:17
std::shared_ptr< muq::Modeling::LinearOperator > newHess
Definition: DILIKernel.h:67
std::shared_ptr< Eigen::VectorXd > oldEigVals
Definition: DILIKernel.h:66
std::shared_ptr< Eigen::MatrixXd > oldW
Definition: DILIKernel.h:63
virtual Eigen::MatrixXd ApplyTranspose(Eigen::Ref< const Eigen::MatrixXd > const &x) override
Definition: DILIKernel.cpp:43
std::shared_ptr< Eigen::ColPivHouseholderQR< Eigen::MatrixXd > > uQR
Definition: DILIKernel.h:64
std::shared_ptr< Eigen::MatrixXd > W
Definition: DILIKernel.h:90
virtual Eigen::MatrixXd ApplyTranspose(Eigen::Ref< const Eigen::MatrixXd > const &x) override
Definition: DILIKernel.cpp:54
std::shared_ptr< Eigen::MatrixXd > U
Definition: DILIKernel.h:90
virtual Eigen::MatrixXd Apply(Eigen::Ref< const Eigen::MatrixXd > const &x) override
Definition: DILIKernel.cpp:49
An implementation of the Dimension Independent Likelihood Informed subspace (DILI) MCMC sampler.
Definition: DILIKernel.h:141
boost::property_tree::ptree csKernelOpts
Definition: DILIKernel.h:264
virtual std::vector< std::shared_ptr< SamplingState > > Step(unsigned int const t, std::shared_ptr< SamplingState > prevState) override
Definition: DILIKernel.cpp:235
std::shared_ptr< muq::Modeling::LinearOperator > lisToFull
Definition: DILIKernel.h:288
std::shared_ptr< Eigen::ColPivHouseholderQR< Eigen::MatrixXd > > hessUQR
Definition: DILIKernel.h:276
static std::shared_ptr< muq::Modeling::ModPiece > CreateLikelihood(std::shared_ptr< muq::Modeling::ModPiece > const &forwardModel, std::shared_ptr< muq::Modeling::ModPiece > const &noiseDensity)
Definition: DILIKernel.cpp:519
std::shared_ptr< muq::Modeling::GaussianBase > prior
Definition: DILIKernel.h:267
void UpdateLIS(unsigned int numSamps, std::vector< Eigen::VectorXd > const &currState)
Definition: DILIKernel.cpp:413
std::shared_ptr< Eigen::MatrixXd > hessW
Definition: DILIKernel.h:282
std::shared_ptr< TransitionKernel > lisKernel
Definition: DILIKernel.h:294
boost::property_tree::ptree eigOpts
Definition: DILIKernel.h:303
std::pair< Eigen::MatrixXd, Eigen::VectorXd > ComputeLocalLIS(std::vector< Eigen::VectorXd > const &currState)
Definition: DILIKernel.cpp:338
Eigen::VectorXd FromLIS(Eigen::VectorXd const &r) const
Definition: DILIKernel.cpp:223
std::shared_ptr< muq::Modeling::ModPiece > noiseDensity
Definition: DILIKernel.h:270
std::shared_ptr< Eigen::VectorXd > hessEigVals
Definition: DILIKernel.h:279
static std::shared_ptr< muq::Modeling::ModPiece > ExtractLikelihood(std::shared_ptr< AbstractSamplingProblem > const &problem, std::string const &nodeName)
Definition: DILIKernel.cpp:498
void SetLIS(Eigen::VectorXd const &eigVals, Eigen::MatrixXd const &eigVecs)
Definition: DILIKernel.cpp:305
boost::property_tree::ptree lisKernelOpts
Definition: DILIKernel.h:263
std::shared_ptr< muq::Modeling::ModPiece > logLikelihood
Definition: DILIKernel.h:266
static std::shared_ptr< muq::Modeling::ModPiece > ExtractForwardModel(std::shared_ptr< muq::Modeling::ModPiece > const &likelihoodIn)
Definition: DILIKernel.cpp:481
std::shared_ptr< Eigen::MatrixXd > hessU
Definition: DILIKernel.h:273
static std::shared_ptr< muq::Modeling::ModPiece > ExtractNoiseModel(std::shared_ptr< muq::Modeling::ModPiece > const &likelihood)
Definition: DILIKernel.cpp:471
Eigen::VectorXd ToLIS(Eigen::VectorXd const &x) const
Definition: DILIKernel.cpp:215
std::shared_ptr< TransitionKernel > csKernel
Definition: DILIKernel.h:297
static std::shared_ptr< muq::Modeling::GaussianBase > ExtractPrior(std::shared_ptr< AbstractSamplingProblem > const &problem, std::string const &nodeName)
Definition: DILIKernel.cpp:441
void CreateLIS(std::vector< Eigen::VectorXd > const &currState)
Definition: DILIKernel.cpp:372
std::shared_ptr< muq::Modeling::ModPiece > forwardModel
Definition: DILIKernel.h:269
virtual void PostStep(unsigned int const t, std::vector< std::shared_ptr< SamplingState >> const &state) override
Allow the kernel to adapt given a new state.
Definition: DILIKernel.cpp:206
Eigen::VectorXd ToCS(Eigen::VectorXd const &x) const
Definition: DILIKernel.cpp:229
DILIKernel(boost::property_tree::ptree const &pt, std::shared_ptr< AbstractSamplingProblem > problem)
Definition: DILIKernel.cpp:71
std::shared_ptr< Eigen::VectorXd > lisL
Definition: DILIKernel.h:285
std::shared_ptr< muq::Modeling::LinearOperator > fullToCS
Definition: DILIKernel.h:291
std::shared_ptr< Eigen::MatrixXd > U
Definition: DILIKernel.h:111
std::shared_ptr< Eigen::VectorXd > L
Definition: DILIKernel.h:112
virtual Eigen::MatrixXd ApplyTranspose(Eigen::Ref< const Eigen::MatrixXd > const &x) override
Definition: DILIKernel.cpp:64
virtual Eigen::MatrixXd Apply(Eigen::Ref< const Eigen::MatrixXd > const &x) override
Definition: DILIKernel.cpp:59
Defines the transition kernel used by an MCMC algorithm.
static std::shared_ptr< TransitionKernel > Construct(boost::property_tree::ptree const &pt, std::shared_ptr< AbstractSamplingProblem > problem)
Static constructor for the transition kernel.
std::shared_ptr< AbstractSamplingProblem > problem
The sampling problem that evaluates/samples the target distribution.
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.h:3956