/** * Compute inverse using determinants method * We are expecting a non singular, square matrix (complete, n=m, n>1) * * @param \Chippyash\Matrix\Matrix $mA * @return Matrix */ public function invert(NumericMatrix $mA) { $rows = $mA->rows(); $cols = $mA->columns(); $work = array(); $fDet = new Det(); $fCof = new Cofactor(); for ($row = 0; $row < $rows; $row++) { for ($col = 0; $col < $cols; $col++) { $t = $fDet($fCof($mA, [$row + 1, $col + 1])); if (fmod($row + $col, 2) == 0) { $work[$row][$col] = $t; } else { $work[$row][$col] = $t->negate(); } $r = $row + 1; $c = $col + 1; } } $fTr = new Transpose(); $fDiv = new Scalar(); return $fTr($fDiv($this->createCorrectMatrixType($mA, $work), $fDet($mA))); }
/** * Compute determinant using a strategy * * @param \Chippyash\Math\Matrix\NumericMatrix $mA * @return numeric * @throws UndefinedComputationException * * @todo put back in LU determinant strategy once figured out what is wrong with it */ protected function getDeterminant(NumericMatrix $mA) { switch ($this->method) { case self::METHOD_AUTO: if ($mA->rows() <= self::$luLimit) { $strategy = new Lu(); } else { throw new UndefinedComputationException('No available strategy found to determine the determinant'); } break; case self::METHOD_LAPLACE: $strategy = new Laplace(); break; case self::METHOD_LU: $strategy = new Lu(); break; default: throw new UndefinedComputationException('Unknown determinant computation method'); } return $strategy->determinant($mA); }
/** * Massage where mA is rectangle * @param \Chippyash\Math\Matrix\NumericMatrix $mA * @param \Chippyash\Math\Matrix\NumericMatrix $mB * @param array $product * @return \Chippyash\Math\Matrix\NumericMatrix */ protected function massageRectangle(NumericMatrix $mA, NumericMatrix $mB, array $product) { if ($mB->is('rectangle') && $mA->rows() < $mB->rows()) { return $this->createCorrectMatrixType($mA, [[$product[0][0], $product[0][1]], [$product[1][0], $product[1][1]]]); } return $this->createCorrectMatrixType($mA, $product); }
/** * Recursive determinant function * * @param \Chippyash\Math\Matrix\NumericMatrix $mA * @return \Chippyash\Type\Interfaces\NumericTypeInterface */ protected function det(NumericMatrix $mA) { $rowCount = $mA->rows(); if ($rowCount == 0) { return $this->createCorrectScalarType($mA, 1); } if ($rowCount == 1) { return $mA->get(1, 1); } $possAnswer = $this->checkInCache($mA); if ($possAnswer !== false) { return $possAnswer; } if ($rowCount == 2) { //2X2 matrix $det = $this->det2($mA); } else { //nXn matrix $det = $this->detN($mA); } $this->storeInCache($mA, $det); return $det; }
/** * Set upper triangular factor. */ protected function setUpperProduct(NumericMatrix $mA) { $n = $this->LU->columns(); $LU = $this->LU->toArray(); $rcFactor = $this->cols - $this->rows; $this->set('U', function () use($n, $LU, $rcFactor, $mA) { $U = []; for ($i = 0; $i < $n; $i++) { for ($j = 0; $j < $n; $j++) { if ($i <= $j) { $U[$i][$j] = isset($LU[$i][$j]) ? $LU[$i][$j] : $this->createCorrectScalarType($mA, 0); } else { $U[$i][$j] = $this->createCorrectScalarType($mA, 0); } } } //remove extra rows for non square matrices if ($rcFactor > 0) { $mUU = new NumericMatrix($U); return $this->createCorrectMatrixType($mA, $mUU('Rowslice', array(1, $mUU->rows() - $rcFactor))->toArray()); } else { return $this->createCorrectMatrixType($mA, $U); } }); }