1 // Copyright (C) 2004, 2006 International Business Machines and others.
2 // All Rights Reserved.
3 // This code is published under the Common Public License.
4 //
5 // $Id: IpNLPScaling.hpp 759 2006-07-07 03:07:08Z andreasw $
6 //
7 // Authors:  Carl Laird, Andreas Waechter     IBM    2004-08-13
8 
9 #ifndef __IPNLPSCALING_HPP__
10 #define __IPNLPSCALING_HPP__
11 
12 #include "IpSymMatrix.hpp"
13 #include "IpScaledMatrix.hpp"
14 #include "IpSymScaledMatrix.hpp"
15 #include "IpOptionsList.hpp"
16 #include "IpRegOptions.hpp"
17 
18 namespace SimTKIpopt
19 {
20   /** This is the abstract base class for problem scaling.
21    *  It is repsonsible for determining the scaling factors
22    *  and mapping quantities in and out of scaled and unscaled
23    *  versions
24    */
25   class NLPScalingObject : public ReferencedObject
26   {
27   public:
28     /**@name Constructors/Destructors */
29     //@{
NLPScalingObject()30     NLPScalingObject()
31     {}
32 
33     /** Default destructor */
~NLPScalingObject()34     virtual ~NLPScalingObject()
35     {}
36     //@}
37 
38     /** Method to initialize the options */
Initialize(const Journalist & jnlst,const OptionsList & options,const std::string & prefix)39     bool Initialize(const Journalist& jnlst,
40                     const OptionsList& options,
41                     const std::string& prefix)
42     {
43       jnlst_ = &jnlst;
44       return InitializeImpl(options, prefix);
45     }
46 
47     /** Methods to map scaled and unscaled matrices */
48     //@{
49     /** Returns an obj-scaled version of the given scalar */
50     virtual Number apply_obj_scaling(const Number& f)=0;
51     /** Returns an obj-unscaled version of the given scalar */
52     virtual Number unapply_obj_scaling(const Number& f)=0;
53     /** Returns an x-scaled version of the given vector */
54     virtual SmartPtr<Vector>
55     apply_vector_scaling_x_NonConst(const SmartPtr<const Vector>& v)=0;
56     /** Returns an x-scaled version of the given vector */
57     virtual SmartPtr<const Vector>
58     apply_vector_scaling_x(const SmartPtr<const Vector>& v)=0;
59     /** Returns an x-unscaled version of the given vector */
60     virtual SmartPtr<Vector>
61     unapply_vector_scaling_x_NonConst(const SmartPtr<const Vector>& v)=0;
62     /** Returns an x-unscaled version of the given vector */
63     virtual SmartPtr<const Vector>
64     unapply_vector_scaling_x(const SmartPtr<const Vector>& v)=0;
65     /** Returns an c-scaled version of the given vector */
66     virtual SmartPtr<const Vector>
67     apply_vector_scaling_c(const SmartPtr<const Vector>& v)=0;
68     /** Returns an c-unscaled version of the given vector */
69     virtual SmartPtr<const Vector>
70     unapply_vector_scaling_c(const SmartPtr<const Vector>& v)=0;
71     /** Returns an c-scaled version of the given vector */
72     virtual SmartPtr<Vector>
73     apply_vector_scaling_c_NonConst(const SmartPtr<const Vector>& v)=0;
74     /** Returns an c-unscaled version of the given vector */
75     virtual SmartPtr<Vector>
76     unapply_vector_scaling_c_NonConst(const SmartPtr<const Vector>& v)=0;
77     /** Returns an d-scaled version of the given vector */
78     virtual SmartPtr<const Vector>
79     apply_vector_scaling_d(const SmartPtr<const Vector>& v)=0;
80     /** Returns an d-unscaled version of the given vector */
81     virtual SmartPtr<const Vector>
82     unapply_vector_scaling_d(const SmartPtr<const Vector>& v)=0;
83     /** Returns an d-scaled version of the given vector */
84     virtual SmartPtr<Vector>
85     apply_vector_scaling_d_NonConst(const SmartPtr<const Vector>& v)=0;
86     /** Returns an d-unscaled version of the given vector */
87     virtual SmartPtr<Vector>
88     unapply_vector_scaling_d_NonConst(const SmartPtr<const Vector>& v)=0;
89     /** Returns a scaled version of the jacobian for c.  If the
90      *  overloaded method does not make a new matrix, make sure to set
91      *  the matrix ptr passed in to NULL.
92      */
93     virtual SmartPtr<const Matrix>
94     apply_jac_c_scaling(SmartPtr<const Matrix> matrix)=0;
95     /** Returns a scaled version of the jacobian for d If the
96      *  overloaded method does not create a new matrix, make sure to
97      *  set the matrix ptr passed in to NULL.
98      */
99     virtual SmartPtr<const Matrix>
100     apply_jac_d_scaling(SmartPtr<const Matrix> matrix)=0;
101     /** Returns a scaled version of the hessian of the lagrangian If
102      *  the overloaded method does not create a new matrix, make sure
103      *  to set the matrix ptr passed in to NULL.
104      */
105     virtual SmartPtr<const SymMatrix>
106     apply_hessian_scaling(SmartPtr<const SymMatrix> matrix)=0;
107     //@}
108 
109     /** Methods for scaling bounds - these wrap those above */
110     //@{
111     /** Returns an x-scaled vector in the x_L or x_U space */
112     SmartPtr<Vector> apply_vector_scaling_x_LU_NonConst(
113       const Matrix& Px_LU,
114       const SmartPtr<const Vector>& lu,
115       const VectorSpace& x_space);
116     /** Returns an x-scaled vector in the x_L or x_U space */
117     SmartPtr<const Vector> apply_vector_scaling_x_LU(
118       const Matrix& Px_LU,
119       const SmartPtr<const Vector>& lu,
120       const VectorSpace& x_space);
121     /** Returns an d-scaled vector in the d_L or d_U space */
122     SmartPtr<Vector> apply_vector_scaling_d_LU_NonConst(
123       const Matrix& Pd_LU,
124       const SmartPtr<const Vector>& lu,
125       const VectorSpace& d_space);
126     /** Returns an d-scaled vector in the d_L or d_U space */
127     SmartPtr<const Vector> apply_vector_scaling_d_LU(
128       const Matrix& Pd_LU,
129       const SmartPtr<const Vector>& lu,
130       const VectorSpace& d_space);
131     /** Returns an d-unscaled vector in the d_L or d_U space */
132     SmartPtr<Vector> unapply_vector_scaling_d_LU_NonConst(
133       const Matrix& Pd_LU,
134       const SmartPtr<const Vector>& lu,
135       const VectorSpace& d_space);
136     /** Returns an d-unscaled vector in the d_L or d_U space */
137     SmartPtr<const Vector> unapply_vector_scaling_d_LU(
138       const Matrix& Pd_LU,
139       const SmartPtr<const Vector>& lu,
140       const VectorSpace& d_space);
141     //@}
142 
143     /** Methods for scaling the gradient of the objective - wraps the
144      *  virtual methods above
145      */
146     //@{
147     /** Returns a grad_f scaled version (d_f * D_x^{-1}) of the given vector */
148     virtual SmartPtr<Vector>
149     apply_grad_obj_scaling_NonConst(const SmartPtr<const Vector>& v);
150     /** Returns a grad_f scaled version (d_f * D_x^{-1}) of the given vector */
151     virtual SmartPtr<const Vector>
152     apply_grad_obj_scaling(const SmartPtr<const Vector>& v);
153     /** Returns a grad_f unscaled version (d_f * D_x^{-1}) of the
154      *  given vector */
155     virtual SmartPtr<Vector>
156     unapply_grad_obj_scaling_NonConst(const SmartPtr<const Vector>& v);
157     /** Returns a grad_f unscaled version (d_f * D_x^{-1}) of the
158      *  given vector */
159     virtual SmartPtr<const Vector>
160     unapply_grad_obj_scaling(const SmartPtr<const Vector>& v);
161     //@}
162 
163     /** @name Methods for determining whether scaling for entities is
164      *  done */
165     //@{
166     /** Returns true if the primal x variables are scaled. */
167     virtual bool have_x_scaling()=0;
168     /** Returns true if the equality constraints are scaled. */
169     virtual bool have_c_scaling()=0;
170     /** Returns true if the inequality constraints are scaled. */
171     virtual bool have_d_scaling()=0;
172     //@}
173 
174     /** This method is called by the IpoptNLP's at a convenient time to
175      *  compute and/or read scaling factors
176      */
177     virtual void DetermineScaling(const SmartPtr<const VectorSpace> x_space,
178                                   const SmartPtr<const VectorSpace> c_space,
179                                   const SmartPtr<const VectorSpace> d_space,
180                                   const SmartPtr<const MatrixSpace> jac_c_space,
181                                   const SmartPtr<const MatrixSpace> jac_d_space,
182                                   const SmartPtr<const SymMatrixSpace> h_space,
183                                   SmartPtr<const MatrixSpace>& new_jac_c_space,
184                                   SmartPtr<const MatrixSpace>& new_jac_d_space,
185                                   SmartPtr<const SymMatrixSpace>& new_h_space)=0;
186   protected:
187     /** Implementation of the initialization method that has to be
188      *  overloaded by for each derived class. */
189     virtual bool InitializeImpl(const OptionsList& options,
190                                 const std::string& prefix)=0;
191 
192     /** Accessor method for the journalist */
Jnlst() const193     const Journalist& Jnlst() const
194     {
195       return *jnlst_;
196     }
197   private:
198 
199     /**@name Default Compiler Generated Methods
200      * (Hidden to avoid implicit creation/calling).
201      * These methods are not implemented and
202      * we do not want the compiler to implement
203      * them for us, so we declare them private
204      * and do not define them. This ensures that
205      * they will not be implicitly created/called. */
206     //@{
207 
208     /** Copy Constructor */
209     NLPScalingObject(const NLPScalingObject&);
210 
211     /** Overloaded Equals Operator */
212     void operator=(const NLPScalingObject&);
213     //@}
214 
215     SmartPtr<const Journalist> jnlst_;
216   };
217 
218   /** This is a base class for many standard scaling
219    *  techniques. The overloaded classes only need to
220    *  provide the scaling parameters
221    */
222   class StandardScalingBase : public NLPScalingObject
223   {
224   public:
225     /**@name Constructors/Destructors */
226     //@{
StandardScalingBase()227     StandardScalingBase()
228     {}
229 
230     /** Default destructor */
~StandardScalingBase()231     virtual ~StandardScalingBase()
232     {}
233     //@}
234 
235     /** Methods to map scaled and unscaled matrices */
236     //@{
237     /** Returns an obj-scaled version of the given scalar */
238     virtual Number apply_obj_scaling(const Number& f) override;
239     /** Returns an obj-unscaled version of the given scalar */
240     virtual Number unapply_obj_scaling(const Number& f) override;
241     /** Returns an x-scaled version of the given vector */
242     virtual SmartPtr<Vector>
243     apply_vector_scaling_x_NonConst(const SmartPtr<const Vector>& v) override;
244     /** Returns an x-scaled version of the given vector */
245     virtual SmartPtr<const Vector>
246     apply_vector_scaling_x(const SmartPtr<const Vector>& v) override;
247     /** Returns an x-unscaled version of the given vector */
248     virtual SmartPtr<Vector>
249     unapply_vector_scaling_x_NonConst(const SmartPtr<const Vector>& v) override;
250     /** Returns an x-unscaled version of the given vector */
251     virtual SmartPtr<const Vector>
252     unapply_vector_scaling_x(const SmartPtr<const Vector>& v) override;
253     /** Returns an c-scaled version of the given vector */
254     virtual SmartPtr<const Vector>
255     apply_vector_scaling_c(const SmartPtr<const Vector>& v) override;
256     /** Returns an c-unscaled version of the given vector */
257     virtual SmartPtr<const Vector>
258     unapply_vector_scaling_c(const SmartPtr<const Vector>& v) override;
259     /** Returns an c-scaled version of the given vector */
260     virtual SmartPtr<Vector>
261     apply_vector_scaling_c_NonConst(const SmartPtr<const Vector>& v) override;
262     /** Returns an c-unscaled version of the given vector */
263     virtual SmartPtr<Vector>
264     unapply_vector_scaling_c_NonConst(const SmartPtr<const Vector>& v) override;
265     /** Returns an d-scaled version of the given vector */
266     virtual SmartPtr<const Vector>
267     apply_vector_scaling_d(const SmartPtr<const Vector>& v) override;
268     /** Returns an d-unscaled version of the given vector */
269     virtual SmartPtr<const Vector>
270     unapply_vector_scaling_d(const SmartPtr<const Vector>& v) override;
271     /** Returns an d-scaled version of the given vector */
272     virtual SmartPtr<Vector>
273     apply_vector_scaling_d_NonConst(const SmartPtr<const Vector>& v) override;
274     /** Returns an d-unscaled version of the given vector */
275     virtual SmartPtr<Vector>
276     unapply_vector_scaling_d_NonConst(const SmartPtr<const Vector>& v) override;
277     /** Returns a scaled version of the jacobian for c.  If the
278      *  overloaded method does not make a new matrix, make sure to set
279      *  the matrix ptr passed in to NULL.
280      */
281     virtual SmartPtr<const Matrix>
282     apply_jac_c_scaling(SmartPtr<const Matrix> matrix) override;
283     /** Returns a scaled version of the jacobian for d If the
284      *  overloaded method does not create a new matrix, make sure to
285      *  set the matrix ptr passed in to NULL.
286      */
287     virtual SmartPtr<const Matrix>
288     apply_jac_d_scaling(SmartPtr<const Matrix> matrix) override;
289     /** Returns a scaled version of the hessian of the lagrangian If
290      *  the overloaded method does not create a new matrix, make sure
291      *  to set the matrix ptr passed in to NULL.
292      */
293     virtual SmartPtr<const SymMatrix>
294     apply_hessian_scaling(SmartPtr<const SymMatrix> matrix) override;
295     //@}
296 
297     /** @name Methods for determining whether scaling for entities is
298      *  done */
299     //@{
300     virtual bool have_x_scaling() override;
301     virtual bool have_c_scaling() override;
302     virtual bool have_d_scaling() override;
303     //@}
304 
305     /** This method is called by the IpoptNLP's at a convenient time to
306      *  compute and/or read scaling factors
307      */
308     virtual void DetermineScaling(const SmartPtr<const VectorSpace> x_space,
309                                   const SmartPtr<const VectorSpace> c_space,
310                                   const SmartPtr<const VectorSpace> d_space,
311                                   const SmartPtr<const MatrixSpace> jac_c_space,
312                                   const SmartPtr<const MatrixSpace> jac_d_space,
313                                   const SmartPtr<const SymMatrixSpace> h_space,
314                                   SmartPtr<const MatrixSpace>& new_jac_c_space,
315                                   SmartPtr<const MatrixSpace>& new_jac_d_space,
316                                   SmartPtr<const SymMatrixSpace>& new_h_space) override;
317 
318     /** Methods for IpoptType */
319     //@{
320     static void RegisterOptions(SmartPtr<RegisteredOptions> roptions);
321     //@}
322 
323   protected:
324     /** Overloaded initialization method */
325     virtual bool InitializeImpl(const OptionsList& options,
326                                 const std::string& prefix) override;
327 
328     /** This is the method that has to be overloaded by a particular
329      *  scaling method that somehow computes the scaling vectors dx,
330      *  dc, and dd.  The pointers to those vectors can be NULL, in
331      *  which case no scaling for that item will be done later. */
332     virtual void DetermineScalingParametersImpl(
333       const SmartPtr<const VectorSpace> x_space,
334       const SmartPtr<const VectorSpace> c_space,
335       const SmartPtr<const VectorSpace> d_space,
336       const SmartPtr<const MatrixSpace> jac_c_space,
337       const SmartPtr<const MatrixSpace> jac_d_space,
338       const SmartPtr<const SymMatrixSpace> h_space,
339       Number& df,
340       SmartPtr<Vector>& dx,
341       SmartPtr<Vector>& dc,
342       SmartPtr<Vector>& dd)=0;
343 
344   private:
345 
346     /**@name Default Compiler Generated Methods
347      * (Hidden to avoid implicit creation/calling).
348      * These methods are not implemented and
349      * we do not want the compiler to implement
350      * them for us, so we declare them private
351      * and do not define them. This ensures that
352      * they will not be implicitly created/called. */
353     //@{
354 
355     /** Copy Constructor */
356     StandardScalingBase(const StandardScalingBase&);
357 
358     /** Overloaded Equals Operator */
359     void operator=(const StandardScalingBase&);
360     //@}
361 
362     /** Scaling parameters - we only need to keep copies of
363      *  the objective scaling and the x scaling - the others we can
364      *  get from the scaled matrix spaces.
365      */
366     //@{
367     /** objective scaling parameter */
368     Number df_;
369     /** x scaling */
370     SmartPtr<Vector> dx_;
371     //@}
372 
373     /** Scaled Matrix Spaces */
374     //@{
375     /** Scaled jacobian of c space */
376     SmartPtr<ScaledMatrixSpace> scaled_jac_c_space_;
377     /** Scaled jacobian of d space */
378     SmartPtr<ScaledMatrixSpace> scaled_jac_d_space_;
379     /** Scaled hessian of lagrangian spacea */
380     SmartPtr<SymScaledMatrixSpace> scaled_h_space_;
381     //@}
382 
383     /** @name Algorithmic parameters */
384     //@{
385     /** Additional scaling value for the objective function */
386     Number obj_scaling_factor_;
387     //@}
388   };
389 
390   /** Class implementing the scaling object that doesn't to any scaling */
391   class NoNLPScalingObject : public StandardScalingBase
392   {
393   public:
394     /**@name Constructors/Destructors */
395     //@{
NoNLPScalingObject()396     NoNLPScalingObject()
397     {}
398 
399     /** Default destructor */
~NoNLPScalingObject()400     virtual ~NoNLPScalingObject()
401     {}
402     //@}
403 
404 
405   protected:
406     /** Overloaded from StandardScalingBase */
407     virtual void DetermineScalingParametersImpl(
408       const SmartPtr<const VectorSpace> x_space,
409       const SmartPtr<const VectorSpace> c_space,
410       const SmartPtr<const VectorSpace> d_space,
411       const SmartPtr<const MatrixSpace> jac_c_space,
412       const SmartPtr<const MatrixSpace> jac_d_space,
413       const SmartPtr<const SymMatrixSpace> h_space,
414       Number& df,
415       SmartPtr<Vector>& dx,
416       SmartPtr<Vector>& dc,
417       SmartPtr<Vector>& dd) override;
418 
419   private:
420 
421     /**@name Default Compiler Generated Methods
422      * (Hidden to avoid implicit creation/calling).
423      * These methods are not implemented and
424      * we do not want the compiler to implement
425      * them for us, so we declare them private
426      * and do not define them. This ensures that
427      * they will not be implicitly created/called. */
428     //@{
429 
430     /** Copy Constructor */
431     NoNLPScalingObject(const NoNLPScalingObject&);
432 
433     /** Overloaded Equals Operator */
434     void operator=(const NoNLPScalingObject&);
435     //@}
436   };
437 
438 } // namespace Ipopt
439 
440 #endif
441