diff --git a/Math/Matrix/InverseType.php b/Math/Matrix/InverseType.php new file mode 100644 index 000000000..47b9ccdd0 --- /dev/null +++ b/Math/Matrix/InverseType.php @@ -0,0 +1,34 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\Math\Matrix; + +use phpOMS\Datatypes\Enum; + +/** + * Account type enum. + * + * @category Framework + * @package phpOMS\DataStorage\Database + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +abstract class InverseType extends Enum +{ + const GAUSS_JORDAN = 0; +} diff --git a/Math/Matrix/Matrix.php b/Math/Matrix/Matrix.php index 1963c4503..027e7ba76 100644 --- a/Math/Matrix/Matrix.php +++ b/Math/Matrix/Matrix.php @@ -160,4 +160,178 @@ class Matrix implements ArrayAccess, Iterator return $newMatrix; } + + public function upperTriangular() : Matrix + { + $matrix = new Matrix($this->n, $this->n); + + $matrixArr = $this->matrix; + $matrix->setMatrix($this->upperTrianglize($matrixArr)); + + return $matrix; + } + + public function lowerTriangular() : Matrix + { + // todo: implement + return new Matrix($this->m, $this->n); + } + + public function diag() : Matrix + { + + } + + public function inverse(int $algorithm = InversionType::GAUSS_JORDAN) : Matrix + { + if($this->n !== $this->m) { + throw new \Exception('Dimension'); + } + + switch($algorithm) { + case InversionType::GAUSS_JORDAN: + return $this->inverseGaussJordan(); + default: + throw new \Exception(''); + } + } + + private function inverseGaussJordan() : Matrix + { + $newMatrixArr = $this->matrix; + + // extending matrix by identity matrix + for($i = 0; $i < $this->n; $i++) { + for($j = $this->n; $j < $this->n * 2; $j++) { + + if($j === ($i + $this->n)) { + $newMatrixArr[$i][$j] = 1; + } else { + $newMatrixArr[$i][$j] = 0; + } + } + } + + // todo: maybe replace by triangulize/vice versa????!!!?!?! + // pivoting + for($i = $this->n - 1; $i > 0; $i--) { + if ($newMatrixArr[$i - 1][0] < $newMatrixArr[$i][0]) { + for($j = 0; $j < $this->n * 2; $j++) { + $temp = $newMatrixArr[$i][$j]; + $newMatrixArr[$i][$j] = $newMatrixArr[$i-1][$j]; + $newMatrixArr[$i-1][$j] = $temp; + } + } + } + + /* create diagonal matrix */ + for($i = 0; $i < $this->n; $i++) { + for($j = 0; $j < $this->n; $j++) { + if ($j !== $i) { + $temp = $newMatrixArr[$j][$i] / $newMatrixArr[$i][$i]; + + for($c = 0; $c < $this->n * 2; $c++) { + $newMatrixArr[$j][$c] -= $newMatrixArr[$i][$c] * $temp; + } + } + } + } + + /* create unit matrix */ + for($i = 0; $i < $this->n; $i++) { + $temp = $newMatrixArr[$i][$i]; + + for($j = 0; $j < $this->n * 2; $j++) { + $newMatrixArr[$i][$j] = $newMatrixArr[$i][$j] / $temp; + } + } + + /* removing identity matrix */ + for($i = 0; $i < $this->n; $i++) { + $newMatrixArr[$i] = array_slice($newMatrixArr[$i], $this->n); + } + + $newMatrix = new Matrix($this->n, $this->n); + $newMatrix->setMatrix($newMatrixArr); + + return $newMatrix; + } + + private function decompositionCholesky() : Matrix + { + $newMatrix = new Matrix($this->n, $this->n); + $newMatrixArr = $newMatrix->getMatrix(); + + for ($i = 0; $i < $this->n; $i++) { + for ($j = 0; $j < $i+1; $j++) { + $temp = 0; + + for ($c = 0; $c < $j; $c++) { + $temp += $newMatrixArr[$i][$c] * $newMatrixArr[$j][$c]; + } + + $newMatrixArr[$i][$j] = ($i == $j) ? sqrt($this->matrix[$i][$i] - $temp) : (1 / $newMatrixArr[$j][$j] * ($this->matrix[$i][$j] - $temp)); + } + } + + $newMatrix->setMatrix($newMatrixArr); + + return $newMatrix; + } + + private function upperTrianglize(array &$arr) : int + { + $n = count($arr); + $sign = 1; + + for ($i = 0; $i < $n; $i++) { + $max = 0; + + for ($j = $i; $j < $n; $j++) { + if (abs($arr[$j][$i]) > abs($arr[$max][$i])) { + $max = $j; + } + } + + if ($max) { + $sign = -$sign; + $temp = $arr[$i]; + $arr[$i] = $arr[$max], $arr[$max] = $temp; + } + + if (!$arr[$i][$i]) { + return 0; + } + + for ($j = $i + 1; $j < $n; $j++) { + $r = $arr[$j][$i] / $arr[$i][$i]; + + if (!$r) { + continue; + } + + for ($c = $i; $c < $n; $c ++) { + $arr[$j][$c] -= $arr[$i][$c] * $r; + } + } + } + + return $sign; + } + + public function det() + { + if($this->n === 1) { + return $this->matrix[0][0]; + } + + $trianglize = $this->matrix; + $prod = $this->(upperTrianglize($trianglize)); + + for($i = 0; $i < $this->n; $i++) { + $prod *= $trianglize[$i][$i]; + } + + return $prod; + } } \ No newline at end of file