PlayaOptRosenbrock.cpp

00001 /* @HEADER@ */
00002 //   
00003 /* @HEADER@ */
00004 
00005 #include "PlayaOptBuilder.hpp"
00006 #include "PlayaEpetraVectorType.hpp"
00007 #include "PlayaVectorType.hpp"
00008 #include "PlayaOut.hpp"
00009 #include "PlayaLinearCombinationImpl.hpp"
00010 
00011 #include "PlayaRosenbrock.hpp"
00012 
00013 #include "Teuchos_GlobalMPISession.hpp"
00014 #include "PlayaMPIComm.hpp"
00015 
00016 
00017 /* ------------------------------------------------------------------------
00018  *
00019  * This example shows the unconstrained optimization of a simple objective
00020  * function. The function is defined in the files PlayaRosenbock.[hpp/cpp].
00021  * 
00022  * The optimizer object is created by the OptBuilder::createOptimizer()
00023  * function, which reads parameters from an XML file. In this example,
00024  * a limited-memory BFGS optmizer is used. Its parameters are read from the
00025  * file basicLMBFGS.xml.
00026  * 
00027  * ------------------------------------------------------------------------ */
00028 
00029 using namespace Playa;
00030 
00031 int main(int argc, char *argv[])
00032 {
00033   int rtn = 0;
00034 
00035   try
00036   {
00037     /* Initialize MPI */
00038     GlobalMPISession session(&argc, &argv);
00039 
00040 
00041     /* The VectorType object will be used when we create vector spaces, 
00042      * specifying what type of low-level linear algebra implementation
00043      * will be used. */
00044     VectorType<double> vecType = new EpetraVectorType();
00045 
00046     /* Construct the objective function */
00047     int M = 6;
00048     double alpha = 40.0;
00049     RCP<ObjectiveBase> obj = rcp(new Rosenbrock(M, alpha, vecType));
00050 
00051     Out::root() << "Objective function is " << obj->description()
00052                 << endl;
00053 
00054     /* Get the starting point for the optimization run */
00055     Vector<double> xInit = obj->getInit();
00056     
00057     /* Run a finite-difference calculation of the function's gradient. This
00058      * will be expensive, but is a valuable test when developing new objective
00059      * functions */
00060     Out::root() << "Doing FD check of gradient..." << endl;
00061     bool fdOK = obj->fdCheck(xInit, 1.0e-6, 0);
00062     TEUCHOS_TEST_FOR_EXCEPTION(!fdOK, std::runtime_error,
00063       "finite difference test of Rosenbrock function gradient FAILED");
00064     Out::root() << "FD check OK!" << endl << endl;
00065 
00066 
00067     /* Create an optimizer object. */
00068     RCP<UnconstrainedOptimizerBase> opt 
00069       = OptBuilder::createOptimizer("basicLMBFGS.xml");
00070 
00071     /* Set the optimizer's verbosity to a desired volume of output */
00072     opt->setVerb(1);
00073 
00074     /* Run the optimizer with xInit s the initial guess. 
00075      * The results (location and value of min) and 
00076      * diagnostic information about the run are stored in the OptState
00077      * object returned by the run() function. */
00078     OptState state = opt->run(obj, xInit);
00079 
00080     /* Check the output */
00081     if (state.status() != Opt_Converged)
00082     {
00083       Out::root() << "optimization failed: " << state.status() << endl;
00084       rtn = -1;
00085     }
00086     else /* We converged, so let's make sure we got the right solution */
00087     {
00088       Out::root() << "optimization converged!" << endl; 
00089       Out::root() << "Iterations taken: " << state.iter() << endl;
00090       Out::root() << "Approximate minimum value: " << state.fCur() << endl;
00091 
00092       /* The exact solution is [1,1,\cdots, 1, 1]. */
00093       Vector<double> exactAns = xInit.space().createMember();
00094       exactAns.setToConstant(1.0);
00095       
00096       /* Compute the norm of the error in the location of the minimum */
00097       double locErr = (exactAns - state.xCur()).norm2();
00098       Out::root() << "||x-x^*||=" << locErr << endl;
00099       
00100       /* Compare the error to a desired tolerance */
00101       double testTol = 1.0e-4;
00102       if (locErr > testTol) 
00103       {
00104         rtn = -1;
00105       }
00106     }
00107      
00108     if (rtn == 0)
00109     {
00110       Out::root() << "test PASSED" << endl;
00111     }
00112     else
00113     {
00114       Out::root() << "test FAILED" << endl;
00115     }
00116   }
00117   catch(std::exception& e)
00118   {
00119     std::cerr << "Caught exception: " << e.what() << endl;
00120     rtn = -1;
00121   }
00122   return rtn;
00123 }

doxygen