SOT
experimental_design.h
1 
8 #ifndef SOT_EXPERIMENTAL_DESIGN_H
9 #define SOT_EXPERIMENTAL_DESIGN_H
10 
11 #include "common.h"
12 #include "utils.h"
13 #include "merit_functions.h"
14 
16 namespace sot {
17 
19 
31  class ExpDesign {
32  public:
34  virtual int dim() const = 0;
35  virtual int numPoints() const = 0;
37  virtual mat generatePoints() const = 0;
39  };
40 
42 
53  class FixedDesign : public ExpDesign {
54  protected:
55  int mDim;
56  int mNumPoints;
58  public:
60 
63  FixedDesign(mat& points) {
64  mPoints = points;
65  mDim = points.n_rows;
66  mNumPoints = points.n_cols;
67  }
69 
72  int dim() const {
73  return mDim;
74  }
76 
79  int numPoints() const {
80  return mNumPoints;
81  }
83 
86  mat generatePoints() const {
87  return mPoints;
88  }
89  };
90 
92 
105  protected:
106  int mDim;
109  public:
111 
116  mNumPoints = numPoints;
117  mDim = dim;
118  }
120 
123  int dim() const {
124  return mDim;
125  }
127 
130  int numPoints() const {
131  return mNumPoints;
132  }
134 
137  mat generatePoints() const {
138  mat points = arma::zeros<mat>(mDim, mNumPoints);
139  points.row(0) = arma::linspace<vec>(1, mNumPoints, mNumPoints).t();
140 
141  int middleInd = mNumPoints/2;
142 
143  if (mNumPoints % 2 == 1) {
144  points.col(middleInd).fill(middleInd + 1);
145  }
146 
147  // Fill upper
148  for(int j=1; j < mDim; j++) {
149  for(int i=0; i < middleInd; i++) {
150  if (rand() < 0.5) {
151  points(j, i) = mNumPoints -i;
152  }
153  else {
154  points(j, i) = i + 1;
155  }
156  }
157  // Shuffle
158  points(j, arma::span(0, middleInd - 1)) = arma::shuffle(points(j, arma::span(0, middleInd - 1)));
159  }
160 
161  // Fill bottom
162  for(int i=middleInd; i < mNumPoints; i++) {
163  points.col(i) = mNumPoints + 1 - points.col(mNumPoints - 1 - i);
164  }
165 
166  return points/double(mNumPoints);
167  }
168  };
169 
171 
181  class LatinHypercube : public ExpDesign {
182  protected:
183  int mDim;
185  public:
187 
192  mNumPoints = numPoints;
193  mDim = dim;
194  }
196 
199  int dim() const {
200  return mDim;
201  }
203 
206  int numPoints() const {
207  return mNumPoints;
208  }
210 
213  mat generatePoints() const {
214  mat XBest;
215  mat X;
216  double bestScore = 0;
217 
218  // Generate 100 LHD and pick the best one
219  for(int iter=0; iter < 100; iter++) {
220  X = arma::zeros(mDim, mNumPoints);
221  vec xvec = (arma::linspace<vec>(1, mNumPoints, mNumPoints) - 0.5) / mNumPoints;
222 
223  for(int j=0; j < mDim; j++) {
224  X.row(j) = xvec(arma::shuffle(arma::linspace<uvec>(0, mNumPoints - 1, mNumPoints))).t();
225  }
226 
227  mat dists = sqrt(mDim)*arma::eye(mNumPoints, mNumPoints) + arma::sqrt(squaredPairwiseDistance(X, X));
228  double score = arma::min((vec)arma::min(dists).t());
229 
230  if (score > bestScore) {
231  XBest = X;
232  bestScore = score;
233  }
234  }
235 
236  return XBest;
237  }
238  };
239 
241 
250  class TwoFactorial : public ExpDesign {
251  protected:
252  int mDim;
254  public:
256 
260  mNumPoints = pow(2, dim);
261  mDim = dim;
262  if(dim >= 15) {throw std::logic_error("Using 2-Factorial for dim >= 15 is a bad idea"); }
263  }
265 
268  int dim() const {
269  return mDim;
270  }
272 
275  int numPoints() const {
276  return mNumPoints;
277  }
279 
282  mat generatePoints() const {
283  mat xSample = arma::zeros<mat>(mDim, mNumPoints);
284  for(int i=0; i < mDim; i++) {
285  int elem = 0;
286  int flip = pow(2, i);
287  for(int j=0; j < mNumPoints; j++) {
288  xSample(i, j) = elem;
289  if((j+1) % flip == 0) { elem = (elem + 1) % 2; }
290  }
291  }
292  return xSample;
293  }
294  };
295 
297 
305  class CornersMid : public ExpDesign {
306  protected:
307  int mDim;
309  public:
311 
315  mNumPoints = 1 + pow(2, dim);
316  mDim = dim;
317  if(dim >= 15) {throw std::logic_error("Using Corners + Mid for dim >= 15 is a bad idea"); }
318  }
320 
323  int dim() const {
324  return mDim;
325  }
327 
330  int numPoints() const {
331  return mNumPoints;
332  }
334 
337  mat generatePoints() const {
338  mat xSample = arma::zeros<mat>(mDim, mNumPoints);
339 
340  for(int i=0; i < mDim; i++) {
341  int elem = 0;
342  int flip = pow(2, i);
343  for(int j = 0; j < mNumPoints; j++) {
344  xSample(i, j) = elem;
345  if((j + 1) % flip == 0) { elem = (elem + 1) % 2; }
346  }
347  }
348  xSample.col(mNumPoints - 1).fill(0.5);
349 
350  return xSample;
351  }
352  };
353 }
354 
355 #endif
mat generatePoints() const
Method that returns the user supplied experimental design.
Definition: experimental_design.h:86
arma::vec vec
Default (column) vector class.
Definition: common.h:17
int numPoints() const
Method for getting the number of points in the experimental design.
Definition: experimental_design.h:206
int numPoints() const
Method for getting the number of points in the experimental design.
Definition: experimental_design.h:130
int mDim
Definition: experimental_design.h:252
virtual mat generatePoints() const =0
Virtual method for generating an experimental design.
Latin hypercube design.
Definition: experimental_design.h:181
int mDim
Definition: experimental_design.h:106
mat mPoints
Definition: experimental_design.h:57
int dim() const
Method for getting the number of dimensions.
Definition: experimental_design.h:323
2-Factorial design
Definition: experimental_design.h:250
int mNumPoints
Definition: experimental_design.h:184
FixedDesign(mat &points)
Constructor.
Definition: experimental_design.h:63
CornersMid(int dim)
Constructor.
Definition: experimental_design.h:314
int mNumPoints
Definition: experimental_design.h:253
double rand()
Generate a U[0,1] realization.
Definition: utils.h:386
int mNumPoints
Definition: experimental_design.h:308
mat generatePoints() const
Method that generates a symmetric Latin hypercube design.
Definition: experimental_design.h:137
int dim() const
Method for getting the number of dimensions.
Definition: experimental_design.h:72
mat generatePoints() const
Method that generates a symmetric Latin hypercube design.
Definition: experimental_design.h:213
mat generatePoints() const
Method that generates a symmetric Latin hypercube design.
Definition: experimental_design.h:337
int mDim
Definition: experimental_design.h:307
MatType squaredPairwiseDistance(const MatType &X, const MatType &Y)
Fast level-3 distance computation between two sets of points.
Definition: utils.h:48
int numPoints() const
Method for getting the number of points in the experimental design.
Definition: experimental_design.h:275
virtual int numPoints() const =0
Virtual method for getting the number of points in the experimental design.
int mDim
Definition: experimental_design.h:183
Abstract class for a SOT experimental design class.
Definition: experimental_design.h:31
LatinHypercube(int numPoints, int dim)
Constructor.
Definition: experimental_design.h:191
Fixed experimental design.
Definition: experimental_design.h:53
int numPoints() const
Method for getting the number of points in the experimental design.
Definition: experimental_design.h:330
int mNumPoints
Definition: experimental_design.h:56
int numPoints() const
Method for getting the number of points in the experimental design.
Definition: experimental_design.h:79
int dim() const
Method for getting the number of dimensions.
Definition: experimental_design.h:123
int dim() const
Method for getting the number of dimensions.
Definition: experimental_design.h:268
Symmetric Latin hypercube design.
Definition: experimental_design.h:104
virtual int dim() const =0
Virtual method for getting the number of dimensions.
SOT namespace.
Definition: sot.h:27
Corners + Midpoint.
Definition: experimental_design.h:305
mat generatePoints() const
Method that generates a symmetric Latin hypercube design.
Definition: experimental_design.h:282
int mNumPoints
Definition: experimental_design.h:107
TwoFactorial(int dim)
Constructor.
Definition: experimental_design.h:259
arma::mat mat
Default matrix class.
Definition: common.h:16
int mDim
Definition: experimental_design.h:55
int dim() const
Method for getting the number of dimensions.
Definition: experimental_design.h:199
SymmetricLatinHypercube(int numPoints, int dim)
Constructor.
Definition: experimental_design.h:115