Changeset 1580


Ignore:
Timestamp:
Nov 12, 2009 8:48:27 AM (11 years ago)
Author:
bradbell
Message:

trunk.new: Fix bug when optimizing power function operator.

optimize.cpp: Add test case that demonstrates bug.
optimize.hpp: fix address for primary result of power function operation.
define.hpp: Move macro for Power function primary result here.
pow.hpp: Use new version of macro.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/cppad/local/define.hpp

    r1401 r1580  
    1919
    2020*/
     21
     22/*!
     23\def CPPAD_POW_FINAL_RESULT
     24The pow function is a special case where the final result is the last,
     25instead of the first, of the multiple variables created.
     26This macro maps the first result address to the address that corresponds
     27to the primary pow function result.
     28This is a kludge so that the log, exp, and mul functions can be used as
     29operators to create the power function.
     30The kludge can be fixed by making the final result the primay result
     31for all operators.
     32*/
     33# define CPPAD_POW_FINAL_RESULT(address, op)  (address +  2)
    2134
    2235/*!
  • trunk/cppad/local/optimize.hpp

    r1535 r1580  
    265265                {
    266266                        // Unary operator where operand is arg[0]
     267                        case PowvpOp:
     268                        i_var = CPPAD_POW_FINAL_RESULT(i_var, op);
    267269                        case AbsOp:
    268270                        case AddvpOp:
     
    277279                        case LogOp:
    278280                        case MulvpOp:
    279                         case PowvpOp:
    280281                        case SinOp:
    281282                        case SinhOp:
     
    286287
    287288                        // Unary operator where operand is arg[1]
     289                        case PowpvOp:
     290                        i_var = CPPAD_POW_FINAL_RESULT(i_var, op);
    288291                        case AddpvOp:
    289292                        case DivpvOp:
    290293                        case MulpvOp:
    291                         case PowpvOp:
    292294                        case SubpvOp:
    293295                        case PrivOp:
     
    296298
    297299                        // Binary operator where operands are arg[0], arg[1]
     300                        case PowvvOp:
     301                        i_var = CPPAD_POW_FINAL_RESULT(i_var, op);
    298302                        case AddvvOp:
    299303                        case DivvvOp:
    300304                        case MulvvOp:
    301                         case PowvvOp:
    302305                        case SubvvOp:
    303306                        connected[ arg[0] ] |= connected[ i_var ];
     
    439442                        keep = vecad_connected[i];
    440443                        break;
     444
     445                        case PowpvOp:
     446                        case PowvpOp:
     447                        case PowvvOp:
     448                        i_var = CPPAD_POW_FINAL_RESULT(i_var, op);
    441449
    442450                        default:
     
    474482                        case DivvpOp:
    475483                        case MulvpOp:
    476                         case PowvpOp:
    477484                        case SubvpOp:
    478485                        CPPAD_ASSERT_NARG_NRES(op, 2, 1);
     
    485492                        break;
    486493
     494                        case PowvpOp:
     495                        CPPAD_ASSERT_NARG_NRES(op, 2, 3);
     496                        new_arg[0] = new_var[ arg[0] ];
     497                        new_arg[1] = rec->PutPar( play->GetPar( arg[1] ) );
     498                        CPPAD_ASSERT_UNKNOWN( new_arg[0] < num_var );
     499
     500                        rec->PutArg( new_arg[0], new_arg[1] );
     501                        new_var[ i_var ] = rec->PutOp(op);
     502                        new_var[ i_var ] =
     503                                CPPAD_POW_FINAL_RESULT(new_var[ i_var ], op);
     504                        break;
     505
    487506                        // Binary operators where left operand is a parameter
    488507                        // and right operand is a variable
     
    490509                        case DivpvOp:
    491510                        case MulpvOp:
    492                         case PowpvOp:
    493511                        case SubpvOp:
    494512                        CPPAD_ASSERT_NARG_NRES(op, 2, 1);
     
    501519                        break;
    502520
     521                        case PowpvOp:
     522                        CPPAD_ASSERT_NARG_NRES(op, 2, 3);
     523                        new_arg[0] = rec->PutPar( play->GetPar( arg[0] ) );
     524                        new_arg[1] = new_var[ arg[1] ];
     525                        CPPAD_ASSERT_UNKNOWN( new_arg[1] < num_var );
     526
     527                        rec->PutArg( new_arg[0], new_arg[1] );
     528                        new_var[ i_var ] = rec->PutOp(op);
     529                        new_var[ i_var ] =
     530                                CPPAD_POW_FINAL_RESULT(new_var[ i_var ], op);
     531                        break;
     532
    503533                        // Binary operator where both operators are variables
    504534                        case AddvvOp:
    505535                        case DivvvOp:
    506536                        case MulvvOp:
    507                         case PowvvOp:
    508537                        case SubvvOp:
    509538                        CPPAD_ASSERT_NARG_NRES(op, 2, 1);
     
    515544                        rec->PutArg( new_arg[0], new_arg[1] );
    516545                        new_var[ i_var ] = rec->PutOp(op);
     546                        break;
     547
     548                        case PowvvOp:
     549                        CPPAD_ASSERT_NARG_NRES(op, 2, 3);
     550                        new_arg[0] = new_var[ arg[0] ];
     551                        new_arg[1] = new_var[ arg[1] ];
     552                        CPPAD_ASSERT_UNKNOWN( new_arg[0] < num_var );
     553                        CPPAD_ASSERT_UNKNOWN( new_arg[1] < num_var );
     554
     555                        rec->PutArg( new_arg[0], new_arg[1] );
     556                        new_var[ i_var ] = rec->PutOp(op);
     557                        new_var[ i_var ] =
     558                                CPPAD_POW_FINAL_RESULT(new_var[ i_var ], op);
    517559                        break;
    518560
  • trunk/cppad/local/pow.hpp

    r1447 r1580  
    104104-------------------------------------------------------------------------------
    105105*/
    106 // The pow function is a special case where the final result is the last,
    107 // instead of the first, of the multiple variables created.
    108 # define CPPAD_POW_FINAL_RESULT(address, op)  address +=  2
    109106
    110107//  BEGIN CppAD namespace
     
    160157                        // put operator in the tape
    161158                        result.taddr_ = tape->Rec_.PutOp(PowvvOp);
    162                         CPPAD_POW_FINAL_RESULT(result.taddr_, PowvvOp);
     159                        result.taddr_ =
     160                                CPPAD_POW_FINAL_RESULT(result.taddr_, PowvvOp);
    163161
    164162                        // make result a variable
     
    179177                        // put operator in the tape
    180178                        result.taddr_ = tape->Rec_.PutOp(PowvpOp);
    181                         CPPAD_POW_FINAL_RESULT(result.taddr_, PowvpOp);
     179                        result.taddr_ =
     180                                CPPAD_POW_FINAL_RESULT(result.taddr_, PowvpOp);
    182181
    183182                        // make result a variable
     
    200199                        // put operator in the tape
    201200                        result.taddr_ = tape->Rec_.PutOp(PowpvOp);
    202                         CPPAD_POW_FINAL_RESULT(result.taddr_, PowpvOp);
     201                        result.taddr_ =
     202                                CPPAD_POW_FINAL_RESULT(result.taddr_, PowpvOp);
    203203
    204204                        // make result a variable
     
    293293} // END CppAD namespace
    294294
    295 # undef CPPAD_POW_FINAL_RESULT
    296295# endif
  • trunk/test_more/optimize.cpp

    r1553 r1580  
    198198                return ok;
    199199        }
     200        bool CaseThree(void)
     201        {       // Power function is a special case for optimize
     202                bool ok = true;
     203                using CppAD::AD;
     204                using CppAD::vector;
     205
     206                size_t n = 3;
     207                size_t j;
     208       
     209                vector< AD<double> >    X(n), Y(n);
     210                vector<double>          x(n), y(n);
     211       
     212                for(j = 0; j < n; j++)
     213                        X[j] = x[j] = double(j+1);
     214       
     215                CppAD::Independent(X);
     216                       
     217                Y[0] = pow(X[0], 2.0);
     218                Y[1] = pow(2.0, X[1]);
     219                Y[2] = pow(X[0], X[1]);
     220       
     221                CppAD::ADFun<double> F(X, Y);
     222                F.optimize();
     223                y = F.Forward(0, x);
     224
     225                // Use identically equal because the result of the operations
     226                // have been stored as double and gaurd bits have been dropped.
     227                // (This may not be true for some compiler in the future).
     228                for(j = 0; j < n; j++)
     229                        ok &= ( y[j] == Value(Y[j]) );
     230       
     231                return ok;
     232        }
    200233}
    201234
    202235bool optimize(void)
    203236{       bool ok = true;
     237# if 0
    204238        ok     &= CaseOne();
    205239        ok     &= CaseTwo();
     240# endif
     241        ok     &= CaseThree();
    206242
    207243        return ok;
Note: See TracChangeset for help on using the changeset viewer.