MUQ  0.4.3
MultiIndexFactory.cpp
Go to the documentation of this file.
2 
3 
4 using namespace std;
5 using namespace muq::Utilities;
6 
8  unsigned int const minOrder,
9  shared_ptr<MultiIndexSet> output,
10  unsigned int const currDim,
11  Eigen::RowVectorXi &base,
12  std::shared_ptr<MultiIndexLimiter> limiter)
13 {
14  int currOrder = base.head(currDim+1).sum();
15  const int length = base.size();
16 
17  if(currDim==length-1)
18  {
19  for(int i=max<int>(0,minOrder-currOrder); i<=maxOrder-currOrder; ++i)
20  {
21  base(length-1) = i;
22  auto newTerm = make_shared<MultiIndex>(base);
23  if(limiter->IsFeasible(newTerm))
24  output->AddActive(newTerm);
25  }
26  }else{
27  for(int i=0; i<=maxOrder-currOrder; ++i)
28  {
29  base.tail(length-currDim).setZero();
30  base(currDim) = i;
31  RecursiveTotalOrderFill(maxOrder,minOrder,output,currDim+1,base,limiter);
32  }
33  }
34 }
35 
37  shared_ptr<MultiIndexSet> output,
38  unsigned int const currDim,
39  Eigen::RowVectorXi &base,
40  const double q,
41  shared_ptr<MultiIndexLimiter> limiter)
42 {
43  double currNorm = 0;
44  for(int i=0; i<currDim; ++i)
45  currNorm += pow(static_cast<double>(base(i)),q);
46 
47  const int length = base.size();
48 
49  if(currDim==length-1)
50  {
51  double newNorm = currNorm;
52  base(length-1) = 0;
53  while(newNorm<maxNormPow)
54  {
55  auto newTerm = make_shared<MultiIndex>(base);
56  if(limiter->IsFeasible(newTerm))
57  output->AddActive(newTerm);
58  base(length-1)++;
59  newNorm = currNorm + pow(static_cast<double>(base(length-1)),q);
60  }
61 
62  }else{
63  double newNorm = currNorm;
64  base.tail(length-currDim).setZero();
65  while(newNorm<maxNormPow)
66  {
67  RecursiveHyperbolicFill(maxNormPow,output,currDim+1,base,q,limiter);
68  base(currDim)++;
69  newNorm = currNorm + pow(static_cast<double>(base(currDim)),q);
70  }
71 
72  }
73 }
74 
75 
76 void muq::Utilities::MultiIndexFactory::RecursiveTensor(Eigen::RowVectorXi const& orders,
77  shared_ptr<MultiIndexSet> output,
78  unsigned int const currDim,
79  Eigen::RowVectorXi &base,
80  std::shared_ptr<MultiIndexLimiter> limiter,
81  bool allInactive)
82 {
83  const unsigned length = base.size();
84  if(currDim==length-1)
85  {
86  int globalInd;
87  shared_ptr<MultiIndex> newMulti;
88  // add all the active indices
89  for(int i=0; i<=orders(length-1); ++i)
90  {
91  base(length-1) = i;
92  newMulti = make_shared<MultiIndex>(base);
93 
94  if(limiter->IsFeasible(newMulti)){
95  if(allInactive){
96  output->AddInactive(newMulti);
97  }else{
98  output->AddActive(newMulti);
99  }
100  }
101  }
102 
103  }else{
104 
105  // add all the active nodes
106  for(int i=0; i<=orders(currDim); ++i)
107  {
108  base.tail(length-currDim).setZero();
109  base(currDim) = i;
110  RecursiveTensor(orders,output,currDim+1,base,limiter, allInactive);
111  }
112 
113  // add inactive neighboring nodes
114  base.tail(length-currDim).setZero();
115  base(currDim) = orders(currDim)+1;
116  RecursiveTensor(orders,output,currDim+1,base,limiter, true);
117 
118  }
119 }
120 
121 
122 shared_ptr<MultiIndexSet> muq::Utilities::MultiIndexFactory::CreateTotalOrder(unsigned int const length,
123  unsigned int const maxOrder,
124  unsigned int const minOrder,
125  std::shared_ptr<MultiIndexLimiter> limiter)
126 {
127  assert(maxOrder>=minOrder);
128  assert(minOrder>=0);
129  assert(length>0);
130 
131  // create an empy multiindex set
132  shared_ptr<MultiIndexSet> output = make_shared<MultiIndexSet>(length,limiter);
133 
134  // start with a vector of zeros
135  Eigen::RowVectorXi base = Eigen::RowVectorXi::Zero(length);
136 
137  RecursiveTotalOrderFill(maxOrder,minOrder,output,0,base,limiter);
138 
139  return output;
140 }
141 
142 std::vector<std::shared_ptr<MultiIndexSet>> muq::Utilities::MultiIndexFactory::CreateTriTotalOrder(unsigned int const length,
143  unsigned int const maxOrder,
144  unsigned int const minOrder,
145  std::shared_ptr<MultiIndexLimiter> limiter)
146 {
147 
148  vector<shared_ptr<MultiIndexSet>> multis(length);
149  for(int d=0; d<length; ++d){
150  auto dimLimiter = make_shared<AndLimiter>(limiter,make_shared<DimensionLimiter>(0,d+1));
151  multis.at(d) = MultiIndexFactory::CreateTotalOrder(length,maxOrder,minOrder,dimLimiter);
152  }
153  return multis;
154 }
155 
156 shared_ptr<MultiIndexSet> muq::Utilities::MultiIndexFactory::CreateHyperbolic(unsigned int const length,
157  unsigned int const maxOrder,
158  const double q,
159  std::shared_ptr<MultiIndexLimiter> limiter)
160 {
161  assert(maxOrder>=0);
162  assert(length>0);
163 
164  // create an empy multiindex set
165  shared_ptr<MultiIndexSet> output = make_shared<MultiIndexSet>(length,limiter);
166 
167  // start with a vector of zeros
168  Eigen::RowVectorXi base = Eigen::RowVectorXi::Zero(length);
169 
170  const double nugget = 1e-5;// needed for maximum power to be inclusive
171  RecursiveHyperbolicFill(pow(static_cast<double>(maxOrder),q)+nugget,output,0,base,q,limiter);
172 
173  return output;
174 }
175 
176 std::vector<std::shared_ptr<MultiIndexSet>> muq::Utilities::MultiIndexFactory::CreateTriHyperbolic(unsigned int const length,
177  unsigned int const maxOrder,
178  const double q,
179  std::shared_ptr<MultiIndexLimiter> limiter)
180 {
181 
182  vector<shared_ptr<MultiIndexSet>> multis(length);
183  for(int d=0; d<length; ++d){
184  auto dimLimiter = make_shared<AndLimiter>(limiter,make_shared<DimensionLimiter>(0,d+1));
185  multis.at(d) = MultiIndexFactory::CreateHyperbolic(length,maxOrder,q,dimLimiter);
186  }
187  return multis;
188 }
189 
190 std::shared_ptr<MultiIndexSet> muq::Utilities::MultiIndexFactory::CreateFullTensor(unsigned int const length,
191  unsigned int const order,
192  std::shared_ptr<MultiIndexLimiter> limiter)
193 {
194  return muq::Utilities::MultiIndexFactory::CreateFullTensor(order*Eigen::RowVectorXi::Ones(length), limiter);
195 }
196 
197 
198 std::shared_ptr<MultiIndexSet> muq::Utilities::MultiIndexFactory::CreateFullTensor(Eigen::RowVectorXi const& orders,
199  std::shared_ptr<MultiIndexLimiter> limiter)
200 {
201  assert(orders.minCoeff()>=0);
202  assert(orders.size()>0);
203 
204  unsigned int length = orders.size();
205  unsigned int numIndices = (orders.array()+2).prod(); // an overestimate of the total number of indices
206  unsigned int numActiveIndices = (orders.array()+1).prod(); // the exact number of active indices
207 
208  // create an empy multiindex set
209  shared_ptr<MultiIndexSet> output = make_shared<MultiIndexSet>(length,limiter);
210 
211  // start with a vector of zeros
212  Eigen::RowVectorXi base = Eigen::RowVectorXi::Zero(length);
213 
214  RecursiveTensor(orders, output, 0, base, limiter, false);
215 
216  return output;
217 }
218 
219 
220 std::shared_ptr<MultiIndexSet> muq::Utilities::MultiIndexFactory::CreateAnisotropic(const Eigen::RowVectorXf& weights, const double epsilon)
221 {
222  auto getNextIndex = [](Eigen::RowVectorXi base, unsigned int d) {
223  auto nextIndex = make_shared<MultiIndex>(base);
224  nextIndex->SetValue(d, nextIndex->GetValue(d) + 1);
225  return nextIndex;
226  };
227 
228  auto limiter = make_shared<AnisotropicLimiter>(weights, epsilon);
229  auto indexSet = make_shared<MultiIndexSet>(weights.size(),limiter);
230 
231  Eigen::RowVectorXi base = Eigen::RowVectorXi::Zero(weights.size());
232  auto nextIndex = make_shared<MultiIndex>(base);
233  indexSet->AddMulti(nextIndex);
234 
235  unsigned int d = 0;
236 
237  while(true) {
238  d = 0;
239  nextIndex = getNextIndex(base, d);
240  while(!limiter->IsFeasible(nextIndex)) {
241  if (base[d] != 0) {
242  base[d] = 0;
243  ++d;
244  if (d >= base.size()) {
245  base.conservativeResize(base.size() + 1);
246  base[d] = 0;
247  }
248  }else if (base.sum() > 0){
249  d = 0;
250  while ((d < base.size() - 1) && (base[d] == 0))
251  ++d;
252  }else{
253  return indexSet;
254  }
255  nextIndex = getNextIndex(base, d);
256  }
257 
258  ++base[d];
259  indexSet->AddMulti(nextIndex);
260  }
261  return indexSet;
262 }
263 
264 
265 std::shared_ptr<MultiIndex> MultiIndexFactory::CreateSingleTerm(int totalDim, int nonzeroDim, int order)
266 {
267  shared_ptr<MultiIndex> output = make_shared<MultiIndex>(totalDim);
268  output->SetValue(nonzeroDim,order);
269  return output;
270 }
static std::shared_ptr< MultiIndexSet > CreateTotalOrder(unsigned int const length, unsigned int const maxOrder, unsigned int const minOrder=0, std::shared_ptr< MultiIndexLimiter > limiter=std::make_shared< NoLimiter >())
Construct a total order limited MultiIndex.
static std::vector< std::shared_ptr< MultiIndexSet > > CreateTriHyperbolic(unsigned int const length, unsigned int const maxOrder, const double q=0.5, std::shared_ptr< MultiIndexLimiter > limiter=std::make_shared< NoLimiter >())
static void RecursiveTensor(const Eigen::RowVectorXi &orders, std::shared_ptr< MultiIndexSet > output, unsigned int const currDim, Eigen::RowVectorXi &base, std::shared_ptr< MultiIndexLimiter > limiter, bool allInactive)
static std::shared_ptr< MultiIndexSet > CreateFullTensor(unsigned int const length, unsigned int const order, std::shared_ptr< MultiIndexLimiter > limiter=std::make_shared< NoLimiter >())
Construct a full tensor product multiindex set.
static std::shared_ptr< MultiIndexSet > CreateHyperbolic(unsigned int const length, unsigned int const maxOrder, const double q=0.5, std::shared_ptr< MultiIndexLimiter > limiter=std::make_shared< NoLimiter >())
Construct a general hyperbolic MultiIndex.
static std::vector< std::shared_ptr< MultiIndexSet > > CreateTriTotalOrder(unsigned int const length, unsigned int const maxOrder, unsigned int const minOrder=0, std::shared_ptr< MultiIndexLimiter > limiter=std::make_shared< NoLimiter >())
static void RecursiveTotalOrderFill(unsigned int const maxOrder, unsigned int const minOrder, std::shared_ptr< MultiIndexSet > output, unsigned int const currDim, Eigen::RowVectorXi &base, std::shared_ptr< MultiIndexLimiter > limiter)
static void RecursiveHyperbolicFill(const double maxOrderPow, std::shared_ptr< MultiIndexSet > output, unsigned int const currDim, Eigen::RowVectorXi &base, const double q, std::shared_ptr< MultiIndexLimiter > limiter)
static std::shared_ptr< MultiIndexSet > CreateAnisotropic(const Eigen::RowVectorXf &weights, const double epsilon)
Construct an anisotropic multiindex set based on a priori information on the importance of each dimen...