mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-11 17:58:41 +00:00
Fix complex and matrix
This commit is contained in:
parent
23f24cf467
commit
9801d86b61
|
|
@ -167,7 +167,74 @@ class Matrix implements \ArrayAccess, \Iterator
|
|||
*/
|
||||
public function rank() : int
|
||||
{
|
||||
return 0;
|
||||
$matrix = $this->matrix;
|
||||
$mDim = $this->m;
|
||||
$nDim = $this->n;
|
||||
|
||||
if ($this->m > $this->n) {
|
||||
$mDim = $this->n;
|
||||
$nDim = $this->m;
|
||||
$matrix = array_map(null, ...$matrix);
|
||||
}
|
||||
|
||||
$rank = $mDim;
|
||||
|
||||
for ($row = 0; $row < $rank; ++$row) {
|
||||
if (isset($matrix[$row][$row]) && $matrix[$row][$row] !== 0) {
|
||||
for ($col = 0; $col < $mDim; ++$col) {
|
||||
if ($col !== $row) {
|
||||
$mult = $matrix[$col][$row] / $matrix[$row][$row];
|
||||
|
||||
for ($i = 0; $i < $rank; ++$i) {
|
||||
$matrix[$col][$i] -= $mult * $matrix[$row][$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$reduce = true;
|
||||
|
||||
for ($i = $row + 1; $i < $mDim; ++$i) {
|
||||
if (isset($matrix[$i][$row]) && $matrix[$i][$row] !== 0) {
|
||||
$this->swapRow($matrix, $row, $i, $rank);
|
||||
$reduce = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($reduce) {
|
||||
--$rank;
|
||||
|
||||
for ($i = 0; $i < $mDim; ++$i) {
|
||||
$matrix[$i][$row] = $matrix[$i][$rank];
|
||||
}
|
||||
|
||||
--$row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $rank;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap values in rows
|
||||
*
|
||||
* @param array $matrix Matrix reference to modify
|
||||
* @param int $row1 Row to swap
|
||||
* @param int $row2 Row to swap
|
||||
* @param int $col Max col to swap to
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function swapRow(array &$matrix, int $row1, int $row2, int $col) : void
|
||||
{
|
||||
for ($i = 0; $i < $col; ++$i) {
|
||||
$temp = $matrix[$row1][$i];
|
||||
$matrix[$row1] = $matrix[$row2][$i];
|
||||
$matrix[$row2] = $temp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -436,7 +503,7 @@ class Matrix implements \ArrayAccess, \Iterator
|
|||
*/
|
||||
private function upperTrianglize(array &$arr) : int
|
||||
{
|
||||
$n = count($arr);
|
||||
$n = $this->n;
|
||||
$sign = 1;
|
||||
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
|
|
@ -504,70 +571,6 @@ class Matrix implements \ArrayAccess, \Iterator
|
|||
return $this->solve(new IdentityMatrix($this->m));
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse matrix using gauss jordan.
|
||||
*
|
||||
* @return Matrix
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function inverseGaussJordan() : Matrix
|
||||
{
|
||||
$newMatrixArr = $this->matrix;
|
||||
|
||||
// extending matrix by identity matrix
|
||||
for ($i = 0; $i < $this->n; ++$i) {
|
||||
for ($j = $this->n; $j < $this->n * 2; ++$j) {
|
||||
|
||||
if ($j === ($i + $this->n)) {
|
||||
$newMatrixArr[$i][$j] = 1;
|
||||
} else {
|
||||
$newMatrixArr[$i][$j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$mDim = count($newMatrixArr);
|
||||
$nDim = count($newMatrixArr[0]);
|
||||
|
||||
// pivoting
|
||||
$newMatrixArr = $this->diag($newMatrixArr);
|
||||
|
||||
/* create unit matrix */
|
||||
for ($i = 0; $i < $mDim; ++$i) {
|
||||
$temp = $newMatrixArr[$i][$i];
|
||||
|
||||
for ($j = 0; $j < $nDim; ++$j) {
|
||||
$newMatrixArr[$i][$j] = $newMatrixArr[$i][$j] / $temp;
|
||||
}
|
||||
}
|
||||
|
||||
/* removing identity matrix */
|
||||
for ($i = 0; $i < $mDim; ++$i) {
|
||||
$newMatrixArr[$i] = array_slice($newMatrixArr[$i], $mDim);
|
||||
}
|
||||
|
||||
$newMatrix = new Matrix($this->n, $this->n);
|
||||
$newMatrix->setMatrix($newMatrixArr);
|
||||
|
||||
return $newMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Diagonalize matrix
|
||||
*
|
||||
* @return Matrix
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function diagonalize() : Matrix
|
||||
{
|
||||
$newMatrix = new Matrix($this->m, $this->n);
|
||||
$newMatrix->setMatrix($this->diag($this->matrix));
|
||||
|
||||
return $newMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Solve matrix
|
||||
*
|
||||
|
|
@ -584,111 +587,6 @@ class Matrix implements \ArrayAccess, \Iterator
|
|||
return $M->solve($B);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform gauss elimination on Matrix
|
||||
*
|
||||
* @param mixed $b Vector b
|
||||
*
|
||||
* @return Matrix
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function gaussElimination($b) : Matrix
|
||||
{
|
||||
$mDim = count($b);
|
||||
$matrix = $this->matrix;
|
||||
|
||||
for ($col = 0; $col < $mDim; $col++) {
|
||||
$j = $col;
|
||||
$max = $matrix[$j][$j];
|
||||
|
||||
for ($i = $col + 1; $i < $mDim; ++$i) {
|
||||
$temp = abs($matrix[$i][$col]);
|
||||
|
||||
if ($temp > $max) {
|
||||
$j = $i;
|
||||
$max = $temp;
|
||||
}
|
||||
}
|
||||
|
||||
if ($col != $j) {
|
||||
$temp = $matrix[$col];
|
||||
$matrix[$col] = $matrix[$j];
|
||||
$matrix[$j] = $temp;
|
||||
|
||||
$temp = $b[$col];
|
||||
$b[$col] = $b[$j];
|
||||
$b[$j] = $temp;
|
||||
}
|
||||
|
||||
for ($i = $col + 1; $i < $mDim; ++$i) {
|
||||
$temp = $matrix[$i][$col] / $matrix[$col][$col];
|
||||
|
||||
for ($j = $col + 1; $j < $mDim; ++$j) {
|
||||
$matrix[$i][$j] -= $temp * $matrix[$col][$j];
|
||||
}
|
||||
|
||||
$matrix[$i][$col] = 0;
|
||||
$b[$i] -= $temp * $b[$col];
|
||||
}
|
||||
}
|
||||
|
||||
$x = [];
|
||||
for ($col = $mDim - 1; $col >= 0; $col--) {
|
||||
$temp = $b[$col];
|
||||
for ($j = $mDim - 1; $j > $col; $j--) {
|
||||
$temp -= $x[$j] * $matrix[$col][$j];
|
||||
}
|
||||
|
||||
$x[$col] = $temp / $matrix[$col][$col];
|
||||
}
|
||||
|
||||
$solution = new self(count($x), count($x[0]));
|
||||
$solution->setMatrix($x);
|
||||
|
||||
return $solution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Diagonalize matrix.
|
||||
*
|
||||
* @param array $arr Matrix to diagonalize
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function diag(array $arr) : array
|
||||
{
|
||||
$mDim = count($arr);
|
||||
$nDim = count($arr[0]);
|
||||
|
||||
for ($i = $mDim - 1; $i > 0; $i--) {
|
||||
if ($arr[$i - 1][0] < $arr[$i][0]) {
|
||||
for ($j = 0; $j < $nDim; ++$j) {
|
||||
$temp = $arr[$i][$j];
|
||||
$arr[$i][$j] = $arr[$i - 1][$j];
|
||||
$arr[$i - 1][$j] = $temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* create diagonal matrix */
|
||||
for ($i = 0; $i < $mDim; ++$i) {
|
||||
for ($j = 0; $j < $mDim; ++$j) {
|
||||
if ($j !== $i) {
|
||||
$temp = $arr[$j][$i] / $arr[$i][$i];
|
||||
|
||||
for ($c = 0; $c < $nDim; ++$c) {
|
||||
$arr[$j][$c] -= $arr[$i][$c] * $temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate det.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -181,9 +181,7 @@ class Complex
|
|||
return $this;
|
||||
}
|
||||
|
||||
for ($i = $value; $i > 0; --$i) {
|
||||
return $this->multComplex($this->powInteger($i));
|
||||
}
|
||||
return $this->multComplex($this->powInteger(--$value));
|
||||
}
|
||||
|
||||
public function powScalar() : Complex
|
||||
|
|
|
|||
|
|
@ -69,14 +69,57 @@ class MatrixTest extends \PHPUnit\Framework\TestCase
|
|||
|
||||
public function testDet()
|
||||
{
|
||||
$this->B = new Matrix();
|
||||
$this->B->setMatrix([
|
||||
$B = new Matrix();
|
||||
$B->setMatrix([
|
||||
[6, 1, 1],
|
||||
[4, -2, 5],
|
||||
[2, 8, 7],
|
||||
]);
|
||||
|
||||
self::assertEquals(-306, $this->B->det());
|
||||
self::assertEquals(-306, $B->det());
|
||||
}
|
||||
|
||||
public function testTranspose()
|
||||
{
|
||||
$B = new Matrix();
|
||||
$B->setMatrix([
|
||||
[6, 1, 1],
|
||||
[4, -2, 5],
|
||||
]);
|
||||
|
||||
self::assertEquals([[6, 4], [1, -2], [1, 5],], $B->transpose()->toArray());
|
||||
}
|
||||
|
||||
public function testRank()
|
||||
{
|
||||
$B = new Matrix();
|
||||
$B->setMatrix([
|
||||
[0, 1, 2],
|
||||
[1, 2, 1],
|
||||
[2, 7, 8],
|
||||
]);
|
||||
|
||||
self::assertEquals(2, $B->rank());
|
||||
|
||||
$B->setMatrix([
|
||||
[1, 0, 2],
|
||||
[2, 1, 0],
|
||||
[3, 2, 1],
|
||||
]);
|
||||
self::assertEquals(3, $B->rank());
|
||||
|
||||
$B->setMatrix([
|
||||
[1, 0, 2],
|
||||
[2, 1, 0],
|
||||
]);
|
||||
self::assertEquals(2, $B->rank());
|
||||
|
||||
$B->setMatrix([
|
||||
[1, 2],
|
||||
[0, 1],
|
||||
[2, 0],
|
||||
]);
|
||||
self::assertEquals(2, $B->rank());
|
||||
}
|
||||
|
||||
public function testInverse()
|
||||
|
|
@ -88,6 +131,8 @@ class MatrixTest extends \PHPUnit\Framework\TestCase
|
|||
[2, 1, 1],
|
||||
]);
|
||||
|
||||
self::markTestIncomplete();
|
||||
// todo: result column 0 and 1 are swapped. why? still correct?
|
||||
/*self::assertEquals([
|
||||
[-0.9, -0.5, 2.2],
|
||||
[0.7, 0.5, -1.6],
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class ComplexTest extends \PHPUnit\Framework\TestCase
|
|||
|
||||
self::assertEquals('7.00 + 24.00i', $cpl->square()->render());
|
||||
self::assertEquals('7.00 + 24.00i', $cpl->pow(2)->render());
|
||||
self::assertEquals('-44.00 - 117.00i', $cpl->pow(3)->render());
|
||||
self::assertEquals('-44.00 + 117.00i', $cpl->pow(3)->render());
|
||||
|
||||
self::assertEquals(5, $cpl->abs(), '', 0.01);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user