mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-07-30 08:42:00 +08:00
LU: remove partial-pivoting path (moderately useful since it's does
not allow to easily get the rank), fix a bug (which could have been triggered by matrices having coefficients of very different magnitudes). Part: add an assert to prevent hard to find bugs Swap: update comments
This commit is contained in:
parent
88bb2087c1
commit
58ba9ca72f
@ -535,7 +535,7 @@ template<typename Derived> class MatrixBase
|
|||||||
|
|
||||||
/////////// LU module ///////////
|
/////////// LU module ///////////
|
||||||
|
|
||||||
const LU<EvalType> lu(int pivoting) const;
|
const LU<EvalType> lu() const;
|
||||||
const EvalType inverse() const;
|
const EvalType inverse() const;
|
||||||
void computeInverse(EvalType *result) const;
|
void computeInverse(EvalType *result) const;
|
||||||
Scalar determinant() const;
|
Scalar determinant() const;
|
||||||
|
@ -179,6 +179,7 @@ struct ei_part_assignment_impl
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ei_assert(Mode == Upper || Mode == Lower || Mode == StrictlyUpper || Mode == StrictlyLower);
|
||||||
if((Mode == Upper && row <= col)
|
if((Mode == Upper && row <= col)
|
||||||
|| (Mode == Lower && row >= col)
|
|| (Mode == Lower && row >= col)
|
||||||
|| (Mode == StrictlyUpper && row < col)
|
|| (Mode == StrictlyUpper && row < col)
|
||||||
|
@ -27,14 +27,9 @@
|
|||||||
|
|
||||||
/** \class SwapWrapper
|
/** \class SwapWrapper
|
||||||
*
|
*
|
||||||
* \brief Expression which must be nested by value
|
* \internal
|
||||||
*
|
*
|
||||||
* \param ExpressionType the type of the object of which we are requiring nesting-by-value
|
* \brief Internal helper class for swapping two expressions
|
||||||
*
|
|
||||||
* This class is the return type of MatrixBase::nestByValue()
|
|
||||||
* and most of the time this is the only way it is used.
|
|
||||||
*
|
|
||||||
* \sa MatrixBase::nestByValue()
|
|
||||||
*/
|
*/
|
||||||
template<typename ExpressionType>
|
template<typename ExpressionType>
|
||||||
struct ei_traits<SwapWrapper<ExpressionType> >
|
struct ei_traits<SwapWrapper<ExpressionType> >
|
||||||
@ -116,12 +111,10 @@ template<typename ExpressionType> class SwapWrapper
|
|||||||
|
|
||||||
/** swaps *this with the expression \a other.
|
/** swaps *this with the expression \a other.
|
||||||
*
|
*
|
||||||
* \note \a other is only marked const because I couln't find another way
|
* \note \a other is only marked for internal reasons, but of course
|
||||||
* to get g++ (4.2 and 4.3) to accept that template parameter resolution.
|
* it gets const-casted. One reason is that one will often call swap
|
||||||
* The problem seems to be that when swapping expressions as in
|
* on temporary objects (hence non-const references are forbidden).
|
||||||
* m.row(i).swap(m.row(j)); the Row object returned by row(j) is a temporary
|
* Another reason is that lazyAssign takes a const argument anyway.
|
||||||
* and g++ doesn't dare to pass it by non-constant reference.
|
|
||||||
* It gets const_cast'd of course. TODO: get rid of const here.
|
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
@ -131,3 +124,9 @@ void MatrixBase<Derived>::swap(const MatrixBase<OtherDerived>& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // EIGEN_SWAP_H
|
#endif // EIGEN_SWAP_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,11 +209,6 @@ enum {
|
|||||||
HasDirectAccess = DirectAccessBit
|
HasDirectAccess = DirectAccessBit
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
PartialPivoting,
|
|
||||||
CompletePivoting
|
|
||||||
};
|
|
||||||
|
|
||||||
const int FullyCoherentAccessPattern = 0x1;
|
const int FullyCoherentAccessPattern = 0x1;
|
||||||
const int InnerCoherentAccessPattern = 0x2 | FullyCoherentAccessPattern;
|
const int InnerCoherentAccessPattern = 0x2 | FullyCoherentAccessPattern;
|
||||||
const int OuterCoherentAccessPattern = 0x4 | InnerCoherentAccessPattern;
|
const int OuterCoherentAccessPattern = 0x4 | InnerCoherentAccessPattern;
|
||||||
|
@ -54,7 +54,7 @@ template<typename MatrixType> class LU
|
|||||||
typedef Matrix<int, MatrixType::ColsAtCompileTime, 1> IntRowVectorType;
|
typedef Matrix<int, MatrixType::ColsAtCompileTime, 1> IntRowVectorType;
|
||||||
typedef Matrix<int, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
|
typedef Matrix<int, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
|
||||||
|
|
||||||
LU(const MatrixType& matrix, int pivoting = CompletePivoting);
|
LU(const MatrixType& matrix);
|
||||||
|
|
||||||
inline const MatrixType& matrixLU() const
|
inline const MatrixType& matrixLU() const
|
||||||
{
|
{
|
||||||
@ -81,6 +81,10 @@ template<typename MatrixType> class LU
|
|||||||
return m_q;
|
return m_q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const Matrix<Scalar, MatrixType::RowsAtCompileTime, Dynamic,
|
||||||
|
MatrixType::MaxRowsAtCompileTime,
|
||||||
|
MatrixType::MaxColsAtCompileTime> kernel() const;
|
||||||
|
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
typename ProductReturnType<Transpose<MatrixType>, OtherDerived>::Type::Eval
|
typename ProductReturnType<Transpose<MatrixType>, OtherDerived>::Type::Eval
|
||||||
solve(const MatrixBase<MatrixType> &b) const;
|
solve(const MatrixBase<MatrixType> &b) const;
|
||||||
@ -107,11 +111,21 @@ template<typename MatrixType> class LU
|
|||||||
return m_lu.cols() - m_rank;
|
return m_lu.cols() - m_rank;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isInvertible() const
|
inline bool isInjective() const
|
||||||
{
|
{
|
||||||
return m_rank == m_lu.cols();
|
return m_rank == m_lu.cols();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isSurjective() const
|
||||||
|
{
|
||||||
|
return m_rank == m_lu.rows();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isInvertible() const
|
||||||
|
{
|
||||||
|
return isInjective() && isSurjective();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MatrixType m_lu;
|
MatrixType m_lu;
|
||||||
IntColVectorType m_p;
|
IntColVectorType m_p;
|
||||||
@ -119,61 +133,48 @@ template<typename MatrixType> class LU
|
|||||||
int m_det_pq;
|
int m_det_pq;
|
||||||
Scalar m_biggest_eigenvalue_of_u;
|
Scalar m_biggest_eigenvalue_of_u;
|
||||||
int m_rank;
|
int m_rank;
|
||||||
int m_pivoting;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
LU<MatrixType>::LU(const MatrixType& matrix, int pivoting)
|
LU<MatrixType>::LU(const MatrixType& matrix)
|
||||||
: m_lu(matrix),
|
: m_lu(matrix),
|
||||||
m_p(matrix.rows()),
|
m_p(matrix.rows()),
|
||||||
m_q(matrix.cols()),
|
m_q(matrix.cols())
|
||||||
m_pivoting(pivoting)
|
|
||||||
{
|
{
|
||||||
const int size = matrix.diagonal().size();
|
const int size = matrix.diagonal().size();
|
||||||
const int rows = matrix.rows();
|
const int rows = matrix.rows();
|
||||||
const int cols = matrix.cols();
|
const int cols = matrix.cols();
|
||||||
ei_assert(pivoting == PartialPivoting || pivoting == CompletePivoting);
|
|
||||||
|
|
||||||
IntColVectorType rows_transpositions(matrix.rows());
|
IntColVectorType rows_transpositions(matrix.rows());
|
||||||
IntRowVectorType cols_transpositions(matrix.cols());
|
IntRowVectorType cols_transpositions(matrix.cols());
|
||||||
int number_of_transpositions = 0;
|
int number_of_transpositions = 0;
|
||||||
|
|
||||||
|
RealScalar biggest;
|
||||||
for(int k = 0; k < size; k++)
|
for(int k = 0; k < size; k++)
|
||||||
{
|
{
|
||||||
int row_of_biggest, col_of_biggest;
|
int row_of_biggest_in_corner, col_of_biggest_in_corner;
|
||||||
Scalar biggest;
|
RealScalar biggest_in_corner;
|
||||||
if(m_pivoting == CompletePivoting)
|
|
||||||
{
|
biggest_in_corner = m_lu.corner(Eigen::BottomRight, rows-k, cols-k)
|
||||||
biggest = m_lu.corner(Eigen::BottomRight, rows-k, cols-k)
|
.cwise().abs()
|
||||||
.cwise().abs()
|
.maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
|
||||||
.maxCoeff(&row_of_biggest, &col_of_biggest);
|
row_of_biggest_in_corner += k;
|
||||||
row_of_biggest += k;
|
col_of_biggest_in_corner += k;
|
||||||
col_of_biggest += k;
|
rows_transpositions.coeffRef(k) = row_of_biggest_in_corner;
|
||||||
rows_transpositions.coeffRef(k) = row_of_biggest;
|
cols_transpositions.coeffRef(k) = col_of_biggest_in_corner;
|
||||||
cols_transpositions.coeffRef(k) = col_of_biggest;
|
if(k != row_of_biggest_in_corner) {
|
||||||
if(k != row_of_biggest) {
|
m_lu.row(k).swap(m_lu.row(row_of_biggest_in_corner));
|
||||||
m_lu.row(k).swap(m_lu.row(row_of_biggest));
|
number_of_transpositions++;
|
||||||
number_of_transpositions++;
|
|
||||||
}
|
|
||||||
if(k != col_of_biggest) {
|
|
||||||
m_lu.col(k).swap(m_lu.col(col_of_biggest));
|
|
||||||
number_of_transpositions++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else // partial pivoting
|
if(k != col_of_biggest_in_corner) {
|
||||||
{
|
m_lu.col(k).swap(m_lu.col(col_of_biggest_in_corner));
|
||||||
biggest = m_lu.col(k).end(rows-k)
|
number_of_transpositions++;
|
||||||
.cwise().abs()
|
|
||||||
.maxCoeff(&row_of_biggest);
|
|
||||||
row_of_biggest += k;
|
|
||||||
rows_transpositions.coeffRef(k) = row_of_biggest;
|
|
||||||
if(k != row_of_biggest) {
|
|
||||||
m_lu.row(k).swap(m_lu.row(row_of_biggest));
|
|
||||||
number_of_transpositions++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(k==0) biggest = biggest_in_corner;
|
||||||
const Scalar lu_k_k = m_lu.coeff(k,k);
|
const Scalar lu_k_k = m_lu.coeff(k,k);
|
||||||
if(ei_isMuchSmallerThan(lu_k_k, biggest)) continue;
|
std::cout << lu_k_k << " " << biggest << std::endl;
|
||||||
|
if(ei_isMuchSmallerThan(lu_k_k, biggest)) { std::cout << "hello" << std::endl; continue; }
|
||||||
if(k<rows-1)
|
if(k<rows-1)
|
||||||
m_lu.col(k).end(rows-k-1) /= lu_k_k;
|
m_lu.col(k).end(rows-k-1) /= lu_k_k;
|
||||||
if(k<size-1)
|
if(k<size-1)
|
||||||
@ -185,18 +186,15 @@ LU<MatrixType>::LU(const MatrixType& matrix, int pivoting)
|
|||||||
for(int k = size-1; k >= 0; k--)
|
for(int k = size-1; k >= 0; k--)
|
||||||
std::swap(m_p.coeffRef(k), m_p.coeffRef(rows_transpositions.coeff(k)));
|
std::swap(m_p.coeffRef(k), m_p.coeffRef(rows_transpositions.coeff(k)));
|
||||||
|
|
||||||
if(pivoting == CompletePivoting)
|
for(int k = 0; k < matrix.cols(); k++) m_q.coeffRef(k) = k;
|
||||||
{
|
for(int k = 0; k < size; k++)
|
||||||
for(int k = 0; k < matrix.cols(); k++) m_q.coeffRef(k) = k;
|
std::swap(m_q.coeffRef(k), m_q.coeffRef(cols_transpositions.coeff(k)));
|
||||||
for(int k = 0; k < size; k++)
|
|
||||||
std::swap(m_q.coeffRef(k), m_q.coeffRef(cols_transpositions.coeff(k)));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_det_pq = (number_of_transpositions%2) ? -1 : 1;
|
m_det_pq = (number_of_transpositions%2) ? -1 : 1;
|
||||||
|
|
||||||
int index_of_biggest;
|
int index_of_biggest_in_diagonal;
|
||||||
m_lu.diagonal().cwise().abs().maxCoeff(&index_of_biggest);
|
m_lu.diagonal().cwise().abs().maxCoeff(&index_of_biggest_in_diagonal);
|
||||||
m_biggest_eigenvalue_of_u = m_lu.diagonal().coeff(index_of_biggest);
|
m_biggest_eigenvalue_of_u = m_lu.diagonal().coeff(index_of_biggest_in_diagonal);
|
||||||
|
|
||||||
m_rank = 0;
|
m_rank = 0;
|
||||||
for(int k = 0; k < size; k++)
|
for(int k = 0; k < size; k++)
|
||||||
@ -212,15 +210,27 @@ typename ei_traits<MatrixType>::Scalar LU<MatrixType>::determinant() const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
template<typename MatrixType>
|
||||||
|
inline const Matrix<Scalar, RowsAtCompileTime, Dynamic,
|
||||||
|
MaxRowsAtCompileTime, MaxColsAtCompileTime> kernel() const
|
||||||
|
{
|
||||||
|
Matrix<Scalar, RowsAtCompileTime, Dynamic,
|
||||||
|
MaxRowsAtCompileTime, MaxColsAtCompileTime>
|
||||||
|
result(m_lu.rows(), dimensionOfKernel());
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/** \return the LU decomposition of \c *this.
|
/** \return the LU decomposition of \c *this.
|
||||||
*
|
*
|
||||||
* \sa class LU
|
* \sa class LU
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
const LU<typename MatrixBase<Derived>::EvalType>
|
const LU<typename MatrixBase<Derived>::EvalType>
|
||||||
MatrixBase<Derived>::lu(int pivoting = CompletePivoting) const
|
MatrixBase<Derived>::lu() const
|
||||||
{
|
{
|
||||||
return LU<typename MatrixBase<Derived>::EvalType>(eval(), pivoting);
|
return eval();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EIGEN_LU_H
|
#endif // EIGEN_LU_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user