upgrade to PHPExcel 1.7.0
This commit is contained in:
@@ -22,7 +22,7 @@
|
|||||||
* @package PHPExcel_Shared_Escher
|
* @package PHPExcel_Shared_Escher
|
||||||
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
* @version 1.6.7, 2009-04-22
|
* @version 1.7.0, 2009-08-10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* @package PHPExcel_Shared_Escher
|
* @package PHPExcel_Shared_Escher
|
||||||
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
* @version 1.6.7, 2009-04-22
|
* @version 1.7.0, 2009-08-10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* @package PHPExcel_Shared_Escher
|
* @package PHPExcel_Shared_Escher
|
||||||
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
* @version 1.6.7, 2009-04-22
|
* @version 1.7.0, 2009-08-10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* @package PHPExcel_Shared_Escher
|
* @package PHPExcel_Shared_Escher
|
||||||
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
* @version 1.6.7, 2009-04-22
|
* @version 1.7.0, 2009-08-10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* @package PHPExcel_Shared_Escher
|
* @package PHPExcel_Shared_Escher
|
||||||
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
* @version 1.6.7, 2009-04-22
|
* @version 1.7.0, 2009-08-10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* @package PHPExcel_Shared_Escher
|
* @package PHPExcel_Shared_Escher
|
||||||
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
* @version 1.6.7, 2009-04-22
|
* @version 1.7.0, 2009-08-10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* @package PHPExcel_Shared_Escher
|
* @package PHPExcel_Shared_Escher
|
||||||
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
* @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
* @version 1.6.7, 2009-04-22
|
* @version 1.7.0, 2009-08-10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,133 +1,149 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @package JAMA
|
* @package JAMA
|
||||||
*
|
*
|
||||||
* Cholesky decomposition class
|
* Cholesky decomposition class
|
||||||
*
|
*
|
||||||
* For a symmetric, positive definite matrix A, the Cholesky decomposition
|
* For a symmetric, positive definite matrix A, the Cholesky decomposition
|
||||||
* is an lower triangular matrix L so that A = L*L'.
|
* is an lower triangular matrix L so that A = L*L'.
|
||||||
*
|
*
|
||||||
* If the matrix is not symmetric or positive definite, the constructor
|
* If the matrix is not symmetric or positive definite, the constructor
|
||||||
* returns a partial decomposition and sets an internal flag that may
|
* returns a partial decomposition and sets an internal flag that may
|
||||||
* be queried by the isSPD() method.
|
* be queried by the isSPD() method.
|
||||||
*
|
*
|
||||||
* @author Paul Meagher
|
* @author Paul Meagher
|
||||||
* @author Michael Bommarito
|
* @author Michael Bommarito
|
||||||
* @version 1.2
|
* @version 1.2
|
||||||
*/
|
*/
|
||||||
class CholeskyDecomposition {
|
class CholeskyDecomposition {
|
||||||
/**
|
|
||||||
* Decomposition storage
|
|
||||||
* @var array
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $L = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matrix row and column dimension
|
|
||||||
* @var int
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $m;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Symmetric positive definite flag
|
|
||||||
* @var boolean
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $isspd = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CholeskyDecomposition
|
|
||||||
* Class constructor - decomposes symmetric positive definite matrix
|
|
||||||
* @param mixed Matrix square symmetric positive definite matrix
|
|
||||||
*/
|
|
||||||
function CholeskyDecomposition( $A = null ) {
|
|
||||||
if( is_a($A, 'Matrix') ) {
|
|
||||||
$this->L = $A->getArray();
|
|
||||||
$this->m = $A->getRowDimension();
|
|
||||||
|
|
||||||
for( $i = 0; $i < $this->m; $i++ ) {
|
|
||||||
for( $j = $i; $j < $this->m; $j++ ) {
|
|
||||||
for( $sum = $this->L[$i][$j], $k = $i - 1; $k >= 0; $k-- )
|
|
||||||
$sum -= $this->L[$i][$k] * $this->L[$j][$k];
|
|
||||||
|
|
||||||
if( $i == $j ) {
|
/**
|
||||||
if( $sum >= 0 ) {
|
* Decomposition storage
|
||||||
$this->L[$i][$i] = sqrt( $sum );
|
* @var array
|
||||||
} else {
|
* @access private
|
||||||
$this->isspd = false;
|
*/
|
||||||
}
|
private $L = array();
|
||||||
} else {
|
|
||||||
if( $this->L[$i][$i] != 0 )
|
/**
|
||||||
$this->L[$j][$i] = $sum / $this->L[$i][$i];
|
* Matrix row and column dimension
|
||||||
}
|
* @var int
|
||||||
}
|
* @access private
|
||||||
|
*/
|
||||||
for ($k = $i+1; $k < $this->m; $k++)
|
private $m;
|
||||||
$this->L[$i][$k] = 0.0;
|
|
||||||
}
|
/**
|
||||||
} else {
|
* Symmetric positive definite flag
|
||||||
trigger_error(ArgumentTypeException, ERROR);
|
* @var boolean
|
||||||
}
|
* @access private
|
||||||
}
|
*/
|
||||||
|
private $isspd = true;
|
||||||
/**
|
|
||||||
* Is the matrix symmetric and positive definite?
|
|
||||||
* @return boolean
|
/**
|
||||||
*/
|
* CholeskyDecomposition
|
||||||
function isSPD () {
|
*
|
||||||
return $this->isspd;
|
* Class constructor - decomposes symmetric positive definite matrix
|
||||||
}
|
* @param mixed Matrix square symmetric positive definite matrix
|
||||||
|
*/
|
||||||
/**
|
public function __construct($A = null) {
|
||||||
* getL
|
if ($A instanceof Matrix) {
|
||||||
* Return triangular factor.
|
$this->L = $A->getArray();
|
||||||
* @return Matrix Lower triangular matrix
|
$this->m = $A->getRowDimension();
|
||||||
*/
|
|
||||||
function getL () {
|
for($i = 0; $i < $this->m; ++$i) {
|
||||||
return new Matrix($this->L);
|
for($j = $i; $j < $this->m; ++$j) {
|
||||||
}
|
for($sum = $this->L[$i][$j], $k = $i - 1; $k >= 0; --$k) {
|
||||||
|
$sum -= $this->L[$i][$k] * $this->L[$j][$k];
|
||||||
/**
|
}
|
||||||
* Solve A*X = B
|
if ($i == $j) {
|
||||||
* @param $B Row-equal matrix
|
if ($sum >= 0) {
|
||||||
* @return Matrix L * L' * X = B
|
$this->L[$i][$i] = sqrt($sum);
|
||||||
*/
|
} else {
|
||||||
function solve ( $B = null ) {
|
$this->isspd = false;
|
||||||
if( is_a($B, 'Matrix') ) {
|
}
|
||||||
if ($B->getRowDimension() == $this->m) {
|
} else {
|
||||||
if ($this->isspd) {
|
if ($this->L[$i][$i] != 0) {
|
||||||
$X = $B->getArrayCopy();
|
$this->L[$j][$i] = $sum / $this->L[$i][$i];
|
||||||
$nx = $B->getColumnDimension();
|
}
|
||||||
|
}
|
||||||
for ($k = 0; $k < $this->m; $k++) {
|
}
|
||||||
for ($i = $k + 1; $i < $this->m; $i++)
|
|
||||||
for ($j = 0; $j < $nx; $j++)
|
for ($k = $i+1; $k < $this->m; ++$k) {
|
||||||
$X[$i][$j] -= $X[$k][$j] * $this->L[$i][$k];
|
$this->L[$i][$k] = 0.0;
|
||||||
|
}
|
||||||
for ($j = 0; $j < $nx; $j++)
|
}
|
||||||
$X[$k][$j] /= $this->L[$k][$k];
|
} else {
|
||||||
}
|
throw new Exception(JAMAError(ArgumentTypeException));
|
||||||
|
}
|
||||||
for ($k = $this->m - 1; $k >= 0; $k--) {
|
} // function __construct()
|
||||||
for ($j = 0; $j < $nx; $j++)
|
|
||||||
$X[$k][$j] /= $this->L[$k][$k];
|
|
||||||
|
/**
|
||||||
for ($i = 0; $i < $k; $i++)
|
* Is the matrix symmetric and positive definite?
|
||||||
for ($j = 0; $j < $nx; $j++)
|
*
|
||||||
$X[$i][$j] -= $X[$k][$j] * $this->L[$k][$i];
|
* @return boolean
|
||||||
}
|
*/
|
||||||
|
public function isSPD() {
|
||||||
return new Matrix($X, $this->m, $nx);
|
return $this->isspd;
|
||||||
} else {
|
} // function isSPD()
|
||||||
trigger_error(MatrixSPDException, ERROR);
|
|
||||||
}
|
|
||||||
} else {
|
/**
|
||||||
trigger_error(MatrixDimensionException, ERROR);
|
* getL
|
||||||
}
|
*
|
||||||
} else {
|
* Return triangular factor.
|
||||||
trigger_error(ArgumentTypeException, ERROR);
|
* @return Matrix Lower triangular matrix
|
||||||
}
|
*/
|
||||||
}
|
public function getL() {
|
||||||
}
|
return new Matrix($this->L);
|
||||||
|
} // function getL()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solve A*X = B
|
||||||
|
*
|
||||||
|
* @param $B Row-equal matrix
|
||||||
|
* @return Matrix L * L' * X = B
|
||||||
|
*/
|
||||||
|
public function solve($B = null) {
|
||||||
|
if ($B instanceof Matrix) {
|
||||||
|
if ($B->getRowDimension() == $this->m) {
|
||||||
|
if ($this->isspd) {
|
||||||
|
$X = $B->getArrayCopy();
|
||||||
|
$nx = $B->getColumnDimension();
|
||||||
|
|
||||||
|
for ($k = 0; $k < $this->m; ++$k) {
|
||||||
|
for ($i = $k + 1; $i < $this->m; ++$i) {
|
||||||
|
for ($j = 0; $j < $nx; ++$j) {
|
||||||
|
$X[$i][$j] -= $X[$k][$j] * $this->L[$i][$k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ($j = 0; $j < $nx; ++$j) {
|
||||||
|
$X[$k][$j] /= $this->L[$k][$k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($k = $this->m - 1; $k >= 0; --$k) {
|
||||||
|
for ($j = 0; $j < $nx; ++$j) {
|
||||||
|
$X[$k][$j] /= $this->L[$k][$k];
|
||||||
|
}
|
||||||
|
for ($i = 0; $i < $k; ++$i) {
|
||||||
|
for ($j = 0; $j < $nx; ++$j) {
|
||||||
|
$X[$i][$j] -= $X[$k][$j] * $this->L[$k][$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Matrix($X, $this->m, $nx);
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(MatrixSPDException));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(MatrixDimensionException));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(ArgumentTypeException));
|
||||||
|
}
|
||||||
|
} // function solve()
|
||||||
|
|
||||||
|
} // class CholeskyDecomposition
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,222 +1,255 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @package JAMA
|
* @package JAMA
|
||||||
*
|
*
|
||||||
* For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
|
* For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
|
||||||
* unit lower triangular matrix L, an n-by-n upper triangular matrix U,
|
* unit lower triangular matrix L, an n-by-n upper triangular matrix U,
|
||||||
* and a permutation vector piv of length m so that A(piv,:) = L*U.
|
* and a permutation vector piv of length m so that A(piv,:) = L*U.
|
||||||
* If m < n, then L is m-by-m and U is m-by-n.
|
* If m < n, then L is m-by-m and U is m-by-n.
|
||||||
*
|
*
|
||||||
* The LU decompostion with pivoting always exists, even if the matrix is
|
* The LU decompostion with pivoting always exists, even if the matrix is
|
||||||
* singular, so the constructor will never fail. The primary use of the
|
* singular, so the constructor will never fail. The primary use of the
|
||||||
* LU decomposition is in the solution of square systems of simultaneous
|
* LU decomposition is in the solution of square systems of simultaneous
|
||||||
* linear equations. This will fail if isNonsingular() returns false.
|
* linear equations. This will fail if isNonsingular() returns false.
|
||||||
*
|
*
|
||||||
* @author Paul Meagher
|
* @author Paul Meagher
|
||||||
* @author Bartosz Matosiuk
|
* @author Bartosz Matosiuk
|
||||||
* @author Michael Bommarito
|
* @author Michael Bommarito
|
||||||
* @version 1.1
|
* @version 1.1
|
||||||
* @license PHP v3.0
|
* @license PHP v3.0
|
||||||
*/
|
*/
|
||||||
class LUDecomposition {
|
class LUDecomposition {
|
||||||
/**
|
|
||||||
* Decomposition storage
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
var $LU = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Row dimension.
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
var $m;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Column dimension.
|
* Decomposition storage
|
||||||
* @var int
|
* @var array
|
||||||
*/
|
*/
|
||||||
var $n;
|
private $LU = array();
|
||||||
|
|
||||||
/**
|
|
||||||
* Pivot sign.
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
var $pivsign;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal storage of pivot vector.
|
* Row dimension.
|
||||||
* @var array
|
* @var int
|
||||||
*/
|
*/
|
||||||
var $piv = array();
|
private $m;
|
||||||
|
|
||||||
/**
|
|
||||||
* LU Decomposition constructor.
|
|
||||||
* @param $A Rectangular matrix
|
|
||||||
* @return Structure to access L, U and piv.
|
|
||||||
*/
|
|
||||||
function LUDecomposition ($A) {
|
|
||||||
if( is_a($A, 'Matrix') ) {
|
|
||||||
// Use a "left-looking", dot-product, Crout/Doolittle algorithm.
|
|
||||||
$this->LU = $A->getArrayCopy();
|
|
||||||
$this->m = $A->getRowDimension();
|
|
||||||
$this->n = $A->getColumnDimension();
|
|
||||||
for ($i = 0; $i < $this->m; $i++)
|
|
||||||
$this->piv[$i] = $i;
|
|
||||||
$this->pivsign = 1;
|
|
||||||
$LUrowi = array();
|
|
||||||
$LUcolj = array();
|
|
||||||
// Outer loop.
|
|
||||||
for ($j = 0; $j < $this->n; $j++) {
|
|
||||||
// Make a copy of the j-th column to localize references.
|
|
||||||
for ($i = 0; $i < $this->m; $i++)
|
|
||||||
$LUcolj[$i] = &$this->LU[$i][$j];
|
|
||||||
// Apply previous transformations.
|
|
||||||
for ($i = 0; $i < $this->m; $i++) {
|
|
||||||
$LUrowi = $this->LU[$i];
|
|
||||||
// Most of the time is spent in the following dot product.
|
|
||||||
$kmax = min($i,$j);
|
|
||||||
$s = 0.0;
|
|
||||||
for ($k = 0; $k < $kmax; $k++)
|
|
||||||
$s += $LUrowi[$k]*$LUcolj[$k];
|
|
||||||
$LUrowi[$j] = $LUcolj[$i] -= $s;
|
|
||||||
}
|
|
||||||
// Find pivot and exchange if necessary.
|
|
||||||
$p = $j;
|
|
||||||
for ($i = $j+1; $i < $this->m; $i++) {
|
|
||||||
if (abs($LUcolj[$i]) > abs($LUcolj[$p]))
|
|
||||||
$p = $i;
|
|
||||||
}
|
|
||||||
if ($p != $j) {
|
|
||||||
for ($k = 0; $k < $this->n; $k++) {
|
|
||||||
$t = $this->LU[$p][$k];
|
|
||||||
$this->LU[$p][$k] = $this->LU[$j][$k];
|
|
||||||
$this->LU[$j][$k] = $t;
|
|
||||||
}
|
|
||||||
$k = $this->piv[$p];
|
|
||||||
$this->piv[$p] = $this->piv[$j];
|
|
||||||
$this->piv[$j] = $k;
|
|
||||||
$this->pivsign = $this->pivsign * -1;
|
|
||||||
}
|
|
||||||
// Compute multipliers.
|
|
||||||
if ( ($j < $this->m) AND ($this->LU[$j][$j] != 0.0) ) {
|
|
||||||
for ($i = $j+1; $i < $this->m; $i++)
|
|
||||||
$this->LU[$i][$j] /= $this->LU[$j][$j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
trigger_error(ArgumentTypeException, ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get lower triangular factor.
|
|
||||||
* @return array Lower triangular factor
|
|
||||||
*/
|
|
||||||
function getL () {
|
|
||||||
for ($i = 0; $i < $this->m; $i++) {
|
|
||||||
for ($j = 0; $j < $this->n; $j++) {
|
|
||||||
if ($i > $j)
|
|
||||||
$L[$i][$j] = $this->LU[$i][$j];
|
|
||||||
else if($i == $j)
|
|
||||||
$L[$i][$j] = 1.0;
|
|
||||||
else
|
|
||||||
$L[$i][$j] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Matrix($L);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get upper triangular factor.
|
* Column dimension.
|
||||||
* @return array Upper triangular factor
|
* @var int
|
||||||
*/
|
*/
|
||||||
function getU () {
|
private $n;
|
||||||
for ($i = 0; $i < $this->n; $i++) {
|
|
||||||
for ($j = 0; $j < $this->n; $j++) {
|
|
||||||
if ($i <= $j)
|
|
||||||
$U[$i][$j] = $this->LU[$i][$j];
|
|
||||||
else
|
|
||||||
$U[$i][$j] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Matrix($U);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return pivot permutation vector.
|
|
||||||
* @return array Pivot vector
|
|
||||||
*/
|
|
||||||
function getPivot () {
|
|
||||||
return $this->piv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alias for getPivot
|
|
||||||
* @see getPivot
|
|
||||||
*/
|
|
||||||
function getDoublePivot () {
|
|
||||||
return $this->getPivot();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the matrix nonsingular?
|
* Pivot sign.
|
||||||
* @return true if U, and hence A, is nonsingular.
|
* @var int
|
||||||
*/
|
*/
|
||||||
function isNonsingular () {
|
private $pivsign;
|
||||||
for ($j = 0; $j < $this->n; $j++) {
|
|
||||||
if ($this->LU[$j][$j] == 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count determinants
|
* Internal storage of pivot vector.
|
||||||
* @return array d matrix deterninat
|
* @var array
|
||||||
*/
|
*/
|
||||||
function det() {
|
private $piv = array();
|
||||||
if ($this->m == $this->n) {
|
|
||||||
$d = $this->pivsign;
|
|
||||||
for ($j = 0; $j < $this->n; $j++)
|
/**
|
||||||
$d *= $this->LU[$j][$j];
|
* LU Decomposition constructor.
|
||||||
return $d;
|
*
|
||||||
} else {
|
* @param $A Rectangular matrix
|
||||||
trigger_error(MatrixDimensionException, ERROR);
|
* @return Structure to access L, U and piv.
|
||||||
}
|
*/
|
||||||
}
|
public function __construct($A) {
|
||||||
|
if ($A instanceof Matrix) {
|
||||||
/**
|
// Use a "left-looking", dot-product, Crout/Doolittle algorithm.
|
||||||
* Solve A*X = B
|
$this->LU = $A->getArrayCopy();
|
||||||
* @param $B A Matrix with as many rows as A and any number of columns.
|
$this->m = $A->getRowDimension();
|
||||||
* @return X so that L*U*X = B(piv,:)
|
$this->n = $A->getColumnDimension();
|
||||||
* @exception IllegalArgumentException Matrix row dimensions must agree.
|
for ($i = 0; $i < $this->m; ++$i) {
|
||||||
* @exception RuntimeException Matrix is singular.
|
$this->piv[$i] = $i;
|
||||||
*/
|
}
|
||||||
function solve($B) {
|
$this->pivsign = 1;
|
||||||
if ($B->getRowDimension() == $this->m) {
|
$LUrowi = $LUcolj = array();
|
||||||
if ($this->isNonsingular()) {
|
|
||||||
// Copy right hand side with pivoting
|
// Outer loop.
|
||||||
$nx = $B->getColumnDimension();
|
for ($j = 0; $j < $this->n; ++$j) {
|
||||||
$X = $B->getMatrix($this->piv, 0, $nx-1);
|
// Make a copy of the j-th column to localize references.
|
||||||
// Solve L*Y = B(piv,:)
|
for ($i = 0; $i < $this->m; ++$i) {
|
||||||
for ($k = 0; $k < $this->n; $k++)
|
$LUcolj[$i] = &$this->LU[$i][$j];
|
||||||
for ($i = $k+1; $i < $this->n; $i++)
|
}
|
||||||
for ($j = 0; $j < $nx; $j++)
|
// Apply previous transformations.
|
||||||
$X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k];
|
for ($i = 0; $i < $this->m; ++$i) {
|
||||||
// Solve U*X = Y;
|
$LUrowi = $this->LU[$i];
|
||||||
for ($k = $this->n-1; $k >= 0; $k--) {
|
// Most of the time is spent in the following dot product.
|
||||||
for ($j = 0; $j < $nx; $j++)
|
$kmax = min($i,$j);
|
||||||
$X->A[$k][$j] /= $this->LU[$k][$k];
|
$s = 0.0;
|
||||||
for ($i = 0; $i < $k; $i++)
|
for ($k = 0; $k < $kmax; ++$k) {
|
||||||
for ($j = 0; $j < $nx; $j++)
|
$s += $LUrowi[$k] * $LUcolj[$k];
|
||||||
$X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k];
|
}
|
||||||
}
|
$LUrowi[$j] = $LUcolj[$i] -= $s;
|
||||||
return $X;
|
}
|
||||||
} else {
|
// Find pivot and exchange if necessary.
|
||||||
trigger_error(MatrixSingularException, ERROR);
|
$p = $j;
|
||||||
}
|
for ($i = $j+1; $i < $this->m; ++$i) {
|
||||||
} else {
|
if (abs($LUcolj[$i]) > abs($LUcolj[$p])) {
|
||||||
trigger_error(MatrixSquareException, ERROR);
|
$p = $i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if ($p != $j) {
|
||||||
|
for ($k = 0; $k < $this->n; ++$k) {
|
||||||
|
$t = $this->LU[$p][$k];
|
||||||
|
$this->LU[$p][$k] = $this->LU[$j][$k];
|
||||||
|
$this->LU[$j][$k] = $t;
|
||||||
|
}
|
||||||
|
$k = $this->piv[$p];
|
||||||
|
$this->piv[$p] = $this->piv[$j];
|
||||||
|
$this->piv[$j] = $k;
|
||||||
|
$this->pivsign = $this->pivsign * -1;
|
||||||
|
}
|
||||||
|
// Compute multipliers.
|
||||||
|
if (($j < $this->m) && ($this->LU[$j][$j] != 0.0)) {
|
||||||
|
for ($i = $j+1; $i < $this->m; ++$i) {
|
||||||
|
$this->LU[$i][$j] /= $this->LU[$j][$j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(ArgumentTypeException));
|
||||||
|
}
|
||||||
|
} // function __construct()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get lower triangular factor.
|
||||||
|
*
|
||||||
|
* @return array Lower triangular factor
|
||||||
|
*/
|
||||||
|
public function getL() {
|
||||||
|
for ($i = 0; $i < $this->m; ++$i) {
|
||||||
|
for ($j = 0; $j < $this->n; ++$j) {
|
||||||
|
if ($i > $j) {
|
||||||
|
$L[$i][$j] = $this->LU[$i][$j];
|
||||||
|
} elseif ($i == $j) {
|
||||||
|
$L[$i][$j] = 1.0;
|
||||||
|
} else {
|
||||||
|
$L[$i][$j] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Matrix($L);
|
||||||
|
} // function getL()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get upper triangular factor.
|
||||||
|
*
|
||||||
|
* @return array Upper triangular factor
|
||||||
|
*/
|
||||||
|
public function getU() {
|
||||||
|
for ($i = 0; $i < $this->n; ++$i) {
|
||||||
|
for ($j = 0; $j < $this->n; ++$j) {
|
||||||
|
if ($i <= $j) {
|
||||||
|
$U[$i][$j] = $this->LU[$i][$j];
|
||||||
|
} else {
|
||||||
|
$U[$i][$j] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Matrix($U);
|
||||||
|
} // function getU()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return pivot permutation vector.
|
||||||
|
*
|
||||||
|
* @return array Pivot vector
|
||||||
|
*/
|
||||||
|
public function getPivot() {
|
||||||
|
return $this->piv;
|
||||||
|
} // function getPivot()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for getPivot
|
||||||
|
*
|
||||||
|
* @see getPivot
|
||||||
|
*/
|
||||||
|
public function getDoublePivot() {
|
||||||
|
return $this->getPivot();
|
||||||
|
} // function getDoublePivot()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the matrix nonsingular?
|
||||||
|
*
|
||||||
|
* @return true if U, and hence A, is nonsingular.
|
||||||
|
*/
|
||||||
|
public function isNonsingular() {
|
||||||
|
for ($j = 0; $j < $this->n; ++$j) {
|
||||||
|
if ($this->LU[$j][$j] == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} // function isNonsingular()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count determinants
|
||||||
|
*
|
||||||
|
* @return array d matrix deterninat
|
||||||
|
*/
|
||||||
|
public function det() {
|
||||||
|
if ($this->m == $this->n) {
|
||||||
|
$d = $this->pivsign;
|
||||||
|
for ($j = 0; $j < $this->n; ++$j) {
|
||||||
|
$d *= $this->LU[$j][$j];
|
||||||
|
}
|
||||||
|
return $d;
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(MatrixDimensionException));
|
||||||
|
}
|
||||||
|
} // function det()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solve A*X = B
|
||||||
|
*
|
||||||
|
* @param $B A Matrix with as many rows as A and any number of columns.
|
||||||
|
* @return X so that L*U*X = B(piv,:)
|
||||||
|
* @exception IllegalArgumentException Matrix row dimensions must agree.
|
||||||
|
* @exception RuntimeException Matrix is singular.
|
||||||
|
*/
|
||||||
|
public function solve($B) {
|
||||||
|
if ($B->getRowDimension() == $this->m) {
|
||||||
|
if ($this->isNonsingular()) {
|
||||||
|
// Copy right hand side with pivoting
|
||||||
|
$nx = $B->getColumnDimension();
|
||||||
|
$X = $B->getMatrix($this->piv, 0, $nx-1);
|
||||||
|
// Solve L*Y = B(piv,:)
|
||||||
|
for ($k = 0; $k < $this->n; ++$k) {
|
||||||
|
for ($i = $k+1; $i < $this->n; ++$i) {
|
||||||
|
for ($j = 0; $j < $nx; ++$j) {
|
||||||
|
$X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Solve U*X = Y;
|
||||||
|
for ($k = $this->n-1; $k >= 0; --$k) {
|
||||||
|
for ($j = 0; $j < $nx; ++$j) {
|
||||||
|
$X->A[$k][$j] /= $this->LU[$k][$k];
|
||||||
|
}
|
||||||
|
for ($i = 0; $i < $k; ++$i) {
|
||||||
|
for ($j = 0; $j < $nx; ++$j) {
|
||||||
|
$X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $X;
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(MatrixSingularException));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(MatrixSquareException));
|
||||||
|
}
|
||||||
|
} // function solve()
|
||||||
|
|
||||||
|
} // class LUDecomposition
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,195 +1,232 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @package JAMA
|
* @package JAMA
|
||||||
*
|
*
|
||||||
* For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n
|
* 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
|
* orthogonal matrix Q and an n-by-n upper triangular matrix R so that
|
||||||
* A = Q*R.
|
* A = Q*R.
|
||||||
*
|
*
|
||||||
* The QR decompostion always exists, even if the matrix does not have
|
* 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
|
* full rank, so the constructor will never fail. The primary use of the
|
||||||
* QR decomposition is in the least squares solution of nonsquare systems
|
* QR decomposition is in the least squares solution of nonsquare systems
|
||||||
* of simultaneous linear equations. This will fail if isFullRank()
|
* of simultaneous linear equations. This will fail if isFullRank()
|
||||||
* returns false.
|
* returns false.
|
||||||
*
|
*
|
||||||
* @author Paul Meagher
|
* @author Paul Meagher
|
||||||
* @license PHP v3.0
|
* @license PHP v3.0
|
||||||
* @version 1.1
|
* @version 1.1
|
||||||
*/
|
*/
|
||||||
class QRDecomposition {
|
class QRDecomposition {
|
||||||
/**
|
|
||||||
* Array for internal storage of decomposition.
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
var $QR = array();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Row dimension.
|
* Array for internal storage of decomposition.
|
||||||
* @var integer
|
* @var array
|
||||||
*/
|
*/
|
||||||
var $m;
|
private $QR = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Column dimension.
|
* Row dimension.
|
||||||
* @var integer
|
* @var integer
|
||||||
*/
|
*/
|
||||||
var $n;
|
private $m;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array for internal storage of diagonal of R.
|
* Column dimension.
|
||||||
* @var array
|
* @var integer
|
||||||
*/
|
*/
|
||||||
var $Rdiag = array();
|
private $n;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* QR Decomposition computed by Householder reflections.
|
* Array for internal storage of diagonal of R.
|
||||||
* @param matrix $A Rectangular matrix
|
* @var array
|
||||||
* @return Structure to access R and the Householder vectors and compute Q.
|
*/
|
||||||
*/
|
private $Rdiag = array();
|
||||||
function QRDecomposition($A) {
|
|
||||||
if( is_a($A, 'Matrix') ) {
|
|
||||||
// Initialize.
|
|
||||||
$this->QR = $A->getArrayCopy();
|
|
||||||
$this->m = $A->getRowDimension();
|
|
||||||
$this->n = $A->getColumnDimension();
|
|
||||||
// Main loop.
|
|
||||||
for ($k = 0; $k < $this->n; $k++) {
|
|
||||||
// Compute 2-norm of k-th column without under/overflow.
|
|
||||||
$nrm = 0.0;
|
|
||||||
for ($i = $k; $i < $this->m; $i++)
|
|
||||||
$nrm = hypo($nrm, $this->QR[$i][$k]);
|
|
||||||
if ($nrm != 0.0) {
|
|
||||||
// Form k-th Householder vector.
|
|
||||||
if ($this->QR[$k][$k] < 0)
|
|
||||||
$nrm = -$nrm;
|
|
||||||
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++) {
|
|
||||||
$s = 0.0;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
trigger_error(ArgumentTypeException, ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the matrix full rank?
|
|
||||||
* @return boolean true if R, and hence A, has full rank, else false.
|
|
||||||
*/
|
|
||||||
function isFullRank() {
|
|
||||||
for ($j = 0; $j < $this->n; $j++)
|
|
||||||
if ($this->Rdiag[$j] == 0)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the Householder vectors
|
* QR Decomposition computed by Householder reflections.
|
||||||
* @return Matrix Lower trapezoidal matrix whose columns define the reflections
|
*
|
||||||
*/
|
* @param matrix $A Rectangular matrix
|
||||||
function getH() {
|
* @return Structure to access R and the Householder vectors and compute Q.
|
||||||
for ($i = 0; $i < $this->m; $i++) {
|
*/
|
||||||
for ($j = 0; $j < $this->n; $j++) {
|
public function __construct($A) {
|
||||||
if ($i >= $j)
|
if($A instanceof Matrix) {
|
||||||
$H[$i][$j] = $this->QR[$i][$j];
|
// Initialize.
|
||||||
else
|
$this->QR = $A->getArrayCopy();
|
||||||
$H[$i][$j] = 0.0;
|
$this->m = $A->getRowDimension();
|
||||||
}
|
$this->n = $A->getColumnDimension();
|
||||||
}
|
// Main loop.
|
||||||
return new Matrix($H);
|
for ($k = 0; $k < $this->n; ++$k) {
|
||||||
}
|
// Compute 2-norm of k-th column without under/overflow.
|
||||||
|
$nrm = 0.0;
|
||||||
|
for ($i = $k; $i < $this->m; ++$i) {
|
||||||
|
$nrm = hypo($nrm, $this->QR[$i][$k]);
|
||||||
|
}
|
||||||
|
if ($nrm != 0.0) {
|
||||||
|
// Form k-th Householder vector.
|
||||||
|
if ($this->QR[$k][$k] < 0) {
|
||||||
|
$nrm = -$nrm;
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
$s = 0.0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(ArgumentTypeException));
|
||||||
|
}
|
||||||
|
} // function __construct()
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the upper triangular factor
|
|
||||||
* @return Matrix upper triangular factor
|
|
||||||
*/
|
|
||||||
function getR() {
|
|
||||||
for ($i = 0; $i < $this->n; $i++) {
|
|
||||||
for ($j = 0; $j < $this->n; $j++) {
|
|
||||||
if ($i < $j)
|
|
||||||
$R[$i][$j] = $this->QR[$i][$j];
|
|
||||||
else if ($i == $j)
|
|
||||||
$R[$i][$j] = $this->Rdiag[$i];
|
|
||||||
else
|
|
||||||
$R[$i][$j] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Matrix($R);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate and return the (economy-sized) orthogonal factor
|
* Is the matrix full rank?
|
||||||
* @return Matrix orthogonal factor
|
*
|
||||||
*/
|
* @return boolean true if R, and hence A, has full rank, else false.
|
||||||
function getQ() {
|
*/
|
||||||
for ($k = $this->n-1; $k >= 0; $k--) {
|
public function isFullRank() {
|
||||||
for ($i = 0; $i < $this->m; $i++)
|
for ($j = 0; $j < $this->n; ++$j) {
|
||||||
$Q[$i][$k] = 0.0;
|
if ($this->Rdiag[$j] == 0) {
|
||||||
$Q[$k][$k] = 1.0;
|
return false;
|
||||||
for ($j = $k; $j < $this->n; $j++) {
|
}
|
||||||
if ($this->QR[$k][$k] != 0) {
|
}
|
||||||
$s = 0.0;
|
return true;
|
||||||
for ($i = $k; $i < $this->m; $i++)
|
} // function isFullRank()
|
||||||
$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];
|
* Return the Householder vectors
|
||||||
}
|
*
|
||||||
}
|
* @return Matrix Lower trapezoidal matrix whose columns define the reflections
|
||||||
}
|
*/
|
||||||
/*
|
public function getH() {
|
||||||
for( $i = 0; $i < count($Q); $i++ )
|
for ($i = 0; $i < $this->m; ++$i) {
|
||||||
for( $j = 0; $j < count($Q); $j++ )
|
for ($j = 0; $j < $this->n; ++$j) {
|
||||||
if(! isset($Q[$i][$j]) )
|
if ($i >= $j) {
|
||||||
$Q[$i][$j] = 0;
|
$H[$i][$j] = $this->QR[$i][$j];
|
||||||
*/
|
} else {
|
||||||
return new Matrix($Q);
|
$H[$i][$j] = 0.0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
}
|
||||||
* Least squares solution of A*X = B
|
return new Matrix($H);
|
||||||
* @param Matrix $B A Matrix with as many rows as A and any number of columns.
|
} // function getH()
|
||||||
* @return Matrix Matrix that minimizes the two norm of Q*R*X-B.
|
|
||||||
*/
|
|
||||||
function solve($B) {
|
/**
|
||||||
if ($B->getRowDimension() == $this->m) {
|
* Return the upper triangular factor
|
||||||
if ($this->isFullRank()) {
|
*
|
||||||
// Copy right hand side
|
* @return Matrix upper triangular factor
|
||||||
$nx = $B->getColumnDimension();
|
*/
|
||||||
$X = $B->getArrayCopy();
|
public function getR() {
|
||||||
// Compute Y = transpose(Q)*B
|
for ($i = 0; $i < $this->n; ++$i) {
|
||||||
for ($k = 0; $k < $this->n; $k++) {
|
for ($j = 0; $j < $this->n; ++$j) {
|
||||||
for ($j = 0; $j < $nx; $j++) {
|
if ($i < $j) {
|
||||||
$s = 0.0;
|
$R[$i][$j] = $this->QR[$i][$j];
|
||||||
for ($i = $k; $i < $this->m; $i++)
|
} elseif ($i == $j) {
|
||||||
$s += $this->QR[$i][$k] * $X[$i][$j];
|
$R[$i][$j] = $this->Rdiag[$i];
|
||||||
$s = -$s/$this->QR[$k][$k];
|
} else {
|
||||||
for ($i = $k; $i < $this->m; $i++)
|
$R[$i][$j] = 0.0;
|
||||||
$X[$i][$j] += $s * $this->QR[$i][$k];
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Solve R*X = Y;
|
return new Matrix($R);
|
||||||
for ($k = $this->n-1; $k >= 0; $k--) {
|
} // function getR()
|
||||||
for ($j = 0; $j < $nx; $j++)
|
|
||||||
$X[$k][$j] /= $this->Rdiag[$k];
|
|
||||||
for ($i = 0; $i < $k; $i++)
|
/**
|
||||||
for ($j = 0; $j < $nx; $j++)
|
* Generate and return the (economy-sized) orthogonal factor
|
||||||
$X[$i][$j] -= $X[$k][$j]* $this->QR[$i][$k];
|
*
|
||||||
}
|
* @return Matrix orthogonal factor
|
||||||
$X = new Matrix($X);
|
*/
|
||||||
return ($X->getMatrix(0, $this->n-1, 0, $nx));
|
public function getQ() {
|
||||||
} else
|
for ($k = $this->n-1; $k >= 0; --$k) {
|
||||||
trigger_error(MatrixRankException, ERROR);
|
for ($i = 0; $i < $this->m; ++$i) {
|
||||||
} else
|
$Q[$i][$k] = 0.0;
|
||||||
trigger_error(MatrixDimensionException, ERROR);
|
}
|
||||||
}
|
$Q[$k][$k] = 1.0;
|
||||||
}
|
for ($j = $k; $j < $this->n; ++$j) {
|
||||||
|
if ($this->QR[$k][$k] != 0) {
|
||||||
|
$s = 0.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]) ) {
|
||||||
|
$Q[$i][$j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return new Matrix($Q);
|
||||||
|
} // function getQ()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
if ($this->isFullRank()) {
|
||||||
|
// Copy right hand side
|
||||||
|
$nx = $B->getColumnDimension();
|
||||||
|
$X = $B->getArrayCopy();
|
||||||
|
// Compute Y = transpose(Q)*B
|
||||||
|
for ($k = 0; $k < $this->n; ++$k) {
|
||||||
|
for ($j = 0; $j < $nx; ++$j) {
|
||||||
|
$s = 0.0;
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Solve R*X = Y;
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$X = new Matrix($X);
|
||||||
|
return ($X->getMatrix(0, $this->n-1, 0, $nx));
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(MatrixRankException));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(MatrixDimensionException));
|
||||||
|
}
|
||||||
|
} // function solve()
|
||||||
|
|
||||||
|
} // class QRDecomposition
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,120 +1,82 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @package JAMA
|
* @package JAMA
|
||||||
*
|
*
|
||||||
* Error handling
|
* Error handling
|
||||||
* @author Michael Bommarito
|
* @author Michael Bommarito
|
||||||
* @version 01292005
|
* @version 01292005
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//Language constant
|
//Language constant
|
||||||
define('LANG', 'EN');
|
define('JAMALANG', 'EN');
|
||||||
|
|
||||||
|
|
||||||
//Error type constants
|
|
||||||
define('ERROR', E_USER_ERROR);
|
|
||||||
define('WARNING', E_USER_WARNING);
|
|
||||||
define('NOTICE', E_USER_NOTICE);
|
|
||||||
|
|
||||||
//All errors may be defined by the following format:
|
//All errors may be defined by the following format:
|
||||||
//define('ExceptionName', N);
|
//define('ExceptionName', N);
|
||||||
//$error['lang'][N] = 'Error message';
|
//$error['lang'][ExceptionName] = 'Error message';
|
||||||
$error = array();
|
$error = array();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
I've used Babelfish and a little poor knowledge of Romance/Germanic languages for the translations
|
I've used Babelfish and a little poor knowledge of Romance/Germanic languages for the translations here.
|
||||||
here. Feel free to correct anything that looks amiss to you.
|
Feel free to correct anything that looks amiss to you.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('PolymorphicArgumentException', -1);
|
define('PolymorphicArgumentException', -1);
|
||||||
$error['EN'][-1] = "Invalid argument pattern for polymorphic function.";
|
$error['EN'][PolymorphicArgumentException] = "Invalid argument pattern for polymorphic function.";
|
||||||
$error['FR'][-1] = "Modèle inadmissible d'argument pour la fonction polymorphe.".
|
$error['FR'][PolymorphicArgumentException] = "Modèle inadmissible d'argument pour la fonction polymorphe.".
|
||||||
$error['DE'][-1] = "Unzulässiges Argumentmuster für polymorphe Funktion.";
|
$error['DE'][PolymorphicArgumentException] = "Unzulässiges Argumentmuster für polymorphe Funktion.";
|
||||||
|
|
||||||
define('ArgumentTypeException', -2);
|
define('ArgumentTypeException', -2);
|
||||||
$error['EN'][-2] = "Invalid argument type.";
|
$error['EN'][ArgumentTypeException] = "Invalid argument type.";
|
||||||
$error['FR'][-2] = "Type inadmissible d'argument.";
|
$error['FR'][ArgumentTypeException] = "Type inadmissible d'argument.";
|
||||||
$error['DE'][-2] = "Unzulässige Argumentart.";
|
$error['DE'][ArgumentTypeException] = "Unzulässige Argumentart.";
|
||||||
|
|
||||||
define('ArgumentBoundsException', -3);
|
define('ArgumentBoundsException', -3);
|
||||||
$error['EN'][-3] = "Invalid argument range.";
|
$error['EN'][ArgumentBoundsException] = "Invalid argument range.";
|
||||||
$error['FR'][-3] = "Gamme inadmissible d'argument.";
|
$error['FR'][ArgumentBoundsException] = "Gamme inadmissible d'argument.";
|
||||||
$error['DE'][-3] = "Unzulässige Argumentstrecke.";
|
$error['DE'][ArgumentBoundsException] = "Unzulässige Argumentstrecke.";
|
||||||
|
|
||||||
define('MatrixDimensionException', -4);
|
define('MatrixDimensionException', -4);
|
||||||
$error['EN'][-4] = "Matrix dimensions are not equal.";
|
$error['EN'][MatrixDimensionException] = "Matrix dimensions are not equal.";
|
||||||
$error['FR'][-4] = "Les dimensions de Matrix ne sont pas égales.";
|
$error['FR'][MatrixDimensionException] = "Les dimensions de Matrix ne sont pas égales.";
|
||||||
$error['DE'][-4] = "Matrixmaße sind nicht gleich.";
|
$error['DE'][MatrixDimensionException] = "Matrixmaße sind nicht gleich.";
|
||||||
|
|
||||||
define('PrecisionLossException', -5);
|
define('PrecisionLossException', -5);
|
||||||
$error['EN'][-5] = "Significant precision loss detected.";
|
$error['EN'][PrecisionLossException] = "Significant precision loss detected.";
|
||||||
$error['FR'][-5] = "Perte significative de précision détectée.";
|
$error['FR'][PrecisionLossException] = "Perte significative de précision détectée.";
|
||||||
$error['DE'][-5] = "Bedeutender Präzision Verlust ermittelte.";
|
$error['DE'][PrecisionLossException] = "Bedeutender Präzision Verlust ermittelte.";
|
||||||
|
|
||||||
define('MatrixSPDException', -6);
|
define('MatrixSPDException', -6);
|
||||||
$error['EN'][-6] = "Can only perform operation on symmetric positive definite matrix.";
|
$error['EN'][MatrixSPDException] = "Can only perform operation on symmetric positive definite matrix.";
|
||||||
$error['FR'][-6] = "Perte significative de précision détectée.";
|
$error['FR'][MatrixSPDException] = "Perte significative de précision détectée.";
|
||||||
$error['DE'][-6] = "Bedeutender Präzision Verlust ermittelte.";
|
$error['DE'][MatrixSPDException] = "Bedeutender Präzision Verlust ermittelte.";
|
||||||
|
|
||||||
define('MatrixSingularException', -7);
|
define('MatrixSingularException', -7);
|
||||||
$error['EN'][-7] = "Can only perform operation on singular matrix.";
|
$error['EN'][MatrixSingularException] = "Can only perform operation on singular matrix.";
|
||||||
|
|
||||||
define('MatrixRankException', -8);
|
define('MatrixRankException', -8);
|
||||||
$error['EN'][-8] = "Can only perform operation on full-rank matrix.";
|
$error['EN'][MatrixRankException] = "Can only perform operation on full-rank matrix.";
|
||||||
|
|
||||||
define('ArrayLengthException', -9);
|
define('ArrayLengthException', -9);
|
||||||
$error['EN'][-9] = "Array length must be a multiple of m.";
|
$error['EN'][ArrayLengthException] = "Array length must be a multiple of m.";
|
||||||
|
|
||||||
define('RowLengthException', -10);
|
define('RowLengthException', -10);
|
||||||
$error['EN'][-10] = "All rows must have the same length.";
|
$error['EN'][RowLengthException] = "All rows must have the same length.";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom error handler
|
* Custom error handler
|
||||||
* @param int $type Error type: {ERROR, WARNING, NOTICE}
|
* @param int $num Error number
|
||||||
* @param int $num Error number
|
*/
|
||||||
* @param string $file File in which the error occured
|
function JAMAError($errorNumber = null) {
|
||||||
* @param int $line Line on which the error occured
|
global $error;
|
||||||
*/
|
|
||||||
function JAMAError( $type = null, $num = null, $file = null, $line = null, $context = null ) {
|
|
||||||
global $error;
|
|
||||||
|
|
||||||
$lang = LANG;
|
|
||||||
if( isset($type) && isset($num) && isset($file) && isset($line) ) {
|
|
||||||
switch( $type ) {
|
|
||||||
case ERROR:
|
|
||||||
echo '<div class="errror"><b>Error:</b> ' . $error[$lang][$num] . '<br />' . $file . ' @ L' . $line . '</div>';
|
|
||||||
die();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WARNING:
|
|
||||||
echo '<div class="warning"><b>Warning:</b> ' . $error[$lang][$num] . '<br />' . $file . ' @ L' . $line . '</div>';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NOTICE:
|
|
||||||
//echo '<div class="notice"><b>Notice:</b> ' . $error[$lang][$num] . '<br />' . $file . ' @ L' . $line . '</div>';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case E_NOTICE:
|
if (isset($errorNumber)) {
|
||||||
//echo '<div class="errror"><b>Notice:</b> ' . $error[$lang][$num] . '<br />' . $file . ' @ L' . $line . '</div>';
|
if (isset($error[JAMALANG][$errorNumber])) {
|
||||||
break;
|
return $error[JAMALANG][$errorNumber];
|
||||||
|
} else {
|
||||||
case E_STRICT:
|
return $error['EN'][$errorNumber];
|
||||||
break;
|
}
|
||||||
|
} else {
|
||||||
case E_WARNING:
|
return ("Invalid argument to JAMAError()");
|
||||||
break;
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
echo "<div class=\"error\"><b>Unknown Error Type:</b> $type - $file @ L{$line}</div>";
|
|
||||||
die();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
die( "Invalid arguments to JAMAError()" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO MarkBaker
|
|
||||||
//set_error_handler('JAMAError');
|
|
||||||
//error_reporting(ERROR | WARNING);
|
|
||||||
|
|
||||||
|
@@ -1,40 +1,43 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @package JAMA
|
* @package JAMA
|
||||||
*
|
*
|
||||||
* Pythagorean Theorem:
|
* Pythagorean Theorem:
|
||||||
*
|
*
|
||||||
* a = 3
|
* a = 3
|
||||||
* b = 4
|
* b = 4
|
||||||
* r = sqrt(square(a) + square(b))
|
* r = sqrt(square(a) + square(b))
|
||||||
* r = 5
|
* r = 5
|
||||||
*
|
*
|
||||||
* r = sqrt(a^2 + b^2) without under/overflow.
|
* r = sqrt(a^2 + b^2) without under/overflow.
|
||||||
*/
|
*/
|
||||||
function hypo($a, $b) {
|
function hypo($a, $b) {
|
||||||
if (abs($a) > abs($b)) {
|
if (abs($a) > abs($b)) {
|
||||||
$r = $b/$a;
|
$r = $b / $a;
|
||||||
$r = abs($a)* sqrt(1+$r*$r);
|
$r = abs($a) * sqrt(1 + $r * $r);
|
||||||
} else if ($b != 0) {
|
} elseif ($b != 0) {
|
||||||
$r = $a/$b;
|
$r = $a / $b;
|
||||||
$r = abs($b)*sqrt(1+$r*$r);
|
$r = abs($b) * sqrt(1 + $r * $r);
|
||||||
} else
|
} else {
|
||||||
$r = 0.0;
|
$r = 0.0;
|
||||||
return $r;
|
}
|
||||||
}
|
return $r;
|
||||||
|
} // function hypo()
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mike Bommarito's version.
|
* Mike Bommarito's version.
|
||||||
* Compute n-dimensional hyotheneuse.
|
* Compute n-dimensional hyotheneuse.
|
||||||
*
|
*
|
||||||
function hypot() {
|
function hypot() {
|
||||||
$s = 0;
|
$s = 0;
|
||||||
foreach (func_get_args() as $d) {
|
foreach (func_get_args() as $d) {
|
||||||
if (is_numeric($d))
|
if (is_numeric($d)) {
|
||||||
$s += pow($d, 2);
|
$s += pow($d, 2);
|
||||||
else
|
} else {
|
||||||
trigger_error(ArgumentTypeException, ERROR);
|
throw new Exception(JAMAError(ArgumentTypeException));
|
||||||
}
|
}
|
||||||
return sqrt($s);
|
}
|
||||||
|
return sqrt($s);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user