{% else-1 %}

                        
<?php 
/****************
4x + 7y + 2z = 34
3x + 1y + 5z = 21
8x + 2y + 6z = 52
****************/
$matrix[0] = array(4, 7, 2);
$matrix[1] = array(3, 1, 5);
$matrix[2] = array(8, 2, 6);
$b[0] = 34;
$b[1] = 21;
$b[2] = 52;
// Решаем уравнение
list($x, $y, $z) = solve($matrix, $b);
echo "Решение<br />";
echo "X = $x<br />";
echo "Y = $y<br />";
echo "Z = $z<br />";
// Проверка
echo 4 * $x + 7 * $y + 2 * $z;
echo "<br>";
echo 3 * $x + 1 * $y + 5 * $z;
echo "<br>";
echo 8 * $x + 2 * $y + 6 * $z;

function solve($matrix, $b)
{
// Вычисляем детерминант исходной матрицы
$determinant = determinant($matrix);
// Формируем детерминант для переменных
for($i = 0; $i < 3; $i++)
{
$xd[$i] = $matrix[$i];
$xd[$i][0] = $b[$i];
$yd[$i] = $matrix[$i];
$yd[$i][1] = $b[$i];
$zd[$i] = $matrix[$i];
$zd[$i][2] = $b[$i];
}
$x = determinant($xd) / $determinant;
$y = determinant($yd) / $determinant;
$z = determinant($zd) / $determinant;

return array($x, $y, $z);
}
// Детерминант трехмерной матрицы
function determinant($m)
{
return $m[0][0] * ($m[1][1] * $m[2][2] - $m[2][1] * $m[1][2]) -
$m[0][1] * ($m[1][0] * $m[2][2] - $m[2][0] * $m[1][2]) +
$m[0][2] * ($m[1][0] * $m[2][1] - $m[2][0] * $m[1][1]);
}
?>
Напоминаем, что если детерминант матрицы равен 0, это означает, что система уравнений линейно зависима и получить единственное решение невозможно.

При решении систем с более чем тремя переменными, следует прибегать к более сложным алогиритмам. Одним из таких алгоритмов является метод Гаусса-Жордана, который часто используют и при ручном вычислении систем линейных уравнений. Ниже приведена возможная реализация для все той же системы с тремя неизвестными, но в отличие от представленного выше скрипта, здесь можно увеличивать количество неизвестных в системе.

Метод Гаусса-Жордана

<?php
/****************
4x + 7y + 2z = 34
3x + 1y + 5z = 21
8x + 2y + 6z = 52
****************/
$matrix[0] = array(4, 7, 2);
$matrix[1] = array(3, 1, 5);
$matrix[2] = array(8, 2, 6);
$b[0] = 34;
$b[1] = 21;
$b[2] = 52;
// Решаем уравнение
list(list($x, $y, $z)) = gaussj($matrix, $b);
echo "Решение<br />";
echo "X = $x<br />";
echo "Y = $y<br />";
echo "Z = $z<br />";
// Проверка
echo 4 * $x + 7 * $y + 2 * $z;
echo "<br>";
echo 3 * $x + 1 * $y + 5 * $z;
echo "<br>";
echo 8 * $x + 2 * $y + 6 * $z;
// Решение системы линейных уравнений
// методом Метод Гаусса-Жордана
function gaussj($a, $b)
{
$n = count($a);
for($j = 0; $j < $n; $j++)
{
$ipiv[$j] = 0;
}
for($i = 0; $i < $n; $i++)
{
$big = 0;
for($j = 0; $j < $n; $j++)
{
if($ipiv[$j] != 1)
{
for($k = 0; $k < $n; $k++)
{
if($ipiv[$k] == 0)
{
if(abs($a[$j][$k]) >= $big)
{
$big = abs($a[$j][$k]);
$irow = $j;
$icol = $k;
}
}
else if($ipiv[$k] > 1)
{
return "Матрица сингулярна";
}
}
}
}
$ipiv[$icol] = $ipiv[$icol] + 1;
if ($irow != $icol)
{
for($l = 0; $l < $n; $l++)
{
$dum = $a[$irow][$l];
$a[$irow][$l] = $a[$icol][$l];
$a[$icol][$l] = $dum;
}
$dum = $b[$irow];
$b[$irow] = $b[$icol];
$b[$icol] = $dum;
}
$indxr[$i] = $irow;
$indxc[$i] = $icol;
if($a[$icol][$icol] == 0) return "Матрица сингулярна";
$pivinv = 1 / $a[$icol][$icol];
$a[$icol][$icol] = 1;
for($l = 0; $l < $n; $l++) $a[$icol][$l] = $a[$icol][$l] * $pivinv;
$b[$icol] = $b[$icol] * $pivinv;
for($ll = 0; $ll < $n; $ll++)
{
if($ll != $icol)
{
$dum = $a[$ll][$icol];
$a[$ll][$icol] = 0;
for($l = 0; $l < $n; $l++)
{
$a[$ll][$l] = $a[$ll][$l] - $a[$icol][$l] * $dum;
}
$b[$ll] = $b[$ll] - $b[$icol] * $dum;
}
}
}
for($l = $n -1; $l >= 0; $l--)
{
if($indxr[$l] != $indxc[$l])
{
for($k = 1; $k < $n; $k++)
{
$dum = $a[$k][$indxr[$l]];
$a[$k][$indxr[$l]] = $a[$k][$indxc[$l]];
$a[$k][$indxc[$l]] = $dum;
}
}
}
// $b - решение уравнения
// $a - обратная матрица
return array($b, $a);
}
?>
Функция gaussj() принимает два параметра: квадратную матрицу коэффециентов $a и вектор свободных членов $b. На выходе также возвращаются два решения: $b содержит значения переменных, а $a - обратную матрицу. Если задача состоит только в нахождении обратной матрицы можно воспользоваться решением


<?php
//$a-это исходная матрица 3*3
$a = array(array(0,1,1), array(1,0,1), array(1,1,0));
for ($k=1;$k<=3;$k++)
{
for ($i=1;$i<=3;$i++)
{
for ($j=1;$j<=3;$j++)
{
if ($i==$k and $j==$k) $b[$i][$j]=1/$a[$i][$j];
if ($i==$k and $j!=$k) $b[$i][$j]=-$a[$i][$j]/$a[$k][$k];
if ($i!=$k and $j==$k) $b[$i][$j]=$a[$i][$k]/$a[$k][$k];
if ($i!=$k and $j!=$k) $b[$i][$j]=$a[$i][$j]-$a[$k][$j]*$a[$i][$k]/$a[$k][$k];
}
}
$a=$b;
}

echo "<pre>";
print_r($a);
?>


В этом примере есть деление на элементы матрицы, но некоторые равны нулю и что тогда делать? По моим подсчётам матрица на выходе должна иметь вид:
array(
array(-0.5, 0.5, 0.5),
array(0.5, -0.5, 0.5),
array(0.5, 0.5, -0.5)
)'

Нашёл ещё один способ. Он был на С++ написан, но переписал его на РНР:



<?php
function q($matrix){
$a = $matrix;
$e = array();
$count = count($a);
for($i=0;$i<$count;$i++)
for($j=0;$j<$count;$j++)
$e[$i][$j]=($i==$j)? 1 : 0;

for($i=0;$i<$count;$i++){
$tmp = $a[$i][$i];
for($j=$count-1;$j>=0;$j--){
$e[$i][$j]/=$tmp;
$a[$i][$j]/=$tmp;
}

for($j=0;$j<$count;$j++){
if($j!=$i){
$tmp = $a[$j][$i];
for($k=$count-1;$k>=0;$k--){
$e[$j][$k]-=$e[$i][$k]*$tmp;
$a[$j][$k]-=$a[$i][$k]*$tmp;
}
}
}
}

for($i=0;$i<$count;$i++)
for($j=0;$j<$count;$j++)
$a[$i][$j]=$e[$i][$j];


return $a;
}
?>

Но, опять же, там есть деление на элементы матрицы, а у нас есть равные нулю(((

Немного функцию облагорожу (в PHP с памятью проще - можно не копировать результат из единичной матрицы в исходную), чтобы потом на тему можно было ссылаться (мой вариант неправильный результат с первым столбцом выдает - почему-то в обратном порядке его выводит)
<?php
function q($matrix)
{
$a = $matrix;
$e = array();
$count = count($a);
for($i = 0; $i < $count; $i++)
for($j = 0; $j< $count; $j++)
$e[$i][$j] = ($i==$j) ? 1 : 0;

for($i = 0; $i < $count; $i++)
{
$tmp = $a[$i][$i];
for($j = $count - 1; $j >= 0; $j--)
{
$e[$i][$j] /= $tmp;
$a[$i][$j] /= $tmp;
}

for($j = 0; $j < $count; $j++)
{
if($j != $i)
{
$tmp = $a[$j][$i];
for($k = $count - 1; $k >= 0; $k--)
{
$e[$j][$k] -= $e[$i][$k]*$tmp;
$a[$j][$k] -= $a[$i][$k]*$tmp;
}
}
}
}

return $e;
}
?>


За одно и перемножение матриц сюда заброшу, чтобы уж все в одном месте было (это для квадратных матриц, для прямоугольных нужно проверять, что там с границами циклов).
<?php
function multi($x, $y)
{
for($i = 0; $i < count($x[0]); $i++)
{
for($j = 0; $j < count($y[0]); $j++)
{
for($k = 0; $k < count($x[0]); $k++)
{
if(!isset($z[$i][$j])) $z[$i][$j] = 0;
$z[$i][$j] += $x[$i][$k] * $y[$k][$j];
}
}
}
return $z;
}
?>
1 12 0
Без комментариев...