31#ifndef __TSG_INDEX_MANIPULATOR_HPP
32#define __TSG_INDEX_MANIPULATOR_HPP
34#include "tsgIndexSets.hpp"
35#include "tsgOneDimensionalWrapper.hpp"
70namespace MultiIndexManipulations{
79inline MultiIndexSet generateFullTensorSet(std::vector<int>
const &num_entries){
80 size_t num_dimensions = num_entries.size();
82 for(
auto &l : num_entries) num_total *= l;
83 std::vector<int> indexes(Utils::size_mult(num_dimensions, num_total));
84 auto iter = indexes.rbegin();
85 for(
int i=num_total-1; i>=0; i--){
87 auto l = num_entries.rbegin();
89 for(
size_t j = 0; j<num_dimensions; j++){
94 return MultiIndexSet(num_dimensions, std::move(indexes));
103inline MultiIndexSet generateLowerMultiIndexSet(
size_t num_dimensions, std::function<
bool(
const std::vector<int> &index)> inside){
104 size_t c = num_dimensions -1;
106 std::vector<int> root(num_dimensions, 0);
107 std::vector<int> indexes;
108 while(is_in || (c > 0)){
110 indexes.insert(indexes.end(), root.begin(), root.end());
111 c = num_dimensions-1;
114 std::fill(root.begin() + c, root.end(), 0);
117 is_in = inside(root);
119 return MultiIndexSet(num_dimensions, std::move(indexes));
128void completeSetToLower(MultiIndexSet &set);
141 ProperWeights(
size_t num_dimensions,
TypeDepth type, std::vector<int>
const &weights){
142 contour = OneDimensionalMeta::getControurType(type);
143 if (weights.empty()) linear = std::vector<int>(num_dimensions, 1);
145 if (!weights.empty()){
149 if (weights.empty()){
150 curved = std::vector<double>(num_dimensions, 0.0);
152 linear = std::vector<int>(weights.begin(), weights.begin() + num_dimensions);
153 curved = std::vector<double>(num_dimensions);
154 std::transform(weights.begin() + num_dimensions, weights.end(), curved.begin(), [&](
int i)->double{ return (double) i; });
157 if (weights.empty()){
158 curved = std::vector<double>(num_dimensions, 1.0);
160 linear = std::vector<int>(num_dimensions, 1);
161 double exponent_normalization = (double) *std::min_element(weights.begin(), weights.end());
162 curved = std::vector<double>(num_dimensions);
163 std::transform(weights.begin(), weights.end(), curved.begin(),
164 [&](
int i)->double{ return ((double) i) / exponent_normalization; });
169 bool provenLower()
const{
171 for(
size_t i=0; i<linear.size(); i++)
172 if ((
double)linear[i] + curved[i] < 0)
return false;
176 int minLinear()
const{
return *std::min_element(linear.begin(), linear.end()); }
178 size_t getNumDimensions()
const{
return linear.size(); }
183 std::vector<int> linear;
185 std::vector<double> curved;
200template<
typename CacheType, TypeDepth contour,
bool isotropic>
201std::vector<std::vector<CacheType>> generateLevelWeightsCache(ProperWeights
const &weights, std::function<
int(
int i)> rule_exactness,
int offset){
202 size_t num_dimensions = weights.getNumDimensions();
203 std::vector<std::vector<CacheType>> cache(num_dimensions);
204 std::vector<int> exactness_cache;
208 for(
auto &vec : cache) vec.reserve((
size_t) offset);
209 exactness_cache.resize((
size_t) offset);
210 exactness_cache[0] = 0;
211 for(
int i=1; i<offset; i++)
212 exactness_cache[i] = 1 + rule_exactness(i - 1);
214 exactness_cache.push_back(0);
217 for(
size_t j=0; j<num_dimensions; j++){
218 int wl = weights.linear[j];
219 double wc = (contour ==
type_level) ? 0.0 : weights.curved[j];
223 cache[j].push_back(w);
226 if (!isotropic && (i >= exactness_cache.size()))
227 exactness_cache.push_back(1 + rule_exactness((
int)(i - 1)));
229 int e = exactness_cache[i];
232 w = (CacheType)(wl * e);
234 w = (CacheType)(wl * e) + (CacheType)(wc * std::log1p((CacheType)e));
236 w = (CacheType)(pow((CacheType) (1 + e), wc));
239 cache[j].push_back(w);
241 }
while( (!isotropic && (std::ceil(w) <= (CacheType) offset)) || (isotropic && (i + 1 < (
size_t) offset)) );
253template<
typename CacheType, TypeDepth contour>
254inline CacheType getIndexWeight(
int const index[], std::vector<std::vector<CacheType>>
const &cache){
256 for(
size_t j=0; j<cache.size(); j++)
258 w *= cache[j][index[j]];
260 w += cache[j][index[j]];
273MultiIndexSet selectTensors(
size_t num_dimensions,
int offset,
TypeDepth type, std::function<
int(
int i)> rule_exactness,
274 std::vector<int>
const &anisotropic_weights, std::vector<int>
const &level_limits);
283std::vector<int> computeLevels(MultiIndexSet
const &mset);
292std::vector<int> getMaxIndexes(
const MultiIndexSet &mset);
302Data2D<int> computeDAGup(MultiIndexSet
const &mset);
311MultiIndexSet selectFlaggedChildren(
const MultiIndexSet &mset,
const std::vector<bool> &flagged,
const std::vector<int> &level_limits);
323MultiIndexSet generateNestedPoints(
const MultiIndexSet &tensors, std::function<
int(
int)> getNumPoints);
333MultiIndexSet generateNonNestedPoints(
const MultiIndexSet &tensors,
const OneDimensionalWrapper &wrapper);
347void resortIndexes(
const MultiIndexSet &iset, std::vector<std::vector<int>> &map, std::vector<std::vector<int>> &lines1d);
358std::vector<int> referencePoints(
const int levels[],
const OneDimensionalWrapper &wrapper,
const MultiIndexSet &points){
359 size_t num_dimensions = (size_t) points.getNumDimensions();
360 std::vector<int> num_points(num_dimensions);
362 for(
size_t j=0; j<num_dimensions; j++) num_points[j] = wrapper.getNumPoints(levels[j]);
363 for(
auto n : num_points) num_total *= n;
365 std::vector<int> refs(num_total);
366 std::vector<int> p(num_dimensions);
368 for(
int i=0; i<num_total; i++){
370 auto n = num_points.rbegin();
371 for(
int j=(
int) num_dimensions-1; j>=0; j--){
372 p[j] = (nested) ? t % *n : wrapper.getPointIndex(levels[j], t % *n);
375 refs[i] = points.getSlot(p);
387std::vector<int> computeTensorWeights(MultiIndexSet
const &mset);
396inline MultiIndexSet createActiveTensors(
const MultiIndexSet &mset,
const std::vector<int> &weights){
397 size_t num_dimensions = mset.getNumDimensions();
398 size_t nz_weights = 0;
399 for(
auto w: weights)
if (w != 0) nz_weights++;
401 std::vector<int> indexes(nz_weights * num_dimensions);
403 auto iter = indexes.begin();
404 auto iset = mset.begin();
405 for(
auto w: weights){
407 std::copy_n(iset, num_dimensions, iter);
408 std::advance(iter, num_dimensions);
410 std::advance(iset, num_dimensions);
413 return MultiIndexSet(num_dimensions, std::move(indexes));
420inline void computeActiveTensorsWeights(MultiIndexSet
const &tensors, MultiIndexSet &active_tensors, std::vector<int> &active_w){
421 std::vector<int> tensors_w = MultiIndexManipulations::computeTensorWeights(tensors);
422 active_tensors = MultiIndexManipulations::createActiveTensors(tensors, tensors_w);
424 active_w = std::vector<int>();
425 active_w.reserve(active_tensors.getNumIndexes());
426 for(
auto w : tensors_w)
if (w != 0) active_w.push_back(w);
436MultiIndexSet createPolynomialSpace(
const MultiIndexSet &tensors, std::function<
int(
int)> exactness);
450inline bool isLowerComplete(std::vector<int>
const &point, MultiIndexSet
const &mset, std::vector<int> &scratch){
451 std::copy(point.begin(), point.end(), scratch.begin());
452 for(
int &d : scratch){
455 if (mset.missing(scratch))
return false;
469inline MultiIndexSet getLargestCompletion(MultiIndexSet
const ¤t, MultiIndexSet
const &candidates){
470 if (candidates.empty())
return MultiIndexSet();
471 auto num_dimensions = candidates.getNumDimensions();
472 MultiIndexSet result;
473 if (current.empty()){
474 if (candidates.missing(std::vector<int>(num_dimensions, 0))){
475 return MultiIndexSet();
477 result = MultiIndexSet(num_dimensions, std::vector<int>(num_dimensions, 0));
481 std::vector<int> kid(num_dimensions);
482 std::vector<int> scratch(num_dimensions);
485 Data2D<int> update(num_dimensions, 0);
487 MultiIndexSet total = current;
488 if (!result.empty()) total += result;
489 for(
int i=0; i<total.getNumIndexes(); i++){
490 std::copy_n(total.getIndex(i), num_dimensions, kid.begin());
493 if (!candidates.missing(kid) && result.missing(kid) && isLowerComplete(kid, total, scratch))
494 update.appendStrip(kid);
499 loopon = (update.getNumStrips() > 0);
500 if (loopon) result += update;
514template<
bool limited>
515MultiIndexSet addExclusiveChildren(
const MultiIndexSet &tensors,
const MultiIndexSet &exclude,
const std::vector<int> level_limits){
516 int num_dimensions = (int) tensors.getNumDimensions();
517 Data2D<int> tens(num_dimensions, 0);
518 std::vector<int> scratch(num_dimensions);
519 for(
int i=0; i<tensors.getNumIndexes(); i++){
520 const int *t = tensors.getIndex(i);
521 std::vector<int> kid(t, t + num_dimensions);
522 auto ilimit = level_limits.begin();
525 if (exclude.missing(kid) && tensors.missing(kid)){
526 if (isLowerComplete(kid, tensors, scratch)){
528 if ((*ilimit == -1) || (k <= *ilimit))
529 tens.appendStrip(kid);
532 tens.appendStrip(kid);
540 return MultiIndexSet(tens);
568template<
class IndexList,
class RuleLike,
class OutputIteratorLike>
569OutputIteratorLike indexesToNodes(IndexList
const &list, RuleLike
const &rule, OutputIteratorLike nodes){
570 return std::transform(list.begin(), list.end(), nodes, [&](
int i)->double{ return rule.getNode(i); });
577template<
class IteratorLike,
class RuleLike,
class OutputIteratorLike>
578OutputIteratorLike indexesToNodes(IteratorLike ibegin,
size_t num_entries, RuleLike
const &rule, OutputIteratorLike nodes){
579 return std::transform(ibegin, ibegin + num_entries, nodes, [&](
int i)->
double{
return rule.getNode(i); });
586template<
class IndexList,
class RuleLike>
587std::vector<double> getIndexesToNodes(IndexList
const &list, RuleLike
const &rule){
588 std::vector<double> result(std::distance(list.begin(), list.end()));
589 indexesToNodes(list, rule, result.begin());
597template<
class IteratorLike,
class RuleLike>
598std::vector<double> getIndexesToNodes(IteratorLike ibegin,
size_t num_entries, RuleLike
const &rule){
599 std::vector<double> result(num_entries);
600 indexesToNodes(ibegin, num_entries, rule, result.begin());
612std::vector<int> inferAnisotropicWeights(AccelerationContext
const *acceleration,
TypeOneDRule rule,
TypeDepth depth,
613 MultiIndexSet
const &points, std::vector<double>
const &coefficients,
double tol);
TypeOneDRule
Used to specify the one dimensional family of rules that induces the sparse grid.
Definition tsgEnumerates.hpp:285
TypeDepth
Used by Global Sequence and Fourier grids, indicates the selection criteria.
Definition tsgEnumerates.hpp:203
@ type_curved
Ignoring the polynomial space, use rules with index .
Definition tsgEnumerates.hpp:213
@ type_level
Ignoring the polynomial space, use rules with index .
Definition tsgEnumerates.hpp:209
@ type_hyperbolic
Ignoring the polynomial space, use rules with index .
Definition tsgEnumerates.hpp:217
Encapsulates the Tasmanian Sparse Grid module.
Definition TasmanianSparseGrid.hpp:68