merge with main repository

This commit is contained in:
Thomas Capricelli
2009-11-09 19:02:52 +01:00
123 changed files with 3010 additions and 2213 deletions

View File

@@ -55,8 +55,8 @@ matrix with a vector or another matrix: \f$ A^{-1} \mathbf{v} \f$ or \f$ A^{-1}
This is a general-purpose algorithm which performs well in most cases (provided the matrix \f$ A \f$
is invertible), so if you are unsure about which algorithm to pick, choose this. The method proceeds
in two steps. First, the %LU decomposition with partial pivoting is computed using the
MatrixBase::partialLu() function. This yields an object of the class PartialLU. Then, the
PartialLU::solve() method is called to compute a solution.
MatrixBase::partialPivLu() function. This yields an object of the class PartialPivLU. Then, the
PartialPivLU::solve() method is called to compute a solution.
As an example, suppose we want to solve the following system of linear equations:
@@ -69,9 +69,9 @@ As an example, suppose we want to solve the following system of linear equations
The following program solves this system:
<table class="tutorial_code"><tr><td>
\include Tutorial_PartialLU_solve.cpp
\include Tutorial_PartialPivLU_solve.cpp
</td><td>
output: \include Tutorial_PartialLU_solve.out
output: \include Tutorial_PartialPivLU_solve.out
</td></tr></table>
There are many situations in which we want to solve the same system of equations with different
@@ -91,7 +91,7 @@ problem, and whether you want to solve it at all, after you solved the first pro
case, it's best to save the %LU decomposition and reuse it to solve the second problem. This is
worth the effort because computing the %LU decomposition is much more expensive than using it to
solve the equation. Here is some code to illustrate the procedure. It uses the constructor
PartialLU::PartialLU(const MatrixType&) to compute the %LU decomposition.
PartialPivLU::PartialPivLU(const MatrixType&) to compute the %LU decomposition.
<table class="tutorial_code"><tr><td>
\include Tutorial_solve_reuse_decomposition.cpp
@@ -102,7 +102,7 @@ output: \include Tutorial_solve_reuse_decomposition.out
\b Warning: All this code presumes that the matrix \f$ A \f$ is invertible, so that the system
\f$ A \mathbf{x} = \mathbf{b} \f$ has a unique solution. If the matrix \f$ A \f$ is not invertible,
then the system \f$ A \mathbf{x} = \mathbf{b} \f$ has either zero or infinitely many solutions. In
both cases, PartialLU::solve() will give nonsense results. For example, suppose that we want to
both cases, PartialPivLU::solve() will give nonsense results. For example, suppose that we want to
solve the same system as above, but with the 10 in the last equation replaced by 9. Then the system
of equations is inconsistent: adding the first and the third equation gives \f$ 8x + 10y + 12z = 7 \f$,
which implies \f$ 4x + 5y + 6z = 3\frac12 \f$, in contradiction with the second equation. If we try
@@ -114,10 +114,10 @@ to solve this inconsistent system with Eigen, we find:
output: \include Tutorial_solve_singular.out
</td></tr></table>
The %LU decomposition with \b full pivoting (class LU) and the singular value decomposition (class
The %LU decomposition with \b full pivoting (class FullPivLU) and the singular value decomposition (class
SVD) may be helpful in this case, as explained in the section \ref TutorialAdvSolvers_Misc below.
\sa LU_Module, MatrixBase::partialLu(), PartialLU::solve(), class PartialLU.
\sa LU_Module, MatrixBase::partialPivLu(), PartialPivLU::solve(), class PartialPivLU.
\subsection TutorialAdvSolvers_Cholesky Cholesky decomposition
@@ -228,7 +228,7 @@ Note that the function inverse() is defined in the \ref LU_Module.
Finally, Eigen also offer solvers based on a singular value decomposition (%SVD) or the %LU
decomposition with full pivoting. These have the same API as the solvers based on the %LU
decomposition with partial pivoting (PartialLU).
decomposition with partial pivoting (PartialPivLU).
The solver based on the %SVD uses the class SVD. It can handle singular matrices. Here is an example
of its use:
@@ -245,7 +245,7 @@ svdOfA.solve(b, &x);
\endcode
%LU decomposition with full pivoting has better numerical stability than %LU decomposition with
partial pivoting. It is defined in the class LU. The solver can also handle singular matrices.
partial pivoting. It is defined in the class FullPivLU. The solver can also handle singular matrices.
\code
#include <Eigen/LU>
@@ -254,13 +254,13 @@ MatrixXf A = MatrixXf::Random(20,20);
VectorXf b = VectorXf::Random(20);
VectorXf x;
A.lu().solve(b, &x);
LU<MatrixXf> luOfA(A);
FullPivLU<MatrixXf> luOfA(A);
luOfA.solve(b, &x);
\endcode
See the section \ref TutorialAdvLU below.
\sa class SVD, SVD::solve(), SVD_Module, class LU, LU::solve(), LU_Module.
\sa class SVD, SVD::solve(), SVD_Module, class FullPivLU, LU::solve(), LU_Module.
@@ -281,7 +281,7 @@ Alternatively, you can construct a named LU decomposition, which allows you to r
\code
#include <Eigen/LU>
MatrixXf A = MatrixXf::Random(20,20);
Eigen::LU<MatrixXf> lu(A);
Eigen::FullPivLU<MatrixXf> lu(A);
cout << "The rank of A is" << lu.rank() << endl;
if(lu.isInvertible()) {
cout << "A is invertible, its inverse is:" << endl << lu.inverse() << endl;
@@ -292,7 +292,7 @@ else {
}
\endcode
\sa LU_Module, LU::solve(), class LU
\sa LU_Module, LU::solve(), class FullPivLU
<a href="#" class="top">top</a>\section TutorialAdvCholesky Cholesky
todo

View File

@@ -215,7 +215,10 @@ ALIASES = "only_for_vectors=This is only for vectors (either row-
"eigenvalues_module=This is defined in the %Eigenvalues module. \code #include <Eigen/Eigenvalues> \endcode" \
"label=\bug" \
"redstar=<a href='#warningarraymodule' style='color:red;text-decoration: none;'>*</a>" \
"nonstableyet=\warning This is not considered to be part of the stable public API yet. Changes may happen in future releases. See \ref Experimental \"Experimental parts of Eigen\""
"nonstableyet=\warning This is not considered to be part of the stable public API yet. Changes may happen in future releases. See \ref Experimental \"Experimental parts of Eigen\"" \
"note_about_arbitrary_choice_of_solution=If there exists more than one solution, this method will arbitrarily choose one." \
"note_about_using_kernel_to_study_multiple_solutions=If you need a complete analysis of the space of solutions, take the one solution obtained by this method and add to it elements of the kernel, as determined by kernel()." \
"note_about_checking_solutions=This method just tries to find as good a solution as possible. If you want to check whether a solution exists or if it is accurate, just call this function to get a result and then compute the error of this result, or use MatrixBase::isApprox() directly, for instance like this: \code bool a_solution_exists = (A*result).isApprox(b, precision); \endcode This method avoids dividing by zero, so that the non-existence of a solution doesn't by itself mean that you'll get \c inf or \c nan values."
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.

View File

@@ -12,7 +12,6 @@ int main(int, char *[])
b << 3, 3, 4;
cout << "Here is the matrix A:" << endl << A << endl;
cout << "Here is the vector b:" << endl << b << endl;
Vector3f x;
A.partialLu().solve(b, &x);
Vector3f x = A.lu().solve(b);
cout << "The solution is:" << endl << x << endl;
}

View File

@@ -6,4 +6,4 @@ cout << "Here is the matrix m:" << endl << m << endl;
cout << "Notice that the middle column is the sum of the two others, so the "
<< "columns are linearly dependent." << endl;
cout << "Here is a matrix whose columns have the same span but are linearly independent:"
<< endl << m.lu().image() << endl;
<< endl << m.fullPivLu().image(m) << endl;

View File

@@ -1,6 +1,6 @@
MatrixXf m = MatrixXf::Random(3,5);
cout << "Here is the matrix m:" << endl << m << endl;
MatrixXf ker = m.lu().kernel();
MatrixXf ker = m.fullPivLu().kernel();
cout << "Here is a matrix whose columns form a basis of the kernel of m:"
<< endl << ker << endl;
cout << "By definition of the kernel, m*ker is zero:"

View File

@@ -1,15 +1,11 @@
typedef Matrix<float,2,3> Matrix2x3;
typedef Matrix<float,3,2> Matrix3x2;
Matrix2x3 m = Matrix2x3::Random();
Matrix<float,2,3> m = Matrix<float,2,3>::Random();
Matrix2f y = Matrix2f::Random();
cout << "Here is the matrix m:" << endl << m << endl;
cout << "Here is the matrix y:" << endl << y << endl;
Matrix3x2 x;
if(m.lu().solve(y, &x))
Matrix<float,3,2> x = m.fullPivLu().solve(y);
if((m*x).isApprox(y))
{
assert(y.isApprox(m*x));
cout << "Here is a solution x to the equation mx=y:" << endl << x << endl;
}
else
cout << "The equation mx=y does not have any solution." << endl;

View File

@@ -4,6 +4,6 @@ Matrix3f y = Matrix3f::Random();
cout << "Here is the matrix m:" << endl << m << endl;
cout << "Here is the matrix y:" << endl << y << endl;
Matrix3f x;
m.householderQr().solve(y, &x);
x = m.householderQr().solve(y);
assert(y.isApprox(m*x));
cout << "Here is a solution x to the equation mx=y:" << endl << x << endl;

View File

@@ -3,6 +3,6 @@ typedef Matrix<float,Dynamic,2> DataMatrix;
DataMatrix samples = DataMatrix::Random(12,2);
VectorXf elevations = 2*samples.col(0) + 3*samples.col(1) + VectorXf::Random(12)*0.1;
// and let's solve samples * [x y]^T = elevations in least square sense:
Matrix<float,2,1> xy;
(samples.adjoint() * samples).llt().solve((samples.adjoint()*elevations), &xy);
Matrix<float,2,1> xy
= (samples.adjoint() * samples).llt().solve((samples.adjoint()*elevations));
cout << xy << endl;

View File

@@ -1,13 +0,0 @@
MatrixXd m(3,3);
m << 1,1,0,
1,3,2,
0,1,1;
cout << "Here is the matrix m:" << endl << m << endl;
LU<Matrix3d> lu(m);
// allocate the matrix img with the correct size to avoid reallocation
MatrixXd img(m.rows(), lu.rank());
lu.computeImage(&img);
cout << "Notice that the middle column is the sum of the two others, so the "
<< "columns are linearly dependent." << endl;
cout << "Here is a matrix whose columns have the same span but are linearly independent:"
<< endl << img << endl;

View File

@@ -1,10 +0,0 @@
MatrixXf m = MatrixXf::Random(3,5);
cout << "Here is the matrix m:" << endl << m << endl;
LU<MatrixXf> lu(m);
// allocate the matrix ker with the correct size to avoid reallocation
MatrixXf ker(m.rows(), lu.dimensionOfKernel());
lu.computeKernel(&ker);
cout << "Here is a matrix whose columns form a basis of the kernel of m:"
<< endl << ker << endl;
cout << "By definition of the kernel, m*ker is zero:"
<< endl << m*ker << endl;

View File

@@ -1,5 +0,0 @@
Matrix3d m = Matrix3d::Random();
cout << "Here is the matrix m:" << endl << m << endl;
Matrix3d inv;
m.computeInverse(&inv);
cout << "Its inverse is:" << endl << inv << endl;

View File

@@ -0,0 +1,13 @@
Matrix3d m = Matrix3d::Random();
cout << "Here is the matrix m:" << endl << m << endl;
Matrix3d inverse;
bool invertible;
double determinant;
m.computeInverseAndDetWithCheck(inverse,determinant,invertible);
cout << "Its determinant is " << determinant << endl;
if(invertible) {
cout << "It is invertible, and its inverse is:" << endl << inverse << endl;
}
else {
cout << "It is not invertible." << endl;
}

View File

@@ -1,8 +1,10 @@
Matrix3d m = Matrix3d::Random();
cout << "Here is the matrix m:" << endl << m << endl;
Matrix3d inv;
if(m.computeInverseWithCheck(&inv)) {
cout << "It is invertible, and its inverse is:" << endl << inv << endl;
Matrix3d inverse;
bool invertible;
m.computeInverseWithCheck(inverse,invertible);
if(invertible) {
cout << "It is invertible, and its inverse is:" << endl << inverse << endl;
}
else {
cout << "It is not invertible." << endl;

View File

@@ -2,7 +2,6 @@ MatrixXd A = MatrixXd::Random(3,3);
MatrixXd B = MatrixXd::Random(3,2);
cout << "Here is the invertible matrix A:" << endl << A << endl;
cout << "Here is the matrix B:" << endl << B << endl;
MatrixXd X;
if(A.lu().solve(B, &X))
MatrixXd X = A.lu().solve(B);
cout << "Here is the (unique) solution X to the equation AX=B:" << endl << X << endl;
cout << "Relative error: " << (A*X-B).norm() / B.norm() << endl;

View File

@@ -3,7 +3,7 @@ A << 1,2,3, 4,5,6, 7,8,10;
Matrix<float,3,2> B;
B << 3,1, 3,1, 4,1;
Matrix<float,3,2> X;
A.partialLu().solve(B, &X);
X = A.lu().solve(B);
cout << "The solution with right-hand side (3,3,4) is:" << endl;
cout << X.col(0) << endl;
cout << "The solution with right-hand side (1,1,1) is:" << endl;

View File

@@ -1,13 +1,13 @@
Matrix3f A(3,3);
A << 1,2,3, 4,5,6, 7,8,10;
PartialLU<Matrix3f> luOfA(A); // compute LU decomposition of A
PartialPivLU<Matrix3f> luOfA(A); // compute LU decomposition of A
Vector3f b;
b << 3,3,4;
Vector3f x;
luOfA.solve(b, &x);
x = luOfA.solve(b);
cout << "The solution with right-hand side (3,3,4) is:" << endl;
cout << x << endl;
b << 1,1,1;
luOfA.solve(b, &x);
x = luOfA.solve(b);
cout << "The solution with right-hand side (1,1,1) is:" << endl;
cout << x << endl;

View File

@@ -5,5 +5,5 @@ b << 3, 3, 4;
cout << "Here is the matrix A:" << endl << A << endl;
cout << "Here is the vector b:" << endl << b << endl;
Vector3f x;
A.partialLu().solve(b, &x);
x = A.lu().solve(b);
cout << "The solution is:" << endl << x << endl;

View File

@@ -2,7 +2,7 @@ typedef Matrix<double, 5, 3> Matrix5x3;
typedef Matrix<double, 5, 5> Matrix5x5;
Matrix5x3 m = Matrix5x3::Random();
cout << "Here is the matrix m:" << endl << m << endl;
Eigen::LU<Matrix5x3> lu(m);
Eigen::FullPivLU<Matrix5x3> lu(m);
cout << "Here is, up to permutations, its LU decomposition matrix:"
<< endl << lu.matrixLU() << endl;
cout << "Here is the L part:" << endl;