/** * Calculates lower triangular matrix L of given symmetric positive definite matrix * * @param NumArray $squareMatrix symmetric positive definite matrix * * @return NumArray * * @throws InvalidArgumentException will be thrown, when `$squareMatrix` is not positive definite * @throws NoSquareMatrixException will be thrown, when `$squareMatrix` is not square * @throws NoSymmetricMatrixException will be thrown, when `$squareMatrix` is not symmetric * * @since 1.0.2 */ public static function cholesky(NumArray $squareMatrix) { if (!Helper::isSquareMatrix($squareMatrix)) { throw new NoSquareMatrixException(sprintf("Matrix with shape (%s) given, matrix has to be square", implode(', ', $squareMatrix->getShape()))); } $shape = $squareMatrix->getShape(); $size = $shape[0]; $aMatrix = clone $squareMatrix; $lMatrix = NumPHP::zerosLike($aMatrix); for ($k = 0; $k < $size; $k++) { $diaElem = $aMatrix->get($k, $k)->getData(); if ($diaElem <= 0) { throw new InvalidArgumentException("Matrix is not positive definite"); } $diaElem = sqrt($diaElem); $lMatrix->set($k, $k, $diaElem); for ($i = $k + 1; $i < $size; $i++) { if ($squareMatrix->get($i, $k) != $squareMatrix->get($k, $i)) { throw new NoSymmetricMatrixException("Matrix is not symmetric"); } $lMatrix->set($i, $k, $aMatrix->get($i, $k)->div($diaElem)); for ($j = $k + 1; $j <= $i; $j++) { $aMatrix->set($i, $j, $aMatrix->get($i, $j)->sub($lMatrix->get($i, $k)->mult($lMatrix->get($j, $k)))); } } } return $lMatrix; }
/** * Calculates the determinant of a matrix * * @param mixed $matrix matrix * * @throws NoSquareMatrixException will be thrown, if given array is no square matrix * * @api * @since 1.0.0 * * @return float */ public static function det($matrix) { if (!$matrix instanceof NumArray) { $matrix = new NumArray($matrix); } elseif ($matrix->inCache(self::CACHE_KEY_DETERMINANT)) { return $matrix->getCache(self::CACHE_KEY_DETERMINANT); } if (!Helper::isSquareMatrix($matrix)) { throw new NoSquareMatrixException(sprintf("Matrix with shape (%s) given, matrix has to be square", implode(', ', $matrix->getShape()))); } $shape = $matrix->getShape(); $lud = self::lud($matrix); /** * Upper triangular matrix * * @var NumArray $uMatrix */ $uMatrix = $lud[2]; $det = 1; for ($i = 0; $i < $shape[0]; $i++) { $det *= $uMatrix->get($i, $i)->getData(); } $matrix->setCache(self::CACHE_KEY_DETERMINANT, $det); return $det; }
/** * Tests if Helper::isSquareMatrix works with invalid square matrix */ public function testCheckSquareMatrixInvalid() { $numArray = NumPHP::ones(2, 3); $this->assertFalse(Helper::isSquareMatrix($numArray)); }