GlobiPack Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ArmijoPolyInterpLineSearch_UnitTests.cpp
Go to the documentation of this file.
1 /*
2 // @HEADER
3 // ***********************************************************************
4 //
5 // GlobiPack: Collection of Scalar 1D globalizaton utilities
6 // Copyright (2009) Sandia Corporation
7 //
8 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
9 // license for use of this work by or on behalf of the U.S. Government.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov)
39 //
40 // ***********************************************************************
41 // @HEADER
42 */
43 
44 
45 #include "GlobiPack_TestLagrPolyMeritFunc1D.hpp"
46 #include "GlobiPack_ArmijoPolyInterpLineSearch.hpp"
47 #include "Teuchos_Tuple.hpp"
48 
49 #include "meritFuncsHelpers.hpp"
50 
52 
53 
54 namespace {
55 
56 
57 //
58 // Helper code and declarations
59 //
60 
61 
65 using GlobiPack::armijoQuadraticLineSearch;
66 using GlobiPack::computeValue;
67 using Teuchos::as;
68 using Teuchos::inOutArg;
69 using Teuchos::outArg;
70 using Teuchos::null;
71 using Teuchos::RCP;
72 using Teuchos::rcpFromRef;
73 using Teuchos::Array;
74 using Teuchos::tuple;
76 using Teuchos::parameterList;
77 
78 
79 double g_tol = Teuchos::ScalarTraits<double>::eps()*100.0;
80 
81 
83 {
85  "tol", &g_tol, "Floating point tolerance" );
86 }
87 
88 
89 //
90 // Unit tests for ArmijoPolyInterpLineSearch
91 //
92 
93 
94 //
95 // Check that internal default parameters are set correctly
96 //
97 
98 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArmijoPolyInterpLineSearch, defaultParams, Scalar )
99 {
101  typedef typename ST::magnitudeType ScalarMag;
102  namespace AQLSU = GlobiPack::ArmijoPolyInterpLineSearchUtils;
103  RCP<ArmijoPolyInterpLineSearch<Scalar> > linesearch =
104  armijoQuadraticLineSearch<Scalar>();
105  TEST_EQUALITY(linesearch->eta(), as<ScalarMag>(AQLSU::eta_default));
106  TEST_EQUALITY(linesearch->minFrac(), as<ScalarMag>(AQLSU::minFrac_default));
107  TEST_EQUALITY(linesearch->maxFrac(), as<ScalarMag>(AQLSU::maxFrac_default));
108  TEST_EQUALITY(linesearch->doMaxIters(), as<ScalarMag>(AQLSU::doMaxIters_default));
109  TEST_EQUALITY(linesearch->maxIters(), as<ScalarMag>(AQLSU::maxIters_default));
110 }
111 
112 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT_REAL_SCALAR_TYPES( ArmijoPolyInterpLineSearch, defaultParams )
113 
114 
115 //
116 // Check that parameter list is parsed correctly
117 //
118 
119 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArmijoPolyInterpLineSearch, parseParams, Scalar )
120 {
122  namespace AQLSU = GlobiPack::ArmijoPolyInterpLineSearchUtils;
123  ECHO(RCP<ArmijoPolyInterpLineSearch<Scalar> > linesearch =
124  armijoQuadraticLineSearch<Scalar>());
125  const double eta = 0.99999;
126  const double minFrac = 4.0;
127  const double maxFrac = 5.0;
128  const int minIters = 5;
129  const int maxIters = 100;
130  const bool doMaxIters = true;
131  ECHO(const RCP<ParameterList> pl = parameterList());
132  ECHO(pl->set("Armijo Slope Fraction", eta));
133  ECHO(pl->set("Min Backtrack Fraction", minFrac));
134  ECHO(pl->set("Max Backtrack Fraction", maxFrac));
135  ECHO(pl->set("Min Num Iterations", minIters));
136  ECHO(pl->set("Max Num Iterations", maxIters));
137  ECHO(pl->set("Do Max Iterations", doMaxIters));
138  ECHO(linesearch->setParameterList(pl));
139  const Scalar tol = ST::eps();
140  TEST_FLOATING_EQUALITY(linesearch->eta(), as<Scalar>(eta), tol);
141  TEST_FLOATING_EQUALITY(linesearch->minFrac(), as<Scalar>(minFrac), tol);
142  TEST_FLOATING_EQUALITY(linesearch->maxFrac(), as<Scalar>(maxFrac), tol);
143  TEST_EQUALITY(linesearch->minIters(), minIters);
144  TEST_EQUALITY(linesearch->maxIters(), maxIters);
145  TEST_EQUALITY(linesearch->doMaxIters(), doMaxIters);
146 }
147 
148 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT_REAL_SCALAR_TYPES( ArmijoPolyInterpLineSearch, parseParams )
149 
150 
151 //
152 // Check that the ArmijoPolyInterpLineSearch object validates its parameters
153 // and their values correctly.
154 //
155 
156 /*
157 
158 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArmijoPolyInterpLineSearch, validateParams, Scalar )
159 {
160  TEUCHOS_TEST_FOR_EXCEPT(true);
161 }
162 
163 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT_REAL_SCALAR_TYPES( ArmijoPolyInterpLineSearch, validateParams )
164 
165 */
166 
167 
168 //
169 // Check that object can exactly interplate a quadratic merit function at the
170 // very first iteration
171 //
172 
173 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArmijoPolyInterpLineSearch, quadExact, Scalar )
174 {
175 
177  typedef typename ST::magnitudeType ScalarMag;
178 
179  const RCP<TestLagrPolyMeritFunc1D<Scalar> > phi = quadPhi<Scalar>();
180 
181  RCP<ArmijoPolyInterpLineSearch<Scalar> > linesearch =
182  armijoQuadraticLineSearch<Scalar>();
183 
184  linesearch->setOStream(rcpFromRef(out));
185 
186  const PointEval1D<Scalar> point_k = computePoint(*phi, ST::zero(), true, true);
187  PointEval1D<Scalar> point_kp1 = computePoint(*phi, as<Scalar>(5.0));
188 
189  int numIters = -1;
190  const bool linesearchResult = linesearch->doLineSearch(
191  *phi, point_k, inOutArg(point_kp1), outArg(numIters) );
192 
193  TEST_ASSERT(linesearchResult);
194  TEST_EQUALITY(numIters, 1);
195  TEST_FLOATING_EQUALITY(point_kp1.alpha, as<Scalar>(2.0), g_tol);
196  TEST_FLOATING_EQUALITY(point_kp1.phi, as<ScalarMag>(3.0), g_tol);
197 
198 }
199 
200 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT_REAL_SCALAR_TYPES( ArmijoPolyInterpLineSearch, quadExact )
201 
202 
203 //
204 // Check that object will accept the inital point passed in without doing any
205 // evaluations.
206 //
207 
208 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArmijoPolyInterpLineSearch, noEval, Scalar )
209 {
210 
212  //typedef typename ST::magnitudeType ScalarMag; // unused
213 
214  const RCP<TestLagrPolyMeritFunc1D<Scalar> > phi = quadPhi<Scalar>();
215 
216  RCP<ArmijoPolyInterpLineSearch<Scalar> > linesearch =
217  armijoQuadraticLineSearch<Scalar>();
218 
219  linesearch->setOStream(rcpFromRef(out));
220 
221  const Scalar alpha_k_init = as<Scalar>(2.1);
222  const PointEval1D<Scalar> point_k = computePoint(*phi, ST::zero(), true, true);
223  PointEval1D<Scalar> point_kp1 = computePoint(*phi, alpha_k_init);
224 
225  int numIters = -1;
226  const bool linesearchResult = linesearch->doLineSearch(
227  *phi, point_k, inOutArg(point_kp1), outArg(numIters) );
228 
229  TEST_ASSERT(linesearchResult);
230  TEST_EQUALITY(numIters, 0);
231  TEST_FLOATING_EQUALITY(point_kp1.alpha, alpha_k_init, g_tol);
232  TEST_FLOATING_EQUALITY(point_kp1.phi, computeValue(*phi, alpha_k_init), g_tol);
233 
234 }
235 
236 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT_REAL_SCALAR_TYPES( ArmijoPolyInterpLineSearch, noEval )
237 
238 
239 //
240 // Check that object will force a minimum number of iterations if asked.
241 //
242 
243 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArmijoPolyInterpLineSearch, minIters, Scalar )
244 {
245 
247  typedef typename ST::magnitudeType ScalarMag;
248 
249  const RCP<TestLagrPolyMeritFunc1D<Scalar> > phi = quadPhi<Scalar>();
250 
251  RCP<ArmijoPolyInterpLineSearch<Scalar> > linesearch =
252  armijoQuadraticLineSearch<Scalar>();
253 
254  const RCP<ParameterList> pl = parameterList();
255  pl->set("Max Backtrack Fraction", 1.0);
256  pl->set("Min Num Iterations", 1);
257  linesearch->setParameterList(pl);
258 
259  linesearch->setOStream(rcpFromRef(out));
260 
261  const Scalar alpha_k_init = as<Scalar>(2.1);
262  const PointEval1D<Scalar> point_k = computePoint(*phi, ST::zero(), true, true);
263  PointEval1D<Scalar> point_kp1 = computePoint(*phi, alpha_k_init);
264 
265  int numIters = -1;
266  const bool linesearchResult = linesearch->doLineSearch(
267  *phi, point_k, inOutArg(point_kp1), outArg(numIters) );
268 
269  TEST_ASSERT(linesearchResult);
270  TEST_EQUALITY(numIters, 1);
271  TEST_FLOATING_EQUALITY(point_kp1.alpha, as<Scalar>(2.0), g_tol);
272  TEST_FLOATING_EQUALITY(point_kp1.phi, as<ScalarMag>(3.0), g_tol);
273 
274 }
275 
276 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT_REAL_SCALAR_TYPES( ArmijoPolyInterpLineSearch, minIters )
277 
278 
279 //
280 // ToDo:
281 //
282 // (*) Check that the object performs min bracketing correctly.
283 //
284 // (*) Check that the object performs max bracketing correctly.
285 //
286 // (*) Check that the ArmijoPolyInterpLineSearch object deals with NaN returns
287 // currectly.
288 //
289 // (*) Check that the ArmijoPolyInterpLineSearch object will throw the right
290 // exception if a positive initial derivative is presented.
291 //
292 // (*) Check that the ArmijoPolyInterpLineSearch object will deal with line search
293 // failure correctly.
294 //
295 // (*) Check that the ArmijoPolyInterpLineSearch object deals with invalid input
296 // correctly (i.e. check preconditions and throws).
297 //
298 
299 
300 } // namespace
TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(Teuchos_Conditions, NumberConditionSerialization, T)
const RCP< TestLagrPolyMeritFunc1D< Scalar > > testLagrPolyMeritFunc1D(const ArrayView< const Scalar > &alpha, const ArrayView< const Scalar > &phi)
static magnitudeType eps()
#define ECHO(statement)
static CommandLineProcessor & getCLP()
Linesearch subclass implementing a backtracking-only line search using an Armijo cord test condition ...
void setOption(const char option_true[], const char option_false[], bool *option_val, const char documentation[]=NULL)
PointEval1D< Scalar > computePoint(const MeritFunc1DBase< Scalar > &phi, const Scalar &alpha, const bool compute_phi=true, const bool compute_Dphi=false)
Compute a point as an object.
TypeTo as(const TypeFrom &t)
#define TEST_FLOATING_EQUALITY(v1, v2, tol)
TEST_ASSERT(castedDep1->getValuesAndValidators().size()==2)
#define TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT_REAL_SCALAR_TYPES(TEST_GROUP, TEST_NAME)
Lagrange Polynomial Merit Function used in testing.
TEST_EQUALITY(rcp_dynamic_cast< const EnhancedNumberValidator< double > >(castedDep1->getValuesAndValidators().find("val1") ->second, true) ->getMax(), double1Vali->getMax())
ScalarTraits< Scalar >::magnitudeType computeValue(const MeritFunc1DBase< Scalar > &phi, const Scalar &alpha)
Compute the value of the merit function phi(alpha).
TEUCHOS_STATIC_SETUP()