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()
* Array for internal storage of decomposition.
* Array for internal storage of diagonal of R.
* QR Decomposition computed by Householder reflections.
* @param matrix $A Rectangular matrix
* @return Structure to access R and the Householder vectors and compute Q.
if( is_a($A, 'Matrix') ) {
$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;
* 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)
* 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++ )
* 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.
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));
|