12 template<
typename EstimateType>
15 termMultis(std::make_shared<
MultiIndexSet>(modelIn->inputSizes(0))),
16 pointCache(modelIn->inputSizes(0))
19 assert(
model->inputSizes.size()==1);
20 assert(
model->outputSizes.size()==1);
23 template<
typename EstimateType>
26 assert(weights.size()<=terms.size());
28 unsigned int firstNzInd = 0;
29 for(
unsigned int i=0; i<weights.size(); ++i){
30 if(std::abs(weights(i))>nzTol) {
36 assert(std::abs(weights(firstNzInd))>nzTol);
39 EstimateType res = AddEstimates(0.0, terms.at(firstNzInd).val, weights(firstNzInd), terms.at(firstNzInd).val);
40 for(
unsigned int i=firstNzInd+1; i<weights.size(); ++i){
41 if(std::abs(weights(i))>nzTol)
42 res = AddEstimates(1.0, res, weights(i), terms.at(i).val);
49 template<
typename EstimateType>
52 unsigned int firstNzInd = 0;
53 const double weightTol = 10.0*std::numeric_limits<double>::epsilon();
54 for(
unsigned int i=0; i<terms.size(); ++i){
55 if(std::abs(terms.at(i).weight)>weightTol) {
62 EstimateType res = AddEstimates(0.0, terms.at(firstNzInd).val, terms.at(firstNzInd).weight, terms.at(firstNzInd).val);
63 for(
unsigned int i=firstNzInd+1; i<terms.size(); ++i){
64 if(std::abs(terms.at(i).weight)>weightTol){
65 res = AddEstimates(1.0, res, terms.at(i).weight, terms.at(i).val);
72 template<
typename EstimateType>
75 auto t_start = std::chrono::high_resolution_clock::now();
80 timeTol = options.get(
"MaximumAdaptTime", std::numeric_limits<double>::infinity());
81 errorTol = options.get(
"ErrorTol", 0.0);
82 maxNumEvals = options.get(
"MaximumEvals",std::numeric_limits<unsigned int>::max());
85 if((timeTol==std::numeric_limits<double>::infinity())&&(errorTol==0)&&(maxNumEvals==std::numeric_limits<unsigned int>::max())){
86 std::stringstream msg;
87 msg <<
"Error in SmolyakEstimator::Adapt. No stopping criteria were set. ";
88 msg <<
"The options property_tree must specify at least one of the following ";
89 msg <<
"variables, \"MaximumAdaptTime\", \"ErrorTol\", or \"MaximumEvals\".";
90 throw std::runtime_error(msg.str());
94 while((globalError>errorTol)&&(runtime<timeTol)&&(numEvals<maxNumEvals)) {
98 auto t_curr =std::chrono::high_resolution_clock::now();
99 runtime = std::chrono::duration<double, std::milli>(t_curr-t_start).count()/1e3;
102 errorHistory.push_back(globalError);
103 timeHistory.push_back(runtime+timeHistory.at(0));
107 return ComputeWeightedSum();
110 template<
typename EstimateType>
115 double maxError = 0.0;
116 for(
unsigned int termInd : termMultis->GetFrontier()){
119 if(!terms.at(termInd).isOld){
120 if(terms.at(termInd).localError > maxError){
122 maxError = terms.at(termInd).localError;
131 terms.at(expandInd).isOld =
true;
134 std::vector<std::shared_ptr<MultiIndex>> neighs = termMultis->GetAdmissibleForwardNeighbors(expandInd);
136 std::vector<std::shared_ptr<MultiIndex>> termsToAdd;
137 for(
auto& neigh : neighs){
140 if(!termMultis->IsActive(neigh)){
142 bool shouldAdd =
true;
145 std::vector<unsigned int> backNeighInds = termMultis->GetBackwardNeighbors(neigh);
147 for(
auto backInd : backNeighInds)
148 shouldAdd = shouldAdd && terms.at(backInd).isOld;
151 termsToAdd.push_back(neigh);
157 AddTerms(termsToAdd);
162 template<
typename EstimateType>
165 std::vector<std::shared_ptr<MultiIndex>> multiVec(fixedSet->Size());
166 for(
unsigned int i=0; i<fixedSet->Size(); ++i)
167 multiVec.at(i) = fixedSet->IndexToMulti(i);
172 template<
typename EstimateType>
175 std::vector<std::vector<Eigen::VectorXd>> output(pointHistory.size());
176 for(
int adaptInd=0; adaptInd<pointHistory.size(); ++adaptInd)
178 output.at(adaptInd).reserve(pointHistory.at(adaptInd).size());
179 for(
auto& ptInd : pointHistory.at(adaptInd))
180 output.at(adaptInd).push_back( GetFromCache(ptInd) );
186 template<
typename EstimateType>
198 termHistory.push_back(fixedSet);
200 for(
unsigned int i=0; i<fixedSet.size(); ++i) {
201 unsigned int termInd = terms.size();
202 terms.push_back(SmolyTerm());
203 termMultis->AddActive(fixedSet.at(i));
205 assert(terms.size()==termMultis->Size());
208 std::vector<Eigen::VectorXd> pts = OneTermPoints(fixedSet.at(i));
211 terms.at(termInd).evalInds.resize(pts.size());
212 for(
unsigned int k=0;
k<pts.size(); ++
k){
215 int cacheId = InCache(pts.at(
k));
217 int cacheInd = AddToCache(pts.at(
k));
218 terms.at(termInd).evalInds.at(
k) = cacheInd;
219 evalCache.push_back( Eigen::VectorXd() );
222 terms.at(termInd).evalInds.at(
k) = cacheId;
229 for(
unsigned int j=0; j<newWeights.size(); ++j)
230 terms.at(j).weight = newWeights(j);
233 for(
unsigned int termInd : termMultis->GetFrontier()){
234 terms.at(termInd).diffWeights = Eigen::VectorXd::Zero(terms.size());
242 for(
unsigned int termInd=0; termInd<terms.size(); ++termInd){
243 if(std::abs(terms.at(termInd).weight) > nzTol)
244 terms.at(termInd).isNeeded =
true;
248 for(
unsigned int termInd : termMultis->GetFrontier()){
249 for(
unsigned int wInd=0; wInd<terms.at(termInd).diffWeights.size(); ++wInd){
250 if(std::abs(terms.at(termInd).diffWeights(wInd))>nzTol)
251 terms.at(wInd).isNeeded =
true;
257 std::set<unsigned int> ptsToEval;
258 for(
unsigned int termInd=0; termInd<terms.size(); ++termInd) {
261 if((terms.at(termInd).isNeeded) && (!terms.at(termInd).isComputed)) {
262 for(
unsigned int i=0; i<terms.at(termInd).evalInds.size(); ++i) {
263 unsigned int ptInd = terms.at(termInd).evalInds.at(i);
265 if(evalCache.at(ptInd).size()==0)
266 ptsToEval.insert(ptInd);
273 EvaluatePoints(ptsToEval);
275 pointHistory.push_back(ptsToEval);
276 evalHistory.push_back(numEvals);
280 for(
unsigned int i=0; i<termMultis->Size(); ++i) {
283 if((terms.at(i).isNeeded) && (!terms.at(i).isComputed)) {
286 std::vector<std::reference_wrapper<const Eigen::VectorXd>> evals;
287 for(
unsigned int ptInd=0; ptInd<terms.at(i).evalInds.size(); ++ptInd){
288 evals.push_back( evalCache.at(terms.at(i).evalInds.at(ptInd) ) );
290 terms.at(i).val = ComputeOneTerm(termMultis->IndexToMulti(i), evals);
291 terms.at(i).isComputed =
true;
298 template<
typename EstimateType>
301 for(
auto& ptInd : ptsToEval){
302 evalCache.at(ptInd) = model->Evaluate( GetFromCache(ptInd) ).at(0);
307 template<
typename EstimateType>
312 std::vector<unsigned int> frontierTerms = termMultis->GetFrontier();
315 for(
unsigned int termInd : frontierTerms){
316 if(!terms.at(termInd).isOld){
317 terms.at(termInd).localError = ComputeMagnitude( ComputeWeightedSum( terms.at(termInd).diffWeights ));
318 globalError += terms.at(termInd).localError;
323 template<
typename EstimateType>
325 boost::property_tree::ptree options)
327 auto t_start = std::chrono::high_resolution_clock::now();
328 double runtime = 0.0;
336 for(
unsigned i=0;i<terms.size();++i)
337 terms.at(i).isOld =
true;
338 for(
unsigned int termInd : termMultis->GetStrictFrontier())
339 terms.at(termInd).isOld =
false;
344 auto t_curr =std::chrono::high_resolution_clock::now();
345 runtime = std::chrono::duration<double, std::milli>(t_curr-t_start).count()/1e3;
346 timeHistory.push_back(runtime);
347 errorHistory.push_back(globalError);
349 bool shouldAdapt = options.get(
"ShouldAdapt",
false);
351 return Adapt(options);
354 return ComputeWeightedSum();
357 template<
typename EstimateType>
360 termMultis = std::make_shared<MultiIndexSet>(model->inputSizes(0));
362 globalError = std::numeric_limits<double>::infinity();
364 errorHistory.clear();
368 pointHistory.clear();
388 template<
typename EstimateType>
391 int cacheId = InCache(newPt);
393 pointCache.add(newPt);
394 return CacheSize()-1;
400 template<
typename EstimateType>
404 std::vector<size_t> indices;
405 std::vector<double> squaredDists;
406 std::tie(indices, squaredDists) = pointCache.query(input, 1);
408 if(squaredDists.at(0)<cacheTol){
409 return indices.at(0);
420 namespace Approximation{
virtual std::vector< std::vector< Eigen::VectorXd > > PointHistory() const
int AddToCache(Eigen::VectorXd const &newPt)
virtual void EvaluatePoints(std::set< unsigned int > const &ptsToEval)
virtual void UpdateErrors()
std::shared_ptr< muq::Modeling::ModPiece > model
The model used to construct the approximations.
virtual EstimateType Compute(std::shared_ptr< muq::Utilities::MultiIndexSet > const &fixedSet, boost::property_tree::ptree options=boost::property_tree::ptree())
virtual void AddTerms(std::shared_ptr< muq::Utilities::MultiIndexSet > const &fixedSet)
virtual EstimateType ComputeWeightedSum() const
virtual EstimateType Adapt(boost::property_tree::ptree options)
static void UpdateWeights(unsigned int activeInd, std::shared_ptr< muq::Utilities::MultiIndexSet > const &multis, Eigen::VectorXd &multiWeights)
static Eigen::VectorXd ComputeWeights(std::shared_ptr< muq::Utilities::MultiIndexSet > const &multis)
A class for holding, sorting, and adapting sets of multiindices.