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