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: IpCompoundMatrix.hpp 759 2006-07-07 03:07:08Z andreasw $
6 //
7 // Authors:  Carl Laird, Andreas Waechter     IBM    2004-08-13
8 
9 #ifndef __IPCOMPOUNDMATRIX_HPP__
10 #define __IPCOMPOUNDMATRIX_HPP__
11 
12 #include "IpUtils.hpp"
13 #include "IpMatrix.hpp"
14 
15 namespace SimTKIpopt
16 {
17 
18   /* forward declarations */
19   class CompoundMatrixSpace;
20 
21   /** Class for Matrices consisting of other matrices.  This matrix is
22    *  a matrix that consists of zero, one or more Matrices's which are
23    *  arranged like this: \f$ M_{\rm compound} =
24    *  \left(\begin{array}{cccc}M_{00} & M_{01} & \ldots & M_{0,{\rm
25    *  ncomp\_cols}-1} \\ \dots &&&\dots \\ M_{{\rm ncomp\_rows}-1,0} &
26    *  M_{{\rm ncomp\_rows}-1,1} & \dots & M_{{\rm ncomp\_rows}-1,{\rm
27    *  ncomp\_cols}-1}\end{array}\right)\f$.  The individual components
28    *  can be associated to different MatrixSpaces.  The individual
29    *  components can also be const and non-const Matrices.  If a
30    *  component is not set (i.e., it's pointer is NULL), then this
31    *  components is treated like a zero-matrix of appropriate
32    *  dimensions.
33    */
34   class CompoundMatrix : public Matrix
35   {
36   public:
37 
38     /**@name Constructors / Destructors */
39     //@{
40 
41     /** Constructor, taking the owner_space.  The owner_space has to
42      *  be defined, so that at each block row and column contain at
43      *  least one non-NULL component.  The individual components can
44      *  be set afterwards with the SeteComp and SetCompNonConst
45      *  methods.
46      */
47     CompoundMatrix(const CompoundMatrixSpace* owner_space);
48 
49     /** Destructor */
50     ~CompoundMatrix();
51     //@}
52 
53     /** Method for setting an individual component at position (irow,
54      *  icol) in the compound matrix.  The counting of indices starts
55      *  at 0. */
56     void SetComp(Index irow, Index jcol, const Matrix& matrix);
57 
58     /** Method to set a non-const Matrix entry */
59     void SetCompNonConst(Index irow, Index jcol, Matrix& matrix);
60 
61     /** Method to create a new matrix from the space for this block */
62     void CreateBlockFromSpace(Index irow, Index jcol);
63 
64     /** Method for retrieving one block from the compound matrix as a
65      *  const Matrix.
66      */
GetComp(Index irow,Index jcol) const67     SmartPtr<const Matrix> GetComp(Index irow, Index jcol) const
68     {
69       return ConstComp(irow, jcol);
70     }
71 
72     /** Method for retrieving one block from the compound matrix as a
73      *  non-const Matrix.  Note that calling this method with mark the
74      *  CompoundMatrix as changed.  Therefore, only use this method if
75      *  you are intending to change the Matrix that you receive. */
GetCompNonConst(Index irow,Index jcol)76     SmartPtr<Matrix> GetCompNonConst(Index irow, Index jcol)
77     {
78       ObjectChanged();
79       return Comp(irow, jcol);
80     }
81 
82     /** Number of block rows of this compound matrix. */
83     inline Index NComps_Rows() const;
84     /** Number of block colmuns of this compound matrix. */
85     inline Index NComps_Cols() const;
86 
87   protected:
88     /**@name Methods overloaded from Matrix */
89     //@{
90     virtual void MultVectorImpl(Number alpha, const Vector& x,
91                                 Number beta, Vector& y) const override;
92 
93     virtual void TransMultVectorImpl(Number alpha, const Vector& x,
94                                      Number beta, Vector& y) const override;
95 
96     /** X = beta*X + alpha*(Matrix S^{-1} Z).  Specialized implementation.
97      */
98     virtual void AddMSinvZImpl(Number alpha, const Vector& S, const Vector& Z,
99                                Vector& X) const override;
100 
101     /** X = S^{-1} (r + alpha*Z*M^Td).  Specialized implementation.
102      */
103     virtual void SinvBlrmZMTdBrImpl(Number alpha, const Vector& S,
104                                     const Vector& R, const Vector& Z,
105                                     const Vector& D, Vector& X) const override;
106 
107     /** Method for determining if all stored numbers are valid (i.e.,
108      *  no Inf or Nan). */
109     virtual bool HasValidNumbersImpl() const override;
110 
111     virtual void PrintImpl(const Journalist& jnlst,
112                            EJournalLevel level,
113                            EJournalCategory category,
114                            const std::string& name,
115                            Index indent,
116                            const std::string& prefix) const override;
117     //@}
118 
119   private:
120     /**@name Default Compiler Generated Methods
121      * (Hidden to avoid implicit creation/calling).
122      * These methods are not implemented and
123      * we do not want the compiler to implement
124      * them for us, so we declare them private
125      * and do not define them. This ensures that
126      * they will not be implicitly created/called. */
127     //@{
128     /** Default Constructor */
129     CompoundMatrix();
130 
131     /** Copy Constructor */
132     CompoundMatrix(const CompoundMatrix&);
133 
134     /** Overloaded Equals Operator */
135     void operator=(const CompoundMatrix&);
136     //@}
137 
138     /** Matrix of matrix's containing the components */
139     std::vector<std::vector<SmartPtr<Matrix> > > comps_;
140 
141     /** Matrix of const matrix's containing the components */
142     std::vector<std::vector<SmartPtr<const Matrix> > > const_comps_;
143 
144     /** Copy of the owner_space ptr as a CompoundMatrixSpace instead
145      *  of MatrixSpace */
146     const CompoundMatrixSpace* owner_space_;
147 
148     /** boolean indicating if the compound matrix is in a "valid" state */
149     mutable bool matrices_valid_;
150 
151     /** Method to check whether or not the matrices are valid */
152     bool MatricesValid() const;
153 
154     inline const Matrix* ConstComp(Index irow, Index jcol) const;
155 
156     inline Matrix* Comp(Index irow, Index jcol);
157   };
158 
159   /** This is the matrix space for CompoundMatrix.  Before a CompoundMatrix
160    *  can be created, at least one MatrixSpace has to be set per block
161    *  row and column.  Individual component MatrixSpace's can be set
162    *  with the SetComp method.
163    */
164   class CompoundMatrixSpace : public MatrixSpace
165   {
166   public:
167     /** @name Constructors / Destructors */
168     //@{
169     /** Constructor, given the number of row and columns blocks, as
170      *  well as the totel number of rows and columns.
171      */
172     CompoundMatrixSpace(Index ncomps_rows,
173                         Index ncomps_cols,
174                         Index total_nRows,
175                         Index total_nCols);
176 
177     /** Destructor */
~CompoundMatrixSpace()178     ~CompoundMatrixSpace()
179     {}
180     ;
181     //@}
182 
183     /** @name Methods for setting information about the components. */
184     //@{
185     /** Set the number nrows of rows in row-block number irow. */
186     void SetBlockRows(Index irow, Index nrows);
187 
188     /** Set the number ncols of columns in column-block number jcol. */
189     void SetBlockCols(Index jcol, Index ncols);
190 
191     /** Get the number nrows of rows in row-block number irow. */
192     Index GetBlockRows(Index irow) const;
193 
194     /** Set the number ncols of columns in column-block number jcol. */
195     Index GetBlockCols(Index jcol) const;
196 
197     /** Set the component MatrixSpace.  If auto_allocate is true, then
198      *  a new CompoundMatrix created later with MakeNew will have this
199      *  component automatically created with the Matrix's MakeNew.
200      *  Otherwise, the corresponding component will be NULL and has to
201      *  be set with the SetComp methods of the CompoundMatrix.
202      */
203     void SetCompSpace(Index irow, Index jcol,
204                       const MatrixSpace& mat_space,
205                       bool auto_allocate = false);
206     //@}
207 
208     /** Obtain the component MatrixSpace in block row irow and block
209      *  column jcol.
210      */
GetCompSpace(Index irow,Index jcol) const211     SmartPtr<const MatrixSpace> GetCompSpace(Index irow, Index jcol) const
212     {
213       DBG_ASSERT(irow<NComps_Rows());
214       DBG_ASSERT(jcol<NComps_Cols());
215       return comp_spaces_[irow][jcol];
216     }
217 
218     /** @name Accessor methods */
219     //@{
220     /** Number of block rows */
NComps_Rows() const221     Index NComps_Rows() const
222     {
223       return ncomps_rows_;
224     }
225     /** Number of block columns */
NComps_Cols() const226     Index NComps_Cols() const
227     {
228       return ncomps_cols_;
229     }
230 
231     /** True if the blocks lie on the diagonal - can make some operations faster */
Diagonal() const232     bool Diagonal() const
233     {
234       return diagonal_;
235     }
236     //@}
237 
238     /** Method for creating a new matrix of this specific type. */
239     CompoundMatrix* MakeNewCompoundMatrix() const;
240 
241     /** Overloaded MakeNew method for the MatrixSpace base class.
242      */
MakeNew() const243     virtual Matrix* MakeNew() const override
244     {
245       return MakeNewCompoundMatrix();
246     }
247 
248   private:
249     /**@name Default Compiler Generated Methods
250      * (Hidden to avoid implicit creation/calling).
251      * These methods are not implemented and
252      * we do not want the compiler to implement
253      * them for us, so we declare them private
254      * and do not define them. This ensures that
255      * they will not be implicitly created/called. */
256     //@{
257     /** Default constructor */
258     CompoundMatrixSpace();
259 
260     /** Copy Constructor */
261     CompoundMatrixSpace(const CompoundMatrixSpace&);
262 
263     /** Overloaded Equals Operator */
264     CompoundMatrixSpace& operator=(const CompoundMatrixSpace&);
265     //@}
266 
267     /** Number of block rows */
268     Index ncomps_rows_;
269 
270     /** Number of block columns */
271     Index ncomps_cols_;
272 
273     /** Store whether or not the dimensions are valid */
274     mutable bool dimensions_set_;
275 
276     /** 2-dim std::vector of matrix spaces for the components */
277     std::vector<std::vector<SmartPtr<const MatrixSpace> > > comp_spaces_;
278 
279     /** 2-dim std::vector of booleans deciding whether to
280      *  allocate a new matrix for the blocks automagically */
281     std::vector<std::vector< bool > > allocate_block_;
282 
283     /** Vector of the number of rows in each comp column */
284     std::vector<Index> block_rows_;
285 
286     /** Vector of the number of cols in each comp row */
287     std::vector<Index> block_cols_;
288 
289     /** true if the CompoundMatrixSpace only has Matrix spaces along the diagonal.
290      *  this means that the CompoundMatrix will only have matrices along the
291      *  diagonal and it could make some operations more efficient
292      */
293     bool diagonal_;
294 
295     /** Auxilliary function for debugging to set if all block
296      *  dimensions have been set. */
297     bool DimensionsSet() const;
298   };
299 
300   /* inline methods */
301   inline
NComps_Rows() const302   Index CompoundMatrix::NComps_Rows() const
303   {
304     return owner_space_->NComps_Rows();
305   }
306 
307   inline
NComps_Cols() const308   Index CompoundMatrix::NComps_Cols() const
309   {
310     return owner_space_->NComps_Cols();
311   }
312 
313   inline
ConstComp(Index irow,Index jcol) const314   const Matrix* CompoundMatrix::ConstComp(Index irow, Index jcol) const
315   {
316     DBG_ASSERT(irow < NComps_Rows());
317     DBG_ASSERT(jcol < NComps_Cols());
318     if (IsValid(comps_[irow][jcol])) {
319       return GetRawPtr(comps_[irow][jcol]);
320     }
321     else if (IsValid(const_comps_[irow][jcol])) {
322       return GetRawPtr(const_comps_[irow][jcol]);
323     }
324 
325     return NULL;
326   }
327 
328   inline
Comp(Index irow,Index jcol)329   Matrix* CompoundMatrix::Comp(Index irow, Index jcol)
330   {
331     DBG_ASSERT(irow < NComps_Rows());
332     DBG_ASSERT(jcol < NComps_Cols());
333     return GetRawPtr(comps_[irow][jcol]);
334   }
335 
336 } // namespace Ipopt
337 #endif
338