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 |