MOAB: Mesh Oriented datABase  (version 5.2.1)
ObjectiveFunctionTests.hpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2006 Sandia National Laboratories.  Developed at the
00005     University of Wisconsin--Madison under SNL contract number
00006     624796.  The U.S. Government and the University of Wisconsin
00007     retain certain rights to this software.
00008 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Lesser General Public
00011     License as published by the Free Software Foundation; either
00012     version 2.1 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     (lgpl.txt) along with this library; if not, write to the Free Software
00021     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 
00023     (2006) kraftche@cae.wisc.edu
00024 
00025   ***************************************************************** */
00026 
00027 /** \file ObjectiveFunctionTests.hpp
00028  *  \brief
00029  *  \author Jason Kraftcheck
00030  */
00031 
00032 #ifndef MSQ_OBJECTIVE_FUNCTION_TESTS_HPP
00033 #define MSQ_OBJECTIVE_FUNCTION_TESTS_HPP
00034 
00035 #include "Mesquite.hpp"
00036 #include "PatchDataInstances.hpp"
00037 #include "IdealWeightInverseMeanRatio.hpp"
00038 #include "ObjectiveFunctionTemplate.hpp"
00039 #include "UnitUtil.hpp"
00040 #include "MsqHessian.hpp"
00041 
00042 #include <memory>
00043 
00044 using namespace MBMesquite;
00045 using namespace std;
00046 
00047 class ObjectiveFunctionTests
00048 {
00049 
00050   public:
00051     /** Which function to call */
00052     enum OFTestMode
00053     {
00054         EVAL,
00055         GRAD,
00056         DIAG,
00057         HESS
00058     };
00059 
00060     /** Test eval type support for OF templates that provide
00061      *  block coordinate descent functionality.
00062      *
00063      *  Note: If OF does not support BCD, this test will fail,
00064      *        even for the ObjectiveFunction::CALCULATE eval type.
00065      */
00066     static void test_eval_type( ObjectiveFunction::EvalType, OFTestMode test_mode, ObjectiveFunctionTemplate* of );
00067 
00068     /** Verify that if QualityMetric returns invalid but not error
00069      *  from evaluate, that the ObjectiveFunction does the same */
00070     static void test_handles_invalid_qm( OFTestMode test_mode, ObjectiveFunctionTemplate* of );
00071 
00072     /** Verify that OF correctly handles error in QM::evaluate() */
00073     static void test_handles_qm_error( OFTestMode test_mode, ObjectiveFunctionTemplate* of );
00074 
00075     /** Test the behavior of the clone() method */
00076     static void test_clone( ObjectiveFunctionTemplate* of );
00077 
00078     /** Test correct handling of QM negate flag */
00079     static void test_negate_flag( OFTestMode test_mode, ObjectiveFunctionTemplate* of );
00080 
00081     /** Test OF value */
00082     static void test_value( const double* input_values, unsigned num_input_values, double expected_value,
00083                             OFTestMode test_mode, ObjectiveFunctionTemplate* of );
00084 
00085     /** Compare numerical and analytical gradient values */
00086     static inline void compare_numerical_gradient( ObjectiveFunctionTemplate* of );
00087     static void compare_numerical_gradient( ObjectiveFunction* of );
00088 
00089     /** Compare gradients from evaluate_with_gradient with gradient
00090      *  from evaluate_with_Hessian
00091      */
00092     static inline void compare_hessian_gradient( ObjectiveFunctionTemplate* of );
00093     static void compare_hessian_gradient( ObjectiveFunction* of );
00094 
00095     /** Compare gradients from evaluate_with_gradient with gradient
00096      *  from evaluate_with_Hessian_diagonal
00097      */
00098     static inline void compare_diagonal_gradient( ObjectiveFunctionTemplate* of );
00099     static void compare_diagonal_gradient( ObjectiveFunction* of );
00100 
00101     /** Compare gradient and diagonal terms from evaluate_with_Hessian
00102      *  and evaluate_with_Hessian_diagonal
00103      */
00104     static inline void compare_hessian_diagonal( ObjectiveFunctionTemplate* of );
00105     static void compare_hessian_diagonal( ObjectiveFunction* of );
00106 
00107     static void compare_numerical_hessian( ObjectiveFunctionTemplate* of );
00108     static void compare_numerical_hessian_diagonal( ObjectiveFunctionTemplate* of );
00109     static void compare_numerical_hessian( ObjectiveFunction* of, bool diagonal_only );
00110 
00111     static PatchData& patch();
00112 
00113   private:
00114     static double evaluate_internal( ObjectiveFunction::EvalType type, OFTestMode test_mode, ObjectiveFunction* of );
00115 };
00116 
00117 /** The QualityMetric to use for testing purposes
00118  *
00119  *  Just pass a specified list of values to the OF
00120  */
00121 class OFTestQM : public QualityMetric
00122 {
00123   public:
00124     OFTestQM() : negateFlag( 1 ) {}
00125 
00126     OFTestQM( const double* values, unsigned num_values ) : mValues( num_values ), negateFlag( 1 )
00127     {
00128         copy( values, values + num_values, mValues.begin() );
00129     }
00130 
00131     void set_values( const double* values, unsigned num_values )
00132     {
00133         mValues.resize( num_values );
00134         copy( values, values + num_values, mValues.begin() );
00135     }
00136 
00137     void append_values( const double* values, unsigned num_values )
00138     {
00139         copy( values, values + num_values, back_inserter( mValues ) );
00140     }
00141 
00142     virtual MetricType get_metric_type() const
00143     {
00144         return ELEMENT_BASED;
00145     }
00146 
00147     virtual string get_name() const
00148     {
00149         return "ObjectiveFunctionTests";
00150     }
00151 
00152     virtual int get_negate_flag() const
00153     {
00154         return negateFlag;
00155     }
00156 
00157     void set_negate_flag( int value )
00158     {
00159         negateFlag = value;
00160     }
00161 
00162     virtual void get_evaluations( PatchData&, vector< size_t >& h, bool, MsqError& )
00163     {
00164         h.resize( mValues.size() );
00165         for( unsigned i = 0; i < mValues.size(); ++i )
00166             h[i] = i;
00167     }
00168 
00169     virtual bool evaluate( PatchData&, size_t h, double& v, MsqError& err )
00170     {
00171         if( h >= mValues.size() )
00172         {
00173             MSQ_SETERR( err )( "handle out of range", MsqError::INVALID_ARG );
00174             return false;
00175         }
00176         v = mValues[h];
00177         return true;
00178     }
00179 
00180     virtual bool evaluate_with_indices( PatchData& pd, size_t h, double& v, vector< size_t >& i, MsqError& err )
00181     {
00182         i.clear();
00183         for( unsigned j = 0; j < pd.num_free_vertices(); ++j )
00184             i.push_back( j );
00185         return evaluate( pd, h, v, err );
00186     }
00187 
00188     virtual bool evaluate_with_gradient( PatchData& pd, size_t h, double& v, vector< size_t >& i, vector< Vector3D >& g,
00189                                          MsqError& err )
00190     {
00191         g.clear();
00192         bool rval = evaluate_with_indices( pd, h, v, i, err );
00193         // grad values are just used to test negate flag, so just
00194         // pass back an arbitrary value for each free vertex
00195         for( unsigned j = 0; j < i.size(); ++j )
00196             g.push_back( Vector3D( 1, 0, 2 ) );
00197         return rval;
00198     }
00199 
00200     virtual bool evaluate_with_Hessian( PatchData& pd, size_t h, double& v, vector< size_t >& i, vector< Vector3D >& g,
00201                                         vector< Matrix3D >& H, MsqError& err )
00202     {
00203         H.clear();
00204         bool rval = evaluate_with_gradient( pd, h, v, i, g, err );
00205         // Hessian values are just used to test negate flag, so
00206         // pass back arbirary values.
00207         for( unsigned r = 0; r < i.size(); ++r )
00208             for( unsigned c = r; c < i.size(); ++c )
00209                 H.push_back( Matrix3D( 1.0 ) );
00210         return rval;
00211     }
00212 
00213   private:
00214     vector< double > mValues;
00215     int negateFlag;
00216 };
00217 
00218 inline void ObjectiveFunctionTests::compare_numerical_gradient( ObjectiveFunctionTemplate* of )
00219 {
00220     MsqPrintError err( std::cout );
00221     IdealWeightInverseMeanRatio metric( err );
00222     ASSERT_NO_ERROR( err );
00223     of->set_quality_metric( &metric );
00224     compare_numerical_gradient( (ObjectiveFunction*)of );
00225 }
00226 
00227 inline void ObjectiveFunctionTests::compare_hessian_gradient( ObjectiveFunctionTemplate* of )
00228 {
00229     MsqPrintError err( std::cout );
00230     IdealWeightInverseMeanRatio metric( err );
00231     ASSERT_NO_ERROR( err );
00232     of->set_quality_metric( &metric );
00233     compare_hessian_gradient( (ObjectiveFunction*)of );
00234 }
00235 
00236 inline void ObjectiveFunctionTests::compare_diagonal_gradient( ObjectiveFunctionTemplate* of )
00237 {
00238     MsqPrintError err( std::cout );
00239     IdealWeightInverseMeanRatio metric( err );
00240     ASSERT_NO_ERROR( err );
00241     of->set_quality_metric( &metric );
00242     compare_diagonal_gradient( (ObjectiveFunction*)of );
00243 }
00244 
00245 inline void ObjectiveFunctionTests::compare_hessian_diagonal( ObjectiveFunctionTemplate* of )
00246 {
00247     MsqPrintError err( std::cout );
00248     IdealWeightInverseMeanRatio metric( err );
00249     ASSERT_NO_ERROR( err );
00250     of->set_quality_metric( &metric );
00251     compare_hessian_diagonal( (ObjectiveFunction*)of );
00252 }
00253 
00254 inline void ObjectiveFunctionTests::compare_numerical_hessian( ObjectiveFunctionTemplate* of )
00255 {
00256     MsqPrintError err( std::cout );
00257     IdealWeightInverseMeanRatio metric( err );
00258     ASSERT_NO_ERROR( err );
00259     of->set_quality_metric( &metric );
00260     compare_numerical_hessian( (ObjectiveFunction*)of, false );
00261 }
00262 
00263 inline void ObjectiveFunctionTests::compare_numerical_hessian_diagonal( ObjectiveFunctionTemplate* of )
00264 {
00265     MsqPrintError err( std::cout );
00266     IdealWeightInverseMeanRatio metric( err );
00267     ASSERT_NO_ERROR( err );
00268     of->set_quality_metric( &metric );
00269     compare_numerical_hessian( (ObjectiveFunction*)of, true );
00270 }
00271 
00272 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines