• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
5 // Copyright (C) 2009-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
6 //
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 
11 #ifndef EIGEN_PERMUTATIONMATRIX_H
12 #define EIGEN_PERMUTATIONMATRIX_H
13 
14 namespace Eigen {
15 
16 namespace internal {
17 
18 enum PermPermProduct_t {PermPermProduct};
19 
20 } // end namespace internal
21 
22 /** \class PermutationBase
23   * \ingroup Core_Module
24   *
25   * \brief Base class for permutations
26   *
27   * \tparam Derived the derived class
28   *
29   * This class is the base class for all expressions representing a permutation matrix,
30   * internally stored as a vector of integers.
31   * The convention followed here is that if \f$ \sigma \f$ is a permutation, the corresponding permutation matrix
32   * \f$ P_\sigma \f$ is such that if \f$ (e_1,\ldots,e_p) \f$ is the canonical basis, we have:
33   *  \f[ P_\sigma(e_i) = e_{\sigma(i)}. \f]
34   * This convention ensures that for any two permutations \f$ \sigma, \tau \f$, we have:
35   *  \f[ P_{\sigma\circ\tau} = P_\sigma P_\tau. \f]
36   *
37   * Permutation matrices are square and invertible.
38   *
39   * Notice that in addition to the member functions and operators listed here, there also are non-member
40   * operator* to multiply any kind of permutation object with any kind of matrix expression (MatrixBase)
41   * on either side.
42   *
43   * \sa class PermutationMatrix, class PermutationWrapper
44   */
45 template<typename Derived>
46 class PermutationBase : public EigenBase<Derived>
47 {
48     typedef internal::traits<Derived> Traits;
49     typedef EigenBase<Derived> Base;
50   public:
51 
52     #ifndef EIGEN_PARSED_BY_DOXYGEN
53     typedef typename Traits::IndicesType IndicesType;
54     enum {
55       Flags = Traits::Flags,
56       RowsAtCompileTime = Traits::RowsAtCompileTime,
57       ColsAtCompileTime = Traits::ColsAtCompileTime,
58       MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime,
59       MaxColsAtCompileTime = Traits::MaxColsAtCompileTime
60     };
61     typedef typename Traits::StorageIndex StorageIndex;
62     typedef Matrix<StorageIndex,RowsAtCompileTime,ColsAtCompileTime,0,MaxRowsAtCompileTime,MaxColsAtCompileTime>
63             DenseMatrixType;
64     typedef PermutationMatrix<IndicesType::SizeAtCompileTime,IndicesType::MaxSizeAtCompileTime,StorageIndex>
65             PlainPermutationType;
66     typedef PlainPermutationType PlainObject;
67     using Base::derived;
68     typedef Inverse<Derived> InverseReturnType;
69     typedef void Scalar;
70     #endif
71 
72     /** Copies the other permutation into *this */
73     template<typename OtherDerived>
74     Derived& operator=(const PermutationBase<OtherDerived>& other)
75     {
76       indices() = other.indices();
77       return derived();
78     }
79 
80     /** Assignment from the Transpositions \a tr */
81     template<typename OtherDerived>
82     Derived& operator=(const TranspositionsBase<OtherDerived>& tr)
83     {
84       setIdentity(tr.size());
85       for(Index k=size()-1; k>=0; --k)
86         applyTranspositionOnTheRight(k,tr.coeff(k));
87       return derived();
88     }
89 
90     /** \returns the number of rows */
rows()91     inline EIGEN_DEVICE_FUNC Index rows() const { return Index(indices().size()); }
92 
93     /** \returns the number of columns */
cols()94     inline EIGEN_DEVICE_FUNC Index cols() const { return Index(indices().size()); }
95 
96     /** \returns the size of a side of the respective square matrix, i.e., the number of indices */
size()97     inline EIGEN_DEVICE_FUNC Index size() const { return Index(indices().size()); }
98 
99     #ifndef EIGEN_PARSED_BY_DOXYGEN
100     template<typename DenseDerived>
evalTo(MatrixBase<DenseDerived> & other)101     void evalTo(MatrixBase<DenseDerived>& other) const
102     {
103       other.setZero();
104       for (Index i=0; i<rows(); ++i)
105         other.coeffRef(indices().coeff(i),i) = typename DenseDerived::Scalar(1);
106     }
107     #endif
108 
109     /** \returns a Matrix object initialized from this permutation matrix. Notice that it
110       * is inefficient to return this Matrix object by value. For efficiency, favor using
111       * the Matrix constructor taking EigenBase objects.
112       */
toDenseMatrix()113     DenseMatrixType toDenseMatrix() const
114     {
115       return derived();
116     }
117 
118     /** const version of indices(). */
indices()119     const IndicesType& indices() const { return derived().indices(); }
120     /** \returns a reference to the stored array representing the permutation. */
indices()121     IndicesType& indices() { return derived().indices(); }
122 
123     /** Resizes to given size.
124       */
resize(Index newSize)125     inline void resize(Index newSize)
126     {
127       indices().resize(newSize);
128     }
129 
130     /** Sets *this to be the identity permutation matrix */
setIdentity()131     void setIdentity()
132     {
133       StorageIndex n = StorageIndex(size());
134       for(StorageIndex i = 0; i < n; ++i)
135         indices().coeffRef(i) = i;
136     }
137 
138     /** Sets *this to be the identity permutation matrix of given size.
139       */
setIdentity(Index newSize)140     void setIdentity(Index newSize)
141     {
142       resize(newSize);
143       setIdentity();
144     }
145 
146     /** Multiplies *this by the transposition \f$(ij)\f$ on the left.
147       *
148       * \returns a reference to *this.
149       *
150       * \warning This is much slower than applyTranspositionOnTheRight(Index,Index):
151       * this has linear complexity and requires a lot of branching.
152       *
153       * \sa applyTranspositionOnTheRight(Index,Index)
154       */
applyTranspositionOnTheLeft(Index i,Index j)155     Derived& applyTranspositionOnTheLeft(Index i, Index j)
156     {
157       eigen_assert(i>=0 && j>=0 && i<size() && j<size());
158       for(Index k = 0; k < size(); ++k)
159       {
160         if(indices().coeff(k) == i) indices().coeffRef(k) = StorageIndex(j);
161         else if(indices().coeff(k) == j) indices().coeffRef(k) = StorageIndex(i);
162       }
163       return derived();
164     }
165 
166     /** Multiplies *this by the transposition \f$(ij)\f$ on the right.
167       *
168       * \returns a reference to *this.
169       *
170       * This is a fast operation, it only consists in swapping two indices.
171       *
172       * \sa applyTranspositionOnTheLeft(Index,Index)
173       */
applyTranspositionOnTheRight(Index i,Index j)174     Derived& applyTranspositionOnTheRight(Index i, Index j)
175     {
176       eigen_assert(i>=0 && j>=0 && i<size() && j<size());
177       std::swap(indices().coeffRef(i), indices().coeffRef(j));
178       return derived();
179     }
180 
181     /** \returns the inverse permutation matrix.
182       *
183       * \note \blank \note_try_to_help_rvo
184       */
inverse()185     inline InverseReturnType inverse() const
186     { return InverseReturnType(derived()); }
187     /** \returns the tranpose permutation matrix.
188       *
189       * \note \blank \note_try_to_help_rvo
190       */
transpose()191     inline InverseReturnType transpose() const
192     { return InverseReturnType(derived()); }
193 
194     /**** multiplication helpers to hopefully get RVO ****/
195 
196 
197 #ifndef EIGEN_PARSED_BY_DOXYGEN
198   protected:
199     template<typename OtherDerived>
assignTranspose(const PermutationBase<OtherDerived> & other)200     void assignTranspose(const PermutationBase<OtherDerived>& other)
201     {
202       for (Index i=0; i<rows();++i) indices().coeffRef(other.indices().coeff(i)) = i;
203     }
204     template<typename Lhs,typename Rhs>
assignProduct(const Lhs & lhs,const Rhs & rhs)205     void assignProduct(const Lhs& lhs, const Rhs& rhs)
206     {
207       eigen_assert(lhs.cols() == rhs.rows());
208       for (Index i=0; i<rows();++i) indices().coeffRef(i) = lhs.indices().coeff(rhs.indices().coeff(i));
209     }
210 #endif
211 
212   public:
213 
214     /** \returns the product permutation matrix.
215       *
216       * \note \blank \note_try_to_help_rvo
217       */
218     template<typename Other>
219     inline PlainPermutationType operator*(const PermutationBase<Other>& other) const
220     { return PlainPermutationType(internal::PermPermProduct, derived(), other.derived()); }
221 
222     /** \returns the product of a permutation with another inverse permutation.
223       *
224       * \note \blank \note_try_to_help_rvo
225       */
226     template<typename Other>
227     inline PlainPermutationType operator*(const InverseImpl<Other,PermutationStorage>& other) const
228     { return PlainPermutationType(internal::PermPermProduct, *this, other.eval()); }
229 
230     /** \returns the product of an inverse permutation with another permutation.
231       *
232       * \note \blank \note_try_to_help_rvo
233       */
234     template<typename Other> friend
235     inline PlainPermutationType operator*(const InverseImpl<Other, PermutationStorage>& other, const PermutationBase& perm)
236     { return PlainPermutationType(internal::PermPermProduct, other.eval(), perm); }
237 
238     /** \returns the determinant of the permutation matrix, which is either 1 or -1 depending on the parity of the permutation.
239       *
240       * This function is O(\c n) procedure allocating a buffer of \c n booleans.
241       */
determinant()242     Index determinant() const
243     {
244       Index res = 1;
245       Index n = size();
246       Matrix<bool,RowsAtCompileTime,1,0,MaxRowsAtCompileTime> mask(n);
247       mask.fill(false);
248       Index r = 0;
249       while(r < n)
250       {
251         // search for the next seed
252         while(r<n && mask[r]) r++;
253         if(r>=n)
254           break;
255         // we got one, let's follow it until we are back to the seed
256         Index k0 = r++;
257         mask.coeffRef(k0) = true;
258         for(Index k=indices().coeff(k0); k!=k0; k=indices().coeff(k))
259         {
260           mask.coeffRef(k) = true;
261           res = -res;
262         }
263       }
264       return res;
265     }
266 
267   protected:
268 
269 };
270 
271 namespace internal {
272 template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndex>
273 struct traits<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, _StorageIndex> >
274  : traits<Matrix<_StorageIndex,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> >
275 {
276   typedef PermutationStorage StorageKind;
277   typedef Matrix<_StorageIndex, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1> IndicesType;
278   typedef _StorageIndex StorageIndex;
279   typedef void Scalar;
280 };
281 }
282 
283 /** \class PermutationMatrix
284   * \ingroup Core_Module
285   *
286   * \brief Permutation matrix
287   *
288   * \tparam SizeAtCompileTime the number of rows/cols, or Dynamic
289   * \tparam MaxSizeAtCompileTime the maximum number of rows/cols, or Dynamic. This optional parameter defaults to SizeAtCompileTime. Most of the time, you should not have to specify it.
290   * \tparam _StorageIndex the integer type of the indices
291   *
292   * This class represents a permutation matrix, internally stored as a vector of integers.
293   *
294   * \sa class PermutationBase, class PermutationWrapper, class DiagonalMatrix
295   */
296 template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndex>
297 class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, _StorageIndex> >
298 {
299     typedef PermutationBase<PermutationMatrix> Base;
300     typedef internal::traits<PermutationMatrix> Traits;
301   public:
302 
303     typedef const PermutationMatrix& Nested;
304 
305     #ifndef EIGEN_PARSED_BY_DOXYGEN
306     typedef typename Traits::IndicesType IndicesType;
307     typedef typename Traits::StorageIndex StorageIndex;
308     #endif
309 
310     inline PermutationMatrix()
311     {}
312 
313     /** Constructs an uninitialized permutation matrix of given size.
314       */
315     explicit inline PermutationMatrix(Index size) : m_indices(size)
316     {
317       eigen_internal_assert(size <= NumTraits<StorageIndex>::highest());
318     }
319 
320     /** Copy constructor. */
321     template<typename OtherDerived>
322     inline PermutationMatrix(const PermutationBase<OtherDerived>& other)
323       : m_indices(other.indices()) {}
324 
325     /** Generic constructor from expression of the indices. The indices
326       * array has the meaning that the permutations sends each integer i to indices[i].
327       *
328       * \warning It is your responsibility to check that the indices array that you passes actually
329       * describes a permutation, i.e., each value between 0 and n-1 occurs exactly once, where n is the
330       * array's size.
331       */
332     template<typename Other>
333     explicit inline PermutationMatrix(const MatrixBase<Other>& indices) : m_indices(indices)
334     {}
335 
336     /** Convert the Transpositions \a tr to a permutation matrix */
337     template<typename Other>
338     explicit PermutationMatrix(const TranspositionsBase<Other>& tr)
339       : m_indices(tr.size())
340     {
341       *this = tr;
342     }
343 
344     /** Copies the other permutation into *this */
345     template<typename Other>
346     PermutationMatrix& operator=(const PermutationBase<Other>& other)
347     {
348       m_indices = other.indices();
349       return *this;
350     }
351 
352     /** Assignment from the Transpositions \a tr */
353     template<typename Other>
354     PermutationMatrix& operator=(const TranspositionsBase<Other>& tr)
355     {
356       return Base::operator=(tr.derived());
357     }
358 
359     /** const version of indices(). */
360     const IndicesType& indices() const { return m_indices; }
361     /** \returns a reference to the stored array representing the permutation. */
362     IndicesType& indices() { return m_indices; }
363 
364 
365     /**** multiplication helpers to hopefully get RVO ****/
366 
367 #ifndef EIGEN_PARSED_BY_DOXYGEN
368     template<typename Other>
369     PermutationMatrix(const InverseImpl<Other,PermutationStorage>& other)
370       : m_indices(other.derived().nestedExpression().size())
371     {
372       eigen_internal_assert(m_indices.size() <= NumTraits<StorageIndex>::highest());
373       StorageIndex end = StorageIndex(m_indices.size());
374       for (StorageIndex i=0; i<end;++i)
375         m_indices.coeffRef(other.derived().nestedExpression().indices().coeff(i)) = i;
376     }
377     template<typename Lhs,typename Rhs>
378     PermutationMatrix(internal::PermPermProduct_t, const Lhs& lhs, const Rhs& rhs)
379       : m_indices(lhs.indices().size())
380     {
381       Base::assignProduct(lhs,rhs);
382     }
383 #endif
384 
385   protected:
386 
387     IndicesType m_indices;
388 };
389 
390 
391 namespace internal {
392 template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndex, int _PacketAccess>
393 struct traits<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, _StorageIndex>,_PacketAccess> >
394  : traits<Matrix<_StorageIndex,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> >
395 {
396   typedef PermutationStorage StorageKind;
397   typedef Map<const Matrix<_StorageIndex, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1>, _PacketAccess> IndicesType;
398   typedef _StorageIndex StorageIndex;
399   typedef void Scalar;
400 };
401 }
402 
403 template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndex, int _PacketAccess>
404 class Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, _StorageIndex>,_PacketAccess>
405   : public PermutationBase<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, _StorageIndex>,_PacketAccess> >
406 {
407     typedef PermutationBase<Map> Base;
408     typedef internal::traits<Map> Traits;
409   public:
410 
411     #ifndef EIGEN_PARSED_BY_DOXYGEN
412     typedef typename Traits::IndicesType IndicesType;
413     typedef typename IndicesType::Scalar StorageIndex;
414     #endif
415 
416     inline Map(const StorageIndex* indicesPtr)
417       : m_indices(indicesPtr)
418     {}
419 
420     inline Map(const StorageIndex* indicesPtr, Index size)
421       : m_indices(indicesPtr,size)
422     {}
423 
424     /** Copies the other permutation into *this */
425     template<typename Other>
426     Map& operator=(const PermutationBase<Other>& other)
427     { return Base::operator=(other.derived()); }
428 
429     /** Assignment from the Transpositions \a tr */
430     template<typename Other>
431     Map& operator=(const TranspositionsBase<Other>& tr)
432     { return Base::operator=(tr.derived()); }
433 
434     #ifndef EIGEN_PARSED_BY_DOXYGEN
435     /** This is a special case of the templated operator=. Its purpose is to
436       * prevent a default operator= from hiding the templated operator=.
437       */
438     Map& operator=(const Map& other)
439     {
440       m_indices = other.m_indices;
441       return *this;
442     }
443     #endif
444 
445     /** const version of indices(). */
446     const IndicesType& indices() const { return m_indices; }
447     /** \returns a reference to the stored array representing the permutation. */
448     IndicesType& indices() { return m_indices; }
449 
450   protected:
451 
452     IndicesType m_indices;
453 };
454 
455 template<typename _IndicesType> class TranspositionsWrapper;
456 namespace internal {
457 template<typename _IndicesType>
458 struct traits<PermutationWrapper<_IndicesType> >
459 {
460   typedef PermutationStorage StorageKind;
461   typedef void Scalar;
462   typedef typename _IndicesType::Scalar StorageIndex;
463   typedef _IndicesType IndicesType;
464   enum {
465     RowsAtCompileTime = _IndicesType::SizeAtCompileTime,
466     ColsAtCompileTime = _IndicesType::SizeAtCompileTime,
467     MaxRowsAtCompileTime = IndicesType::MaxSizeAtCompileTime,
468     MaxColsAtCompileTime = IndicesType::MaxSizeAtCompileTime,
469     Flags = 0
470   };
471 };
472 }
473 
474 /** \class PermutationWrapper
475   * \ingroup Core_Module
476   *
477   * \brief Class to view a vector of integers as a permutation matrix
478   *
479   * \tparam _IndicesType the type of the vector of integer (can be any compatible expression)
480   *
481   * This class allows to view any vector expression of integers as a permutation matrix.
482   *
483   * \sa class PermutationBase, class PermutationMatrix
484   */
485 template<typename _IndicesType>
486 class PermutationWrapper : public PermutationBase<PermutationWrapper<_IndicesType> >
487 {
488     typedef PermutationBase<PermutationWrapper> Base;
489     typedef internal::traits<PermutationWrapper> Traits;
490   public:
491 
492     #ifndef EIGEN_PARSED_BY_DOXYGEN
493     typedef typename Traits::IndicesType IndicesType;
494     #endif
495 
496     inline PermutationWrapper(const IndicesType& indices)
497       : m_indices(indices)
498     {}
499 
500     /** const version of indices(). */
501     const typename internal::remove_all<typename IndicesType::Nested>::type&
502     indices() const { return m_indices; }
503 
504   protected:
505 
506     typename IndicesType::Nested m_indices;
507 };
508 
509 
510 /** \returns the matrix with the permutation applied to the columns.
511   */
512 template<typename MatrixDerived, typename PermutationDerived>
513 EIGEN_DEVICE_FUNC
514 const Product<MatrixDerived, PermutationDerived, AliasFreeProduct>
515 operator*(const MatrixBase<MatrixDerived> &matrix,
516           const PermutationBase<PermutationDerived>& permutation)
517 {
518   return Product<MatrixDerived, PermutationDerived, AliasFreeProduct>
519             (matrix.derived(), permutation.derived());
520 }
521 
522 /** \returns the matrix with the permutation applied to the rows.
523   */
524 template<typename PermutationDerived, typename MatrixDerived>
525 EIGEN_DEVICE_FUNC
526 const Product<PermutationDerived, MatrixDerived, AliasFreeProduct>
527 operator*(const PermutationBase<PermutationDerived> &permutation,
528           const MatrixBase<MatrixDerived>& matrix)
529 {
530   return Product<PermutationDerived, MatrixDerived, AliasFreeProduct>
531             (permutation.derived(), matrix.derived());
532 }
533 
534 
535 template<typename PermutationType>
536 class InverseImpl<PermutationType, PermutationStorage>
537   : public EigenBase<Inverse<PermutationType> >
538 {
539     typedef typename PermutationType::PlainPermutationType PlainPermutationType;
540     typedef internal::traits<PermutationType> PermTraits;
541   protected:
542     InverseImpl() {}
543   public:
544     typedef Inverse<PermutationType> InverseType;
545     using EigenBase<Inverse<PermutationType> >::derived;
546 
547     #ifndef EIGEN_PARSED_BY_DOXYGEN
548     typedef typename PermutationType::DenseMatrixType DenseMatrixType;
549     enum {
550       RowsAtCompileTime = PermTraits::RowsAtCompileTime,
551       ColsAtCompileTime = PermTraits::ColsAtCompileTime,
552       MaxRowsAtCompileTime = PermTraits::MaxRowsAtCompileTime,
553       MaxColsAtCompileTime = PermTraits::MaxColsAtCompileTime
554     };
555     #endif
556 
557     #ifndef EIGEN_PARSED_BY_DOXYGEN
558     template<typename DenseDerived>
559     void evalTo(MatrixBase<DenseDerived>& other) const
560     {
561       other.setZero();
562       for (Index i=0; i<derived().rows();++i)
563         other.coeffRef(i, derived().nestedExpression().indices().coeff(i)) = typename DenseDerived::Scalar(1);
564     }
565     #endif
566 
567     /** \return the equivalent permutation matrix */
568     PlainPermutationType eval() const { return derived(); }
569 
570     DenseMatrixType toDenseMatrix() const { return derived(); }
571 
572     /** \returns the matrix with the inverse permutation applied to the columns.
573       */
574     template<typename OtherDerived> friend
575     const Product<OtherDerived, InverseType, AliasFreeProduct>
576     operator*(const MatrixBase<OtherDerived>& matrix, const InverseType& trPerm)
577     {
578       return Product<OtherDerived, InverseType, AliasFreeProduct>(matrix.derived(), trPerm.derived());
579     }
580 
581     /** \returns the matrix with the inverse permutation applied to the rows.
582       */
583     template<typename OtherDerived>
584     const Product<InverseType, OtherDerived, AliasFreeProduct>
585     operator*(const MatrixBase<OtherDerived>& matrix) const
586     {
587       return Product<InverseType, OtherDerived, AliasFreeProduct>(derived(), matrix.derived());
588     }
589 };
590 
591 template<typename Derived>
592 const PermutationWrapper<const Derived> MatrixBase<Derived>::asPermutation() const
593 {
594   return derived();
595 }
596 
597 namespace internal {
598 
599 template<> struct AssignmentKind<DenseShape,PermutationShape> { typedef EigenBase2EigenBase Kind; };
600 
601 } // end namespace internal
602 
603 } // end namespace Eigen
604 
605 #endif // EIGEN_PERMUTATIONMATRIX_H
606