PHP逆矩阵

时间:2009-11-28 01:30:07

标签: php matrix linear-algebra matrix-inverse

我看到了this question,并提出了这个想法。

在PHP中有一种有效的方法吗?

修改

最佳演示?

6 个答案:

答案 0 :(得分:2)

你可以使用梨包Math_Matrix

答案 1 :(得分:1)

package claims能够做你想要的。

答案 2 :(得分:1)

/**
* matrix_inverse
*
* Matrix Inverse
* Guass-Jordan Elimination Method
* Reduced Row Eshelon Form (RREF)
*
* In linear algebra an n-by-n (square) matrix A is called invertible (some
* authors use nonsingular or nondegenerate) if there exists an n-by-n matrix    B
* such that AB = BA = In where In denotes the n-by-n identity matrix and the
* multiplication used is ordinary matrix multiplication. If this is the case,
* then the matrix B is uniquely determined by A and is called the inverse of A,
* denoted by A-1. It follows from the theory of matrices that if for finite
* square matrices A and B, then also non-square matrices (m-by-n matrices for
* which m ? n) do not have an inverse. However, in some cases such a matrix may
* have a left inverse or right inverse. If A is m-by-n and the rank of A is
* equal to n, then A has a left inverse: an n-by-m matrix B such that BA = I.
* If A has rank m, then it has a right inverse: an n-by-m matrix B such that
* AB = I.
*
* A square matrix that is not invertible is called singular or degenerate. A
* square matrix is singular if and only if its determinant is 0. Singular
* matrices are rare in the sense that if you pick a random square matrix over
* a continuous uniform distribution on its entries, it will almost surely not
* be singular.
*
* While the most common case is that of matrices over the real or complex
* numbers, all these definitions can be given for matrices over any commutative
* ring. However, in this case the condition for a square matrix to be
* invertible is that its determinant is invertible in the ring, which in
* general is a much stricter requirement than being nonzero. The conditions for
* existence of left-inverse resp. right-inverse are more complicated since a
* notion of rank does not exist over rings.
*/
public function matrix_inverse($m1)
{
    $rows = $this->rows($m1);
    $cols = $this->columns($m1);
    if ($rows != $cols)
    {
        die("Matrim1 is not square. Can not be inverted.");
    }

    $m2 = $this->eye($rows);

    for ($j = 0; $j < $cols; $j++)
    {
        $factor = $m1[$j][$j];
        if ($this->debug)
        {
            fms_writeln('Divide Row [' . $j . '] by ' . $m1[$j][$j] . ' (to
                                                  give us a "1" in the desired position):');
        }
        $m1 = $this->rref_div($m1, $j, $factor);
        $m2 = $this->rref_div($m2, $j, $factor);
        if ($this->debug)
        {
            $this->disp2($m1, $m2);
        }
        for ($i = 0; $i < $rows; $i++)
        {
            if ($i != $j)
            {
                $factor = $m1[$i][$j];
                if ($this->debug)
                {
                    $this->writeln('Row[' . $i . '] - ' . number_format($factor, 4) . ' ×
                                                Row[' . $j . '] (to give us 0 in the desired position):');
                }
                $m1 = $this->rref_sub($m1, $i, $factor, $j);
                $m2 = $this->rref_sub($m2, $i, $factor, $j);
                if ($this->debug)
                {
                    $this->disp2($m1, $m2);
                }
            }
        }
    }
    return $m2;
}

答案 3 :(得分:0)

有一个开源PHP Library能够反转矩阵。

您需要做的就是

<?php
include_once ("Matrix.class.php");
$matrixA = new Matrix(array(array(0, 1), array(2, 6)));
echo $matrixA->getInverse()->getMathMl();
?>

答案 4 :(得分:0)

此处测试代码https://gist.github.com/unix1/7510208 只有identity_matrix()和invert()函数就足够了

答案 5 :(得分:0)

是的,有几种方法可以在php中完成。有一些可用的库。另外,您可以维护自己的类并根据需要自定义。这是我们内部图书馆的摘录,该摘录是基于链接中描述的数学方法的。课堂结束时有一个示范,供进一步参考。

https://www.intmath.com/matrices-determinants/inverse-matrix-gauss-jordan-elimination.php

    class MatrixLibrary
    {
        //Gauss-Jordan elimination method for matrix inverse
        public function inverseMatrix(array $matrix)
        {
            //TODO $matrix validation

            $matrixCount = count($matrix);

            $identityMatrix = $this->identityMatrix($matrixCount);
            $augmentedMatrix = $this->appendIdentityMatrixToMatrix($matrix, $identityMatrix);
            $inverseMatrixWithIdentity = $this->createInverseMatrix($augmentedMatrix);
            $inverseMatrix = $this->removeIdentityMatrix($inverseMatrixWithIdentity);

            return $inverseMatrix;
        }

        private function createInverseMatrix(array $matrix)
        {
            $numberOfRows = count($matrix);

            for($i=0; $i<$numberOfRows; $i++)
            {
                $matrix = $this->oneOperation($matrix, $i, $i);

                for($j=0; $j<$numberOfRows; $j++)
                {
                    if($i !== $j)
                    {
                        $matrix = $this->zeroOperation($matrix, $j, $i, $i);
                    }
                }
            }
            $inverseMatrixWithIdentity = $matrix;

            return $inverseMatrixWithIdentity;
        }

        private function oneOperation(array $matrix, $rowPosition, $zeroPosition)
        {
            if($matrix[$rowPosition][$zeroPosition] !== 1)
            {
                $numberOfCols = count($matrix[$rowPosition]);

                if($matrix[$rowPosition][$zeroPosition] === 0)
                {
                    $divisor = 0.0000000001;
                    $matrix[$rowPosition][$zeroPosition] = 0.0000000001;
                }
                else
                {
                    $divisor = $matrix[$rowPosition][$zeroPosition];
                }

                for($i=0; $i<$numberOfCols; $i++)
                {
                    $matrix[$rowPosition][$i] = $matrix[$rowPosition][$i] / $divisor;
                }
            }

            return $matrix;
        }

        private function zeroOperation(array $matrix, $rowPosition, $zeroPosition, $subjectRow)
        {
            $numberOfCols = count($matrix[$rowPosition]);

            if($matrix[$rowPosition][$zeroPosition] !== 0)
            {
                $numberToSubtract = $matrix[$rowPosition][$zeroPosition];

                for($i=0; $i<$numberOfCols; $i++)
                {
                    $matrix[$rowPosition][$i] = $matrix[$rowPosition][$i] - $numberToSubtract * $matrix[$subjectRow][$i];
                }
            }

            return $matrix;
        }

        private function removeIdentityMatrix(array $matrix)
        {
            $inverseMatrix = array();
            $matrixCount = count($matrix);

            for($i=0; $i<$matrixCount; $i++)
            {
                $inverseMatrix[$i] = array_slice($matrix[$i], $matrixCount);
            }

            return $inverseMatrix;
        }

        private function appendIdentityMatrixToMatrix(array $matrix, array $identityMatrix)
        {
            //TODO $matrix & $identityMatrix compliance validation (same number of rows/columns, etc)

            $augmentedMatrix = array();

            for($i=0; $i<count($matrix); $i++)
            {
                $augmentedMatrix[$i] = array_merge($matrix[$i], $identityMatrix[$i]);
            }

            return $augmentedMatrix;
        }

        public function identityMatrix(int $size)
        {
            //TODO validate $size

            $identityMatrix = array();

            for($i=0; $i<$size; $i++)
            {
                for($j=0; $j<$size; $j++)
                {
                    if($i == $j)
                    {
                        $identityMatrix[$i][$j] = 1;
                    }
                    else
                    {
                        $identityMatrix[$i][$j] = 0;
                    }
                }
            }

            return $identityMatrix;
        }
    }

    $matrix = array(
        array(11, 3, 12),
        array(8, 7, 10),
        array(13, 14, 15),
    );

    $matrixLibrary = new MatrixLibrary();
    $inverseMatrix = $matrixLibrary->inverseMatrix($matrix);

    print_r($inverseMatrix);

    /*
    Array
    (
        [0] => Array
        (
            [0] => 0.33980582524272
            [1] => -1.1941747572816
            [2] => 0.52427184466019
        )

        [1] => Array
        (
            [0] => -0.097087378640777
            [1] => -0.087378640776699
            [2] => 0.13592233009709
        )

        [2] => Array
        (
            [0] => -0.20388349514563
            [1] => 1.1165048543689
            [2] => -0.51456310679612
        )

    )
    */