PHP矩阵逆

PHP inverse of a matrix

我看到了这个问题,然后弹出了这个主意。

在PHP中有有效的方法吗?

编辑

最适合演示吗?


您可以为此使用梨包Math_Matrix。


此程序包声称能够执行您想要的操作。


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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
    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://gist.github.com/unix1/7510208
仅identity_matrix()和invert()函数就足够了


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
* 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;
}


有一个开源的PHP库,能够转换矩阵。

您需要做的只是

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