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