1 // Copyright (C) 2005, 2006 International Business Machines and others. 2 // All Rights Reserved. 3 // This code is published under the Common Public License. 4 // 5 // $Id: IpNLPScaling.cpp 759 2006-07-07 03:07:08Z andreasw $ 6 // 7 // Authors: Carl Laird, Andreas Waechter IBM 2005-06-25 8 9 #include "IpNLPScaling.hpp" 10 11 namespace SimTKIpopt 12 { 13 14 #ifdef IP_DEBUG 15 static const Index dbg_verbosity = 0; 16 #endif 17 apply_vector_scaling_x_LU_NonConst(const Matrix & Px_LU,const SmartPtr<const Vector> & lu,const VectorSpace & x_space)18 SmartPtr<Vector> NLPScalingObject::apply_vector_scaling_x_LU_NonConst( 19 const Matrix& Px_LU, 20 const SmartPtr<const Vector>& lu, 21 const VectorSpace& x_space) 22 { 23 SmartPtr<Vector> scaled_x_LU = lu->MakeNew(); 24 if (have_x_scaling()) { 25 SmartPtr<Vector> tmp_x = x_space.MakeNew(); 26 27 // move to full x space 28 Px_LU.MultVector(1.0, *lu, 0.0, *tmp_x); 29 30 // scale in full x space 31 tmp_x = apply_vector_scaling_x_NonConst(ConstPtr(tmp_x)); 32 33 // move back to x_L space 34 Px_LU.TransMultVector(1.0, *tmp_x, 0.0, *scaled_x_LU); 35 } 36 else { 37 scaled_x_LU->Copy(*lu); 38 } 39 40 return scaled_x_LU; 41 } 42 apply_vector_scaling_x_LU(const Matrix & Px_LU,const SmartPtr<const Vector> & lu,const VectorSpace & x_space)43 SmartPtr<const Vector> NLPScalingObject::apply_vector_scaling_x_LU( 44 const Matrix& Px_LU, 45 const SmartPtr<const Vector>& lu, 46 const VectorSpace& x_space) 47 { 48 if (have_x_scaling()) { 49 return ConstPtr(apply_vector_scaling_x_LU_NonConst(Px_LU, lu, x_space)); 50 } 51 else { 52 return lu; 53 } 54 } 55 apply_vector_scaling_d_LU_NonConst(const Matrix & Pd_LU,const SmartPtr<const Vector> & lu,const VectorSpace & d_space)56 SmartPtr<Vector> NLPScalingObject::apply_vector_scaling_d_LU_NonConst( 57 const Matrix& Pd_LU, 58 const SmartPtr<const Vector>& lu, 59 const VectorSpace& d_space) 60 { 61 SmartPtr<Vector> scaled_d_LU = lu->MakeNew(); 62 if (have_d_scaling()) { 63 SmartPtr<Vector> tmp_d = d_space.MakeNew(); 64 65 // move to full d space 66 Pd_LU.MultVector(1.0, *lu, 0.0, *tmp_d); 67 68 // scale in full x space 69 tmp_d = apply_vector_scaling_d_NonConst(ConstPtr(tmp_d)); 70 71 // move back to x_L space 72 Pd_LU.TransMultVector(1.0, *tmp_d, 0.0, *scaled_d_LU); 73 } 74 else { 75 scaled_d_LU->Copy(*lu); 76 } 77 78 return scaled_d_LU; 79 } 80 apply_vector_scaling_d_LU(const Matrix & Pd_LU,const SmartPtr<const Vector> & lu,const VectorSpace & d_space)81 SmartPtr<const Vector> NLPScalingObject::apply_vector_scaling_d_LU( 82 const Matrix& Pd_LU, 83 const SmartPtr<const Vector>& lu, 84 const VectorSpace& d_space) 85 { 86 if (have_d_scaling()) { 87 return ConstPtr(apply_vector_scaling_d_LU_NonConst(Pd_LU, lu, d_space)); 88 } 89 else { 90 return lu; 91 } 92 } 93 unapply_vector_scaling_d_LU_NonConst(const Matrix & Pd_LU,const SmartPtr<const Vector> & lu,const VectorSpace & d_space)94 SmartPtr<Vector> NLPScalingObject::unapply_vector_scaling_d_LU_NonConst( 95 const Matrix& Pd_LU, 96 const SmartPtr<const Vector>& lu, 97 const VectorSpace& d_space) 98 { 99 SmartPtr<Vector> unscaled_d_LU = lu->MakeNew(); 100 if (have_d_scaling()) { 101 SmartPtr<Vector> tmp_d = d_space.MakeNew(); 102 103 // move to full d space 104 Pd_LU.MultVector(1.0, *lu, 0.0, *tmp_d); 105 106 // scale in full x space 107 tmp_d = unapply_vector_scaling_d_NonConst(ConstPtr(tmp_d)); 108 109 // move back to x_L space 110 Pd_LU.TransMultVector(1.0, *tmp_d, 0.0, *unscaled_d_LU); 111 } 112 else { 113 unscaled_d_LU->Copy(*lu); 114 } 115 116 return unscaled_d_LU; 117 } 118 unapply_vector_scaling_d_LU(const Matrix & Pd_LU,const SmartPtr<const Vector> & lu,const VectorSpace & d_space)119 SmartPtr<const Vector> NLPScalingObject::unapply_vector_scaling_d_LU( 120 const Matrix& Pd_LU, 121 const SmartPtr<const Vector>& lu, 122 const VectorSpace& d_space) 123 { 124 if (have_d_scaling()) { 125 return ConstPtr(unapply_vector_scaling_d_LU_NonConst(Pd_LU, lu, d_space)); 126 } 127 else { 128 return lu; 129 } 130 } 131 apply_grad_obj_scaling_NonConst(const SmartPtr<const Vector> & v)132 SmartPtr<Vector> NLPScalingObject::apply_grad_obj_scaling_NonConst( 133 const SmartPtr<const Vector>& v) 134 { 135 SmartPtr<Vector> scaled_v = unapply_vector_scaling_x_NonConst(v); 136 Number df = apply_obj_scaling(1.0); 137 if (df != 1.) { 138 scaled_v->Scal(df); 139 } 140 return scaled_v; 141 } 142 apply_grad_obj_scaling(const SmartPtr<const Vector> & v)143 SmartPtr<const Vector> NLPScalingObject::apply_grad_obj_scaling( 144 const SmartPtr<const Vector>& v) 145 { 146 Number df = apply_obj_scaling(1.); 147 if (df != 1.) { 148 SmartPtr<Vector> scaled_v = apply_grad_obj_scaling_NonConst(v); 149 return ConstPtr(scaled_v); 150 } 151 else { 152 SmartPtr<const Vector> scaled_v = unapply_vector_scaling_x(v); 153 return scaled_v; 154 } 155 } 156 unapply_grad_obj_scaling_NonConst(const SmartPtr<const Vector> & v)157 SmartPtr<Vector> NLPScalingObject::unapply_grad_obj_scaling_NonConst( 158 const SmartPtr<const Vector>& v) 159 { 160 SmartPtr<Vector> unscaled_v = apply_vector_scaling_x_NonConst(v); 161 Number df = unapply_obj_scaling(1.); 162 if (df != 1.) { 163 unscaled_v->Scal(df); 164 } 165 return unscaled_v; 166 } 167 unapply_grad_obj_scaling(const SmartPtr<const Vector> & v)168 SmartPtr<const Vector> NLPScalingObject::unapply_grad_obj_scaling( 169 const SmartPtr<const Vector>& v) 170 { 171 Number df = unapply_obj_scaling(1.); 172 if (df != 1.) { 173 SmartPtr<Vector> unscaled_v = unapply_grad_obj_scaling_NonConst(v); 174 return ConstPtr(unscaled_v); 175 } 176 else { 177 SmartPtr<const Vector> scaled_v = apply_vector_scaling_x(v); 178 return scaled_v; 179 } 180 } 181 182 void RegisterOptions(SmartPtr<RegisteredOptions> roptions)183 StandardScalingBase::RegisterOptions(SmartPtr<RegisteredOptions> roptions) 184 { 185 roptions->AddNumberOption( 186 "obj_scaling_factor", 187 "Scaling factor for the objective function.", 188 1., 189 "This option sets a scaling factor for the objective function. " 190 "The scaling is seen internally by Ipopt but the unscaled objective is " 191 "reported in the console output. " 192 "If additional scaling parameters are computed " 193 "(e.g. user-scaling or gradient-based), both factors are multiplied. " 194 "If this value is chosen to be negative, Ipopt will " 195 "maximize the objective function instead of minimizing it."); 196 } 197 InitializeImpl(const OptionsList & options,const std::string & prefix)198 bool StandardScalingBase::InitializeImpl(const OptionsList& options, 199 const std::string& prefix) 200 { 201 options.GetNumericValue("obj_scaling_factor", obj_scaling_factor_, prefix); 202 return true; 203 } 204 DetermineScaling(const SmartPtr<const VectorSpace> x_space,const SmartPtr<const VectorSpace> c_space,const SmartPtr<const VectorSpace> d_space,const SmartPtr<const MatrixSpace> jac_c_space,const SmartPtr<const MatrixSpace> jac_d_space,const SmartPtr<const SymMatrixSpace> h_space,SmartPtr<const MatrixSpace> & new_jac_c_space,SmartPtr<const MatrixSpace> & new_jac_d_space,SmartPtr<const SymMatrixSpace> & new_h_space)205 void StandardScalingBase::DetermineScaling( 206 const SmartPtr<const VectorSpace> x_space, 207 const SmartPtr<const VectorSpace> c_space, 208 const SmartPtr<const VectorSpace> d_space, 209 const SmartPtr<const MatrixSpace> jac_c_space, 210 const SmartPtr<const MatrixSpace> jac_d_space, 211 const SmartPtr<const SymMatrixSpace> h_space, 212 SmartPtr<const MatrixSpace>& new_jac_c_space, 213 SmartPtr<const MatrixSpace>& new_jac_d_space, 214 SmartPtr<const SymMatrixSpace>& new_h_space) 215 { 216 SmartPtr<Vector> dc; 217 SmartPtr<Vector> dd; 218 DetermineScalingParametersImpl(x_space, c_space, d_space, 219 jac_c_space, jac_d_space, 220 h_space, df_, dx_, dc, dd); 221 222 df_ *= obj_scaling_factor_; 223 224 if (Jnlst().ProduceOutput(J_VECTOR, J_MAIN)) { 225 Jnlst().Printf(J_VECTOR, J_MAIN, "objective scaling factor = %g\n", df_); 226 if (IsValid(dx_)) { 227 dx_->Print(Jnlst(), J_VECTOR, J_MAIN, "x scaling vector"); 228 } 229 else { 230 Jnlst().Printf(J_VECTOR, J_MAIN, "No x scaling provided\n"); 231 } 232 if (IsValid(dc)) { 233 dc->Print(Jnlst(), J_VECTOR, J_MAIN, "c scaling vector"); 234 } 235 else { 236 Jnlst().Printf(J_VECTOR, J_MAIN, "No c scaling provided\n"); 237 } 238 if (IsValid(dd)) { 239 dd->Print(Jnlst(), J_VECTOR, J_MAIN, "d scaling vector"); 240 } 241 else { 242 Jnlst().Printf(J_VECTOR, J_MAIN, "No d scaling provided\n"); 243 } 244 } 245 246 // create the scaling matrix spaces 247 if (IsValid(dx_) || IsValid(dc)) { 248 scaled_jac_c_space_ = 249 new ScaledMatrixSpace(ConstPtr(dc), false, jac_c_space, 250 ConstPtr(dx_), true); 251 new_jac_c_space = GetRawPtr(scaled_jac_c_space_); 252 } 253 else { 254 scaled_jac_c_space_ = NULL; 255 new_jac_c_space = jac_c_space; 256 } 257 258 if (IsValid(dx_) || IsValid(dc)) { 259 scaled_jac_d_space_ = 260 new ScaledMatrixSpace(ConstPtr(dd), false, jac_d_space, 261 ConstPtr(dx_), true); 262 new_jac_d_space = GetRawPtr(scaled_jac_d_space_); 263 } 264 else { 265 scaled_jac_d_space_ = NULL; 266 new_jac_d_space =jac_d_space ; 267 } 268 269 if (IsValid(h_space)) { 270 if (IsValid(dx_)) { 271 scaled_h_space_ = new SymScaledMatrixSpace(ConstPtr(dx_), true, h_space); 272 new_h_space = GetRawPtr(scaled_h_space_); 273 } 274 else { 275 scaled_h_space_ = NULL; 276 new_h_space = h_space; 277 } 278 } 279 else { 280 new_h_space = NULL; 281 } 282 } 283 apply_obj_scaling(const Number & f)284 Number StandardScalingBase::apply_obj_scaling(const Number& f) 285 { 286 return df_*f; 287 } 288 unapply_obj_scaling(const Number & f)289 Number StandardScalingBase::unapply_obj_scaling(const Number& f) 290 { 291 return f/df_; 292 } 293 apply_vector_scaling_x_NonConst(const SmartPtr<const Vector> & v)294 SmartPtr<Vector> StandardScalingBase::apply_vector_scaling_x_NonConst( 295 const SmartPtr<const Vector>& v) 296 { 297 DBG_START_METH("StandardScalingBase::apply_vector_scaling_x_NonConst", 298 dbg_verbosity); 299 SmartPtr<Vector> scaled_x = v->MakeNewCopy(); 300 if (IsValid(dx_)) { 301 scaled_x->ElementWiseMultiply(*dx_); 302 } 303 else { 304 DBG_PRINT((1, "Creating copy in apply_vector_scaling_x_NonConst!")); 305 } 306 return scaled_x; 307 } 308 apply_vector_scaling_x(const SmartPtr<const Vector> & v)309 SmartPtr<const Vector> StandardScalingBase::apply_vector_scaling_x( 310 const SmartPtr<const Vector>& v) 311 { 312 if (IsValid(dx_)) { 313 return ConstPtr(apply_vector_scaling_x_NonConst(v)); 314 } 315 else { 316 return v; 317 } 318 } 319 unapply_vector_scaling_x_NonConst(const SmartPtr<const Vector> & v)320 SmartPtr<Vector> StandardScalingBase::unapply_vector_scaling_x_NonConst( 321 const SmartPtr<const Vector>& v) 322 { 323 DBG_START_METH("StandardScalingBase::unapply_vector_scaling_x_NonConst", 324 dbg_verbosity); 325 SmartPtr<Vector> unscaled_x = v->MakeNewCopy(); 326 if (IsValid(dx_)) { 327 unscaled_x->ElementWiseDivide(*dx_); 328 } 329 else { 330 DBG_PRINT((1, "Creating copy in unapply_vector_scaling_x_NonConst!")); 331 } 332 return unscaled_x; 333 } 334 unapply_vector_scaling_x(const SmartPtr<const Vector> & v)335 SmartPtr<const Vector> StandardScalingBase::unapply_vector_scaling_x( 336 const SmartPtr<const Vector>& v) 337 { 338 if (IsValid(dx_)) { 339 return ConstPtr(unapply_vector_scaling_x_NonConst(v)); 340 } 341 else { 342 return v; 343 } 344 } 345 apply_vector_scaling_c_NonConst(const SmartPtr<const Vector> & v)346 SmartPtr<Vector> StandardScalingBase::apply_vector_scaling_c_NonConst( 347 const SmartPtr<const Vector>& v) 348 { 349 DBG_START_METH("StandardScalingBase::apply_vector_scaling_c_NonConst", 350 dbg_verbosity); 351 SmartPtr<Vector> scaled_c = v->MakeNewCopy(); 352 if (IsValid(scaled_jac_c_space_) && 353 IsValid(scaled_jac_c_space_->RowScaling())) { 354 scaled_c->ElementWiseMultiply(*scaled_jac_c_space_->RowScaling()); 355 } 356 else { 357 DBG_PRINT((1,"Creating copy in apply_vector_scaling_c_NonConst!")); 358 } 359 return scaled_c; 360 } 361 apply_vector_scaling_c(const SmartPtr<const Vector> & v)362 SmartPtr<const Vector> StandardScalingBase::apply_vector_scaling_c( 363 const SmartPtr<const Vector>& v) 364 { 365 if (IsValid(scaled_jac_c_space_) && 366 IsValid(scaled_jac_c_space_->RowScaling())) { 367 return ConstPtr(apply_vector_scaling_c_NonConst(v)); 368 } 369 else { 370 return v; 371 } 372 } 373 unapply_vector_scaling_c_NonConst(const SmartPtr<const Vector> & v)374 SmartPtr<Vector> StandardScalingBase::unapply_vector_scaling_c_NonConst( 375 const SmartPtr<const Vector>& v) 376 { 377 DBG_START_METH("StandardScalingBase::unapply_vector_scaling_c_NonConst", 378 dbg_verbosity); 379 SmartPtr<Vector> scaled_c = v->MakeNewCopy(); 380 if (IsValid(scaled_jac_c_space_) && 381 IsValid(scaled_jac_c_space_->RowScaling())) { 382 scaled_c->ElementWiseDivide(*scaled_jac_c_space_->RowScaling()); 383 } 384 else { 385 DBG_PRINT((1,"Creating copy in unapply_vector_scaling_c_NonConst!")); 386 } 387 return scaled_c; 388 } 389 unapply_vector_scaling_c(const SmartPtr<const Vector> & v)390 SmartPtr<const Vector> StandardScalingBase::unapply_vector_scaling_c( 391 const SmartPtr<const Vector>& v) 392 { 393 if (IsValid(scaled_jac_c_space_) && 394 IsValid(scaled_jac_c_space_->RowScaling())) { 395 return ConstPtr(unapply_vector_scaling_c_NonConst(v)); 396 } 397 else { 398 return v; 399 } 400 } 401 apply_vector_scaling_d_NonConst(const SmartPtr<const Vector> & v)402 SmartPtr<Vector> StandardScalingBase::apply_vector_scaling_d_NonConst( 403 const SmartPtr<const Vector>& v) 404 { 405 DBG_START_METH("StandardScalingBase::apply_vector_scaling_d_NonConst", 406 dbg_verbosity); 407 SmartPtr<Vector> scaled_d = v->MakeNewCopy(); 408 if (IsValid(scaled_jac_d_space_) && 409 IsValid(scaled_jac_d_space_->RowScaling())) { 410 scaled_d->ElementWiseMultiply(*scaled_jac_d_space_->RowScaling()); 411 } 412 else { 413 DBG_PRINT((1,"Creating copy in apply_vector_scaling_d_NonConst!")); 414 } 415 return scaled_d; 416 } 417 apply_vector_scaling_d(const SmartPtr<const Vector> & v)418 SmartPtr<const Vector> StandardScalingBase::apply_vector_scaling_d( 419 const SmartPtr<const Vector>& v) 420 { 421 if (IsValid(scaled_jac_d_space_) && 422 IsValid(scaled_jac_d_space_->RowScaling())) { 423 return ConstPtr(apply_vector_scaling_d_NonConst(v)); 424 } 425 else { 426 return v; 427 } 428 } 429 unapply_vector_scaling_d_NonConst(const SmartPtr<const Vector> & v)430 SmartPtr<Vector> StandardScalingBase::unapply_vector_scaling_d_NonConst( 431 const SmartPtr<const Vector>& v) 432 { 433 DBG_START_METH("StandardScalingBase::unapply_vector_scaling_d_NonConst", 434 dbg_verbosity); 435 SmartPtr<Vector> scaled_d = v->MakeNewCopy(); 436 if (IsValid(scaled_jac_d_space_) && 437 IsValid(scaled_jac_d_space_->RowScaling())) { 438 scaled_d->ElementWiseDivide(*scaled_jac_d_space_->RowScaling()); 439 } 440 else { 441 DBG_PRINT((1,"Creating copy in unapply_vector_scaling_d_NonConst!")); 442 } 443 return scaled_d; 444 } 445 unapply_vector_scaling_d(const SmartPtr<const Vector> & v)446 SmartPtr<const Vector> StandardScalingBase::unapply_vector_scaling_d( 447 const SmartPtr<const Vector>& v) 448 { 449 if (IsValid(scaled_jac_d_space_) && 450 IsValid(scaled_jac_d_space_->RowScaling())) { 451 return ConstPtr(unapply_vector_scaling_d_NonConst(v)); 452 } 453 else { 454 return v; 455 } 456 } 457 458 // ToDo: matrix not passed by reference, so setting to NULL doesn't make difference apply_jac_c_scaling(SmartPtr<const Matrix> matrix)459 SmartPtr<const Matrix> StandardScalingBase::apply_jac_c_scaling( 460 SmartPtr<const Matrix> matrix) 461 { 462 if (IsValid(scaled_jac_c_space_)) { 463 SmartPtr<ScaledMatrix> ret = scaled_jac_c_space_->MakeNewScaledMatrix(false); 464 ret->SetUnscaledMatrix(matrix); 465 return GetRawPtr(ret); 466 } 467 else { 468 SmartPtr<const Matrix> ret = matrix; 469 matrix = NULL; 470 return ret; 471 } 472 } 473 apply_jac_d_scaling(SmartPtr<const Matrix> matrix)474 SmartPtr<const Matrix> StandardScalingBase::apply_jac_d_scaling( 475 SmartPtr<const Matrix> matrix) 476 { 477 if (IsValid(scaled_jac_d_space_)) { 478 SmartPtr<ScaledMatrix> ret = scaled_jac_d_space_->MakeNewScaledMatrix(false); 479 ret->SetUnscaledMatrix(matrix); 480 return GetRawPtr(ret); 481 } 482 else { 483 SmartPtr<const Matrix> ret = matrix; 484 matrix = NULL; 485 return ret; 486 } 487 } 488 apply_hessian_scaling(SmartPtr<const SymMatrix> matrix)489 SmartPtr<const SymMatrix> StandardScalingBase::apply_hessian_scaling( 490 SmartPtr<const SymMatrix> matrix) 491 { 492 if (IsValid(scaled_h_space_)) { 493 SmartPtr<SymScaledMatrix> ret = scaled_h_space_->MakeNewSymScaledMatrix(false); 494 ret->SetUnscaledMatrix(matrix); 495 return GetRawPtr(ret); 496 } 497 else { 498 SmartPtr<const SymMatrix> ret = matrix; 499 matrix = NULL; 500 return ret; 501 } 502 } 503 have_x_scaling()504 bool StandardScalingBase::have_x_scaling() 505 { 506 return IsValid(dx_); 507 } 508 have_c_scaling()509 bool StandardScalingBase::have_c_scaling() 510 { 511 return (IsValid(scaled_jac_c_space_) && 512 IsValid(scaled_jac_c_space_->RowScaling())); 513 } 514 have_d_scaling()515 bool StandardScalingBase::have_d_scaling() 516 { 517 return (IsValid(scaled_jac_d_space_) && 518 IsValid(scaled_jac_d_space_->RowScaling())); 519 } 520 DetermineScalingParametersImpl(const SmartPtr<const VectorSpace> x_space,const SmartPtr<const VectorSpace> c_space,const SmartPtr<const VectorSpace> d_space,const SmartPtr<const MatrixSpace> jac_c_space,const SmartPtr<const MatrixSpace> jac_d_space,const SmartPtr<const SymMatrixSpace> h_space,Number & df,SmartPtr<Vector> & dx,SmartPtr<Vector> & dc,SmartPtr<Vector> & dd)521 void NoNLPScalingObject::DetermineScalingParametersImpl( 522 const SmartPtr<const VectorSpace> x_space, 523 const SmartPtr<const VectorSpace> c_space, 524 const SmartPtr<const VectorSpace> d_space, 525 const SmartPtr<const MatrixSpace> jac_c_space, 526 const SmartPtr<const MatrixSpace> jac_d_space, 527 const SmartPtr<const SymMatrixSpace> h_space, 528 Number& df, 529 SmartPtr<Vector>& dx, 530 SmartPtr<Vector>& dc, 531 SmartPtr<Vector>& dd) 532 { 533 df = 1.; 534 dx = NULL; 535 dc = NULL; 536 dd = NULL; 537 } 538 539 } // namespace Ipopt 540