ROL
function/test_17.cpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Rapid Optimization Library (ROL) Package
4//
5// Copyright 2014 NTESS and the ROL contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
15#include "ROL_Stream.hpp"
16#include "Teuchos_GlobalMPISession.hpp"
17
18#include "ROL_Bounds.hpp"
19#include "ROL_Constraint.hpp"
21#include "ROL_StdVector.hpp"
22#include "ROL_UnaryFunctions.hpp"
23
24typedef double RealT;
25
27 RealT one(1);
28 a.axpy(-one, b);
29 a.applyUnary(ROL::Elementwise::AbsoluteValue<RealT>());
30 return a.reduce(ROL::Elementwise::ReductionMax<RealT>());
31}
32
33int testRandomInputs(int numPoints, RealT tol,
34 ROL::Ptr<std::ostream> outStream) {
35
36 int errorFlag = 0;
37 RealT errorInftyNorm;
38
39 // Generate standard vectors that hold data.
40 ROL::Ptr<std::vector<RealT>> vsv
41 = ROL::makePtr<std::vector<RealT>>(numPoints, 0.0);
42 ROL::Ptr<std::vector<RealT>> xsv
43 = ROL::makePtr<std::vector<RealT>>(numPoints, 0.0);
44 ROL::Ptr<std::vector<RealT>> gsv
45 = ROL::makePtr<std::vector<RealT>>(numPoints, 0.0);
46 ROL::Ptr<std::vector<RealT>> lsv
47 = ROL::makePtr<std::vector<RealT>>(numPoints, 0.0);
48 ROL::Ptr<std::vector<RealT>> usv
49 = ROL::makePtr<std::vector<RealT>>(numPoints, 0.0);
50 // Include space for storing results.
51 ROL::Ptr<std::vector<RealT>> out1sv
52 = ROL::makePtr<std::vector<RealT>>(numPoints, 0.0);
53 ROL::Ptr<std::vector<RealT>> out2sv
54 = ROL::makePtr<std::vector<RealT>>(numPoints, 0.0);
55
56 // Use these standard vectors to define ROL::StdVectors (or, in the case of lp
57 // and up, pointers to ROL::Vectors).
61 ROL::Ptr<ROL::Vector<RealT>> lp = ROL::makePtr<ROL::StdVector<RealT>>(lsv);
62 ROL::Ptr<ROL::Vector<RealT>> up = ROL::makePtr<ROL::StdVector<RealT>>(usv);
63 ROL::StdVector<RealT> out1(out1sv);
64 ROL::StdVector<RealT> out2(out2sv);
65
66 // Initialize.
67 lp->randomize(-10.0, 10.0);
68 up->randomize( 0.0, 10.0);
69 up->plus(*lp);
70 x.randomize(-20.0, 20.0);
71 v.randomize(- 3.0, 3.0);
72 g.randomize(-20.0, 20.0);
73
74 ROL::Bounds<RealT> boundsBC( lp , up );
75 ROL::StdBoundConstraint<RealT> stdvecBC(*lsv,*usv);
76 boundsBC.projectInterior(x);
77
78 // Test 1 - Check that the Elementwise applyInverseScalingFunction does
79 // indeed apply a scale factor to the vector v.
80
81 boundsBC.applyInverseScalingFunction(out1, v, x, g);
82 out1.applyUnary(ROL::Elementwise::Reciprocal<RealT>());
83 boundsBC.applyInverseScalingFunction(out2, out1, x, g);
84 out2.applyUnary(ROL::Elementwise::Reciprocal<RealT>());
85 errorInftyNorm = calcError(out2, v);
86 errorFlag += errorInftyNorm > tol;
87
88 *outStream << std::endl;
89 *outStream << "Scaling Check at " << numPoints
90 << " Randomly Sampled Points -- " << std::endl
91 << " Infinity Norm of | v - 1/f(1/f(v)) | = "
92 << errorInftyNorm << std::endl;
93 *outStream << std::endl;
94
95 // Test 2 - Use finite differences to check that the Elementwise
96 // applyScalingFunctionJacobian and applyInverseScalingFunction are
97 // consistent with each other.
98 // This test is meant to be visually inspected; it cannot cause the
99 // cpp file to fail.
100
101 class TestWrapper : public ROL::Constraint<RealT> {
102 private:
103 ROL::Bounds<RealT> boundsBC_;
106
107 public:
108 TestWrapper(ROL::Bounds<RealT>& boundsBC, ROL::StdVector<RealT>& g)
109 : boundsBC_(boundsBC), g_(g), v_(g) {
110 RealT one(1);
111 v_.setScalar(one);
112 }
113
115 RealT& tol) override {
116 boundsBC_.applyInverseScalingFunction(c, v_, x, g_);
117 c.applyUnary( ROL::Elementwise::Reciprocal<RealT>());
118 c.applyBinary(ROL::Elementwise::Multiply<RealT>(), g_);
119 }
120
122 const ROL::Vector<RealT>& x, RealT& tol) override {
123 boundsBC_.applyScalingFunctionJacobian(jv, v, x, g_);
124 }
125 } testWrapper(boundsBC, g);
126
127 // Use out1 and and out2 as working arrays to build a point comfortably
128 // within our bounds (so that the finite difference increments don't all step
129 // out). Larger values of gamma => larger separation between this point
130 // and our bounds.
131 RealT gamma = 1e-8;
132 out1.randomize(-1.0, 1.0);
133 out2.set(*up);
134 out2.axpy(-1,*lp);
135 out2.scale(1 - gamma);
136 out1.applyBinary(ROL::Elementwise::Multiply<RealT>(), out2);
137 out1.plus(*lp);
138 out1.plus(*up);
139 out1.scale(0.5); // the point at which we check the Jacobian
140
141 *outStream << "Elementwise Jacobian Check:" << std::endl;
142 testWrapper.checkApplyJacobian(out1, v, out2, true, *outStream, 15);
143 *outStream << std::endl;
144
145 // Test 3 - Check that applyInverseScalingFunction and
146 // applyScalingFunctionJacobian agree between the Elementwise and
147 // StdVector implementations.
148
149 boundsBC.applyInverseScalingFunction(out1, v, x, g);
150 stdvecBC.applyInverseScalingFunction(out2, v, x, g);
151 errorInftyNorm = 100;
152 errorInftyNorm = calcError(out1, out2);
153 errorFlag += errorInftyNorm > tol;
154
155 *outStream << "Consistency Check at " << numPoints
156 << " Randomly Sampled Points -- " << std::endl
157 << " Infinity Norm of | StdBoundConstraint - Elementwise |:"
158 << std::endl
159 << " Inverse = " << errorInftyNorm << std::endl;
160
161 boundsBC.applyScalingFunctionJacobian(out1, v, x, g);
162 stdvecBC.applyScalingFunctionJacobian(out2, v, x, g);
163 errorInftyNorm = calcError(out1, out2);
164 errorFlag += errorInftyNorm > tol;
165
166 *outStream << " Jacobian = " << errorInftyNorm << std::endl;
167 *outStream << std::endl;
168
169 return errorFlag;
170}
171
172int testCases(RealT tol, ROL::Ptr<std::ostream> outStream) {
173
174 // Test 4 - Check the Elementwise and StdVector implementations of
175 // applyInverseScalingFunction and applyScalingFunctionJacobian on
176 // specific test cases.
177
178 int numCases = 3;
179
180 std::vector<RealT> ewErrors, svErrors;
181
182 // Generate standard vectors that hold data.
183 ROL::Ptr<std::vector<RealT>> vsv
184 = ROL::makePtr<std::vector<RealT>>(numCases, 0.0);
185 ROL::Ptr<std::vector<RealT>> xsv
186 = ROL::makePtr<std::vector<RealT>>(numCases, 0.0);
187 ROL::Ptr<std::vector<RealT>> gsv
188 = ROL::makePtr<std::vector<RealT>>(numCases, 0.0);
189 ROL::Ptr<std::vector<RealT>> lsv
190 = ROL::makePtr<std::vector<RealT>>(numCases, 0.0);
191 ROL::Ptr<std::vector<RealT>> usv
192 = ROL::makePtr<std::vector<RealT>>(numCases, 0.0);
193 // Include space for storing results.
194 ROL::Ptr<std::vector<RealT>> resultp
195 = ROL::makePtr<std::vector<RealT>>(numCases, 0.0);
196 ROL::Ptr<std::vector<RealT>> targetp
197 = ROL::makePtr<std::vector<RealT>>(numCases, 0.0);
198
199 // Use the standard vectors above to define ROL::StdVectors (or, in the
200 // case of lp and up, pointers to ROL::Vectors).
204 ROL::Ptr<ROL::Vector<RealT>> lp = ROL::makePtr<ROL::StdVector<RealT>>(lsv);
205 ROL::Ptr<ROL::Vector<RealT>> up = ROL::makePtr<ROL::StdVector<RealT>>(usv);
206 ROL::StdVector<RealT> result(resultp);
207 ROL::StdVector<RealT> target(targetp);
208
209 // Problem 1
210 (*vsv)[0] = 4.0;
211 (*xsv)[0] = 1.9;
212 (*gsv)[0] = 0.5;
213 (*lsv)[0] = 0.0;
214 (*usv)[0] = 2.0;
215
216 // Problem 2
217 (*vsv)[1] = -1.0;
218 (*xsv)[1] = 10.0;
219 (*gsv)[1] = 0.0002;
220 (*lsv)[1] = ROL::ROL_NINF<RealT>();
221 (*usv)[1] = ROL::ROL_INF<RealT>();
222
223 // Problem 3
224 (*vsv)[2] = -0.0002;
225 (*xsv)[2] = 1.0;
226 (*gsv)[2] = 0.5;
227 (*lsv)[2] = 0.0;
228 (*usv)[2] = ROL::ROL_INF<RealT>();
229
230 ROL::Bounds<RealT> boundsBC( lp, up );
231 ROL::StdBoundConstraint<RealT> stdvecBC(*lsv,*usv);
232
233 // Expected results when applying the scaling function to v.
234 (*targetp)[0] = (*vsv)[0]*(*gsv)[0];
235 (*targetp)[1] = (*vsv)[1]*1.0;
236 (*targetp)[2] = (*vsv)[2]*1.0;
237
238 target.applyBinary(ROL::Elementwise::DivideAndInvert<RealT>(), v);
239 target.applyBinary(ROL::Elementwise::Multiply<RealT>(), v);
240 boundsBC.applyInverseScalingFunction(result, v, x, g);
241 ewErrors.push_back(calcError(result, target));
242 stdvecBC.applyInverseScalingFunction(result, v, x, g);
243 svErrors.push_back(calcError(result, target));
244
245 // Expected results when applying the Jacobian to v.
246 (*targetp)[0] = (*vsv)[0]*(*gsv)[0];
247 (*targetp)[1] = 0.0;
248 (*targetp)[2] = 0.0;
249 boundsBC.applyScalingFunctionJacobian(result, v, x, g);
250 ewErrors.push_back(calcError(result, target));
251 stdvecBC.applyScalingFunctionJacobian(result, v, x, g);
252 svErrors.push_back(calcError(result, target));
253
254 *outStream << "Elementwise Test Case Errors (Infinity Norm):" << std::endl
255 << " Inverse = " << ewErrors[1] << std::endl
256 << " Jacobian = " << ewErrors[2] << std::endl;
257 *outStream << "StdBoundConstraint Test Case Errors (Infinity Norm):" << std::endl
258 << " Inverse = " << svErrors[1] << std::endl
259 << " Jacobian = " << svErrors[2] << std::endl;
260 *outStream << std::endl;
261
262 RealT maxError = std::max(*std::max_element(svErrors.begin(), svErrors.end()),
263 *std::max_element(ewErrors.begin(), ewErrors.end()));
264 return maxError > tol;
265}
266
267int main(int argc, char *argv[]) {
268
269 Teuchos::GlobalMPISession mpiSession(&argc, &argv);
270
271 // This little trick lets us print to std::cout only if a
272 // (dummy) command-line argument is provided.
273 int iprint = argc - 1;
274 ROL::Ptr<std::ostream> outStream;
275 ROL::nullstream bhs; // outputs nothing
276 if (iprint > 0)
277 outStream = ROL::makePtrFromRef(std::cout);
278 else
279 outStream = ROL::makePtrFromRef(bhs);
280
281 int errorFlag = 0;
282
283 // *** Test body.
284
285 try {
286 RealT tol = 1e-8; // tolerance
287 int n = 1e+3; // number of random test points
288 errorFlag += testRandomInputs(n, tol, outStream);
289 errorFlag += testCases(tol, outStream);
290 }
291
292 catch (std::logic_error& err) {
293 *outStream << err.what() << "\n";
294 errorFlag = -1000;
295 }; // end try
296
297 if (errorFlag != 0)
298 std::cout << "End Result: TEST FAILED\n";
299 else
300 std::cout << "End Result: TEST PASSED\n";
301
302 return 0;
303}
Contains definitions for std::vector bound constraints.
Defines a no-output stream class ROL::NullStream and a function makeStreamPtr which either wraps a re...
Provides the elementwise interface to apply upper and lower bound constraints.
void applyInverseScalingFunction(Vector< Real > &dv, const Vector< Real > &v, const Vector< Real > &x, const Vector< Real > &g) const override
Apply inverse scaling function.
void projectInterior(Vector< Real > &x) override
Project optimization variables into the interior of the feasible set.
void applyScalingFunctionJacobian(Vector< Real > &dv, const Vector< Real > &v, const Vector< Real > &x, const Vector< Real > &g) const override
Apply scaling function Jacobian.
Defines the general constraint operator interface.
virtual void value(Vector< Real > &c, const Vector< Real > &x, Real &tol)=0
Evaluate the constraint operator at .
virtual void applyJacobian(Vector< Real > &jv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Apply the constraint Jacobian at , , to vector .
void applyScalingFunctionJacobian(Vector< Real > &dv, const Vector< Real > &v, const Vector< Real > &x, const Vector< Real > &g) const override
Apply scaling function Jacobian.
void applyInverseScalingFunction(Vector< Real > &dv, const Vector< Real > &v, const Vector< Real > &x, const Vector< Real > &g) const override
Apply inverse scaling function.
Provides the ROL::Vector interface for scalar values, to be used, for example, with scalar constraint...
void scale(const Real alpha)
Compute where .
void randomize(const Real l=0.0, const Real u=1.0)
Set vector to be uniform random between [l,u].
void axpy(const Real alpha, const Vector< Real > &x)
Compute where .
void set(const Vector< Real > &x)
Set where .
void applyBinary(const Elementwise::BinaryFunction< Real > &f, const Vector< Real > &x)
void setScalar(const Real C)
Set where .
void applyUnary(const Elementwise::UnaryFunction< Real > &f)
Defines the linear algebra or vector space interface.
virtual void applyUnary(const Elementwise::UnaryFunction< Real > &f)
virtual void applyBinary(const Elementwise::BinaryFunction< Real > &f, const Vector &x)
virtual Real reduce(const Elementwise::ReductionOp< Real > &r) const
virtual void axpy(const Real alpha, const Vector &x)
Compute where .
int main(int argc, char *argv[])
RealT calcError(ROL::Vector< RealT > &a, const ROL::Vector< RealT > &b)
int testRandomInputs(int numPoints, RealT tol, ROL::Ptr< std::ostream > outStream)
int testCases(RealT tol, ROL::Ptr< std::ostream > outStream)
double RealT