Doxygen 1.9.1
Toolkit for Adaptive Stochastic Modeling and Non-Intrusive ApproximatioN: Tasmanian v8.2 (development)
tsgHierarchyManipulator.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, Miroslav Stoyanov
3  *
4  * This file is part of
5  * Toolkit for Adaptive Stochastic Modeling And Non-Intrusive ApproximatioN: TASMANIAN
6  *
7  * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
12  * and the following disclaimer in the documentation and/or other materials provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
20  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
21  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * UT-BATTELLE, LLC AND THE UNITED STATES GOVERNMENT MAKE NO REPRESENTATIONS AND DISCLAIM ALL WARRANTIES, BOTH EXPRESSED AND IMPLIED.
25  * THERE ARE NO EXPRESS OR IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY PATENT,
26  * COPYRIGHT, TRADEMARK, OR OTHER PROPRIETARY RIGHTS, OR THAT THE SOFTWARE WILL ACCOMPLISH THE INTENDED RESULTS OR THAT THE SOFTWARE OR ITS USE WILL NOT RESULT IN INJURY OR DAMAGE.
27  * THE USER ASSUMES RESPONSIBILITY FOR ALL LIABILITIES, PENALTIES, FINES, CLAIMS, CAUSES OF ACTION, AND COSTS AND EXPENSES, CAUSED BY, RESULTING FROM OR ARISING OUT OF,
28  * IN WHOLE OR IN PART THE USE, STORAGE OR DISPOSAL OF THE SOFTWARE.
29  */
30 
31 #ifndef __TSG_HIERARCHY_MANIPULATOR_HPP
32 #define __TSG_HIERARCHY_MANIPULATOR_HPP
33 
34 #include "tsgRuleLocalPolynomial.hpp"
35 #include "tsgIndexManipulator.hpp"
36 
67 namespace TasGrid{
68 
74 namespace HierarchyManipulations{
75 
87 template<RuleLocal::erule effrule>
97 Data2D<int> computeDAGup(MultiIndexSet const &mset, RuleLocal::erule effrule);
108 template<RuleLocal::erule effrule>
109 Data2D<int> computeDAGup(MultiIndexSet const &mset, bool &is_complete);
110 
122 template<RuleLocal::erule effrule>
124 
131 template<RuleLocal::erule effrule>
132 std::vector<int> computeLevels(MultiIndexSet const &mset);
139 std::vector<int> computeLevels(MultiIndexSet const &mset, RuleLocal::erule effrule);
140 
147 template<RuleLocal::erule effrule>
148 void completeToLower(MultiIndexSet const &mset, MultiIndexSet &refined);
149 
156 template<RuleLocal::erule effrule, typename callable_method>
157 void touchAllImmediateRelatives(std::vector<int> &point, MultiIndexSet const &mset, callable_method apply){
158  int max_kids = RuleLocal::getMaxNumKids<effrule>();
159  for(auto &v : point){
160  int save = v; // replace one by one each index of p with either parent or kid
161 
162  // check the parents
163  v = RuleLocal::getParent<effrule>(save);
164  if (v > -1){
165  int parent_index = mset.getSlot(point);
166  if (parent_index > -1)
167  apply(parent_index);
168  }
169 
170  v = RuleLocal::getStepParent<effrule>(save);
171  if (v > -1){
172  int parent_index = mset.getSlot(point);
173  if (parent_index > -1)
174  apply(parent_index);
175  }
176 
177  for(int k=0; k<max_kids; k++){
178  v = RuleLocal::getKid<effrule>(save, k);
179  if (v > -1){
180  int kid_index = mset.getSlot(point);
181  if (kid_index > -1)
182  apply(kid_index);
183  }
184  }
185 
186  v = save; // restore the original index for the next iteration
187  }
188 }
189 
197 template<RuleLocal::erule effrule>
198 MultiIndexSet getLevelZeroPoints(size_t num_dimensions){
199  int num_parents = 0;
200  while(RuleLocal::getParent<effrule>(num_parents) == -1) num_parents++;
201  return MultiIndexManipulations::generateFullTensorSet(std::vector<int>(num_dimensions, num_parents));
202 }
203 
211 template<RuleLocal::erule effrule>
213  if (candidates.empty()) return MultiIndexSet();
214  auto num_dimensions = candidates.getNumDimensions();
215 
216  // always consider the points without parents
217  MultiIndexSet level_zero = getLevelZeroPoints<effrule>(num_dimensions);
218 
219  MultiIndexSet result; // keep track of the cumulative result
220  MultiIndexSet total = current; // forms a working copy of the entire merged graph
221 
222  // do not consider the points already included in total, complexity is level_zero.getNumIndexes()
223  if (!total.empty()) level_zero = level_zero - total;
224 
225  if (level_zero.getNumIndexes() > 0){ // level zero nodes are missing from current
226  Data2D<int> roots(num_dimensions, 0);
227  for(int i=0; i<level_zero.getNumIndexes(); i++){
228  std::vector<int> p(level_zero.getIndex(i), level_zero.getIndex(i) + num_dimensions);
229  if (!candidates.missing(p))
230  roots.appendStrip(p);
231  }
232 
233  result = MultiIndexSet(roots);
234  total += result;
235  }
236 
237  if (total.empty()) return MultiIndexSet(); // current was empty and no roots could be added
238 
239  int max_kids = RuleLocal::getMaxNumKids<effrule>();
240  int max_relatives = RuleLocal::getMaxNumParents<effrule>() + max_kids;
241  Data2D<int> update;
242  do{
243  update = Data2D<int>(num_dimensions, 0);
244 
245  for(int i=0; i<total.getNumIndexes(); i++){
246  std::vector<int> relative(total.getIndex(i), total.getIndex(i) + num_dimensions);
247  for(auto &r : relative){
248  int k = r; // save the value
249  for(int j=0; j<max_relatives; j++){
250  r = (j < max_kids) ? RuleLocal::getKid<effrule>(k, j)
251  : ((j - max_kids == 0) ? RuleLocal::getParent<effrule>(k) : RuleLocal::getStepParent<effrule>(k));
252  if ((r != -1) && !candidates.missing(relative) && total.missing(relative))
253  update.appendStrip(relative);
254  }
255  r = k;
256  }
257  }
258 
259  if (update.getNumStrips() > 0){
260  MultiIndexSet update_set(update);
261  result += update_set;
262  total += update_set;
263  }
264  }while(update.getNumStrips() > 0);
265 
266  return result;
267 }
268 
269 
277 template<typename T>
278 std::vector<Data2D<T>> splitByLevels(size_t stride, typename std::vector<T>::const_iterator ibegin, typename std::vector<T>::const_iterator iend, std::vector<int>::const_iterator ilevels){
279  size_t top_level = (size_t) *std::max_element(ilevels, ilevels + std::distance(ibegin, iend) / stride);
280 
281  std::vector<Data2D<T>> split(top_level + 1, Data2D<T>(stride, 0));
282 
283  for( struct { std::vector<int>::const_iterator il; typename std::vector<T>::const_iterator idata;} v = {ilevels, ibegin};
284  v.idata != iend;
285  v.il++, std::advance(v.idata, stride))
286  split[*v.il].appendStrip(v.idata);
287 
288  return split;
289 }
290 
295 inline std::vector<Data2D<int>> splitByLevels(MultiIndexSet const &mset, std::vector<int> const &levels){
296  return splitByLevels<int>(mset.getNumDimensions(), mset.begin(), mset.end(), levels.begin());
297 }
298 
303 template<typename T>
304 inline std::vector<Data2D<T>> splitByLevels(Data2D<T> const &data, std::vector<int> const &levels){
305  return splitByLevels<T>(data.getStride(), data.begin(), data.end(), levels.begin());
306 }
307 
312 inline std::vector<Data2D<double>> splitByLevels(StorageSet const &stortage, std::vector<int> const &levels){
313  return splitByLevels<double>(stortage.getNumOutputs(), stortage.begin(), stortage.end(), levels.begin());
314 }
315 
324 public:
329 
331  int getNumJobs() const{ return (int) job_pnts.size(); }
333  int getJobDirection(int job) const{ return job_directions[job]; }
335  int getJobNumPoints(int job) const{ return (int) job_pnts[job].size(); }
337  const int* getJobPoints(int job) const{ return job_pnts[job].data(); }
339  int getMaxNumPoints() const { return (job_pnts.size() > 0) ? (int) std::max_element(job_pnts.begin(), job_pnts.end(),
340  [&](std::vector<int> const &a, std::vector<int> const& b)->bool{ return (a.size() < b.size()); })->size() : 0; }
341 
342 private:
343  std::vector<int> job_directions;
344  std::vector<std::vector<int>> job_pnts;
345 };
346 
347 }
348 
349 }
350 
351 #endif
Generic 2D data structure divided into contiguous strips of fixed length (similar to a matrix).
Definition: tsgIndexSets.hpp:104
std::vector< T >::iterator begin()
Returns an iterator to the beginning of the internal data.
Definition: tsgIndexSets.hpp:167
void appendStrip(typename std::vector< T >::const_iterator const &x)
Uses std::vector::insert to append the data.
Definition: tsgIndexSets.hpp:179
std::vector< T >::iterator end()
Returns an iterator to the end of the internal data.
Definition: tsgIndexSets.hpp:171
int getNumStrips() const
Returns the number of strips.
Definition: tsgIndexSets.hpp:149
size_t getStride() const
Returns the stride.
Definition: tsgIndexSets.hpp:147
Reorganize the points into sets of nodes that align in one-dimension, used for directional localp ref...
Definition: tsgHierarchyManipulator.hpp:323
int getJobDirection(int job) const
Return the direction for the job.
Definition: tsgHierarchyManipulator.hpp:333
int getNumJobs() const
Returns the number of one dimensional jobs.
Definition: tsgHierarchyManipulator.hpp:331
~SplitDirections()
Destroy all data.
Definition: tsgHierarchyManipulator.hpp:328
SplitDirections(const MultiIndexSet &points)
Constructor, deinfe the set to split into directions.
int getMaxNumPoints() const
Return the max number of points for any job.
Definition: tsgHierarchyManipulator.hpp:339
int getJobNumPoints(int job) const
Return the number of points associated with the job.
Definition: tsgHierarchyManipulator.hpp:335
const int * getJobPoints(int job) const
Return the indexes of the points associated with the job.
Definition: tsgHierarchyManipulator.hpp:337
Class that stores multi-indexes in sorted (lexicographical) order.
Definition: tsgIndexSets.hpp:234
size_t getNumDimensions() const
Returns the number of dimensions.
Definition: tsgIndexSets.hpp:263
int getSlot(const int *p) const
Returns the slot containing index p, returns -1 if not found.
bool missing(const std::vector< int > &p) const
Returns true if p is missing from the set, false otherwise.
Definition: tsgIndexSets.hpp:291
const int * getIndex(int i) const
Returns the i-th index of the set, useful to loop over all indexes or to cross reference with values.
Definition: tsgIndexSets.hpp:294
int getNumIndexes() const
Returns the number of indexes.
Definition: tsgIndexSets.hpp:265
bool empty() const
Returns true if there are no multi-indexes in the set, false otherwise.
Definition: tsgIndexSets.hpp:260
std::vector< int >::const_iterator begin() const
Returns a const iterator to the beginning of the internal data.
Definition: tsgIndexSets.hpp:277
std::vector< int >::const_iterator end() const
Returns a const iterator to the end of the internal data.
Definition: tsgIndexSets.hpp:279
Class that stores values, i.e., model outputs, the order of the values is in sync with the order of s...
Definition: tsgIndexSets.hpp:334
size_t getNumOutputs() const
Returns the number of outputs.
Definition: tsgIndexSets.hpp:366
std::vector< double >::const_iterator end() const
Returns a const iterator to the end of the internal data.
Definition: tsgIndexSets.hpp:389
std::vector< double >::const_iterator begin() const
Returns a const iterator to the beginning of the internal data.
Definition: tsgIndexSets.hpp:387
void completeToLower(MultiIndexSet const &mset, MultiIndexSet &refined)
Complete refined so that the union of refined and mset is lower w.r.t. the rule. .
MultiIndexSet getLevelZeroPoints(size_t num_dimensions)
Return the tensor set of all points that sit on level zero (i.e., have no parents).
Definition: tsgHierarchyManipulator.hpp:198
MultiIndexSet getLargestConnected(MultiIndexSet const &current, MultiIndexSet const &candidates)
Return the largest subset of candidates such that adding it to current will result in a connected gra...
Definition: tsgHierarchyManipulator.hpp:212
Data2D< int > computeDAGup(MultiIndexSet const &mset)
Cache the indexes slot numbers of the parents of the multi-indexes in mset.
std::vector< int > computeLevels(MultiIndexSet const &mset)
Returns a vector that is the sum of the one dimensional levels of each multi-index in the set....
Data2D< int > computeDAGDown(MultiIndexSet const &mset)
Cache the indexes slot numbers of the children of the multi-indexes in mset.
std::vector< Data2D< T > > splitByLevels(size_t stride, typename std::vector< T >::const_iterator ibegin, typename std::vector< T >::const_iterator iend, std::vector< int >::const_iterator ilevels)
Split the range between ibegin and iend into strips of stride and orders those by levels according to...
Definition: tsgHierarchyManipulator.hpp:278
void touchAllImmediateRelatives(std::vector< int > &point, MultiIndexSet const &mset, callable_method apply)
Will call apply() with the slot index in mset of each parent/child of point..
Definition: tsgHierarchyManipulator.hpp:157
MultiIndexSet generateFullTensorSet(std::vector< int > const &num_entries)
Create a full-tensor multi-index set with num_entries in each direction.
Definition: tsgIndexManipulator.hpp:79
Encapsulates the Tasmanian Sparse Grid module.
Definition: TasmanianSparseGrid.hpp:68
Algorithms for manipulating sets of multi-indexes.