【问题标题】:PHP inverse of a matrix矩阵的 PHP 逆
【发布时间】:2009-11-28 01:30:06
【问题描述】:

我看到this question,突然冒出这个想法。

在 PHP 中有没有一种有效的方法来做到这一点?

编辑

最好有演示?

【问题讨论】:

    标签: php matrix linear-algebra matrix-inverse


    【解决方案1】:

    您可以为此使用 pear 包 Math_Matrix

    【讨论】:

    • 该链接不会产生页面。
    • 哇。梨页面真的不喜欢那个链接。我自己去了那里并试图更正链接。同样的问题。似乎无法直接链接到它。只需点击顶部菜单上的搜索包并搜索矩阵
    • 正确的链接是 pear.php.net/package/Math-Matrix (对不起,我不能编辑你的帖子来更正链接)
    【解决方案2】:

    这个package claims 能够满足您的需求。

    【讨论】:

      【解决方案3】:

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

      你需要做的就是

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

      【讨论】:

        【解决方案4】:
        /**
        * 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;
        }
        

        【讨论】:

        • 这段代码有一堆对$this 上的函数的重要引用,这些引用从未显示过。没有这个上下文,不幸的是代码毫无用处。
        【解决方案5】:

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

        【讨论】:

        • 图书馆似乎不再可用
        • @MarkBaker 它绝对可用 - 自 2013 年 11 月成立以来,该要点一直是公开的并且在该位置。免责声明:我是该要点的作者。
        【解决方案6】:

        是的,有几种方法可以在 php.ini 中实现这一点。有一些可用的库。或者,您可以维护自己的类并根据需要进行自定义。这是我们内部库的摘录,该库基于链接中描述的数学方法。课后有演示供进一步参考。

        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
                )
        
            )
            */
        

        【讨论】:

        • 虽然此代码 sn-p 可能是解决方案,但 including an explanation 确实有助于提高您的帖子质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
        猜你喜欢
        • 1970-01-01
        • 2012-04-21
        • 1970-01-01
        • 1970-01-01
        • 2019-02-08
        • 2010-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多