PHP inverse of a matrix

我们两清 提交于 2019-12-10 18:16:25

问题


I saw this question,and pop up this idea.

Is there an efficient way to do this in PHP?

EDIT

Best with a demo?


回答1:


You could use the pear package Math_Matrix for this.




回答2:


This package claims to be able to do what you are looking for.




回答3:


/**
* 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;
}



回答4:


There is this open source PHP Library that is able to invert a Matrix.

All you need to do is

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



回答5:


Here tested code https://gist.github.com/unix1/7510208 Only identity_matrix() and invert() functions are enough




回答6:


Yes there are several ways to accomplish this in php. There are a handful of available libraries. Alternatively, you could maintain your own class and customize as needed. Here is an excerpt from our inhouse library that is based on the mathematical method described in the link. There is a demonstration at the end of the class for further reference.

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
        )

    )
    */


来源:https://stackoverflow.com/questions/1811250/php-inverse-of-a-matrix

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!