MOOCHO (Single Doxygen Collection) Version of the Day
IterationPack_TestAlgorithmState.cpp
Go to the documentation of this file.
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 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #include <ostream>
00030 #include <iomanip>
00031 #include <typeinfo>
00032 
00033 #include "IterationPack_TestIterationPack.hpp"
00034 #include "IterationPack_AlgorithmState.hpp"
00035 #include "IterationPack_IterQuantityAccessContiguous.hpp"
00036 #include "Teuchos_AbstractFactoryStd.hpp"
00037 #include "TestingHelperPack_update_success.hpp"
00038 #include "Teuchos_TestForException.hpp"
00039 
00040 // explicit instantiation for testing compilation only
00041 //template Teuchos::RCP<double>;
00042 //class B {};
00043 //class D : public B {};
00044 //template IterationPack::IterQuantityAccessDerivedToBase<B,D>;
00045 
00046 namespace {
00047 
00048 // Create class hierarchy for derived to base conversion.
00049 
00050 class B {
00051 public:
00052   virtual B& operator=(const B&) = 0;
00053   virtual void alpha(double) = 0;
00054   virtual double alpha() const = 0; 
00055 };  // end class B
00056 
00057 class D : public B {
00058 public:
00059   B& operator=(const B& b) {
00060     const D* d = dynamic_cast<const D*>(&b);
00061     if(!d)
00062       throw std::logic_error("D::operator=(...) : b is not of type D");
00063     alpha_ = d->alpha_;
00064     return *this;
00065   }
00066   void alpha(double alpha) {
00067     alpha_ = alpha;
00068   }
00069   double alpha() const {
00070     return alpha_;  
00071   }
00072 private:
00073   double alpha_; 
00074 };  // end class D
00075 
00076 } // end namespace
00077 
00078 bool IterationPack::TestingPack::TestAlgorithmState(std::ostream* out) {
00079 
00080   using std::endl;
00081   using std::setw;
00082   using TestingHelperPack::update_success;
00083 
00084   try {
00085 
00086   bool success = true, result;
00087 //  const int w = 15;
00088   if(out) *out << std::boolalpha;
00089     
00090   if(out)
00091     *out<< "\n\n******************************\n"
00092       << "*** Testing AlgorithmState ***\n"
00093       << "******************************\n"
00094       << "\nWarning: this interface is weakly typed and mistakes"
00095       << "can be very bad\n";
00096 
00097   typedef double                          alpha_k_t;
00098   typedef std::vector<double>                   x_k_t;
00099   typedef B                           V_k_t;
00100   typedef IterQuantityAccessContiguous<alpha_k_t>         alpha_t;
00101   typedef IterQuantityAccessContiguous<x_k_t>           x_t;
00102   typedef IterQuantityAccessContiguous<V_k_t>           V_t;
00103 
00104   if(out) *out << "\n*** Create state object ...\n";
00105   AlgorithmState state(4);
00106 
00107   // Set three types of iteration quantity access objects.
00108 
00109   if(out) *out << "\n*** Set three types of iteration quantity access objects.\n";
00110 
00111   if(out) *out << "set IterQuantityAccessContiguous<double>(2,\"alpha\")\n";
00112   state.set_iter_quant( "alpha", Teuchos::rcp(
00113     new alpha_t(
00114       2,"alpha"
00115 #ifdef _MIPS_CXX
00116       ,Teuchos::RCP<Teuchos::AbstractFactoryStd<alpha_k_t,alpha_k_t> >(
00117         new Teuchos::AbstractFactoryStd<alpha_k_t,alpha_k_t>())
00118 #endif      
00119       )) );
00120 
00121   if(out) *out << "set IterQuantityAccessContiguous<std::vector<double> >(2,\"x\")\n";
00122   state.set_iter_quant( "x", Teuchos::rcp(
00123     new x_t(
00124       2,"x"
00125 #ifdef _MIPS_CXX
00126       ,Teuchos::RCP<Teuchos::AbstractFactoryStd<x_k_t,x_k_t> >(
00127         new Teuchos::AbstractFactoryStd<x_k_t,x_k_t>())
00128 #endif      
00129       )) );
00130 
00131   if(out) *out << "set IterQuantityAccessDerivedToBase<B,D>(1,\"V\")\n";
00132   state.set_iter_quant(
00133     "V"
00134     ,Teuchos::rcp(
00135       new V_t(
00136         1
00137         ,"V"
00138         ,Teuchos::rcp( new Teuchos::AbstractFactoryStd<V_k_t,D> )
00139         )
00140         )
00141     );
00142 
00143   // Try to add the same name again.
00144 
00145   if(out) *out << "\nTry to add \"x\" (should throw execption) : ";
00146   try {
00147     state.set_iter_quant( "x", Teuchos::rcp(
00148       new x_t(
00149         2,"x"
00150 #ifdef _MIPS_CXX
00151         ,Teuchos::RCP<Teuchos::AbstractFactoryStd<x_k_t,x_k_t> >(
00152           new Teuchos::AbstractFactoryStd<x_k_t,x_k_t>())
00153 #endif      
00154         )) );
00155     success = false;
00156     if(out)
00157       *out << "false\n";
00158   }
00159   catch(const AlgorithmState::AlreadyExists& expt) {
00160     if(out) *out << "Caught a AlgorithmState::AlreadyExists execption : " << expt.what() << " : true\n" << endl;
00161   }
00162 
00163   // dump the iteration quantity names, ids, and concrete types.
00164 
00165   if(out) {
00166     *out << "\n*** dump iteration quantitys\n";
00167     state.dump_iter_quant(*out);
00168   }
00169 
00170   update_success( result = state.k() == 0, &success );
00171   if(out) *out << "\nstate.k() == 0 : " << result << endl; 
00172 
00173   // Set the iteration quantities for the kth iteration and check them
00174 
00175   if(out) *out << "\n*** Set iteration quantities for the kth iteration\n";
00176 
00177   if(out) *out << "\nSet alpha_k(0) = 5.0 then get alpha_k(0) == 5.0 : ";
00178   alpha_t *alpha = dynamic_cast<alpha_t*>( &state.iter_quant("alpha") );
00179   alpha->set_k(0) = 5.0; 
00180   alpha = dynamic_cast<alpha_t*>( &state.iter_quant("alpha") );
00181   update_success( result = alpha->get_k(0) == 5.0, &success );
00182   if(out) *out << result << endl;
00183 
00184   if(out) *out << "\nSet x_k(0)[0] = 2.0 then get x_k(0)[0] == 2.0 : ";
00185   x_t *x = dynamic_cast<x_t*>( &state.iter_quant("x") );
00186   x->set_k(0).resize(1);
00187   x->set_k(0)[0] = 2.0;
00188   x = dynamic_cast<x_t*>( &state.iter_quant("x") );
00189   update_success( result = x->get_k(0)[0] == 2.0, &success );
00190   if(out) *out << result << endl;
00191 
00192   if(out) *out << "\nSet V_k(0).alpha() = 3.0 then get V_k(0).alpha() == 3.0 : ";
00193   V_t *V = dynamic_cast<V_t*>( &state.iter_quant("V") );
00194   V->set_k(0).alpha(3.0);
00195   V = dynamic_cast<V_t*>( &state.iter_quant("V") );
00196   update_success( result = V->get_k(0).alpha() == 3.0, &success );
00197   if(out) *out << result << endl;
00198 
00199   // Use an id to get at an iteration quantity.
00200 
00201   if(out) *out << "\n*** Use an id to get at an iteration quantity\n";
00202 
00203   if(out) *out << "\nid for \"x\" is : ";
00204   AlgorithmState::iq_id_type x_id = state.get_iter_quant_id("x");
00205   if(out) *out << x_id << endl;
00206 
00207   if(out) *out << "\nAccess \"x\" using id and x_k(0)[0] == 2.0 : ";
00208   x = dynamic_cast<x_t*>( &state.iter_quant(x_id) );
00209   update_success( result = x->get_k(0)[0] == 2.0, &success );
00210   if(out) *out << result << endl;
00211 
00212   // use a nonexistant name
00213 
00214   if(out) *out << "\n*** Use a nonexistant name or id to access iteration quantity\n";
00215 
00216   if(out) *out << "id for \"X\" is DOES_NOT_EXIST : ";
00217   update_success( result = state.get_iter_quant_id("X") == AlgorithmState::DOES_NOT_EXIST
00218     , & success );
00219   if(out) *out << result << endl;
00220 
00221   if(out) *out << "\nAccess nonexistant iteration quantity by name \"X\" throws a AlgorithmState::DoesNotExist exception : ";
00222   try {
00223     state.iter_quant("X");
00224     success = false;
00225     if(out) *out << false << endl;
00226   }
00227   catch(const AlgorithmState::DoesNotExist& expt) {
00228     if(out) *out << true << endl;
00229   }
00230 
00231   // use a nonexistant id
00232 
00233   if(out) *out << "\nUse of a nonexistant id = 100 throws a AlgorithmState::DoesNotExist exception : ";
00234   try {
00235     state.iter_quant(100);
00236     success = false;
00237     if(out) *out << false << endl;
00238   }
00239   catch(const AlgorithmState::DoesNotExist& expt) {
00240     if(out) *out << true << endl;
00241   }
00242 
00243   // update the iteration
00244 
00245   if(out) *out << "\n*** Update iteration quantities k+1 = k then check\n";
00246 
00247   if(out) *out << "alpha_k(+1) = alpha_k(0)...\n";
00248   alpha = dynamic_cast<alpha_t*>( &state.iter_quant("alpha") );
00249   {
00250     alpha_k_t &alpha_k = alpha->get_k(0);
00251     alpha->set_k(+1) = alpha_k;
00252   }
00253 
00254   if(out) *out << "x_k(+1) = x_k(0)...\n";
00255   x = dynamic_cast<x_t*>( &state.iter_quant("x") );
00256   {
00257     x_k_t &x_k = x->get_k(0);
00258     x->set_k(+1) = x_k;
00259   }
00260 
00261   if(out) *out << "V_k(+1) = V_k(0)...\n";
00262   V = dynamic_cast<V_t*>( &state.iter_quant("V") );
00263   {
00264     V_k_t &V_k = V->get_k(0);
00265     V->set_k(+1) = V_k;
00266   }
00267 
00268   if(out) *out << "shift reference from k to k+1...\n";
00269   state.next_iteration();
00270 
00271   if(out) *out << "\nalpha_k(-1) == 5.0 : ";
00272   alpha = dynamic_cast<alpha_t*>( &state.iter_quant("alpha") );
00273   update_success( result = alpha->get_k(-1) == 5.0, &success );
00274   if(out) *out << result << endl;
00275   if(out) *out << "alpha_k(0) == 5.0 : ";
00276   update_success( result = alpha->get_k(0) == 5.0, &success );
00277   if(out) *out << result << endl;
00278 
00279   if(out) *out << "\nx_k(-1)[0] == 2.0 : ";
00280   x = dynamic_cast<x_t*>( &state.iter_quant("x") );
00281   update_success( result = x->get_k(-1)[0] == 2.0, &success );
00282   if(out) *out << result << endl;
00283   if(out) *out << "x_k(0)[0] == 2.0 : ";
00284   update_success( result = x->get_k(0)[0] == 2.0, &success );
00285   if(out) *out << result << endl;
00286 
00287   if(out) *out << "\nV_k(0).alpha() == 3.0 : ";
00288   V = dynamic_cast<V_t*>( &state.iter_quant("V") );
00289   update_success( result = V->get_k(0).alpha() == 3.0, &success );
00290   if(out) *out << result << endl;
00291 
00292   // erase an iteration quantity then try to access it
00293 
00294   if(out) *out << "\n*** Erasing iteration quantity \"x\" then trying to access it throws"
00295           " a AlgorithmState::DoesNotExist exception : ";
00296   state.erase_iter_quant("x");
00297   try {
00298     state.iter_quant(x_id);
00299     if(out) *out << false << endl;
00300     update_success( false, &success );
00301   }
00302   catch(const AlgorithmState::DoesNotExist& expt) {
00303     if(out) *out << true << endl;
00304   }
00305 
00306   // final printout.
00307 
00308   if(out) {
00309     if(success) {
00310       *out << "\n*** Congradulations, all of the tests for AlgorihtmState"
00311           " returned the expected results\n";
00312     }
00313     else {
00314       *out << "\n*** Oops, at least one of the above tests for AlgorihtmState"
00315           " did not return the expected results ***\n";
00316     }
00317   }
00318 
00319   return success;
00320 
00321   } // end try
00322   catch(const std::exception& excpt) {
00323     if(out) *out << "\nCaught a std::exception: " << typeName(excpt) << " : " <<  excpt.what() << endl;
00324   }
00325   catch(...) {
00326     if(out) *out << "\nCaught an unknown exception\n";
00327   }
00328 
00329   if(out) *out << "\n*** Oops, If you read this some function throw an unexpected exception and the tests have failed!\n";
00330 
00331   return false;
00332 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines