Changeset 3359


Ignore:
Timestamp:
Sep 25, 2014 8:12:56 PM (6 years ago)
Author:
bradbell
Message:

Fix bug in optimization with discrete functions.

opt_discrete.sh: test of the fix.
discrete.hpp: spelling error in comment.
hash_code.hpp: make discrete operator a special case.
optimize.hpp: handle discrete operator.
optimize.cpp: test of the fix.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/bug/opt_discrete.sh

    r3358 r3359  
    3232
    3333namespace {
    34         double my_abs(const double& x)
    35         {       return std::fabs(x); }
     34        double floor(const double& x)
     35        {       return std::floor(x); }
    3636
    37         CPPAD_DISCRETE_FUNCTION(double,my_abs);
     37        CPPAD_DISCRETE_FUNCTION(double, floor);
    3838}
    3939
    4040int main()
    41 {
    42   CppAD::vector< CppAD::AD<double> > x(2), y(1);
    43   x[0]=0;
    44   x[1]=0;
    45   CppAD::Independent(x);
    46   y[0]=my_abs(x[0]);
    47   CppAD::ADFun<double> F(x,y);
    48  
    49   F.optimize();
     41{       using CppAD::vector;
     42
     43        vector< CppAD::AD<double> > ax(1), ay(1);
     44        ax[0] = 0.0;
     45        CppAD::Independent(ax);
     46        ay[0] =  floor(ax[0]) + floor(ax[0]); 
     47        CppAD::ADFun<double> f(ax, ay);
     48
     49        size_t size_before = f.size_var();
     50        f.optimize();
     51        size_t size_after = f.size_var();
     52        assert( size_after + 1 == size_before );
     53
     54        vector<double> x(1), y(1);
     55        x[0] = -2.2;
     56        y    = f.Forward(0, x);
     57        assert( y[0] == -6.0 );
     58
    5059}
    5160EOF
  • trunk/cppad/local/discrete.hpp

    r3232 r3359  
    230230        Constructor called for each invocation of CPPAD_DISCRETE_FUNCTION.
    231231
    232         Put this objec in the list of all objects for this class and set
     232        Put this object in the list of all objects for this class and set
    233233        the constant private data name_, f_, and index_.
    234234
  • trunk/cppad/local/hash_code.hpp

    r3232 r3359  
    8080
    8181\li unary operators:
    82 AbsOp, AcosOp, AsinOp, AtanOp, CosOp, CoshOp, DisOp,
     82AbsOp, AcosOp, AsinOp, AtanOp, CosOp, CoshOp
    8383ExpOp, LogOp, SinOp, SinhOp, SqrtOp, TanOp, TanhOp
    8484
     
    8989DivvpOp, PowvpOp, SubvpOp
    9090
    91 \li binary operators where both arguments are parameters:
     91\li binary operators where first is an index and second is a variable:
     92DisOp
     93
     94\li binary operators where both arguments are variables:
    9295AddvvOp, DivvvOp, MulvvOp, PowvvOp, SubvvOp
    9396
     
    176179                break;
    177180
     181                // Binary operator where first argument is an index and
     182                // second is a variable (same as both variables).
     183                case DisOp:
     184
    178185                // Binary operators where both arguments are variables
    179186                case AddvvOp:
     
    211218                case CosOp:
    212219                case CoshOp:
    213                 case DisOp:
    214220                case ExpOp:
    215221                case LogOp:
  • trunk/cppad/local/optimize.hpp

    r3232 r3359  
    586586template <class Base>
    587587inline size_t binary_match(
    588         const CppAD::vector<struct struct_old_variable>& tape           ,
     588        const CppAD::vector<struct struct_old_variable>&   tape           ,
    589589        size_t                                             current        ,
    590590        size_t                                             npar           ,
     
    603603        CPPAD_ASSERT_UNKNOWN( NumRes(op) >  0 );
    604604        switch(op)
    605         {       // parameter op variable ----------------------------------
     605        {       // index op variable
     606                case DisOp:
     607                // parameter not defined for this case
     608                CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < current );
     609                new_arg[0]   = arg[0];
     610                new_arg[1]   = tape[arg[1]].new_var;
     611                break;
     612
     613                // parameter op variable ----------------------------------
    606614                case AddpvOp:
    607615                case MulpvOp:
     
    663671        if( op == tape[i].op )
    664672        {       bool match = true;
    665                 size_t j;
    666                 for(j = 0; j < 2; j++)
    667                 {       size_t k = tape[i].arg[j];
    668                         if( parameter[j] )
    669                         {       CPPAD_ASSERT_UNKNOWN( k < npar );
    670                                 match &= IdenticalEqualPar(
    671                                         par[ arg[j] ], par[k]
    672                                 );
    673                         }
    674                         else
    675                         {       CPPAD_ASSERT_UNKNOWN( k < i );
    676                                 match &= (new_arg[j] == tape[k].new_var);
     673                if( op == DisOp )
     674                {       match   &= new_arg[0] == tape[i].arg[0];
     675                        size_t k = tape[i].arg[1];
     676                        match   &= new_arg[1] == tape[k].new_var;
     677                }
     678                else
     679                {       for(size_t j = 0; j < 2; j++)
     680                        {       size_t k = tape[i].arg[j];
     681                                if( parameter[j] )
     682                                {       CPPAD_ASSERT_UNKNOWN( k < npar );
     683                                        match &= IdenticalEqualPar(
     684                                                par[ arg[j] ], par[k]
     685                                        );
     686                                }
     687                                else
     688                                {       CPPAD_ASSERT_UNKNOWN( k < i );
     689                                        match &= (new_arg[j] == tape[k].new_var);
     690                                }
    677691                        }
    678692                }
     
    13931407                switch( op )
    13941408                {
    1395                         // Unary operator where operand is arg[0]
     1409                        // One variable corresponding to arg[0]
    13961410                        case AbsOp:
    13971411                        case AcosOp:
     
    14401454                        break; // --------------------------------------------
    14411455
    1442                         // Unary operator where operand is arg[1]
     1456                        // One variable corresponding to arg[1]
    14431457                        case DisOp:
    14441458                        case DivpvOp:
     
    16711685                        break;  // --------------------------------------------
    16721686
    1673                         // Operations where there is noting to do
     1687                        // Operations where there is nothing to do
    16741688                        case ComOp:
    16751689                        case EndOp:
     
    21822196                        }
    21832197                        break;
     2198                        // ---------------------------------------------------
     2199                        // Binary operators where
     2200                        // left is an index and right is a variable
     2201                        case DisOp:
     2202                        match_var = binary_match(
     2203                                tape                ,  // inputs
     2204                                i_var               ,
     2205                                play->num_par_rec() ,
     2206                                play->GetPar()      ,
     2207                                hash_table_var      ,
     2208                                code                  // outputs
     2209                        );
     2210                        if( match_var > 0 )
     2211                                tape[i_var].new_var = match_var;
     2212                        else
     2213                        {       new_arg[0] = arg[0];
     2214                                new_arg[1] = tape[ arg[1] ].new_var;
     2215                                rec->PutArg( new_arg[0], new_arg[1] );
     2216                                tape[i_var].new_op  = rec->num_op_rec();
     2217                                tape[i_var].new_var = rec->PutOp(op);
     2218                                CPPAD_ASSERT_UNKNOWN(
     2219                                        size_t(new_arg[1]) < tape[i_var].new_var
     2220                                );
     2221                                replace_hash = true;
     2222                        }
     2223                        break;
     2224
    21842225                        // ---------------------------------------------------
    21852226                        // Binary operators where
  • trunk/omh/whats_new/whats_new_14.omh

    r3348 r3359  
    5555assist you in learning about changes between various versions of CppAD.
    5656
    57 $head 10-21$$
     57$head 09-25$$
     58Fix a bug when
     59$cref/f.optimize/optimize/$$ was used with a function $icode f$$
     60that contained $cref discrete$$ functions.
     61
     62$head 09-21$$
    5863Fix a typo in documentation for
    5964$cref/any order reverse/reverse_any/$$.
  • trunk/test_more/optimize.cpp

    r3008 r3359  
    14311431                return ok;
    14321432        }
     1433        // -----------------------------------------------------------------------
     1434        double floor(const double& x)
     1435        {       return std::floor(x); }
     1436        CPPAD_DISCRETE_FUNCTION(double, floor)
     1437        bool discrete_function(void)
     1438        {       bool ok = true;
     1439                using CppAD::vector;
     1440       
     1441                vector< CppAD::AD<double> > ax(1), ay(1);
     1442                ax[0] = 0.0;
     1443                CppAD::Independent(ax);
     1444                ay[0] =  floor(ax[0]) + floor(ax[0]); 
     1445                CppAD::ADFun<double> f(ax, ay);
     1446       
     1447                size_t size_before = f.size_var();
     1448                f.optimize();
     1449                size_t size_after = f.size_var();
     1450                ok &= size_after + 1 == size_before;
     1451       
     1452                vector<double> x(1), y(1);
     1453                x[0] = -2.2;
     1454                y    = f.Forward(0, x);
     1455                ok &= y[0] == -6.0;
     1456       
     1457                return ok;
     1458        }
     1459        // -----------------------------------------------------------------------
    14331460}
    14341461
     
    14731500        // case where results are not identically equal
    14741501        ok     &= not_identically_equal();
     1502        // case where a discrete function is used
     1503        ok     &= discrete_function();
    14751504        //
    14761505        CppAD::user_atomic<double>::clear();
Note: See TracChangeset for help on using the changeset viewer.