NLPInterfacePack: C++ Interfaces and Implementation for Non-Linear Programs Version of the Day
NLPInterfacePack_NLPTester.cpp
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
00005 //                  Copyright (2003) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 
00038 // 
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #include <assert.h>
00043 
00044 #include <iomanip>
00045 #include <ostream>
00046 
00047 #include "NLPInterfacePack_NLPTester.hpp"
00048 #include "NLPInterfacePack_NLP.hpp"
00049 #include "AbstractLinAlgPack_VectorSpace.hpp"
00050 #include "AbstractLinAlgPack_VectorMutable.hpp"
00051 #include "AbstractLinAlgPack_VectorOut.hpp"
00052 #include "AbstractLinAlgPack_VectorStdOps.hpp"
00053 #include "AbstractLinAlgPack_VectorAuxiliaryOps.hpp"
00054 #include "AbstractLinAlgPack_assert_print_nan_inf.hpp"
00055 #include "TestingHelperPack_update_success.hpp"
00056 
00057 namespace NLPInterfacePack {
00058 
00059 NLPTester::NLPTester(
00060   bool     print_all
00061   ,bool    throw_exception
00062   )
00063   :print_all_(print_all), throw_exception_(throw_exception)
00064 {}
00065 
00066 bool NLPTester::test_interface(
00067   NLP                     *nlp
00068   ,const Vector           &xo
00069   ,bool                   print_all_warnings
00070   ,std::ostream           *out
00071   )
00072 {
00073   using TestingHelperPack::update_success;
00074   using AbstractLinAlgPack::assert_print_nan_inf;
00075 
00076   bool result;
00077   bool success = true;
00078 
00079   if(out) {
00080     *out << std::boolalpha
00081        << std::endl
00082        << "**************************************\n"
00083        << "*** NLPTester::test_interface(...) ***\n"
00084        << "**************************************\n";
00085   }
00086 
00087   try {
00088 
00089     // Initialize the NLP if it has not been already and force in bounds
00090     if(out)
00091       *out << "\nnlp->force_xinit_in_bounds(true)";
00092     nlp->force_xinit_in_bounds();
00093     if(out)
00094       *out << "\nnlp->initialize(true)\n";
00095     nlp->initialize(true);
00096     
00097     const size_type
00098       n = nlp->n(),
00099       m = nlp->m();
00100     if(out)
00101       *out << "\n*** Dimensions of the NLP ...\n"
00102          << "\nnlp->n()  = " << n
00103          << "\nnlp->m()  = " << m
00104          << std::endl;
00105     if( n < m ) {
00106       if(*out)
00107         *out << "Error! n = " << n << " < m = " << m << " is not allowed!\n";
00108       TEUCHOS_TEST_FOR_EXCEPTION(
00109         throw_exception_, std::logic_error
00110         ,"NLPTester::test_interface(...): Error! n = " << n << " < m = " << m << " is not allowed!"
00111         );
00112     }
00113 
00114     // Validate the vector spaces
00115     if(out)
00116       *out << "\n*** Validate the dimensions of the vector spaces ...\n";
00117     
00118     result = nlp->space_x()->dim() == nlp->n();
00119     update_success( result, &success );
00120     if(out)
00121       *out << "\ncheck: nlp->space_x()->dim() = " << nlp->space_x()->dim()
00122            << " == nlp->n() = " << nlp->n() << ": " << result << std::endl;
00123 
00124     if( nlp->m() ) {
00125       result = nlp->space_c()->dim() == nlp->m();
00126       update_success( result, &success );
00127       if(out)
00128         *out << "\ncheck: nlp->space_c()->dim() = " << nlp->space_c()->dim()
00129              << " == nlp->m() = " << nlp->m() << ": " << result << std::endl;
00130     }
00131     else {
00132       result = nlp->space_c().get() == NULL;
00133       update_success( result, &success );
00134       if(out)
00135         *out << "\ncheck: nlp->space_c().get() = " << nlp->space_c().get()
00136              << " == NULL: " << result << std::endl;
00137     }
00138 
00139     // Validate the initial guess the bounds on the unknowns.
00140     if(out)
00141       *out << "\n*** Validate that the initial starting point is in bounds ...\n";
00142     const Vector &xinit = nlp->xinit();
00143     if(out) *out << "\n||nlp->xinit()||inf = " << xinit.norm_inf() << std::endl;
00144     if(out && print_all()) *out << "\nnlp->xinit() =\n" << xinit;
00145     assert_print_nan_inf(xinit,"xinit",true,out); 
00146     const Vector
00147       &xl = nlp->xl(),
00148       &xu = nlp->xu();
00149     if(out && print_all())
00150       *out << "\nnlp->xl() =\n" << xl
00151          << "\nnlp->xu() =\n" << xu;
00152     assert_print_nan_inf(xl,"xl",true,out); 
00153     assert_print_nan_inf(xu,"xu",true,out); 
00154 
00155     // Validate that xl <= xinit <= xu.
00156     VectorSpace::vec_mut_ptr_t
00157       d = nlp->space_x()->create_member();
00158     *d = 1.0;
00159     std::pair<value_type,value_type>
00160       u = AbstractLinAlgPack::max_near_feas_step(
00161         xinit, *d, nlp->xl(), nlp->xu(), 0.0
00162         );
00163     result = u.first >= 0.0;
00164     update_success( result, &success );
00165     if(out) {
00166       *out << "\ncheck: xl <= x <= xu : " << result;
00167       if(result)
00168         *out << "\nxinit is in bounds with { max |u| | xl <= x + u <= xu } -> "
00169            << ( u.first > -u.second ? u.first : u.second  ) << std::endl;
00170     }
00171     size_type 
00172       num_bounded_x = AbstractLinAlgPack::num_bounded(
00173         nlp->xl(), nlp->xu(), NLP::infinite_bound()
00174         );
00175     result = (num_bounded_x == nlp->num_bounded_x());
00176     update_success( result, &success );
00177     if(out)
00178       *out << "\ncheck: num_bounded(nlp->xl(),nlp->xu()) = " << num_bounded_x
00179          << " == nlp->num_bounded_x() = " << nlp->num_bounded_x()
00180          << ": " << result << std::endl;
00181 
00182     // Get the initial Lagrange multipliers
00183     if(out)
00184       *out << "\nGetting the initial estimates for the Lagrange mutipliers ...\n";
00185     VectorSpace::vec_mut_ptr_t  lambda, nu;
00186     nlp->get_init_lagrange_mult(
00187       (  nlp->m()
00188          ? (lambda  = nlp->space_c()->create_member()).get() 
00189          : (VectorMutable*)NULL )
00190       ,( nlp->num_bounded_x()
00191          ? (nu = nlp->space_x()->create_member()).get()
00192          : (VectorMutable*)NULL )
00193       );
00194 
00195     if(out) {
00196       if(lambda.get())
00197         *out << "\n||lambda||inf  = " << lambda->norm_inf();
00198       if(nu.get())
00199         *out << "\n||nu||inf      = " << nu->norm_inf()
00200            << "\nnu.nz()        = " << nu->nz();
00201       *out << std::endl;
00202       if(print_all()) {
00203         if(lambda.get())
00204           *out << "\nlambda =\n" << *lambda;
00205         if(nu.get())
00206           *out << "\nnu =\n" << *nu;
00207       }
00208     }
00209     if(lambda.get())
00210       assert_print_nan_inf(*lambda,"lambda",true,out); 
00211     if(nu.get())
00212       assert_print_nan_inf(*nu,"nu",true,out); 
00213 
00214     // Save the current reference that are set to be set back at the end
00215     value_type      *f_saved = NULL;
00216     VectorMutable   *c_saved = NULL;
00217     f_saved = nlp->get_f();
00218     if( nlp->m() )  c_saved = nlp->get_c();
00219 
00220     // Create calcualtion quantities
00221     value_type                   f;
00222     VectorSpace::vec_mut_ptr_t   c;
00223     if( nlp->m() )
00224       c = nlp->space_c()->create_member();
00225 
00226     // Set the calculation quantities
00227     nlp->set_f(&f);
00228     if( nlp->m() )  nlp->set_c(c.get());
00229 
00230     // Calculate the quantities at xo
00231 
00232     if(out)
00233       *out << "\n*** Evaluate the point xo ...\n";
00234 
00235     if(out) *out << "\n||xo||inf = " << xo.norm_inf() << std::endl;
00236     if(out && print_all()) *out << "\nxo =\n" << xo;
00237     assert_print_nan_inf(xo,"xo",true,out); 
00238 
00239     nlp->calc_f(xo,true);
00240     if(nlp->m())  nlp->calc_c(xo,false);
00241 
00242     if(out) {
00243       *out << "\nf(xo) = " << f;
00244       if(nlp->m())
00245         *out << "\n||c(xo)||inf = " << nlp->c().norm_inf();
00246       *out << std::endl;
00247       if(print_all()) {
00248         if(nlp->m())
00249           *out << "\nc(xo) =\n" << nlp->c();
00250       }
00251     }
00252 
00253     if(c.get())
00254       assert_print_nan_inf(*c,"c(xo)",true,out); 
00255 
00256     // Report the final solution!
00257     if(out)
00258       *out << "\n*** Report this point to the NLP as suboptimal ...\n";
00259     nlp->report_final_solution( xo, lambda.get(), nu.get(), false );
00260 
00261     // Print the number of evaluations!
00262     if(out) {
00263       *out << "\n*** Print the number of evaluations ...\n";
00264       *out << "\nnlp->num_f_evals() = " << nlp->num_f_evals();
00265       if(nlp->m())
00266         *out << "\nnlp->num_c_evals() = " << nlp->num_c_evals();
00267       *out << std::endl;
00268     }
00269 
00270     // Set the original quantities back
00271     nlp->set_f(f_saved);
00272     if(nlp->m())  nlp->set_c(c_saved);
00273 
00274   }
00275   catch(const std::exception& except) {
00276     if(out)
00277       *out << "Caught a std::exception: " << except.what() << std::endl;
00278     success = false;
00279     if(throw_exception())
00280       throw;
00281   }
00282   catch(...) {
00283     if(out)
00284       *out << "Caught an unknown exception!\n";
00285     success = false;
00286     if(throw_exception())
00287       throw;
00288   }
00289 
00290   return success;
00291 }
00292 
00293 } // namespace NLPInterfacePack
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends