Source for file QRDecomposition.php
Documentation is available at QRDecomposition.php
* For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n
* orthogonal matrix Q and an n-by-n upper triangular matrix R so that
* The QR decompostion always exists, even if the matrix does not have
* full rank, so the constructor will never fail. The primary use of the
* QR decomposition is in the least squares solution of nonsquare systems
* of simultaneous linear equations. This will fail if isFullRank()
const MatrixRankException = "Can only perform operation on full-rank matrix.";
* Array for internal storage of decomposition.
* Array for internal storage of diagonal of R.
private $Rdiag = array();
* QR Decomposition computed by Householder reflections.
* @param matrix $A Rectangular matrix
* @return Structure to access R and the Householder vectors and compute Q.
$this->QR = $A->getArrayCopy();
$this->m = $A->getRowDimension();
$this->n = $A->getColumnDimension();
for ($k = 0; $k < $this->n; ++ $k) {
// Compute 2-norm of k-th column without under/overflow.
for ($i = $k; $i < $this->m; ++ $i) {
$nrm = hypo($nrm, $this->QR[$i][$k]);
// Form k-th Householder vector.
if ($this->QR[$k][$k] < 0) {
for ($i = $k; $i < $this->m; ++ $i) {
$this->QR[$i][$k] /= $nrm;
$this->QR[$k][$k] += 1.0;
// Apply transformation to remaining columns.
for ($j = $k+ 1; $j < $this->n; ++ $j) {
for ($i = $k; $i < $this->m; ++ $i) {
$s += $this->QR[$i][$k] * $this->QR[$i][$j];
$s = - $s/ $this->QR[$k][$k];
for ($i = $k; $i < $this->m; ++ $i) {
$this->QR[$i][$j] += $s * $this->QR[$i][$k];
$this->Rdiag[$k] = - $nrm;
} // function __construct()
* Is the matrix full rank?
* @return boolean true if R, and hence A, has full rank, else false.
for ($j = 0; $j < $this->n; ++ $j) {
if ($this->Rdiag[$j] == 0) {
} // function isFullRank()
* Return the Householder vectors
* @return Matrix Lower trapezoidal matrix whose columns define the reflections
for ($i = 0; $i < $this->m; ++ $i) {
for ($j = 0; $j < $this->n; ++ $j) {
$H[$i][$j] = $this->QR[$i][$j];
* Return the upper triangular factor
* @return Matrix upper triangular factor
for ($i = 0; $i < $this->n; ++ $i) {
for ($j = 0; $j < $this->n; ++ $j) {
$R[$i][$j] = $this->QR[$i][$j];
$R[$i][$j] = $this->Rdiag[$i];
* Generate and return the (economy-sized) orthogonal factor
* @return Matrix orthogonal factor
for ($k = $this->n- 1; $k >= 0; -- $k) {
for ($i = 0; $i < $this->m; ++ $i) {
for ($j = $k; $j < $this->n; ++ $j) {
if ($this->QR[$k][$k] != 0) {
for ($i = $k; $i < $this->m; ++ $i) {
$s += $this->QR[$i][$k] * $Q[$i][$j];
$s = - $s/ $this->QR[$k][$k];
for ($i = $k; $i < $this->m; ++ $i) {
$Q[$i][$j] += $s * $this->QR[$i][$k];
for($i = 0; $i < count($Q); ++$i) {
for($j = 0; $j < count($Q); ++$j) {
if(! isset($Q[$i][$j]) ) {
* Least squares solution of A*X = B
* @param Matrix $B A Matrix with as many rows as A and any number of columns.
* @return Matrix Matrix that minimizes the two norm of Q*R*X-B.
public function solve($B) {
if ($B->getRowDimension() == $this->m) {
$nx = $B->getColumnDimension();
// Compute Y = transpose(Q)*B
for ($k = 0; $k < $this->n; ++ $k) {
for ($j = 0; $j < $nx; ++ $j) {
for ($i = $k; $i < $this->m; ++ $i) {
$s += $this->QR[$i][$k] * $X[$i][$j];
$s = - $s/ $this->QR[$k][$k];
for ($i = $k; $i < $this->m; ++ $i) {
$X[$i][$j] += $s * $this->QR[$i][$k];
for ($k = $this->n- 1; $k >= 0; -- $k) {
for ($j = 0; $j < $nx; ++ $j) {
$X[$k][$j] /= $this->Rdiag[$k];
for ($i = 0; $i < $k; ++ $i) {
for ($j = 0; $j < $nx; ++ $j) {
$X[$i][$j] -= $X[$k][$j]* $this->QR[$i][$k];
return ($X->getMatrix(0, $this->n- 1, 0, $nx));
throw new Exception(self::MatrixRankException);
} // PHPExcel_Shared_JAMA_class QRDecomposition
|