00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00035 #include <acado/utils/acado_utils.hpp>
00036 #include <acado/symbolic_operator/symbolic_operator.hpp>
00037
00038
00039
00040 BEGIN_NAMESPACE_ACADO
00041
00042
00043
00044
00045 Product::Product():BinaryOperator(){ }
00046
00047 Product::Product( Operator *_argument1, Operator *_argument2 )
00048 :BinaryOperator( _argument1, _argument2 ){
00049
00050 }
00051
00052
00053 Product::Product( const Product &arg ):BinaryOperator( arg ){
00054
00055 }
00056
00057
00058 Product::~Product(){
00059
00060 }
00061
00062 Product& Product::operator=( const Product &arg ){
00063
00064 if( this != &arg ){
00065
00066 BinaryOperator::operator=( arg );
00067 }
00068
00069 return *this;
00070 }
00071
00072
00073
00074 returnValue Product::evaluate( int number, double *x, double *result ){
00075
00076 if( number >= bufferSize ){
00077 bufferSize += number;
00078 argument1_result = (double*)realloc( argument1_result,bufferSize*sizeof(double));
00079 argument2_result = (double*)realloc( argument2_result,bufferSize*sizeof(double));
00080 dargument1_result = (double*)realloc(dargument1_result,bufferSize*sizeof(double));
00081 dargument2_result = (double*)realloc(dargument2_result,bufferSize*sizeof(double));
00082 }
00083
00084 argument1->evaluate( number, x , &argument1_result[number] );
00085 argument2->evaluate( number, x , &argument2_result[number] );
00086
00087 result[0] = argument1_result[number] * argument2_result[number];
00088
00089 return SUCCESSFUL_RETURN;
00090 }
00091
00092
00093 returnValue Product::evaluate( EvaluationBase *x ){
00094
00095 x->product(*argument1,*argument2);
00096 return SUCCESSFUL_RETURN;
00097 }
00098
00099
00100 Operator* Product::differentiate( int index ){
00101
00102 dargument1 = argument1->differentiate( index );
00103 dargument2 = argument2->differentiate( index );
00104
00105 Operator *prodTmp1 = myProd(dargument1, argument2);
00106 Operator *prodTmp2 = myProd(argument1, dargument2);
00107 Operator *result = myAdd(prodTmp1, prodTmp2);
00108
00109 delete prodTmp1;
00110 delete prodTmp2;
00111
00112 return result;
00113 }
00114
00115
00116 Operator* Product::AD_forward( int dim,
00117 VariableType *varType,
00118 int *component,
00119 Operator **seed,
00120 int &nNewIS,
00121 TreeProjection ***newIS ){
00122
00123 if( dargument1 != 0 )
00124 delete dargument1;
00125
00126 if( dargument2 != 0 )
00127 delete dargument2;
00128
00129 dargument1 = argument1->AD_forward(dim,varType,component,seed,nNewIS,newIS);
00130 dargument2 = argument2->AD_forward(dim,varType,component,seed,nNewIS,newIS);
00131
00132 Operator *prodTmp1 = myProd(dargument1, argument2);
00133 Operator *prodTmp2 = myProd(argument1, dargument2);
00134 Operator *result = myAdd(prodTmp1, prodTmp2);
00135
00136 delete prodTmp1;
00137 delete prodTmp2;
00138
00139 return result;
00140 }
00141
00142
00143 returnValue Product::AD_backward( int dim ,
00144 VariableType *varType ,
00145 int *component,
00146 Operator *seed ,
00147 Operator **df ,
00148 int &nNewIS ,
00149 TreeProjection ***newIS ){
00150
00151
00152 if( seed->isOneOrZero() != NE_ZERO ){
00153
00154 TreeProjection tmp;
00155 tmp = *seed;
00156
00157 Operator *prodTmp1 = myProd(argument2, &tmp);
00158
00159 argument1->AD_backward( dim, varType, component,
00160 prodTmp1->clone(),
00161 df, nNewIS, newIS );
00162
00163 Operator *prodTmp2 = myProd(argument1, &tmp);
00164
00165 argument2->AD_backward( dim, varType, component,
00166 prodTmp2->clone(),
00167 df, nNewIS, newIS );
00168
00169 delete prodTmp1;
00170 delete prodTmp2;
00171 }
00172
00173 delete seed;
00174 return SUCCESSFUL_RETURN;
00175 }
00176
00177
00178 returnValue Product::AD_symmetric( int dim ,
00179 VariableType *varType ,
00180 int *component ,
00181 Operator *l ,
00182 Operator **S ,
00183 int dimS ,
00184 Operator **dfS ,
00185 Operator **ldf ,
00186 Operator **H ,
00187 int &nNewLIS ,
00188 TreeProjection ***newLIS ,
00189 int &nNewSIS ,
00190 TreeProjection ***newSIS ,
00191 int &nNewHIS ,
00192 TreeProjection ***newHIS ){
00193
00194 TreeProjection dx,dy,dxx,dxy,dyy;
00195
00196 dx = *argument2;
00197 dy = *argument1;
00198 dxx = DoubleConstant(0.0,NE_ZERO);
00199 dxy = DoubleConstant(1.0,NE_ONE );
00200 dyy = DoubleConstant(0.0,NE_ZERO);
00201
00202 return ADsymCommon2( argument1,argument2,dx,dy,dxx,dxy,dyy, dim, varType, component, l, S, dimS, dfS,
00203 ldf, H, nNewLIS, newLIS, nNewSIS, newSIS, nNewHIS, newHIS );
00204 }
00205
00206
00207
00208
00209 Operator* Product::substitute( int index, const Operator *sub ){
00210
00211 return new Product( argument1->substitute( index , sub ),
00212 argument2->substitute( index , sub ) );
00213
00214 }
00215
00216
00217 BooleanType Product::isLinearIn( int dim,
00218 VariableType *varType,
00219 int *component,
00220 BooleanType *implicit_dep ){
00221
00222 if( argument1->isLinearIn( dim, varType, component, implicit_dep ) == BT_TRUE &&
00223 argument2->isDependingOn( dim, varType, component, implicit_dep ) == BT_FALSE ){
00224 return BT_TRUE;
00225 }
00226
00227 if( argument2->isLinearIn( dim, varType, component, implicit_dep ) == BT_TRUE &&
00228 argument1->isDependingOn( dim, varType, component, implicit_dep ) == BT_FALSE ){
00229 return BT_TRUE;
00230 }
00231
00232 return BT_FALSE;
00233 }
00234
00235
00236 BooleanType Product::isPolynomialIn( int dim,
00237 VariableType *varType,
00238 int *component,
00239 BooleanType *implicit_dep ){
00240
00241 if( argument1->isPolynomialIn( dim, varType, component, implicit_dep ) == BT_TRUE &&
00242 argument2->isPolynomialIn( dim, varType, component, implicit_dep ) == BT_TRUE ){
00243 return BT_TRUE;
00244 }
00245
00246 return BT_FALSE;
00247 }
00248
00249
00250 BooleanType Product::isRationalIn( int dim,
00251 VariableType *varType,
00252 int *component,
00253 BooleanType *implicit_dep ){
00254
00255 if( argument1->isRationalIn( dim, varType, component, implicit_dep ) == BT_TRUE &&
00256 argument2->isRationalIn( dim, varType, component, implicit_dep ) == BT_TRUE ){
00257 return BT_TRUE;
00258 }
00259
00260 return BT_FALSE;
00261 }
00262
00263
00264 MonotonicityType Product::getMonotonicity( ){
00265
00266 if( monotonicity != MT_UNKNOWN ) return monotonicity;
00267
00268 MonotonicityType m1, m2;
00269
00270 m1 = argument1->getMonotonicity();
00271 m2 = argument2->getMonotonicity();
00272
00273 if( m1 == MT_CONSTANT ){
00274
00275 if( m2 == MT_CONSTANT ) return MT_CONSTANT;
00276
00277 double res;
00278 argument1->evaluate(0,0,&res);
00279
00280 if( res >= 0.0 ) return m2;
00281
00282 if( m2 == MT_NONDECREASING ) return MT_NONINCREASING;
00283 if( m2 == MT_NONINCREASING ) return MT_NONDECREASING;
00284
00285 return MT_NONMONOTONIC;
00286 }
00287
00288 if( m2 == MT_CONSTANT ){
00289
00290 double res;
00291 argument2->evaluate(0,0,&res);
00292
00293 if( res >= 0.0 ) return m1;
00294
00295 if( m1 == MT_NONDECREASING ) return MT_NONINCREASING;
00296 if( m1 == MT_NONINCREASING ) return MT_NONDECREASING;
00297
00298 return MT_NONMONOTONIC;
00299 }
00300
00301 return MT_NONMONOTONIC;
00302 }
00303
00304
00305 CurvatureType Product::getCurvature( ){
00306
00307 if( curvature != CT_UNKNOWN ) return curvature;
00308
00309 CurvatureType c1, c2;
00310
00311 c1 = argument1->getCurvature();
00312 c2 = argument2->getCurvature();
00313
00314 if( c1 == CT_CONSTANT ){
00315
00316 if( c2 == CT_CONSTANT ) return CT_CONSTANT;
00317
00318 double res;
00319 argument1->evaluate(0,0,&res);
00320
00321 if( res >= 0.0 ) return c2;
00322
00323 if( c2 == CT_AFFINE ) return CT_AFFINE ;
00324 if( c2 == CT_CONVEX ) return CT_CONCAVE;
00325 if( c2 == CT_CONCAVE ) return CT_CONVEX ;
00326
00327 return CT_NEITHER_CONVEX_NOR_CONCAVE;
00328 }
00329
00330 if( c2 == CT_CONSTANT ){
00331
00332 if( c1 == CT_CONSTANT ) return CT_CONSTANT;
00333
00334 double res;
00335 argument2->evaluate(0,0,&res);
00336
00337 if( res >= 0.0 ) return c1;
00338
00339 if( c1 == CT_AFFINE ) return CT_AFFINE ;
00340 if( c1 == CT_CONVEX ) return CT_CONCAVE;
00341 if( c1 == CT_CONCAVE ) return CT_CONVEX ;
00342
00343 return CT_NEITHER_CONVEX_NOR_CONCAVE;
00344 }
00345
00346 return CT_NEITHER_CONVEX_NOR_CONCAVE;
00347 }
00348
00349
00350 double Product::getValue() const
00351 {
00352 if ( ( argument1 == 0 ) || ( argument2 == 0 ) )
00353 return INFTY;
00354
00355 if ( ( acadoIsEqual( argument1->getValue(),INFTY ) == BT_TRUE ) ||
00356 ( acadoIsEqual( argument2->getValue(),INFTY ) == BT_TRUE ) )
00357 return INFTY;
00358
00359 return (argument1->getValue() * argument2->getValue());
00360 }
00361
00362
00363 returnValue Product::AD_forward( int number, double *x, double *seed,
00364 double *f, double *df ){
00365
00366 if( number >= bufferSize ){
00367 bufferSize += number;
00368 argument1_result = (double*)realloc( argument1_result,bufferSize*sizeof(double));
00369 argument2_result = (double*)realloc( argument2_result,bufferSize*sizeof(double));
00370 dargument1_result = (double*)realloc(dargument1_result,bufferSize*sizeof(double));
00371 dargument2_result = (double*)realloc(dargument2_result,bufferSize*sizeof(double));
00372 }
00373
00374 argument1->AD_forward( number, x, seed, &argument1_result[number],
00375 &dargument1_result[number] );
00376 argument2->AD_forward( number,
00377 x, seed, &argument2_result[number], &dargument2_result[number] );
00378
00379 f[0] = argument1_result[number]*argument2_result[number];
00380 df[0] = argument2_result[number]*dargument1_result[number] +
00381 argument1_result[number]*dargument2_result[number];
00382
00383 return SUCCESSFUL_RETURN;
00384 }
00385
00386
00387
00388 returnValue Product::AD_forward( int number, double *seed, double *df ){
00389
00390 argument1->AD_forward( number, seed, &dargument1_result[number] );
00391 argument2->AD_forward( number, seed, &dargument2_result[number] );
00392
00393 df[0] = argument2_result[number]*dargument1_result[number] +
00394 argument1_result[number]*dargument2_result[number];
00395
00396 return SUCCESSFUL_RETURN;
00397 }
00398
00399
00400 returnValue Product::AD_backward( int number, double seed, double *df ){
00401
00402 argument1->AD_backward( number, argument2_result[number]*seed, df );
00403 argument2->AD_backward( number, argument1_result[number]*seed, df );
00404
00405 return SUCCESSFUL_RETURN;
00406 }
00407
00408
00409 returnValue Product::AD_forward2( int number, double *seed, double *dseed,
00410 double *df, double *ddf ){
00411
00412 double ddargument1_result;
00413 double ddargument2_result;
00414 double dargument_result1 ;
00415 double dargument_result2 ;
00416
00417 argument1->AD_forward2( number, seed, dseed,
00418 &dargument_result1, &ddargument1_result);
00419 argument2->AD_forward2( number, seed, dseed,
00420 &dargument_result2, &ddargument2_result);
00421
00422 df[0] = argument2_result[number]*dargument_result1
00423 +argument1_result[number]*dargument_result2;
00424 ddf[0] = argument2_result[number]*ddargument1_result
00425 +argument1_result[number]*ddargument2_result
00426 +dargument_result1*dargument2_result[number]
00427 +dargument_result2*dargument1_result[number];
00428
00429 return SUCCESSFUL_RETURN;
00430 }
00431
00432
00433 returnValue Product::AD_backward2( int number, double seed1, double seed2,
00434 double *df, double *ddf ){
00435
00436 argument1->AD_backward2( number,
00437 seed1*argument2_result[number],
00438 seed2*argument2_result[number] +
00439 seed1*dargument2_result[number],
00440 df, ddf );
00441
00442 argument2->AD_backward2( number,
00443 seed1*argument1_result[number],
00444 seed2*argument1_result[number] +
00445 seed1*dargument1_result[number] ,
00446 df, ddf );
00447
00448 return SUCCESSFUL_RETURN;
00449 }
00450
00451
00452
00453 std::ostream& Product::print( std::ostream &stream ) const{
00454
00455 if ( ( acadoIsFinite( argument1->getValue() ) == BT_FALSE ) ||
00456 ( acadoIsFinite( argument2->getValue() ) == BT_FALSE ) )
00457 {
00458 return (((((stream << "(") << *argument1) << "*") << *argument2) << ")");
00459 }
00460 else
00461 {
00462 return stream << "((real_t)(" << ((argument1->getValue()) * (argument2->getValue())) << "))";
00463 }
00464 }
00465
00466
00467 Operator* Product::clone() const{
00468
00469 return new Product(*this);
00470
00471 }
00472
00473
00474
00475
00476
00477
00478 OperatorName Product::getName(){
00479
00480 return ON_PRODUCT;
00481 }
00482
00483
00484
00485 CLOSE_NAMESPACE_ACADO
00486
00487