1 /* _______________________________________________________________________
2
3 Surfpack: A Software Library of Multidimensional Surface Fitting Methods
4 Copyright (c) 2006, Sandia National Laboratories.
5 This software is distributed under the GNU Lesser General Public License.
6 For more information, see the README file in the top Surfpack directory.
7 _______________________________________________________________________ */
8
9 #ifndef __SURFPACK_H__
10 #define __SURFPACK_H__
11
12 #include "surfpack_system_headers.h"
13
14 #include "MersenneTwister.h"
15 #include "SurfpackMatrix.h"
16
17 //class AbstractSurfDataIterator;
18 class SurfData;
19
20 enum DifferenceType {
21 DT_ABSOLUTE,
22 DT_SQUARED,
23 DT_SCALED
24 };
25
26 enum MetricType {
27 MT_RELATIVE_MAXIMUM,
28 MT_RELATIVE_AVERAGE,
29 MT_MINIMUM,
30 MT_MAXIMUM,
31 MT_SUM,
32 MT_MEAN,
33 MT_ROOT_MEAN
34 };
35
36 namespace surfpack {
37
38 enum { SILENT_OUTPUT, QUIET_OUTPUT, NORMAL_OUTPUT, VERBOSE_OUTPUT,
39 DEBUG_OUTPUT };
40
41 // _____________________________________________________________________________
42 // Debugging Output Strategy
43 // _____________________________________________________________________________
44
45 class DbgStream {
46 public:
47 mutable int level;
DbgStream()48 DbgStream() : level(0) {}
~DbgStream()49 ~DbgStream() {}
operator()50 const DbgStream& operator()(int level_in) const {
51 level = level_in;
52 return *this;
53 }
54 template<typename T> const DbgStream& operator<<(const T& item) const {
55 if (level) {
56 std::cout << item;
57 }
58 return *this;
59 }
60 };
61 const DbgStream& dbg(int level_in);
62 // _____________________________________________________________________________
63 // Mersenne Twister Random Number Generator
64 // _____________________________________________________________________________
65
66 class MyRandomNumberGenerator : std::unary_function<int,int>
67 {
68 public:
MyRandomNumberGenerator()69 MyRandomNumberGenerator() {}
70 MTRand mtrand;
71 // operator for std::random_shuffle; int in [0, n-1]
operator()72 int operator()(int n)
73 {
74 return mtrand.randInt(n-1);
75 }
seed(int seeder)76 void seed(int seeder)
77 {
78 mtrand.seed(seeder);
79 }
80 /// double in [0,1]
rand()81 double rand()
82 {
83 return mtrand.rand();
84 }
85 /// double in [0,1)
randExc()86 double randExc()
87 {
88 return mtrand.randExc();
89 }
90 /// int in [0,n]
randInt(int n)91 int randInt(int n)
92 {
93 return mtrand.randInt(n);
94 }
95
96 };
97
98 MyRandomNumberGenerator& shared_rng();
99
100 // _____________________________________________________________________________
101 // Block partitioning helper methods
102 // _____________________________________________________________________________
103
104 unsigned block_low(unsigned id, unsigned p, unsigned n);
105 unsigned block_high(unsigned id, unsigned p, unsigned n);
106 unsigned block_size(unsigned id, unsigned p, unsigned n);
107 unsigned block_owner(unsigned j, unsigned p, unsigned n);
108
109 // _____________________________________________________________________________
110 // Constants
111 // _____________________________________________________________________________
112 // Precision of output for double precision numbers
113 const unsigned output_precision = 6;
114
115 // Length of the field for double-precision number stream output
116 const unsigned field_width = output_precision + 9;
117
118 // _____________________________________________________________________________
119 // Nested Types
120 // _____________________________________________________________________________
121
122 /// For use in comparing the actual value of some function with the estimate
123 /// given by a Surface approximation
124 struct ErrorStruct {
125 double observed;
126 double estimated;
127 };
128
129 /// Thrown when an attempt to open a file for reading or writing fails
130 class file_open_failure: public std::runtime_error
131 {
132 public:
133 file_open_failure(const std::string& filename = "")
134 : std::runtime_error("File " + filename + " could not be opened.") {}
135 };
136
137 /// Thrown when end-of-file is reached unexpectedly, when an unrecognized or
138 /// unacceptable file extension is encountered, or when a file contains
139 /// unexpected or illegally formatted contents.
140 class io_exception: public std::runtime_error
141 {
142 public:
runtime_error(msg)143 io_exception(const std::string& msg = "") : std::runtime_error(msg) {}
144 };
145
146 // ____________________________________________________________________________
147 // MISC functions
148 // ____________________________________________________________________________
149
150 // windows doesn't have a native atanh function, long term we may want to switch to boost but for now we implement it ourselves.
atanh(double x)151 inline double atanh(double x)
152 {
153 #if defined(_WIN32) || defined(_WIN64)
154 return 0.5*(std::log(1.0+x) - std::log(1.0-x));
155 #else
156 return ::atanh(x);
157 #endif
158 };
159
160
161 // ____________________________________________________________________________
162 // I/O
163 // ____________________________________________________________________________
164
165 /// Write the value of contents to the file specified by filename. Throw an
166 /// exception if the file cannot be opened.
167 void writeFile(std::string filename, std::string contents);
168
169 /// Write the parameter header, followed by the matrix mat (the dimensions of
170 /// which are specified by parameters rows and columns) to the parameter os.
171 /// If c_style is true, the memory layout is assumed to follow the C
172 /// convention (if mat points to an m by n matrix, the first m values are
173 /// interpreted as the first row). Otherwise, the layout is assumed to
174 /// follow the Fortran convention (the first n values are interpreted as the
175 /// first column).
176 void writeMatrix(const std::string header, double* mat, unsigned rows,
177 unsigned columns, std::ostream& os, bool c_style = false);
178
179 /// Write the parameter header, followed by the matrix mat (the dimensions of
180 /// which are specified by parameters rows and columns) to the parameter os.
181 /// If c_style is true, the memory layout is assumed to follow the C
182 /// convention (if mat points to an m by n matrix, the first m values are
183 /// interpreted as the first row). Otherwise, the layout is assumed to
184 /// follow the Fortran convention (the first n values are interpreted as the
185 /// first column).
186 void writeMatrix(const std::string header, unsigned* mat, unsigned rows,
187 unsigned columns, std::ostream& os, bool c_style = false);
188
189 /// Write the contents of a matrix to a file specified by parameter filename.
190 /// Open the file and call another version of writeMatrix.
191 void writeMatrix(const std::string filename, double* mat, unsigned rows,
192 unsigned columns, bool c_style = false);
193
194 /// Write the contents of a matrix to a file specified by parameter filename.
195 /// Open the file and call another version of writeMatrix.
196 void writeMatrix(const std::string filename, unsigned* mat, unsigned rows,
197 unsigned columns, bool c_style = false);
198
199 /// Write the parameter header followed by the values in the vector
200 void printVector(const std::string header, VecDbl& vec,
201 std::ostream& os = std::cout);
202
203 /// Return true if the file specified by parameter file name has the extension
204 /// specified by parameter extension
205 bool hasExtension(const std::string& filename, const std::string extension);
206
207 /// Return true for binary model filename, false for text
208 bool isBinaryModelFilename(const std::string& filename);
209
210 /// Throw an exception if end-of-file has been reached
211 void checkForEOF(std::istream& is);
212
213 /// Open the file specified by filename and return the type of Surface that
214 /// is written there. Throw an exception if the file cannot be opened, or if
215 /// the file extension is anything other than .txt or .srf.
216 const std::string surfaceName(const std::string filename);
217
218 /// Return the next item in the file as a string. If the file is opened in
219 /// binary mode, first read an integer that specifies the number of
220 /// characters in the string, then read the string.
221 const std::string readName(std::istream& is, bool binary);
222
223 /// Round values that are close to integers to integers
224 void approximateByIntegers(VecDbl& vals, double epsilon = 1.e-6);
225
226 // ____________________________________________________________________________
227 // Vector helper methods
228 // ____________________________________________________________________________
229
230 /// Return the sum of the vector of values
231 double sum_vector(VecDbl& vals);
232
233 /// Return the arithmetic mean (average) of the values in vector vals
234 double mean(const VecDbl& vals);
235
236 /// Return the sample variance of the values in vals
237 double sample_var(VecDbl& vals);
238
239 /// Return the sample standard deviation of the values in vals
240 double sample_sd(VecDbl& vals);
241
242 /// Return the sum of squared deviations from the mean
243 double sum_squared_deviations(VecDbl& vals);
244
245 /// Return the sum of absolute deviations from the mean
246 double sum_absolute_deviations(VecDbl& vals);
247
248 /// Return absolute, squared, or relative differences of second and third
249 /// parameters through the first parameter
250 void differences(VecDbl& results, VecDbl& observed,
251 VecDbl& predicted, enum DifferenceType dp = DT_ABSOLUTE);
252
253 /// Return the euclidean distance between pt1 and pt2. Throw an exception if
254 /// the dimensionality of the two vectors does not match.
255 double euclideanDistance(const VecDbl& pt1,
256 const VecDbl& pt2);
257
258 /// Store the vector difference between pt1 and pt2 in the paramter diff.
259 /// Throw an exception if the dimensionality of the points does not match.
260 void vectorDifference(VecDbl& diff, const VecDbl& pt1, const VecDbl& pt2);
261 // ____________________________________________________________________________
262 // Functions for common linear algebra tasks
263 // ____________________________________________________________________________
264 /// Least squares solve of system Ax = b
265 void linearSystemLeastSquares(MtxDbl& A, VecDbl& x, VecDbl b);
266
267 /// Least squares solve os system Ax = c, subject to Bx = d
268 void leastSquaresWithEqualityConstraints(MtxDbl& A,
269 VecDbl& x, VecDbl& c,
270 MtxDbl& B, VecDbl& d);
271
272 /// Calls dgetrf followed by dgetri
273 MtxDbl& inverse(MtxDbl& matrix);
274
275 /// Calls dgetrf to compute LU Decomposition
276 MtxDbl& LUFact(MtxDbl& matrix,
277 std::vector<int>& ipvt);
278
279 /// Calls dgetri to compute matrix inverse, after prior call to dgetrf
280 MtxDbl& inverseAfterLUFact(MtxDbl& matrix, std::vector<int>& ipvt);
281
282 // Solves triangular system of the form Ax=b
283 VecDbl inverseAfterQRFact(const MtxDbl& matrix, VecDbl vector,
284 char uplo, char trans = 'N');
285
286 /// Note: These matrix functions would not fit easily in SurfpackMatrix.h
287 /// because the fortran math functions are not templated
288 /// matrix-vector mutltiplication
289 VecDbl& matrixVectorMult(VecDbl& result,
290 MtxDbl& matrix, VecDbl& the_vector,
291 char trans = 'N');
292
293 /// matrix-matrix multiplication
294 MtxDbl& matrixMatrixMult(MtxDbl& result, MtxDbl& matrixA, MtxDbl& matrixB,
295 char transA = 'N', char transB = 'N');
296
297 /// matrix-matrix addition
298 MtxDbl& matrixSum(MtxDbl& result, MtxDbl& matrixA, MtxDbl& matrixB);
299 MtxDbl& matrixSubtraction(MtxDbl& result, MtxDbl& matrixA, MtxDbl& matrixB);
300
301 /// vector-vector inner product
302 double dot_product(const VecDbl& vector_a, const VecDbl& vector_b);
303
304 /// Adds or subtracts same value to all vector elements
305 VecDbl& vectorShift(VecDbl& the_vector, double shift_value);
306
307 /// Returns the weighted average of two vectors: alpha*first+(1-alpha)*second
308 VecDbl weightedAvg(const VecDbl& first, const VecDbl& second, double alpha = 0.5);
309 // ____________________________________________________________________________
310 // Converting a string to a vector
311 // ____________________________________________________________________________
312 template<typename T>
toVec(const std::string & s)313 std::vector<T> toVec(const std::string& s)
314 {
315 std::istringstream is(s);
316 std::vector<T> result;
317 if (s == "") return result;
318 T temp;
319 do {
320 is >> temp;
321 result.push_back(temp);
322 } while (!is.eof());
323 return result;
324 }
325
326 template<typename T>
toString(const T arg)327 std::string toString(const T arg)
328 {
329 std::ostringstream os;
330 os << arg;
331 return os.str();
332 }
333
334 template<typename T>
fromVec(const std::vector<T> & vec)335 std::string fromVec(const std::vector<T>& vec)
336 {
337 std::ostringstream os;
338 for (typename std::vector<T>::const_iterator itr = vec.begin();
339 itr != vec.end(); ++itr) {
340 if (itr != vec.begin()) os << " ";
341 os << *itr;
342 }
343 return os.str();
344 }
345
346 void stripQuotes(std::string& str);
347
348 // ____________________________________________________________________________
349 // Testing
350 // ____________________________________________________________________________
351 /// Return the value of the test function specified by parameter name at the
352 /// point specified by parameter pt
353 /// \todo Change if-else construct to lookup in STL map of <name, function>
354 /// pairs.
355 double testFunction(const std::string name, const VecDbl& pt);
356
357 /// Non-trivial polynomial function
358 double moderatepoly(const VecDbl& pt);
359
360 /// Tony Giunta's test function: a little wave mixed with a big wave, plus
361 /// noise
362 double quasisine(const VecDbl& pt);
363
364 /// f(x) = sigma{i=1 to n}(x_i^2 - 10*cos(2*pi*x) + 10). With side
365 /// constraints near zero (e.g. +/-10) along each dimension, the function
366 /// appears highly-multimodal. With larger bounds, the bowl shape becomes
367 /// more dominant and the waviness is reduced to noise.
368 double rastrigin(const VecDbl& pt);
369
370 /// A multi-dimensional extension of the classic Rosenbrock test function
371 double rosenbrock(const VecDbl& pt);
372
373 /// f(x) = 3 + sigma{i=1 to n}(2*x_i)
374 double simplepoly(const VecDbl& pt);
375
376 /// Sum of the sine function along each dimension
377 double sinewave(const VecDbl& pt);
378
379 /// Sum of squares along each dimension
380 double sphere(const VecDbl& pt);
381
382 /// f(x) = sigma{i=1 to i}(x_i)
383 double sumofall(const VecDbl& pt);
384
385 /// f(x) = sigma{i=1 to n}(x_i + sin x_i)
386 double xplussinex(const VecDbl& pt);
387
388 /// Random (different queries for the same point will give different results)
389 double noise(const VecDbl& pt);
390 } // namespace surfpack
391
392 #endif // __SURFPACK_H__
393