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

Source for file LUDecomposition.php

Documentation is available at LUDecomposition.php

  1. <?php
  2. /**
  3.  *    @package JAMA
  4.  *
  5.  *     For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
  6.  *     unit lower triangular matrix L, an n-by-n upper triangular matrix U,
  7.  *     and a permutation vector piv of length m so that A(piv,:) = L*U.
  8.  *     If m < n, then L is m-by-m and U is m-by-n.
  9.  *
  10.  *     The LU decompostion with pivoting always exists, even if the matrix is
  11.  *     singular, so the constructor will never fail. The primary use of the
  12.  *     LU decomposition is in the solution of square systems of simultaneous
  13.  *     linear equations. This will fail if isNonsingular() returns false.
  14.  *
  15.  *    @author Paul Meagher
  16.  *    @author Bartosz Matosiuk
  17.  *    @author Michael Bommarito
  18.  *    @version 1.1
  19.  *    @license PHP v3.0
  20.  */
  21. class LUDecomposition {
  22.  
  23.     /**
  24.      *    Decomposition storage
  25.      *    @var array 
  26.      */
  27.     private $LU array();
  28.  
  29.     /**
  30.      *    Row dimension.
  31.      *    @var int 
  32.      */
  33.     private $m;
  34.  
  35.     /**
  36.      *    Column dimension.
  37.      *    @var int 
  38.      */
  39.     private $n;
  40.  
  41.     /**
  42.      *    Pivot sign.
  43.      *    @var int 
  44.      */
  45.     private $pivsign;
  46.  
  47.     /**
  48.      *    Internal storage of pivot vector.
  49.      *    @var array 
  50.      */
  51.     private $piv array();
  52.  
  53.  
  54.     /**
  55.      *    LU Decomposition constructor.
  56.      *
  57.      *    @param $A Rectangular matrix
  58.      *    @return Structure to access L, U and piv.
  59.      */
  60.     public function __construct($A{
  61.         if ($A instanceof Matrix{
  62.             // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
  63.             $this->LU $A->getArrayCopy();
  64.             $this->m  $A->getRowDimension();
  65.             $this->n  $A->getColumnDimension();
  66.             for ($i 0$i $this->m++$i{
  67.                 $this->piv[$i$i;
  68.             }
  69.             $this->pivsign 1;
  70.             $LUrowi $LUcolj array();
  71.  
  72.             // Outer loop.
  73.             for ($j 0$j $this->n++$j{
  74.                 // Make a copy of the j-th column to localize references.
  75.                 for ($i 0$i $this->m++$i{
  76.                     $LUcolj[$i&$this->LU[$i][$j];
  77.                 }
  78.                 // Apply previous transformations.
  79.                 for ($i 0$i $this->m++$i{
  80.                     $LUrowi $this->LU[$i];
  81.                     // Most of the time is spent in the following dot product.
  82.                     $kmax min($i,$j);
  83.                     $s 0.0;
  84.                     for ($k 0$k $kmax++$k{
  85.                         $s += $LUrowi[$k$LUcolj[$k];
  86.                     }
  87.                     $LUrowi[$j$LUcolj[$i-= $s;
  88.                 }
  89.                 // Find pivot and exchange if necessary.
  90.                 $p $j;
  91.                 for ($i $j+1$i $this->m++$i{
  92.                     if (abs($LUcolj[$i]abs($LUcolj[$p])) {
  93.                         $p $i;
  94.                     }
  95.                 }
  96.                 if ($p != $j{
  97.                     for ($k 0$k $this->n++$k{
  98.                         $t $this->LU[$p][$k];
  99.                         $this->LU[$p][$k$this->LU[$j][$k];
  100.                         $this->LU[$j][$k$t;
  101.                     }
  102.                     $k $this->piv[$p];
  103.                     $this->piv[$p$this->piv[$j];
  104.                     $this->piv[$j$k;
  105.                     $this->pivsign $this->pivsign * -1;
  106.                 }
  107.                 // Compute multipliers.
  108.                 if (($j $this->m&& ($this->LU[$j][$j!= 0.0)) {
  109.                     for ($i $j+1$i $this->m++$i{
  110.                         $this->LU[$i][$j/= $this->LU[$j][$j];
  111.                     }
  112.                 }
  113.             }
  114.         else {
  115.             throw new Exception(JAMAError(ArgumentTypeException));
  116.         }
  117.     }    //    function __construct()
  118.  
  119.  
  120.     /**
  121.      *    Get lower triangular factor.
  122.      *
  123.      *    @return array Lower triangular factor
  124.      */
  125.     public function getL({
  126.         for ($i 0$i $this->m++$i{
  127.             for ($j 0$j $this->n++$j{
  128.                 if ($i $j{
  129.                     $L[$i][$j$this->LU[$i][$j];
  130.                 elseif ($i == $j{
  131.                     $L[$i][$j1.0;
  132.                 else {
  133.                     $L[$i][$j0.0;
  134.                 }
  135.             }
  136.         }
  137.         return new Matrix($L);
  138.     }    //    function getL()
  139.  
  140.  
  141.     /**
  142.      *    Get upper triangular factor.
  143.      *
  144.      *    @return array Upper triangular factor
  145.      */
  146.     public function getU({
  147.         for ($i 0$i $this->n++$i{
  148.             for ($j 0$j $this->n++$j{
  149.                 if ($i <= $j{
  150.                     $U[$i][$j$this->LU[$i][$j];
  151.                 else {
  152.                     $U[$i][$j0.0;
  153.                 }
  154.             }
  155.         }
  156.         return new Matrix($U);
  157.     }    //    function getU()
  158.  
  159.  
  160.     /**
  161.      *    Return pivot permutation vector.
  162.      *
  163.      *    @return array Pivot vector
  164.      */
  165.     public function getPivot({
  166.         return $this->piv;
  167.     }    //    function getPivot()
  168.  
  169.  
  170.     /**
  171.      *    Alias for getPivot
  172.      *
  173.      *    @see getPivot
  174.      */
  175.     public function getDoublePivot({
  176.         return $this->getPivot();
  177.     }    //    function getDoublePivot()
  178.  
  179.  
  180.     /**
  181.      *    Is the matrix nonsingular?
  182.      *
  183.      *    @return true if U, and hence A, is nonsingular.
  184.      */
  185.     public function isNonsingular({
  186.         for ($j 0$j $this->n++$j{
  187.             if ($this->LU[$j][$j== 0{
  188.                 return false;
  189.             }
  190.         }
  191.         return true;
  192.     }    //    function isNonsingular()
  193.  
  194.  
  195.     /**
  196.      *    Count determinants
  197.      *
  198.      *    @return array d matrix deterninat
  199.      */
  200.     public function det({
  201.         if ($this->== $this->n{
  202.             $d $this->pivsign;
  203.             for ($j 0$j $this->n++$j{
  204.                 $d *= $this->LU[$j][$j];
  205.             }
  206.             return $d;
  207.         else {
  208.             throw new Exception(JAMAError(MatrixDimensionException));
  209.         }
  210.     }    //    function det()
  211.  
  212.  
  213.     /**
  214.      *    Solve A*X = B
  215.      *
  216.      *    @param  $B  A Matrix with as many rows as A and any number of columns.
  217.      *    @return  so that L*U*X = B(piv,:)
  218.      *    @exception  IllegalArgumentException Matrix row dimensions must agree.
  219.      *    @exception  RuntimeException  Matrix is singular.
  220.      */
  221.     public function solve($B{
  222.         if ($B->getRowDimension(== $this->m{
  223.             if ($this->isNonsingular()) {
  224.                 // Copy right hand side with pivoting
  225.                 $nx $B->getColumnDimension();
  226.                 $X  $B->getMatrix($this->piv0$nx-1);
  227.                 // Solve L*Y = B(piv,:)
  228.                 for ($k 0$k $this->n++$k{
  229.                     for ($i $k+1$i $this->n++$i{
  230.                         for ($j 0$j $nx++$j{
  231.                             $X->A[$i][$j-= $X->A[$k][$j$this->LU[$i][$k];
  232.                         }
  233.                     }
  234.                 }
  235.                 // Solve U*X = Y;
  236.                 for ($k $this->n-1$k >= 0--$k{
  237.                     for ($j 0$j $nx++$j{
  238.                         $X->A[$k][$j/= $this->LU[$k][$k];
  239.                     }
  240.                     for ($i 0$i $k++$i{
  241.                         for ($j 0$j $nx++$j{
  242.                             $X->A[$i][$j-= $X->A[$k][$j$this->LU[$i][$k];
  243.                         }
  244.                     }
  245.                 }
  246.                 return $X;
  247.             else {
  248.                 throw new Exception(JAMAError(MatrixSingularException));
  249.             }
  250.         else {
  251.             throw new Exception(JAMAError(MatrixSquareException));
  252.         }
  253.     }    //    function solve()
  254.  
  255. }    //    class LUDecomposition

Documentation generated on Tue, 01 Jun 2010 17:05:06 +0200 by phpDocumentor 1.4.3