MOAB: Mesh Oriented datABase  (version 5.3.0)
ObjectiveFunctionTests Class Reference

#include <ObjectiveFunctionTests.hpp>

+ Inheritance diagram for ObjectiveFunctionTests:

Public Types

enum  OFTestMode { EVAL, GRAD, DIAG, HESS }

Static Public Member Functions

static void test_eval_type (ObjectiveFunction::EvalType, OFTestMode test_mode, ObjectiveFunctionTemplate *of)
static void test_handles_invalid_qm (OFTestMode test_mode, ObjectiveFunctionTemplate *of)
static void test_handles_qm_error (OFTestMode test_mode, ObjectiveFunctionTemplate *of)
static void test_clone (ObjectiveFunctionTemplate *of)
static void test_negate_flag (OFTestMode test_mode, ObjectiveFunctionTemplate *of)
static void test_value (const double *input_values, unsigned num_input_values, double expected_value, OFTestMode test_mode, ObjectiveFunctionTemplate *of)
static void compare_numerical_gradient (ObjectiveFunctionTemplate *of)
static void compare_numerical_gradient (ObjectiveFunction *of)
static void compare_hessian_gradient (ObjectiveFunctionTemplate *of)
static void compare_hessian_gradient (ObjectiveFunction *of)
static void compare_diagonal_gradient (ObjectiveFunctionTemplate *of)
static void compare_diagonal_gradient (ObjectiveFunction *of)
static void compare_hessian_diagonal (ObjectiveFunctionTemplate *of)
static void compare_hessian_diagonal (ObjectiveFunction *of)
static void compare_numerical_hessian (ObjectiveFunctionTemplate *of)
static void compare_numerical_hessian_diagonal (ObjectiveFunctionTemplate *of)
static void compare_numerical_hessian (ObjectiveFunction *of, bool diagonal_only)
static PatchDatapatch ()

Static Private Member Functions

static double evaluate_internal (ObjectiveFunction::EvalType type, OFTestMode test_mode, ObjectiveFunction *of)

Detailed Description

Definition at line 47 of file ObjectiveFunctionTests.hpp.


Member Enumeration Documentation

Which function to call

Enumerator:
EVAL 
GRAD 
DIAG 
HESS 

Definition at line 52 of file ObjectiveFunctionTests.hpp.

    {
        EVAL,
        GRAD,
        DIAG,
        HESS
    };

Member Function Documentation

Compare gradients from evaluate_with_gradient with gradient from evaluate_with_Hessian_diagonal

Definition at line 236 of file ObjectiveFunctionTests.hpp.

References ASSERT_NO_ERROR, and MBMesquite::ObjectiveFunctionTemplate::set_quality_metric().

Definition at line 440 of file ObjectiveFunctionTests.cpp.

References ASSERT_NO_ERROR, CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::create_twelve_hex_patch(), MBMesquite::ObjectiveFunction::evaluate_with_gradient(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian_diagonal(), MBMesquite::grad(), MBMesquite::hess(), and MBMesquite::PatchData::num_free_vertices().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    create_twelve_hex_patch( pd, err );
    ASSERT_NO_ERROR( err );

    std::vector< Vector3D > grad, hess_grad;
    std::vector< SymMatrix3D > hess;
    double grad_val, hess_val;
    bool valid;

    valid = of->evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, grad_val, grad, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( valid );
    CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), grad.size() );

    valid = of->evaluate_with_Hessian_diagonal( ObjectiveFunction::CALCULATE, pd, hess_val, hess_grad, hess, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( valid );
    CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), hess_grad.size() );

    CPPUNIT_ASSERT_DOUBLES_EQUAL( grad_val, hess_val, 1e-6 );
    for( size_t i = 0; i < pd.num_free_vertices(); ++i )
    {
        CPPUNIT_ASSERT_VECTORS_EQUAL( grad[i], hess_grad[i], 1e-6 );
    }
}

Compare gradient and diagonal terms from evaluate_with_Hessian and evaluate_with_Hessian_diagonal

Definition at line 245 of file ObjectiveFunctionTests.hpp.

References ASSERT_NO_ERROR, and MBMesquite::ObjectiveFunctionTemplate::set_quality_metric().

{
    MsqPrintError err( std::cout );
    IdealWeightInverseMeanRatio metric( err );
    ASSERT_NO_ERROR( err );
    of->set_quality_metric( &metric );
    compare_hessian_diagonal( (ObjectiveFunction*)of );
}

Definition at line 469 of file ObjectiveFunctionTests.cpp.

References ASSERT_NO_ERROR, CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_MATRICES_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::create_twelve_hex_patch(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian_diagonal(), MBMesquite::MsqHessian::get_block(), MBMesquite::hess(), MBMesquite::MsqHessian::initialize(), MBMesquite::PatchData::num_free_vertices(), and MBMesquite::MsqHessian::size().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    create_twelve_hex_patch( pd, err );
    ASSERT_NO_ERROR( err );

    std::vector< Vector3D > diag_grad, hess_grad;
    std::vector< SymMatrix3D > diag;
    MsqHessian hess;
    double diag_val, hess_val;
    bool valid;

    valid = of->evaluate_with_Hessian_diagonal( ObjectiveFunction::CALCULATE, pd, diag_val, diag_grad, diag, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( valid );
    CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), diag_grad.size() );
    CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), diag.size() );

    hess.initialize( pd, err );
    ASSERT_NO_ERROR( err );
    valid = of->evaluate_with_Hessian( ObjectiveFunction::CALCULATE, pd, hess_val, hess_grad, hess, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( valid );
    CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), hess_grad.size() );
    CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), hess.size() );

    CPPUNIT_ASSERT_DOUBLES_EQUAL( hess_val, diag_val, 1e-6 );
    for( size_t i = 0; i < pd.num_free_vertices(); ++i )
    {
        CPPUNIT_ASSERT_VECTORS_EQUAL( hess_grad[i], diag_grad[i], 1e-6 );
        CPPUNIT_ASSERT_MATRICES_EQUAL( *hess.get_block( i, i ), diag[i], 1e-6 );
    }
}

Compare gradients from evaluate_with_gradient with gradient from evaluate_with_Hessian

Definition at line 227 of file ObjectiveFunctionTests.hpp.

References ASSERT_NO_ERROR, and MBMesquite::ObjectiveFunctionTemplate::set_quality_metric().

{
    MsqPrintError err( std::cout );
    IdealWeightInverseMeanRatio metric( err );
    ASSERT_NO_ERROR( err );
    of->set_quality_metric( &metric );
    compare_hessian_gradient( (ObjectiveFunction*)of );
}

Definition at line 409 of file ObjectiveFunctionTests.cpp.

References ASSERT_NO_ERROR, CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::create_twelve_hex_patch(), MBMesquite::ObjectiveFunction::evaluate_with_gradient(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian(), MBMesquite::grad(), MBMesquite::hess(), MBMesquite::MsqHessian::initialize(), and MBMesquite::PatchData::num_free_vertices().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    create_twelve_hex_patch( pd, err );
    ASSERT_NO_ERROR( err );

    std::vector< Vector3D > grad, hess_grad;
    MsqHessian hess;
    double grad_val, hess_val;
    bool valid;

    valid = of->evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, grad_val, grad, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( valid );
    CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), grad.size() );

    hess.initialize( pd, err );
    ASSERT_NO_ERROR( err );
    valid = of->evaluate_with_Hessian( ObjectiveFunction::CALCULATE, pd, hess_val, hess_grad, hess, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( valid );
    CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), hess_grad.size() );

    CPPUNIT_ASSERT_DOUBLES_EQUAL( grad_val, hess_val, 1e-6 );
    for( size_t i = 0; i < pd.num_free_vertices(); ++i )
    {
        CPPUNIT_ASSERT_VECTORS_EQUAL( grad[i], hess_grad[i], 1e-6 );
    }
}

Compare numerical and analytical gradient values

Definition at line 218 of file ObjectiveFunctionTests.hpp.

References ASSERT_NO_ERROR, and MBMesquite::ObjectiveFunctionTemplate::set_quality_metric().

Definition at line 381 of file ObjectiveFunctionTests.cpp.

References ASSERT_NO_ERROR, CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, MBMesquite::create_twelve_hex_patch(), MBMesquite::ObjectiveFunction::evaluate_with_gradient(), and MBMesquite::PatchData::num_free_vertices().

{
    MsqPrintError err( std::cout );
    PatchData pd;
    create_twelve_hex_patch( pd, err );
    ASSERT_NO_ERROR( err );

    std::vector< Vector3D > num_grad, ana_grad;
    double num_val, ana_val;
    bool valid;

    valid = of->evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, ana_val, ana_grad, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( valid );
    CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), ana_grad.size() );

    valid = of->ObjectiveFunction::evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, num_val, num_grad, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( valid );
    CPPUNIT_ASSERT_EQUAL( pd.num_free_vertices(), num_grad.size() );

    CPPUNIT_ASSERT_DOUBLES_EQUAL( ana_val, num_val, 1e-6 );
    for( size_t i = 0; i < pd.num_free_vertices(); ++i )
    {
        CPPUNIT_ASSERT_VECTORS_EQUAL( num_grad[i], ana_grad[i], 1e-3 );
    }
}
void ObjectiveFunctionTests::compare_numerical_hessian ( ObjectiveFunction of,
bool  diagonal_only 
) [static]

Definition at line 511 of file ObjectiveFunctionTests.cpp.

References ASSERT_NO_ERROR, CHECK_EQUAL_MATRICES, CPPUNIT_ASSERT, MBMesquite::create_qm_two_tet_patch(), MBMesquite::ObjectiveFunction::evaluate(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian_diagonal(), MBMesquite::MsqHessian::get_block(), MBMesquite::grad(), MBMesquite::hess(), MBMesquite::MsqHessian::initialize(), MBMesquite::PatchData::move_vertex(), MBMesquite::PatchData::num_free_vertices(), MBMesquite::PatchData::set_vertex_coordinates(), MBMesquite::transpose(), value(), and MBMesquite::PatchData::vertex_by_index().

{
    const double delta = 0.0001;

    MsqPrintError err( std::cout );
    PatchData pd;
    create_qm_two_tet_patch( pd, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( pd.num_free_vertices() != 0 );

    // get analytical Hessian from objective function
    std::vector< Vector3D > grad;
    std::vector< SymMatrix3D > diag;
    MsqHessian hess;
    hess.initialize( pd, err );
    ASSERT_NO_ERROR( err );
    double value;
    bool valid;
    if( diagonal_only )
        valid = of->evaluate_with_Hessian_diagonal( ObjectiveFunction::CALCULATE, pd, value, grad, diag, err );
    else
        valid = of->evaluate_with_Hessian( ObjectiveFunction::CALCULATE, pd, value, grad, hess, err );
    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( valid );

    // do numerical approximation of each block and compare to analytical value
    for( size_t i = 0; i < pd.num_free_vertices(); ++i )
    {
        const size_t j_end = diagonal_only ? i + 1 : pd.num_free_vertices();
        for( size_t j = i; j < j_end; ++j )
        {
            // do numerical approximation for block corresponding to
            // coorindates for ith and jth vertices.
            Matrix3D block;
            for( int k = 0; k < 3; ++k )
            {
                for( int m = 0; m < 3; ++m )
                {
                    double dk, dm, dkm;
                    Vector3D ik = pd.vertex_by_index( i );
                    Vector3D im = pd.vertex_by_index( j );

                    Vector3D delta_k( 0.0 );
                    delta_k[k] = delta;
                    pd.move_vertex( delta_k, i, err );
                    ASSERT_NO_ERROR( err );
                    valid = of->evaluate( ObjectiveFunction::CALCULATE, pd, dk, true, err );
                    ASSERT_NO_ERROR( err );
                    CPPUNIT_ASSERT( valid );

                    Vector3D delta_m( 0.0 );
                    delta_m[m] = delta;
                    pd.move_vertex( delta_m, j, err );
                    ASSERT_NO_ERROR( err );
                    valid = of->evaluate( ObjectiveFunction::CALCULATE, pd, dkm, true, err );
                    ASSERT_NO_ERROR( err );
                    CPPUNIT_ASSERT( valid );

                    // be careful here that we do the right thing if i==j
                    pd.set_vertex_coordinates( ik, i, err );
                    ASSERT_NO_ERROR( err );
                    pd.set_vertex_coordinates( im, j, err );
                    ASSERT_NO_ERROR( err );
                    pd.move_vertex( delta_m, j, err );
                    ASSERT_NO_ERROR( err );
                    valid = of->evaluate( ObjectiveFunction::CALCULATE, pd, dm, true, err );
                    ASSERT_NO_ERROR( err );
                    CPPUNIT_ASSERT( valid );

                    pd.set_vertex_coordinates( ik, i, err );
                    ASSERT_NO_ERROR( err );
                    pd.set_vertex_coordinates( im, j, err );
                    ASSERT_NO_ERROR( err );

                    block[k][m] = ( dkm - dk - dm + value ) / ( delta * delta );
                }
            }
            // compare to analytical value
            if( diagonal_only )
            {
                CPPUNIT_ASSERT( i == j );  // see j_end above
                CPPUNIT_ASSERT( i < diag.size() );
                CHECK_EQUAL_MATRICES( block, Matrix3D( diag[i] ) );
            }
            else
            {
                Matrix3D* m  = hess.get_block( i, j );
                Matrix3D* mt = hess.get_block( j, i );
                if( NULL != m ) { CHECK_EQUAL_MATRICES( block, *m ); }
                if( NULL != mt ) { CHECK_EQUAL_MATRICES( transpose( block ), *m ); }
                if( NULL == mt && NULL == m ) { CHECK_EQUAL_MATRICES( Matrix3D( 0.0 ), block ); }
            }
        }
    }
}
double ObjectiveFunctionTests::evaluate_internal ( ObjectiveFunction::EvalType  type,
OFTestMode  test_mode,
ObjectiveFunction of 
) [static, private]

Internal helper function for test_eval_type

Definition at line 54 of file ObjectiveFunctionTests.cpp.

References ASSERT_NO_ERROR, CPPUNIT_ASSERT, DIAG, EVAL, MBMesquite::ObjectiveFunction::evaluate(), MBMesquite::ObjectiveFunction::evaluate_with_gradient(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian_diagonal(), GRAD, MBMesquite::grad(), HESS, MBMesquite::hess(), MBMesquite::MsqHessian::initialize(), MBMesquite::OF_FREE_EVALS_ONLY, and patch().

Referenced by test_clone(), test_eval_type(), and test_value().

{
    MsqPrintError err( cout );
    vector< Vector3D > grad;
    vector< SymMatrix3D > diag;
    MsqHessian hess;
    bool valid = false;
    double result;

    switch( test_mode )
    {
        case EVAL:
            valid = of->evaluate( type, patch(), result, OF_FREE_EVALS_ONLY, err );
            break;
        case GRAD:
            valid = of->evaluate_with_gradient( type, patch(), result, grad, err );
            break;
        case DIAG:
            valid = of->evaluate_with_Hessian_diagonal( type, patch(), result, grad, diag, err );
            break;
        case HESS:
            hess.initialize( patch(), err );
            ASSERT_NO_ERROR( err );
            valid = of->evaluate_with_Hessian( type, patch(), result, grad, hess, err );
            break;
        default:
            CPPUNIT_ASSERT( false );
    }

    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( valid );
    return result;
}

Definition at line 36 of file ObjectiveFunctionTests.cpp.

References CPPUNIT_ASSERT, and init_pd().

Referenced by evaluate_internal(), test_clone(), test_handles_invalid_qm(), test_handles_qm_error(), and test_negate_flag().

{
    static PatchData the_pd;
    static bool did_init = init_pd( the_pd );
    CPPUNIT_ASSERT( did_init );
    return the_pd;
}

Test the behavior of the clone() method

Definition at line 271 of file ObjectiveFunctionTests.cpp.

References OFTestQM::append_values(), MBMesquite::MsqError::clear(), MBMesquite::ObjectiveFunction::clear(), MBMesquite::ObjectiveFunction::clone(), CPPUNIT_ASSERT_DOUBLES_EQUAL, EVAL, MBMesquite::ObjectiveFunction::evaluate(), evaluate_internal(), patch(), MBMesquite::ObjectiveFunctionTemplate::set_quality_metric(), and OFTestQM::set_values().

Referenced by PMeanPTemplateTest::test_clone(), StdDevTemplateTest::test_clone(), and StdDevTemplateTest::test_clone_sqr().

{
    const double some_vals[] = { 1, 2, 3, 4, 5, 6, 0.5 };
    const unsigned num_vals  = sizeof( some_vals ) / sizeof( some_vals[0] );
    OFTestQM metric( some_vals, num_vals );
    of->set_quality_metric( &metric );

    // test that we get the same value from both
    unique_ptr< ObjectiveFunction > of2( of->clone() );
    double exp_val, val;
    exp_val = evaluate_internal( ObjectiveFunction::CALCULATE, EVAL, of );
    val     = evaluate_internal( ObjectiveFunction::CALCULATE, EVAL, of2.get() );
    CPPUNIT_ASSERT_DOUBLES_EQUAL( exp_val, val, 1e-12 );

    // check if OF supports BCD -- if not then done
    MsqError err;
    of->evaluate( ObjectiveFunction::UPDATE, patch(), val, false, err );
    if( err )
    {
        err.clear();
        return;
    }

    // build up some saved state in the objective function
    of->clear();
    const double vals1[]   = { 1.0, 3.0, 4.0, 8.0 };
    const size_t vals1_len = sizeof( vals1 ) / sizeof( vals1[0] );
    const double vals2[]   = { 21.5, 11.1, 30.0, 0.5 };
    const size_t vals2_len = sizeof( vals2 ) / sizeof( vals2[0] );
    metric.set_values( vals1, vals1_len );
    evaluate_internal( ObjectiveFunction::SAVE, EVAL, of );
    metric.append_values( vals2, vals2_len );
    evaluate_internal( ObjectiveFunction::ACCUMULATE, EVAL, of );

    // check that clone has same accumulated data
    of2 = unique_ptr< ObjectiveFunction >( of->clone() );
    metric.set_values( some_vals, num_vals );
    exp_val = evaluate_internal( ObjectiveFunction::UPDATE, EVAL, of );
    val     = evaluate_internal( ObjectiveFunction::UPDATE, EVAL, of2.get() );
    CPPUNIT_ASSERT_DOUBLES_EQUAL( exp_val, val, 1e-12 );
}

Test eval type support for OF templates that provide block coordinate descent functionality.

Note: If OF does not support BCD, this test will fail, even for the ObjectiveFunction::CALCULATE eval type.

Definition at line 89 of file ObjectiveFunctionTests.cpp.

References OFTestQM::append_values(), MBMesquite::ObjectiveFunction::clear(), CPPUNIT_ASSERT_DOUBLES_EQUAL, evaluate_internal(), MBMesquite::ObjectiveFunctionTemplate::set_quality_metric(), and OFTestQM::set_values().

Referenced by PMeanPTemplateTest::test_eval_type().

{
    // define two sets of quality metric values
    const double vals1[]   = { 1.0, 3.0, 4.0, 8.0 };
    const size_t vals1_len = sizeof( vals1 ) / sizeof( vals1[0] );
    const double vals2[]   = { 21.5, 11.1, 30.0, 0.5 };
    const size_t vals2_len = sizeof( vals2 ) / sizeof( vals2[0] );

    // create a quality metric to use
    OFTestQM metric;
    of->set_quality_metric( &metric );

    // get some initial values to compare to
    of->clear();
    metric.set_values( vals1, vals1_len );
    const double init1 = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
    of->clear();
    metric.set_values( vals2, vals2_len );
    const double init2 = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
    of->clear();
    metric.append_values( vals1, vals1_len );
    const double inits = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
    of->clear();

    double val, expected;
    switch( type )
    {
        case ObjectiveFunction::CALCULATE:

            // first make sure we get back the same values
            metric.set_values( vals1, vals1_len );
            val = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );
            metric.set_values( vals2, vals2_len );
            val = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( init2, val, 1e-6 );

            // now do something that should modify the accumulated value of the OF
            evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );

            // check that the values are unchanged
            metric.set_values( vals1, vals1_len );
            val = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );
            metric.set_values( vals2, vals2_len );
            val = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( init2, val, 1e-6 );

            break;

        case ObjectiveFunction::ACCUMULATE:

            // begin with first set
            metric.set_values( vals1, vals1_len );
            val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );

            // add in second set
            metric.set_values( vals2, vals2_len );
            val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( inits, val, 1e-6 );

            // clear
            of->clear();

            // begin with second set
            metric.set_values( vals2, vals2_len );
            val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( init2, val, 1e-6 );

            // add in first set
            metric.set_values( vals1, vals1_len );
            val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( inits, val, 1e-6 );

            break;

        case ObjectiveFunction::SAVE:

            // calculate value for first set twice
            metric.set_values( vals1, vals1_len );
            metric.append_values( vals1, vals1_len );
            expected = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );

            // begin with the first set
            metric.set_values( vals1, vals1_len );
            val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );

            // add the second set
            metric.set_values( vals2, vals2_len );
            val = evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( inits, val, 1e-6 );

            // now save the second set of values - OF value should not change
            metric.set_values( vals2, vals2_len );
            val = evaluate_internal( ObjectiveFunction::SAVE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( inits, val, 1e-6 );

            // now replace the second set with the first
            metric.set_values( vals1, vals1_len );
            val = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( expected, val, 1e-6 );

            // check that saved values are cleared
            of->clear();
            metric.set_values( vals2, vals2_len );
            val = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( init2, val, 1e-6 );

            break;

        case ObjectiveFunction::UPDATE:

            // With no saved data, an update should produce the same
            // result as CALCULATE
            metric.set_values( vals1, vals1_len );
            val = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );

            // Doing an update with a second patch should change
            // the global value to that of the second set
            metric.set_values( vals2, vals2_len );
            val = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( init2, val, 1e-6 );

            // Now add in the second set again
            metric.set_values( vals2, vals2_len );
            evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );

            // Now replace one accumulation of the second set with the first
            // Should result in the first set + the second set
            metric.set_values( vals1, vals1_len );
            val = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( inits, val, 1e-6 );

            break;

        case ObjectiveFunction::TEMPORARY:

            // With no saved data, an TEMPORARY should produce the same
            // result as CALCULATE
            metric.set_values( vals1, vals1_len );
            val = evaluate_internal( ObjectiveFunction::TEMPORARY, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( init1, val, 1e-6 );

            // Begin with two instances of the second set in the
            // accumulated value, with one instance saved so it
            // can be removed later
            metric.set_values( vals2, vals2_len );
            evaluate_internal( ObjectiveFunction::ACCUMULATE, test_mode, of );
            evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );

            // Now do a temporary eval, replacing one instance of the
            // second set wiht the first set
            metric.set_values( vals1, vals1_len );
            val = evaluate_internal( ObjectiveFunction::TEMPORARY, test_mode, of );

            // TEMPORARY should produce the same value as UPDATE, but without
            // modifying any internal state.
            expected = evaluate_internal( ObjectiveFunction::UPDATE, test_mode, of );
            CPPUNIT_ASSERT_DOUBLES_EQUAL( expected, val, 1e-6 );

            break;

        default:
            CPPUNIT_ASSERT_MESSAGE( "No test for specified evaluation type", false );
            break;
    }
}

Verify that if QualityMetric returns invalid but not error from evaluate, that the ObjectiveFunction does the same

Definition at line 668 of file ObjectiveFunctionTests.cpp.

References ASSERT_NO_ERROR, CPPUNIT_ASSERT, DIAG, EVAL, MBMesquite::ObjectiveFunction::evaluate(), MBMesquite::ObjectiveFunction::evaluate_with_gradient(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian_diagonal(), GRAD, MBMesquite::grad(), HESS, MBMesquite::hess(), MBMesquite::MsqHessian::initialize(), MBMesquite::OF_FREE_EVALS_ONLY, patch(), and MBMesquite::ObjectiveFunctionTemplate::set_quality_metric().

{
    OFTestBadQM metric( false );
    of->set_quality_metric( &metric );

    MsqPrintError err( cout );
    vector< Vector3D > grad;
    vector< SymMatrix3D > diag;
    MsqHessian hess;
    double result;
    bool valid = false;

    switch( test_mode )
    {
        case EVAL:
            valid = of->evaluate( ObjectiveFunction::CALCULATE, patch(), result, OF_FREE_EVALS_ONLY, err );
            break;
        case GRAD:
            valid = of->evaluate_with_gradient( ObjectiveFunction::CALCULATE, patch(), result, grad, err );
            break;
        case DIAG:
            valid =
                of->evaluate_with_Hessian_diagonal( ObjectiveFunction::CALCULATE, patch(), result, grad, diag, err );
            break;
        case HESS:
            hess.initialize( patch(), err );
            ASSERT_NO_ERROR( err );
            valid = of->evaluate_with_Hessian( ObjectiveFunction::CALCULATE, patch(), result, grad, hess, err );
            break;
        default:
            CPPUNIT_ASSERT( false );
    }

    ASSERT_NO_ERROR( err );
    CPPUNIT_ASSERT( !valid );
}

Verify that OF correctly handles error in QM::evaluate()

Definition at line 705 of file ObjectiveFunctionTests.cpp.

References ASSERT_NO_ERROR, CPPUNIT_ASSERT, DIAG, EVAL, MBMesquite::ObjectiveFunction::evaluate(), MBMesquite::ObjectiveFunction::evaluate_with_gradient(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian_diagonal(), GRAD, MBMesquite::grad(), HESS, MBMesquite::hess(), MBMesquite::MsqHessian::initialize(), MBMesquite::OF_FREE_EVALS_ONLY, patch(), and MBMesquite::ObjectiveFunctionTemplate::set_quality_metric().

{
    OFTestBadQM metric( true );
    of->set_quality_metric( &metric );

    MsqError err;
    vector< Vector3D > grad;
    vector< SymMatrix3D > diag;
    MsqHessian hess;
    double result;
    bool valid;

    switch( test_mode )
    {
        case EVAL:
            valid = of->evaluate( ObjectiveFunction::CALCULATE, patch(), result, OF_FREE_EVALS_ONLY, err );
            break;
        case GRAD:
            valid = of->evaluate_with_gradient( ObjectiveFunction::CALCULATE, patch(), result, grad, err );
            break;
        case DIAG:
            valid =
                of->evaluate_with_Hessian_diagonal( ObjectiveFunction::CALCULATE, patch(), result, grad, diag, err );
            break;
        case HESS:
            hess.initialize( patch(), err );
            ASSERT_NO_ERROR( err );
            valid = of->evaluate_with_Hessian( ObjectiveFunction::CALCULATE, patch(), result, grad, hess, err );
            break;
        default:
            CPPUNIT_ASSERT( false );
    }

    CPPUNIT_ASSERT( err );
}

Test correct handling of QM negate flag

Definition at line 314 of file ObjectiveFunctionTests.cpp.

References ASSERT_NO_ERROR, CPPUNIT_ASSERT, CPPUNIT_ASSERT_DOUBLES_EQUAL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_MATRICES_EQUAL, CPPUNIT_ASSERT_VECTORS_EQUAL, DIAG, EVAL, MBMesquite::ObjectiveFunction::evaluate(), MBMesquite::ObjectiveFunction::evaluate_with_gradient(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian(), MBMesquite::ObjectiveFunction::evaluate_with_Hessian_diagonal(), MBMesquite::MsqHessian::get_block(), GRAD, MBMesquite::grad(), HESS, MBMesquite::hess(), MBMesquite::MsqHessian::initialize(), patch(), OFTestQM::set_negate_flag(), MBMesquite::ObjectiveFunctionTemplate::set_quality_metric(), MBMesquite::MsqHessian::size(), size, and value().

{
    const double some_vals[] = { 1, 2, 3, 4, 5, 6, 0.5 };
    const unsigned num_vals  = sizeof( some_vals ) / sizeof( some_vals[0] );
    OFTestQM metric( some_vals, num_vals );
    of->set_quality_metric( &metric );

    MsqPrintError err( cout );
    bool rval = false;
    double value[2];
    vector< Vector3D > grad[2];
    vector< SymMatrix3D > diag[2];
    MsqHessian hess[2];

    // Do twice, once w/out negate flag set and then once
    // with negate flag == -1.
    ObjectiveFunction::EvalType type = ObjectiveFunction::CALCULATE;
    for( unsigned i = 0; i < 2; ++i )
    {
        switch( test_mode )
        {
            case EVAL:
                rval = of->evaluate( type, patch(), value[i], false, err );
                break;
            case GRAD:
                rval = of->evaluate_with_gradient( type, patch(), value[i], grad[i], err );
                break;
            case DIAG:
                rval = of->evaluate_with_Hessian_diagonal( type, patch(), value[i], grad[i], diag[i], err );
                break;
            case HESS:
                hess[i].initialize( patch(), err );
                ASSERT_NO_ERROR( err );
                rval = of->evaluate_with_Hessian( type, patch(), value[i], grad[i], hess[i], err );
                break;
            default:
                CPPUNIT_ASSERT_MESSAGE( "Invalid enum value in test code", false );
                break;
        }
        ASSERT_NO_ERROR( err );
        CPPUNIT_ASSERT( rval );
        metric.set_negate_flag( -1 );
    }

    switch( test_mode )
    {
        case HESS:
            CPPUNIT_ASSERT_EQUAL( hess[0].size(), hess[1].size() );
            for( size_t r = 0; r < hess[0].size(); ++r )
                for( size_t c = r; c < hess[0].size(); ++c )
                    if( hess[0].get_block( r, c ) )
                        CPPUNIT_ASSERT_MATRICES_EQUAL( -*hess[0].get_block( r, c ), *hess[1].get_block( r, c ), 1e-6 );
        case DIAG:
            // NOTE: When case HESS: falls through to here, diag[0] and diag[1]
            // will be empty, making this a no-op.
            CPPUNIT_ASSERT_EQUAL( diag[0].size(), diag[1].size() );
            for( size_t j = 0; j < diag[0].size(); ++j )
                CPPUNIT_ASSERT_MATRICES_EQUAL( -diag[0][j], diag[1][j], 1e-6 );
        case GRAD:
            CPPUNIT_ASSERT_EQUAL( grad[0].size(), grad[1].size() );
            for( size_t j = 0; j < grad[0].size(); ++j )
                CPPUNIT_ASSERT_VECTORS_EQUAL( -grad[0][j], grad[1][j], 1e-6 );
        default:
            CPPUNIT_ASSERT_DOUBLES_EQUAL( -value[0], value[1], 1e-6 );
    }
}
void ObjectiveFunctionTests::test_value ( const double *  input_values,
unsigned  num_input_values,
double  expected_value,
OFTestMode  test_mode,
ObjectiveFunctionTemplate of 
) [static]

Test OF value

Definition at line 261 of file ObjectiveFunctionTests.cpp.

References CPPUNIT_ASSERT_DOUBLES_EQUAL, evaluate_internal(), and MBMesquite::ObjectiveFunctionTemplate::set_quality_metric().

{
    OFTestQM metric( input_values, num_input_values );
    of->set_quality_metric( &metric );

    double val = evaluate_internal( ObjectiveFunction::CALCULATE, test_mode, of );
    CPPUNIT_ASSERT_DOUBLES_EQUAL( expected_value, val, 1e-6 );
}

List of all members.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines