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