10 #include <Eigen/Dense>
11 #include <Eigen/SparseCore>
19 std::shared_ptr<KernelBase> covKernelIn,
20 boost::property_tree::ptree options) :
StateSpaceGP(covKernelIn->GetStateSpace(options),
27 StateSpaceGP::StateSpaceGP(std::tuple<std::shared_ptr<muq::Modeling::LinearSDE>, std::shared_ptr<muq::Modeling::LinearOperator>, Eigen::MatrixXd> ssInfo,
28 std::shared_ptr<MeanFunctionBase> meanIn,
29 std::shared_ptr<KernelBase> covKernelIn) :
GaussianProcess(meanIn, covKernelIn), stateDim(std::
get<2>(ssInfo).rows()),
30 sde(std::
get<0>(ssInfo)),
31 obsOp(std::
get<1>(ssInfo)),
32 L(std::
get<2>(ssInfo).selfadjointView<Eigen::Lower>().llt().matrixL()),
34 covKernel(covKernelIn)
42 auto obsComp = [](std::shared_ptr<ObservationInformation> a, std::shared_ptr<ObservationInformation> b) {
return a->loc(0) < b->loc(0); };
52 Eigen::MatrixXd output(
obsOp->rows(), times.size());
57 Eigen::VectorXd x =
L.triangularView<Eigen::Lower>()*RandomGenerator::GetNormal(
L.rows());
59 output.col(0) =
obsOp->Apply(x);
62 for(
int i=0; i<times.size()-1; ++i)
64 x =
sde->EvolveState(x, times(i+1)-times(i));
65 output.col(i+1) =
obsOp->Apply(x);
70 throw muq::NotImplementedError(
"The Sample function of muq::Approximation::StateSpaceGP does not currently support Gaussian Processes that have been conditioned on data.");
84 bool computeAQ =
false;
85 if( (
sdeA.rows()==0) || (
sdeA.cols()==0) || (std::abs(dt-
dtAQ)>2.0*std::numeric_limits<double>::epsilon()) ){
106 if(times.rows() != 1)
107 throw muq::WrongSizeError(
"In StateSpaceGP::Predict: The StateSpaceGP class only supports 1d fields, but newPts has " +
std::to_string(times.rows()) +
" dimensions (i.e., rows).");
110 for(
int i=1; i<times.cols(); ++i)
112 if(times(0,i)<=times(0,i-1))
113 throw std::invalid_argument(
"In StateSpaceGP::Predict: The input points must be monotonically increasing, but index " +
std::to_string(i-1) +
" has a value of " +
std::to_string(times(0,i-1)) +
" and index " +
std::to_string(i) +
" has a value of " +
std::to_string(times(1,i)) +
".");
118 throw std::invalid_argument(
"In StateSpaceGP::Predict: The statespace GP does not compute the full covariance.");
121 std::vector< std::pair<Eigen::VectorXd, Eigen::MatrixXd>> evalDists(times.cols());
123 std::vector< std::pair<Eigen::VectorXd, Eigen::MatrixXd>> obsDists(
observations.size());
124 std::vector< std::pair<Eigen::VectorXd, Eigen::MatrixXd>> obsFilterDists(
observations.size());
126 std::pair<Eigen::VectorXd, Eigen::MatrixXd>* currDist;
127 double currTime, nextTime;
136 obsDists.at(0).second =
L.triangularView<Eigen::Lower>()*
L.transpose();
137 obsDists.at(0).first = Eigen::VectorXd::Zero(
stateDim);
139 std::shared_ptr<LinearOperator> H = std::make_shared<ProductOperator>(
observations.at(0)->H,
obsOp);
140 obsFilterDists.at(0) = KalmanFilter::Analyze(obsDists.at(0),
145 currDist = &obsFilterDists.at(0);
151 evalDists.at(0).second =
L.triangularView<Eigen::Lower>()*
L.transpose();
152 evalDists.at(0).first = Eigen::VectorXd::Zero(
stateDim);
154 currDist = &evalDists.at(0);
163 if(evalInd>=times.cols()){
165 }
else if(
observations.at(obsInd)->loc(0) < times(evalInd)){
174 obsDists.at(obsInd).first =
sdeA * currDist->first;
175 obsDists.at(obsInd).second =
sdeA * currDist->second *
sdeA.transpose() +
sdeQ;
179 std::shared_ptr<LinearOperator> H = std::make_shared<ProductOperator>(
observations.at(obsInd)->H,
obsOp);
181 obsFilterDists.at(obsInd) = KalmanFilter::Analyze(obsDists.at(obsInd),
186 currDist = &obsFilterDists.at(obsInd);
194 evalDists.at(evalInd).first =
sdeA * currDist->first;
195 evalDists.at(evalInd).second =
sdeA * currDist->second *
sdeA.transpose() +
sdeQ;
197 currTime = times(evalInd);
198 currDist = &evalDists.at(evalInd);
210 evalInd = times.size()-1;
211 for(evalInd = times.size()-1; evalInd >=0; --evalInd)
221 std::pair<Eigen::VectorXd, Eigen::MatrixXd> filterDist = obsDists.at(
observations.size()-1);
222 std::pair<Eigen::VectorXd, Eigen::MatrixXd> smoothDist = obsFilterDists.at(
observations.size()-1);
238 smoothDist = KalmanSmoother::Analyze(obsFilterDists.at(obsInd), filterDist, smoothDist,
sdeA);
239 filterDist.swap( obsDists.at(obsInd) );
247 smoothDist = KalmanSmoother::Analyze(evalDists.at(evalInd), filterDist, smoothDist,
sdeA);
249 filterDist.swap( evalDists.at(evalInd) );
250 evalDists.at(evalInd) = smoothDist;
252 nextTime = times(evalInd);
263 std::pair<Eigen::MatrixXd, Eigen::MatrixXd> output;
264 output.first.resize(
coDim, times.cols());
265 for(
int i=0; i<times.cols(); ++i)
266 output.first.col(i) =
mean->Evaluate(times.col(i)) +
obsOp->Apply(evalDists.at(i).first);
270 output.second.resize(
coDim,
coDim*times.cols());
272 for(
int i=0; i<times.cols(); ++i)
276 output.second.resize(
coDim, times.cols());
278 for(
int i=0; i<times.cols(); ++i)
279 output.second.col(i) =
obsOp->Apply(
obsOp->Apply(evalDists.at(i).second).transpose() ).diagonal();
287 Eigen::MatrixXd
const& vals)
305 if(newObs->cols() !=
obsOp->cols())
virtual std::pair< Eigen::MatrixXd, Eigen::MatrixXd > Predict(Eigen::MatrixXd const &newLocs, CovarianceType covType)
std::vector< std::shared_ptr< ObservationInformation > > observations
virtual double MarginalLogLikelihood()
virtual Eigen::MatrixXd PredictMean(Eigen::MatrixXd const &newPts) override
virtual std::pair< Eigen::MatrixXd, Eigen::MatrixXd > Predict(Eigen::MatrixXd const &newLocs, CovarianceType covType) override
bool ComputeAQ(double dt)
virtual Eigen::MatrixXd Sample(Eigen::MatrixXd const ×) override
void SetObs(std::shared_ptr< muq::Modeling::LinearOperator > newObs)
std::shared_ptr< MeanFunctionBase > mean
std::shared_ptr< muq::Modeling::LinearSDE > sde
std::shared_ptr< muq::Modeling::LinearOperator > obsOp
virtual double LogLikelihood(Eigen::MatrixXd const &xs, Eigen::MatrixXd const &vals) override
StateSpaceGP(MeanFunctionBase &meanIn, KernelBase &kernelIn, boost::property_tree::ptree options=boost::property_tree::ptree())
Class for virtual base functions that are not implemented.
Exception to throw when matrices, vectors, or arrays are the wrong size.
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values