MathPHP\LinearAlgebra\Matrix::solve PHP Method

solve() public method

If A is nxn invertible matrix, and the inverse is already computed: x = A⁻¹b If 2x2, just take the inverse and solve: x = A⁻¹b If 3x3 or higher, check if the RREF is already computed, and if so, then just take the inverse and solve: x = A⁻¹b Otherwise, it is more efficient to decompose and then solve. Use LU Decomposition and solve Ax = b. LU Decomposition: - Equation to solve: Ax = b - LU Decomposition produces: PA = LU - Substitute: LUx = Pb, or Pb = LUx - Can rewrite as Pb = L(Ux) - Can say y = Ux - Then can rewrite as Pb = Ly - Solve for y (we know Pb and L) - Solve for x in y = Ux once we know y Solving triangular systems Ly = Pb and Ux = y - Solve for Ly = Pb using forward substitution 1 / ᵢ₋₁ \ yᵢ = --- | bᵢ - ∑ Lᵢⱼyⱼ | Lᵢᵢ \ ʲ⁼¹ / - Solve for Ux = y using back substitution 1 / m \ xᵢ = --- | yᵢ - ∑ Uᵢⱼxⱼ | Uᵢᵢ \ ʲ⁼ⁱ⁺¹ /
public solve ( Vector/array $b ) : Vector
$b Vector/array
return Vector x
    public function solve($b)
    {
        // Input must be a Vector or array.
        if (!($b instanceof Vector || is_array($b))) {
            throw new Exception\IncorrectTypeException('b in Ax = b must be a Vector or array');
        }
        if (is_array($b)) {
            $b = new Vector($b);
        }
        // If inverse is already calculated, solve: x = A⁻¹b
        if (isset($this->A⁻¹)) {
            return new Vector($this->A⁻¹->multiply($b)->getColumn(0));
        }
        // If 2x2, just compute the inverse and solve: x = A⁻¹b
        if ($this->m === 2 && $this->n === 2) {
            $this->inverse();
            return new Vector($this->A⁻¹->multiply($b)->getColumn(0));
        }
        // For 3x3 or higher, check if the RREF is already computed.
        // If so, just compute the inverse and solve: x = A⁻¹b
        if (isset($this->rref)) {
            $this->inverse();
            return new Vector($this->A⁻¹->multiply($b)->getColumn(0));
        }
        // No inverse or RREF pre-computed.
        // Use LU Decomposition.
        $this->LUDecomposition();
        $L = $this->L;
        $U = $this->U;
        $P = $this->P;
        $m = $this->m;
        // Pivot solution vector b with permutation matrix: Pb
        $Pb = $P->multiply($b);
        /* Solve for Ly = Pb using forward substitution
         *         1   /    ᵢ₋₁      \
         *   yᵢ = --- | bᵢ - ∑ Lᵢⱼyⱼ |
         *        Lᵢᵢ  \    ʲ⁼¹      /
         */
        $y = [];
        $y[0] = $Pb[0][0] / $L[0][0];
        for ($i = 1; $i < $m; $i++) {
            $sum = 0;
            for ($j = 0; $j <= $i - 1; $j++) {
                $sum += $L[$i][$j] * $y[$j];
            }
            $y[$i] = ($Pb[$i][0] - $sum) / $L[$i][$i];
        }
        /* Solve for Ux = y using back substitution
         *         1   /     m       \
         *   xᵢ = --- | yᵢ - ∑ Uᵢⱼxⱼ |
         *        Uᵢᵢ  \   ʲ⁼ⁱ⁺¹     /
         */
        $x = [];
        $x[$m - 1] = $y[$m - 1] / $U[$m - 1][$m - 1];
        for ($i = $m - 2; $i >= 0; $i--) {
            $sum = 0;
            for ($j = $i + 1; $j < $m; $j++) {
                $sum += $U[$i][$j] * $x[$j];
            }
            $x[$i] = ($y[$i] - $sum) / $U[$i][$i];
        }
        // Return unknown xs as Vector
        return new Vector(array_reverse($x));
    }