JAMA
[ class tree: JAMA ] [ index: JAMA ] [ all elements ]

Source for file QRDecomposition.php

Documentation is available at QRDecomposition.php

  1. <?php
  2. /**
  3.  *    @package JAMA
  4.  *
  5.  *     For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n
  6.  *     orthogonal matrix Q and an n-by-n upper triangular matrix R so that
  7.  *     A = Q*R.
  8.  *
  9.  *     The QR decompostion always exists, even if the matrix does not have
  10.  *     full rank, so the constructor will never fail.  The primary use of the
  11.  *     QR decomposition is in the least squares solution of nonsquare systems
  12.  *     of simultaneous linear equations.  This will fail if isFullRank()
  13.  *     returns false.
  14.  *
  15.  *    @author  Paul Meagher
  16.  *    @license PHP v3.0
  17.  *    @version 1.1
  18.  */
  19.  
  20.     const MatrixRankException    "Can only perform operation on full-rank matrix.";
  21.  
  22.     /**
  23.      *    Array for internal storage of decomposition.
  24.      *    @var array 
  25.      */
  26.     private $QR array();
  27.  
  28.     /**
  29.      *    Row dimension.
  30.      *    @var integer 
  31.      */
  32.     private $m;
  33.  
  34.     /**
  35.     *    Column dimension.
  36.     *    @var integer 
  37.     */
  38.     private $n;
  39.  
  40.     /**
  41.      *    Array for internal storage of diagonal of R.
  42.      *    @var  array 
  43.      */
  44.     private $Rdiag array();
  45.  
  46.  
  47.     /**
  48.      *    QR Decomposition computed by Householder reflections.
  49.      *
  50.      *    @param matrix $A Rectangular matrix
  51.      *    @return Structure to access R and the Householder vectors and compute Q.
  52.      */
  53.     public function __construct($A{
  54.         if($A instanceof PHPExcel_Shared_JAMA_Matrix{
  55.             // Initialize.
  56.             $this->QR $A->getArrayCopy();
  57.             $this->m  $A->getRowDimension();
  58.             $this->n  $A->getColumnDimension();
  59.             // Main loop.
  60.             for ($k 0$k $this->n++$k{
  61.                 // Compute 2-norm of k-th column without under/overflow.
  62.                 $nrm 0.0;
  63.                 for ($i $k$i $this->m++$i{
  64.                     $nrm hypo($nrm$this->QR[$i][$k]);
  65.                 }
  66.                 if ($nrm != 0.0{
  67.                     // Form k-th Householder vector.
  68.                     if ($this->QR[$k][$k0{
  69.                         $nrm = -$nrm;
  70.                     }
  71.                     for ($i $k$i $this->m++$i{
  72.                         $this->QR[$i][$k/= $nrm;
  73.                     }
  74.                     $this->QR[$k][$k+= 1.0;
  75.                     // Apply transformation to remaining columns.
  76.                     for ($j $k+1$j $this->n++$j{
  77.                         $s 0.0;
  78.                         for ($i $k$i $this->m++$i{
  79.                             $s += $this->QR[$i][$k$this->QR[$i][$j];
  80.                         }
  81.                         $s = -$s/$this->QR[$k][$k];
  82.                         for ($i $k$i $this->m++$i{
  83.                             $this->QR[$i][$j+= $s $this->QR[$i][$k];
  84.                         }
  85.                     }
  86.                 }
  87.                 $this->Rdiag[$k= -$nrm;
  88.             }
  89.         else {
  90.             throw new Exception(PHPExcel_Shared_JAMA_Matrix::ArgumentTypeException);
  91.         }
  92.     }    //    function __construct()
  93.  
  94.  
  95.     /**
  96.      *    Is the matrix full rank?
  97.      *
  98.      *    @return boolean true if R, and hence A, has full rank, else false.
  99.      */
  100.     public function isFullRank({
  101.         for ($j 0$j $this->n++$j{
  102.             if ($this->Rdiag[$j== 0{
  103.                 return false;
  104.             }
  105.         }
  106.         return true;
  107.     }    //    function isFullRank()
  108.  
  109.  
  110.     /**
  111.      *    Return the Householder vectors
  112.      *
  113.      *    @return Matrix Lower trapezoidal matrix whose columns define the reflections
  114.      */
  115.     public function getH({
  116.         for ($i 0$i $this->m++$i{
  117.             for ($j 0$j $this->n++$j{
  118.                 if ($i >= $j{
  119.                     $H[$i][$j$this->QR[$i][$j];
  120.                 else {
  121.                     $H[$i][$j0.0;
  122.                 }
  123.             }
  124.         }
  125.         return new PHPExcel_Shared_JAMA_Matrix($H);
  126.     }    //    function getH()
  127.  
  128.  
  129.     /**
  130.      *    Return the upper triangular factor
  131.      *
  132.      *    @return Matrix upper triangular factor
  133.      */
  134.     public function getR({
  135.         for ($i 0$i $this->n++$i{
  136.             for ($j 0$j $this->n++$j{
  137.                 if ($i $j{
  138.                     $R[$i][$j$this->QR[$i][$j];
  139.                 elseif ($i == $j{
  140.                     $R[$i][$j$this->Rdiag[$i];
  141.                 else {
  142.                     $R[$i][$j0.0;
  143.                 }
  144.             }
  145.         }
  146.         return new PHPExcel_Shared_JAMA_Matrix($R);
  147.     }    //    function getR()
  148.  
  149.  
  150.     /**
  151.      *    Generate and return the (economy-sized) orthogonal factor
  152.      *
  153.      *    @return Matrix orthogonal factor
  154.      */
  155.     public function getQ({
  156.         for ($k $this->n-1$k >= 0--$k{
  157.             for ($i 0$i $this->m++$i{
  158.                 $Q[$i][$k0.0;
  159.             }
  160.             $Q[$k][$k1.0;
  161.             for ($j $k$j $this->n++$j{
  162.                 if ($this->QR[$k][$k!= 0{
  163.                     $s 0.0;
  164.                     for ($i $k$i $this->m++$i{
  165.                         $s += $this->QR[$i][$k$Q[$i][$j];
  166.                     }
  167.                     $s = -$s/$this->QR[$k][$k];
  168.                     for ($i $k$i $this->m++$i{
  169.                         $Q[$i][$j+= $s $this->QR[$i][$k];
  170.                     }
  171.                 }
  172.             }
  173.         }
  174.         /*
  175.         for($i = 0; $i < count($Q); ++$i) {
  176.             for($j = 0; $j < count($Q); ++$j) {
  177.                 if(! isset($Q[$i][$j]) ) {
  178.                     $Q[$i][$j] = 0;
  179.                 }
  180.             }
  181.         }
  182.         */
  183.         return new PHPExcel_Shared_JAMA_Matrix($Q);
  184.     }    //    function getQ()
  185.  
  186.  
  187.     /**
  188.      *    Least squares solution of A*X = B
  189.      *
  190.      *    @param Matrix $B A Matrix with as many rows as A and any number of columns.
  191.      *    @return Matrix Matrix that minimizes the two norm of Q*R*X-B.
  192.      */
  193.     public function solve($B{
  194.         if ($B->getRowDimension(== $this->m{
  195.             if ($this->isFullRank()) {
  196.                 // Copy right hand side
  197.                 $nx $B->getColumnDimension();
  198.                 $X  $B->getArrayCopy();
  199.                 // Compute Y = transpose(Q)*B
  200.                 for ($k 0$k $this->n++$k{
  201.                     for ($j 0$j $nx++$j{
  202.                         $s 0.0;
  203.                         for ($i $k$i $this->m++$i{
  204.                             $s += $this->QR[$i][$k$X[$i][$j];
  205.                         }
  206.                         $s = -$s/$this->QR[$k][$k];
  207.                         for ($i $k$i $this->m++$i{
  208.                             $X[$i][$j+= $s $this->QR[$i][$k];
  209.                         }
  210.                     }
  211.                 }
  212.                 // Solve R*X = Y;
  213.                 for ($k $this->n-1$k >= 0--$k{
  214.                     for ($j 0$j $nx++$j{
  215.                         $X[$k][$j/= $this->Rdiag[$k];
  216.                     }
  217.                     for ($i 0$i $k++$i{
  218.                         for ($j 0$j $nx++$j{
  219.                             $X[$i][$j-= $X[$k][$j]$this->QR[$i][$k];
  220.                         }
  221.                     }
  222.                 }
  223.                 $X new PHPExcel_Shared_JAMA_Matrix($X);
  224.                 return ($X->getMatrix(0$this->n-10$nx));
  225.             else {
  226.                 throw new Exception(self::MatrixRankException);
  227.             }
  228.         else {
  229.             throw new Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException);
  230.         }
  231.     }    //    function solve()
  232.  
  233. }    //    PHPExcel_Shared_JAMA_class QRDecomposition

Documentation generated on Sun, 27 Feb 2011 16:33:39 -0800 by phpDocumentor 1.4.3