[eigen] qr().solve() implementation |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen <eigen@xxxxxxxxxxxxxxxxxxx>
- Subject: [eigen] qr().solve() implementation
- From: Keir Mierle <mierle@xxxxxxxxx>
- Date: Tue, 27 Jan 2009 10:33:51 -0800
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:date:message-id:subject :from:to:content-type; bh=XDHn1E/b8uY0zjKeC9riED2a1PpuW23Ly4vaTfiu8w0=; b=llGNcxXrwmadnmbFyANwhyu4kpvUOxVFSGQtBHA1pNY8qxLifMeQeb2+Sr1ue0Wa3C DFFK5ozrY/zf0WscMCywmr59vhdHMAXii5oQ+UhcPFIsFVQ1h+Vrdh0wunaQYb1bTMM6 3NqujMrJJ/L3rgrPkwKnj2SXHg+bnq8Jwxyjo=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=DiTKEIJorFgJ1hw58+z09Ljj4KR002zg0fqZ1bmkue3OFbeDdaWeNB68ZPzALS0+/c i/6jDghlK3ytWyK0xOqqyEupBag8e5fEss6YBX7Kdi9JEo5+ZBn5UT9yb7nQ19OPcOhY oCyip9GllmrRtsEqFxhX5Kp+PINxYkblOGPSM=
Here is a (incomplete) implementation of qr().solve(b, &x).
There is something wrong with the generated docs; it seems to take the
results from LU_solve.cpp rather than QR_solve.cpp but I don't have
time to figure this out now.
It is probably wasteful in that it explicitly computes matrixQ() and
matrixR(). However, it does work.
Keir
Index: doc/snippets/compile_snippet.cpp.in
===================================================================
--- doc/snippets/compile_snippet.cpp.in (revision 917187)
+++ doc/snippets/compile_snippet.cpp.in (working copy)
@@ -1,6 +1,7 @@
#include <Eigen/Core>
#include <Eigen/Array>
#include <Eigen/LU>
+#include <Eigen/QR>
#include <Eigen/Cholesky>
#include <Eigen/Geometry>
Index: doc/snippets/QR_solve.cpp
===================================================================
--- doc/snippets/QR_solve.cpp (revision 0)
+++ doc/snippets/QR_solve.cpp (revision 0)
@@ -0,0 +1,14 @@
+typedef Matrix<float,3,3> Matrix3x3;
+Matrix3x3 m = Matrix3x3::Random();
+Matrix3f y = Matrix3f::Random();
+cout << "Here is the matrix m:" << endl << m << endl;
+cout << "Here is the matrix y:" << endl << y << endl;
+Matrix3f x;
+if(m.qr().solve(y, &x))
+{
+ 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;
+
Index: Eigen/src/QR/QR.h
===================================================================
--- Eigen/src/QR/QR.h (revision 917187)
+++ Eigen/src/QR/QR.h (working copy)
@@ -69,6 +69,32 @@
return MatrixRBlockType(m_qr, 0, 0, cols, cols).nestByValue().template part<UpperTriangular>();
}
+ /** This method finds a solution x to the equation Ax=b, where A is the matrix of which
+ * *this is the QR decomposition, if any exists.
+ *
+ * \param b the right-hand-side of the equation to solve. Must be a vector
+ * with the same number of rows as A.
+ * \param result a pointer to the vector in which to store the solution, if any exists.
+ * Resized if necessary, so that result->rows()==A.cols() and result->cols()==b.cols().
+ * If no solution exists, *result is left with undefined coefficients.
+ *
+ * \returns true if any solution exists, false if no solution exists.
+ *
+ * \note If there exist more than one solution, this method will arbitrarily choose one.
+ * 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 The case where b is a matrix is not yet implemented. Also, this
+ * code is space inefficient.
+ *
+ * Example: \include QR_solve.cpp
+ * Output: \verbinclude QR_solve.out
+ *
+ * \sa MatrixBase::solveTriangular(), kernel(), computeKernel(), inverse(), computeInverse()
+ */
+ template<typename OtherDerived, typename ResultType>
+ bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const;
+
MatrixType matrixQ(void) const;
private:
@@ -160,6 +186,25 @@
}
}
+template<typename MatrixType>
+template<typename OtherDerived, typename ResultType>
+bool QR<MatrixType>::solve(
+ const MatrixBase<OtherDerived>& b,
+ ResultType *result
+) const
+{
+ const int rows = m_qr.rows();
+ ei_assert(b.rows() == rows);
+ ei_assert(b.cols() == 1); // TODO(keir): Support more than one column in b.
+
+ result->resize(rows, b.cols());
+ // TODO(keir): There is almost certainly a faster way to multiply by
+ // Q^T without explicitly forming matrixQ(). Investigate.
+ *result = matrixR().solveTriangular(matrixQ().transpose()*b);
+ // TODO(keir): Triangular solver can't fail; is that what's wanted here?
+ return true;
+}
+
/** \returns the matrix Q */
template<typename MatrixType>
MatrixType QR<MatrixType>::matrixQ(void) const