1 /* _______________________________________________________________________
2
3 PECOS: Parallel Environment for Creation Of Stochastics
4 Copyright (c) 2011, 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 Pecos directory.
7 _______________________________________________________________________ */
8
9 #include <ctype.h>
10 #include <string>
11 #include <cmath>
12 #include <iostream>
13
14 #include <Teuchos_UnitTestHarness.hpp>
15
16 #include <teuchos_data_types.hpp>
17 #include <CppFunction.hpp>
18 #include <BoundedVariables.hpp>
19 #include <AffineVariableTransformation.hpp>
20 #include <RegressionBuilder.hpp>
21
22 #include <DirectANN.hpp>
23
24 using namespace Pecos;
25 using namespace Pecos::util;
26 using namespace Pecos::surrogates;
27
28 namespace {
29
30 //--------------------------------------
31 // Helper functions
32
33 /**
34 \brief Evaluate a quadratic polynomial with no interaction terms, i.e.
35 * \[q_i = (i+1) + \sum_j (i+1)*(2*x_j-1)^2+(i+2)*(2*x_j-1)\]
36 */
additive_quadratic_function(const Real * sample,Real * func_vals,const OptionsList & opts)37 void additive_quadratic_function(const Real* sample, Real* func_vals, const OptionsList &opts){
38 const int num_vars = opts.get<int>("num_vars");
39 const int num_qoi = opts.get<int>("num_qoi");
40
41 for (int i=0; i<num_qoi; i++){
42 func_vals[i] = (Real)(i+1);
43 for (int j=0; j<num_vars; j++){
44 Real x = (2*sample[j]-1);
45 func_vals[i] += (Real)(i+1)*x*x+(Real)(i+2)*x;
46 }
47 }
48 }
49 /**
50 \brief Evaluate the "textbook" function of two real variables, i.e.
51 * \[q = (x_1 - 1)^4 + (x_2 - 2)^4 \]
52 */
53
textbook_function(const Real * sample,Real * func_vals,const OptionsList & opts)54 void textbook_function(const Real* sample, Real* func_vals, const OptionsList &opts){
55 Real x1 = sample[0];
56 Real x2 = sample[1];
57 func_vals[0] = pow(x1 - 1., 4.) + pow(x2 - 1., 4.);
58 }
59
60 // Compute the mean pointwise absolute error
mean_abs_error(RealMatrix & pred,RealMatrix & truth)61 double mean_abs_error(RealMatrix &pred, RealMatrix &truth) {
62 double K = pred.numRows();
63 if (K != truth.numRows())
64 throw(std::runtime_error("Mismatch between predicted and truth vector dimensions"));
65 double eval = 0.0;
66 for (int i = 0; i < K; i++) {
67 eval += std::abs(pred(i,0) - truth(i,0));
68 }
69 eval /= K;
70 return eval;
71 }
72
73 // Compute the relative mean pointwise absolute error
relative_mean_abs_error(RealMatrix & pred,RealMatrix & truth)74 double relative_mean_abs_error(RealMatrix &pred, RealMatrix &truth) {
75 double K = pred.numRows();
76 if (K != truth.numRows())
77 throw(std::runtime_error("Mismatch between predicted and truth vector dimensions"));
78 double eval = 0.0;
79 double tmp;
80 for (int i = 0; i < K; i++) {
81 eval += std::abs((pred(i,0) - truth(i,0))/truth(i,0));
82 }
83 eval /= K;
84 return eval;
85 }
86
test_directANN(Real atol)87 int test_directANN(Real atol){
88 // Data generation parameters
89 int num_vars = 2;
90 int num_samples = 100;
91 int training_data_seed = 3105;
92 int test_data_seed = 1000;
93
94 // direct ANN parameters
95 int num_qoi = 1; // must be 1 for directANN
96 double range_param = 2.0;
97 int directANN_seed = 8105;
98 int nodes = num_samples - 1;
99
100 // Define the function variables
101 //RealVector ranges;
102 //define_homogeneous_ranges(num_vars, 0., 1., ranges);
103 RealVector ranges(4);
104 ranges[0] = 0.;
105 ranges[1] = 1.;
106 ranges[2] = -1.;
107 ranges[3] = 1.;
108 std::shared_ptr<Variables> variables(new BoundedVariables);
109 std::dynamic_pointer_cast<BoundedVariables>(variables)->set_ranges(ranges);
110
111 // Define the variable transformation
112 std::shared_ptr<VariableTransformation>
113 var_transform(new AffineVariableTransformation);
114 var_transform->set_variables(variables);
115
116 // Define the function to approximate
117 CppFunction model;
118 OptionsList model_opts;
119 model_opts.set("num_vars", num_vars);
120 model_opts.set("num_qoi", num_qoi);
121 model.set_options(model_opts);
122 model.set_function(&additive_quadratic_function);
123 //model.set_function(&textbook_function);
124
125 // Generate training and test data
126 RealMatrix training_samples, training_vals;
127 generate_uniform_samples(num_vars, num_samples, training_data_seed, *var_transform,
128 training_samples);
129 model.value(training_samples, training_vals);
130
131 RealMatrix test_samples, test_vals;
132 generate_uniform_samples(num_vars, num_samples, test_data_seed, *var_transform,
133 test_samples);
134 model.value(test_samples, test_vals);
135
136 // Build the Direct ANN approximation for 3 different scalers
137 // and compare to "gold" values
138 double mean_normalization_gold = 1.06246e-5;
139 double min_max_normalization_gold = 3.26542e-5;
140 double standardization_gold = 3.04479e-4;
141
142 RealMatrix pred(num_samples, 1);
143 double error_eval;
144
145 std::string scaler_type = "mean normalization";
146 DirectANN directANN_mean_nm(nodes, range_param, training_samples, training_vals,
147 scaler_type, directANN_seed);
148 directANN_mean_nm.value(test_samples, pred);
149 error_eval = relative_mean_abs_error(pred, test_vals);
150 if (!(std::abs(error_eval - mean_normalization_gold < atol))) {
151 std::cout << "1\n";
152 return 1;
153 }
154
155 scaler_type = "min-max normalization";
156 DirectANN directANN_mm_nm(nodes, range_param, training_samples, training_vals,
157 scaler_type, directANN_seed);
158 directANN_mm_nm.value(test_samples, pred);
159 error_eval = relative_mean_abs_error(pred, test_vals);
160 if (!(std::abs(error_eval - min_max_normalization_gold < atol))) {
161 std::cout << "2\n";
162 return 2;
163 }
164
165 scaler_type = "standardization";
166 DirectANN directANN_sd(nodes, range_param, training_samples, training_vals,
167 scaler_type, directANN_seed);
168 directANN_sd.value(test_samples, pred);
169 error_eval = relative_mean_abs_error(pred, test_vals);
170 if (!(std::abs(error_eval - standardization_gold < atol))) {
171 std::cout << "3\n";
172 return 3;
173 }
174 else {
175 return 0;
176 }
177 }
178
179 //----------------------------------------------------------------
180 // Unit tests
181
182 /**
183 \brief Create a direct ANN from sample data and test performance
184 for 3 data scaler types
185 */
TEUCHOS_UNIT_TEST(dry_run,test_directANN)186 TEUCHOS_UNIT_TEST(dry_run, test_directANN)
187 {
188 TEST_ASSERT(!test_directANN(1e-10));
189 }
190
191 }
192