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),
25 oldEigVals(oldValsIn),
28 assert(
oldW->rows()>0);
29 assert(
oldW->cols()>0);
32 thinQ =
uQR->householderQ().setLength(
uQR->nonzeroPivots()) * Eigen::MatrixXd::Identity(
oldW->rows(),
uQR->rank());
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));
51 return x -
U->leftCols(
lisDim)*
W->leftCols(
lisDim).transpose() * x;
56 return x -
W->leftCols(
lisDim)*
U->leftCols(
lisDim).transpose() * x;
61 return U->leftCols(
lisDim) *
L->asDiagonal() * x;
66 return L->asDiagonal() *
U->leftCols(
lisDim).transpose() * x;
72 std::shared_ptr<AbstractSamplingProblem> problem) :
DILIKernel(pt,
74 ExtractPrior(problem, pt.
get(
"Prior Node",
"Prior")),
75 ExtractLikelihood(problem,pt.
get(
"Likelihood Node",
"Likelihood")))
80 std::shared_ptr<AbstractSamplingProblem> problem,
81 Eigen::VectorXd
const& genEigVals,
82 Eigen::MatrixXd
const& genEigVecs) :
DILIKernel(pt,
84 ExtractPrior(problem, pt.
get(
"Prior Node",
"Prior")),
85 ExtractLikelihood(problem,pt.
get(
"Likelihood Node",
"Likelihood")),
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)),
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",1
e-4)),
109 lisValTol(pt.
get(
"LIS Tolerance", 0.1))
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&){
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,
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)),
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",1
e-4)),
138 lisValTol(pt.
get(
"LIS Tolerance", 0.1))
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&){
147 SetLIS(genEigVals, genEigVecs);
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),
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",1
e-4)),
166 lisValTol(pt.
get(
"LIS Tolerance", 0.1))
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&){
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,
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),
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",1
e-4)),
194 lisValTol(pt.
get(
"LIS Tolerance", 0.1))
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&){
203 SetLIS(genEigVals, genEigVecs);
207 std::vector<std::shared_ptr<SamplingState>>
const& state)
217 return lisL->array().inverse().matrix().asDiagonal() *
hessW->leftCols(
lisDim).transpose()*x;
236 std::shared_ptr<SamplingState> prevState)
242 std::vector<Eigen::VectorXd> splitVec(2);
245 splitVec.at(1) = prevState->state.at(
blockInd);
246 std::shared_ptr<SamplingState> splitState = std::make_shared<SamplingState>(splitVec);
247 splitState->meta = prevState->meta;
249 auto nextSteps =
csKernel->Step(t, splitState);
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;
263 splitVec.at(1) = prevState->state.at(
blockInd);
265 std::shared_ptr<SamplingState> splitState = std::make_shared<SamplingState>(splitVec);
266 splitState->meta = prevState->meta;
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());
273 std::vector<std::shared_ptr<SamplingState>> output(nextSteps.size() + nextSteps2.size());
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));
279 output.at(i) = std::make_shared<SamplingState>(prevState->state);
280 output.at(i)->state.at(
blockInd) = x;
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;
297 std::stringstream lisStream;
298 lisStream << prefix <<
" LIS (dim=" <<
lisDim <<
"): ";
299 std::string newPrefix = lisStream.str();
301 newPrefix = prefix +
" CS: ";
307 bool subDimChange =
false;
311 assert(eigVals(1)<eigVals(0));
313 hessU = std::make_shared<Eigen::MatrixXd>(eigVecs);
314 hessUQR = std::make_shared<Eigen::ColPivHouseholderQR<Eigen::MatrixXd>>(eigVecs);
316 hessW = std::make_shared<Eigen::MatrixXd>(
prior->ApplyPrecision(eigVecs));
317 hessEigVals = std::make_shared<Eigen::VectorXd>(eigVals);
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());
341 std::shared_ptr<LinearOperator> hessOp;
352 std::cerr <<
"\nERROR: Unrecognized Hessian type. Options are \"Exact\" or \"GaussNewton\".\n\n";
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);
367 solver.
compute(hessOp, precOp, covOp);
376 Eigen::MatrixXd vecs;
377 Eigen::VectorXd vals;
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");
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);
403 auto prob = std::make_shared<SamplingProblem>(graph->CreateModPiece(
"Posterior"));
414 std::vector<Eigen::VectorXd>
const& currState)
416 std::shared_ptr<LinearOperator> hessOp, newOp, precOp, covOp;
422 std::cerr <<
"\nERROR: Unrecognized Hessian type. Options are \"Exact\" or \"GaussNewton\".\n\n";
426 precOp = std::make_shared<GaussianOperator>(
prior, Gaussian::Precision);
427 covOp = std::make_shared<GaussianOperator>(
prior, Gaussian::Covariance);
436 solver.
compute(hessOp, precOp, covOp);
442 std::string
const& nodeName)
445 auto regProb = std::dynamic_pointer_cast<SamplingProblem>(
problem);
447 throw std::runtime_error(
"In DILIKernel::ExtractPrior: Could not cast AbstractSamplingProblem instance into SamplingProblem.");
451 auto postPiece = regProb->GetDistribution();
452 auto postGraphPiece = std::dynamic_pointer_cast<ModGraphPiece>(postPiece);
454 throw std::runtime_error(
"In DILIKernel::ExtractPrior: Could not cast Posterior ModPiece to ModGraphPiece.");
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);
460 throw std::runtime_error(
"In DILIKernel::ExtractPrior: Could not cast prior WorkPiece to Density.");
463 std::shared_ptr<muq::Modeling::GaussianBase> output = std::dynamic_pointer_cast<GaussianBase>(priorDens->GetDistribution());
465 throw std::runtime_error(
"In DILIKernel::ExtractPrior: Could not cast prior distribution to GaussianBase.");
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.");
478 return likelyGraphPiece->GetOutputPiece();
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.");
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.");
492 auto graph = likelyGraphPiece->GetGraph();
493 std::vector<std::string> modelNames = graph->GetParents(likelyGraphPiece->GetOutputName());
495 return likelyGraphPiece->GetSubModel(modelNames.at(0));
499 std::string
const& nodeName)
502 auto regProb = std::dynamic_pointer_cast<SamplingProblem>(
problem);
504 throw std::runtime_error(
"In DILIKernel::ExtractLikelihood: Could not cast AbstractSamplingProblem instance into SamplingProblem.");
508 auto postPiece = regProb->GetDistribution();
509 auto postGraphPiece = std::dynamic_pointer_cast<ModGraphPiece>(postPiece);
511 throw std::runtime_error(
"In DILIKernel::ExtractLikelihood: Could not cast Posterior ModPiece to ModGraphPiece.");
514 std::shared_ptr<muq::Modeling::ModPiece> likelihood = postGraphPiece->GetSubModel(nodeName);
520 std::shared_ptr<muq::Modeling::ModPiece>
const& noiseDensity)
525 graph.
AddEdge(
"Forward Model", 0,
"Likelihood",0);
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.
void AddNode(std::shared_ptr< WorkPiece > input, std::string const &name)
Add a new node to the graph.
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.
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.
virtual Eigen::MatrixXd Apply(Eigen::Ref< const Eigen::MatrixXd > const &x) override
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)
std::shared_ptr< muq::Modeling::LinearOperator > newHess
std::shared_ptr< Eigen::VectorXd > oldEigVals
std::shared_ptr< Eigen::MatrixXd > oldW
virtual Eigen::MatrixXd ApplyTranspose(Eigen::Ref< const Eigen::MatrixXd > const &x) override
std::shared_ptr< Eigen::ColPivHouseholderQR< Eigen::MatrixXd > > uQR
std::shared_ptr< Eigen::MatrixXd > W
virtual Eigen::MatrixXd ApplyTranspose(Eigen::Ref< const Eigen::MatrixXd > const &x) override
std::shared_ptr< Eigen::MatrixXd > U
virtual Eigen::MatrixXd Apply(Eigen::Ref< const Eigen::MatrixXd > const &x) override
An implementation of the Dimension Independent Likelihood Informed subspace (DILI) MCMC sampler.
boost::property_tree::ptree csKernelOpts
virtual std::vector< std::shared_ptr< SamplingState > > Step(unsigned int const t, std::shared_ptr< SamplingState > prevState) override
std::shared_ptr< muq::Modeling::LinearOperator > lisToFull
std::shared_ptr< Eigen::ColPivHouseholderQR< Eigen::MatrixXd > > hessUQR
static std::shared_ptr< muq::Modeling::ModPiece > CreateLikelihood(std::shared_ptr< muq::Modeling::ModPiece > const &forwardModel, std::shared_ptr< muq::Modeling::ModPiece > const &noiseDensity)
std::shared_ptr< muq::Modeling::GaussianBase > prior
void UpdateLIS(unsigned int numSamps, std::vector< Eigen::VectorXd > const &currState)
std::shared_ptr< Eigen::MatrixXd > hessW
std::shared_ptr< TransitionKernel > lisKernel
boost::property_tree::ptree eigOpts
std::pair< Eigen::MatrixXd, Eigen::VectorXd > ComputeLocalLIS(std::vector< Eigen::VectorXd > const &currState)
Eigen::VectorXd FromLIS(Eigen::VectorXd const &r) const
std::shared_ptr< muq::Modeling::ModPiece > noiseDensity
std::shared_ptr< Eigen::VectorXd > hessEigVals
static std::shared_ptr< muq::Modeling::ModPiece > ExtractLikelihood(std::shared_ptr< AbstractSamplingProblem > const &problem, std::string const &nodeName)
void SetLIS(Eigen::VectorXd const &eigVals, Eigen::MatrixXd const &eigVecs)
boost::property_tree::ptree lisKernelOpts
std::shared_ptr< muq::Modeling::ModPiece > logLikelihood
const int initialHessSamps
static std::shared_ptr< muq::Modeling::ModPiece > ExtractForwardModel(std::shared_ptr< muq::Modeling::ModPiece > const &likelihoodIn)
std::shared_ptr< Eigen::MatrixXd > hessU
static std::shared_ptr< muq::Modeling::ModPiece > ExtractNoiseModel(std::shared_ptr< muq::Modeling::ModPiece > const &likelihood)
Eigen::VectorXd ToLIS(Eigen::VectorXd const &x) const
std::shared_ptr< TransitionKernel > csKernel
static std::shared_ptr< muq::Modeling::GaussianBase > ExtractPrior(std::shared_ptr< AbstractSamplingProblem > const &problem, std::string const &nodeName)
void CreateLIS(std::vector< Eigen::VectorXd > const &currState)
std::shared_ptr< muq::Modeling::ModPiece > forwardModel
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.
Eigen::VectorXd ToCS(Eigen::VectorXd const &x) const
DILIKernel(boost::property_tree::ptree const &pt, std::shared_ptr< AbstractSamplingProblem > problem)
std::shared_ptr< Eigen::VectorXd > lisL
unsigned int numLisUpdates
std::shared_ptr< muq::Modeling::LinearOperator > fullToCS
const unsigned int lisDim
std::shared_ptr< Eigen::MatrixXd > U
std::shared_ptr< Eigen::VectorXd > L
virtual Eigen::MatrixXd ApplyTranspose(Eigen::Ref< const Eigen::MatrixXd > const &x) override
virtual Eigen::MatrixXd Apply(Eigen::Ref< const Eigen::MatrixXd > const &x) override
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.
virtual void PrintStatus() const
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())