28 #include "FlowEquation.h"
50 #include <boost/property_tree/ptree.hpp>
80 Discretization(
unsigned int numCellsIn)
82 numCells = numCellsIn;
83 numNodes = numCells+1;
85 nodeLocs = Eigen::VectorXd::LinSpaced(numCells+1,0,1);
87 cellLocs.resize(1,numCells);
88 cellLocs.row(0) = 0.5*(nodeLocs.tail(numCells) + nodeLocs.head(numCells));
91 unsigned int numCells;
92 unsigned int numNodes;
95 Eigen::VectorXd nodeLocs;
98 Eigen::MatrixXd cellLocs;
143 double priorVar = 1.0;
144 double priorLength = 0.2;
145 double priorNu = 3.0/2.0;
147 auto covKernel = std::make_shared<MaternKernel>(1, priorVar, priorLength, priorNu);
149 auto meanFunc = std::make_shared<ZeroMean>(1,1);
151 auto priorGP = std::make_shared<GaussianProcess>(meanFunc,covKernel);
153 return priorGP->Discretize(mesh.cellLocs);
165 return (10.0*mesh.cellLocs.row(0)).array().cos();
172 Eigen::VectorXd
GenerateData(Discretization
const& mesh,
unsigned int obsThin,
double obsVar)
175 unsigned numRefine = 2;
176 Discretization fineMesh(numRefine*mesh.numCells);
180 Eigen::VectorXd recharge = Eigen::VectorXd::Ones(fineMesh.numCells);
181 auto mod = std::make_shared<FlowEquation>(recharge);
184 Eigen::VectorXd trueSol = mod->Evaluate( trueCond ).at(0);
187 auto slicer = std::make_shared<SliceOperator>(fineMesh.numNodes,0,fineMesh.numCells,numRefine*obsThin);
189 return slicer->Evaluate(trueSol).at(0) + std::sqrt(obsVar)*RandomGenerator::GetNormal(slicer->outputSizes(0));
215 std::shared_ptr<Gaussian>
const& priorDist,
216 Eigen::VectorXd
const& data,
217 unsigned int obsThin,
221 Eigen::VectorXd recharge = Eigen::VectorXd::Ones(mesh.numCells);
222 auto forwardMod = std::make_shared<FlowEquation>(recharge);
224 auto graph = std::make_shared<WorkGraph>();
229 graph->AddNode(std::make_shared<IdentityOperator>(mesh.numCells),
"Log Conductivity");
230 graph->AddNode(std::make_shared<ExpOperator>(mesh.numCells),
"Conductivity");
231 graph->AddEdge(
"Log Conductivity", 0,
"Conductivity", 0);
234 graph->AddNode(forwardMod,
"Forward Model");
235 graph->AddEdge(
"Conductivity", 0,
"Forward Model", 0);
238 graph->AddNode(std::make_shared<SliceOperator>(mesh.numNodes,0,mesh.numCells,obsThin),
"Observables");
239 graph->AddEdge(
"Forward Model", 0,
"Observables", 0);
242 auto likelihood = std::make_shared<Gaussian>(data, obsVar*Eigen::VectorXd::Ones(data.size()));
243 graph->AddNode(likelihood->AsDensity(),
"Likelihood");
244 graph->AddEdge(
"Observables", 0,
"Likelihood", 0);
248 graph->AddNode(priorDist->AsDensity(),
"Prior");
249 graph->AddEdge(
"Log Conductivity", 0,
"Prior", 0);
253 graph->AddNode(std::make_shared<DensityProduct>(2),
"Posterior");
254 graph->AddEdge(
"Prior",0,
"Posterior",0);
255 graph->AddEdge(
"Likelihood",0,
"Posterior",1);
258 graph->Visualize(
"WorkGraph.pdf");
260 return graph->CreateModPiece(
"Posterior");
269 Eigen::VectorXd
ComputeMAP(std::shared_ptr<ModPiece>
const& logPosterior,
270 Eigen::VectorXd
const& startPt)
272 std::cout <<
"\n======================================" << std::endl;
273 std::cout <<
"Computing MAP Point" << std::endl;
274 std::cout <<
"--------------------------------------" << std::endl;
276 boost::property_tree::ptree opts;
277 opts.put(
"Algorithm",
"NewtonTrust");
278 opts.put(
"Ftol.AbsoluteTolerance", 1
e-3);
279 opts.put(
"PrintLevel", 1);
282 auto objective = std::make_shared<ModPieceCostFunction>(logPosterior, -1.0);
283 auto solver = Optimizer::Construct(objective, opts);
285 Eigen::VectorXd xopt;
287 std::tie(xopt,fopt) = solver->Solve({startPt});
289 std::cout <<
"\nMAP Point: " << std::endl;
290 std::cout << xopt.transpose() << std::endl;
328 std::shared_ptr<Gaussian>
const& priorDist,
329 Eigen::VectorXd
const& mapPt)
332 double inflation = 1.2;
334 diliKernel->CreateLIS(std::vector<Eigen::VectorXd>{mapPt});
336 Eigen::VectorXd csSamp = diliKernel->ToCS( mapPt + inflation*(priorDist->Sample() - priorDist->GetMean()) );
337 Eigen::VectorXd lisSamp = diliKernel->FromLIS( diliKernel->ToLIS(mapPt) + inflation*RandomGenerator::GetNormal(diliKernel->LISDim()) );
339 return csSamp + lisSamp;
348 std::shared_ptr<SampleCollection>
SampleDILI(std::shared_ptr<ModPiece>
const& posterior,
349 Eigen::VectorXd
const& mapPt,
350 std::shared_ptr<Gaussian>
const& priorDist,
351 unsigned int numSamps)
353 boost::property_tree::ptree pt;
354 pt.put(
"NumSamples",numSamps);
356 pt.put(
"PrintLevel",3);
357 pt.put(
"HessianType",
"Exact");
358 pt.put(
"Adapt Interval", 0);
359 pt.put(
"Initial Weight", 100);
360 pt.put(
"Prior Node",
"Prior");
361 pt.put(
"Likelihood Node",
"Likelihood");
363 pt.put(
"LIS Block",
"LIS");
364 pt.put(
"LIS.Method",
"MHKernel");
365 pt.put(
"LIS.Proposal",
"MyProposal");
366 pt.put(
"LIS.MyProposal.Method",
"MALAProposal");
367 pt.put(
"LIS.MyProposal.StepSize", 0.4);
369 pt.put(
"CS Block",
"CS");
370 pt.put(
"CS.Method",
"MHKernel");
371 pt.put(
"CS.Proposal",
"MyProposal");
372 pt.put(
"CS.MyProposal.Method",
"CrankNicolsonProposal");
373 pt.put(
"CS.MyProposal.Beta",1.0);
374 pt.put(
"CS.MyProposal.PriorNode",
"Prior");
377 auto problem = std::make_shared<SamplingProblem>(posterior);
379 auto diliKernel = std::make_shared<DILIKernel>(pt, problem);
380 std::vector<std::shared_ptr<TransitionKernel>> kernels(1);
381 kernels.at(0) = diliKernel;
383 auto sampler = std::make_shared<SingleChainMCMC>(pt, kernels);
387 return sampler->Run(startPt);
395 std::shared_ptr<SampleCollection>
SamplePCN(std::shared_ptr<ModPiece>
const& posterior,
396 Eigen::VectorXd
const& startPt,
397 unsigned int numSamps)
399 boost::property_tree::ptree pt;
400 pt.put(
"NumSamples", numSamps);
402 pt.put(
"PrintLevel",3);
403 pt.put(
"KernelList",
"Kernel1");
404 pt.put(
"Kernel1.Method",
"MHKernel");
405 pt.put(
"Kernel1.Proposal",
"MyProposal");
406 pt.put(
"Kernel1.MyProposal.Method",
"CrankNicolsonProposal");
407 pt.put(
"Kernel1.MyProposal.Beta", 0.05);
408 pt.put(
"Kernel1.MyProposal.PriorNode",
"Prior");
411 auto problem = std::make_shared<SamplingProblem>(posterior);
413 auto sampler = std::make_shared<SingleChainMCMC>(pt,problem);
415 return sampler->Run(startPt);
426 unsigned int numCells = 50;
427 Discretization mesh(numCells);
430 unsigned int obsThin = 4;
431 double obsVar = 0.01*0.01;
435 std::shared_ptr<Gaussian> prior =
CreatePrior(mesh);
438 std::shared_ptr<ModPiece> posterior =
ConstructPosterior(mesh, prior, data, obsThin, obsVar);
441 Eigen::VectorXd mapPt =
ComputeMAP(posterior, prior->GetMean());
444 unsigned int numSamps = 30000;
445 unsigned int numChains = 4;
446 std::vector<std::shared_ptr<SampleCollection>> chains(numChains);
448 for(
int i=0; i<numChains; ++i){
449 std::cout <<
"\n===============================" << std::endl;
450 std::cout <<
"Running DILI Chain " << i+1 <<
" / " << numChains << std::endl;
451 std::cout <<
"-------------------------------" << std::endl;
453 chains.at(i) =
SampleDILI(posterior, mapPt, prior, numSamps);
461 for(
auto& chain : chains)
462 diliESS += chain->ESS(
"MultiBatch")(0);
464 boost::property_tree::ptree opts;
465 opts.put(
"Split",
true);
466 opts.put(
"Transform",
false);
467 opts.put(
"Multivariate",
true);
469 Eigen::VectorXd diliMPSRF = Diagnostics::Rhat(chains, opts);
471 std::cout <<
"\n\nDILI Diagnostics:\n Multivariate ESS: " << diliESS <<
"\n MPSRF: " << diliMPSRF(0) << std::endl;
474 if(diliMPSRF(0)>1.01){
475 std::cout <<
"\nDILI HAS NOT CONVERGED!" << std::endl;
477 std::cout <<
"\nDILI CONVERGED!" << std::endl;
484 std::vector<std::shared_ptr<SampleCollection>> pcnChains(numChains);
486 for(
int i=0; i<numChains; ++i){
487 std::cout <<
"\n===============================" << std::endl;
488 std::cout <<
"Running pCN Chain " << i+1 <<
" / " << numChains << std::endl;
489 std::cout <<
"-------------------------------" << std::endl;
491 pcnChains.at(i) =
SamplePCN(posterior, chains.at(i)->at(0)->ToVector(), numSamps);
496 for(
auto& chain : pcnChains)
497 pcnESS += chain->ESS(
"MultiBatch")(0);
499 Eigen::VectorXd pcnMPSRF = Diagnostics::Rhat(pcnChains, opts);
501 std::cout <<
"\n\npCN Diagnostics:\n Multivariate ESS: " << pcnESS <<
"\n MPSRF: " << pcnMPSRF(0) << std::endl;
504 if(pcnMPSRF(0)>1.01){
505 std::cout <<
"\npCN HAS NOT CONVERGED!" << std::endl;
507 std::cout <<
"\npCN CONVERGED!" << std::endl;
std::shared_ptr< SampleCollection > SamplePCN(std::shared_ptr< ModPiece > const &posterior, Eigen::VectorXd const &startPt, unsigned int numSamps)
Eigen::VectorXd GenerateData(Discretization const &mesh, unsigned int obsThin, double obsVar)
std::shared_ptr< ModPiece > ConstructPosterior(Discretization const &mesh, std::shared_ptr< Gaussian > const &priorDist, Eigen::VectorXd const &data, unsigned int obsThin, double obsVar)
std::shared_ptr< SampleCollection > SampleDILI(std::shared_ptr< ModPiece > const &posterior, Eigen::VectorXd const &mapPt, std::shared_ptr< Gaussian > const &priorDist, unsigned int numSamps)
Eigen::VectorXd SampleInflatedLaplace(std::shared_ptr< DILIKernel > const &diliKernel, std::shared_ptr< Gaussian > const &priorDist, Eigen::VectorXd const &mapPt)
Eigen::VectorXd GetTrueLogConductivity(Discretization const &mesh)
std::shared_ptr< Gaussian > CreatePrior(Discretization const &mesh)
Eigen::VectorXd ComputeMAP(std::shared_ptr< ModPiece > const &logPosterior, Eigen::VectorXd const &startPt)