Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Как найти обратную матрицу
 
 автор: DEM   (03.01.2012 в 19:23)   письмо автору
 
 

Долго искал в интернете, нашёл несколько решений, но там как-то неправильно (пример одного из них напишу внизу). Завтра сдавать лабораторную в которой одно из условий - реализация этой фигни, а я никак не могу это сам сделать (((


Пример из интернета:

<?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)
)'

  Ответить  
 
 автор: cheops   (03.01.2012 в 19:47)   письмо автору
 
   для: DEM   (03.01.2012 в 19:23)
 

Вам именно обратная матрица нужна? Или просто нужно решить систему уравнений http://softtime.ru/scripts/matrix.php?

  Ответить  
 
 автор: DEM   (03.01.2012 в 19:53)   письмо автору
 
   для: cheops   (03.01.2012 в 19:47)
 

Именно обратную матрицу и она может быть размера не 3*3, а, к примеру, 10*10 или больше...

  Ответить  
 
 автор: DEM   (03.01.2012 в 23:14)   письмо автору
 
   для: DEM   (03.01.2012 в 19:53)
 

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


<?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)? 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;
}
?>



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

  Ответить  
 
 автор: cheops   (04.01.2012 в 00:58)   письмо автору
 
   для: DEM   (03.01.2012 в 23:14)
 

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

  Ответить  
 
 автор: DEM   (04.01.2012 в 01:02)   письмо автору
 
   для: cheops   (04.01.2012 в 00:58)
 

Дело в том, что моя матрица имеет обратную, перепроверил уже много раз :) Даже воспользовался Mathematica для такого)))

Просто у меня уже голова не варит, вообще ничего не понимаю :(

Но всё равно спасибо большое! Буду думать дальше, целая ночь впереди :)

  Ответить  
 
 автор: cheops   (04.01.2012 в 01:04)   письмо автору
 
   для: DEM   (04.01.2012 в 01:02)
 

Заглядывайте сюда, может совершу подвиг и распотрошу какую-нибудь Fortran-библиотеку с интересным алгоритмом.

  Ответить  
 
 автор: DEM   (04.01.2012 в 01:06)   письмо автору
 
   для: cheops   (04.01.2012 в 01:04)
 

буду очень благодарен :)

  Ответить  
 
 автор: cheops   (04.01.2012 в 01:17)   письмо автору
 
   для: DEM   (04.01.2012 в 01:02)
 

Там кстати, в этом методе Гаусса-Жордана, тоже в конце получается обратная матрица $a (я её просто не вывожу) и она отличается от вашей первым столбцом, сейчас постараюсь проверить точно где ошибка.

  Ответить  
 
 автор: DEM   (04.01.2012 в 01:26)   письмо автору
 
   для: cheops   (04.01.2012 в 01:17)
 

а как мне узнать параметр $b? У меня же просто матрица, а не уравнения...

  Ответить  
 
 автор: cheops   (04.01.2012 в 01:35)   письмо автору
 
   для: DEM   (04.01.2012 в 01:26)
 

Эээ... там на хитрость идут, используют все переменные равные 1, поэтому в нормальном алгоритме их даже вычислять не надо.
Слушайте, вы наверное недавно алгебру слушали, правильно я помню, что умножение матрицы на обратную дает единичную матрицу (это собственно и к абзацу выше)? Помоему ни у вас ни у меня ни фига не обратная матрица, перемножаю и матрицы и обратную матрицу на коэффициенты - фигня получается... а должны получаться исходные данные. Ведь метод Гаусса он там не совсем обратную матрицу кажется делает, он делает матрицу треугольной, за счет чего можно быстро получить детерминант, а можно вообще без него...

Вам в любом случае сначала нужно вычислить детерминант - если он 0 дальше считать нет смысла, если он отличен от нуля - обратная матрица есть обязательно, я в принципе с этого и начал, да вот у несло меня в другую степь...

Надо наверное систему попроще брать - двумерную, вычислять вручную и смотреть где и что происходит, а потом уже обощать на трехмерную.

  Ответить  
 
 автор: cheops   (04.01.2012 в 01:51)   письмо автору
 
   для: DEM   (04.01.2012 в 01:26)
 

Суть в том, что вы можете подставить вместо $b единицы и в ходе решения должна появится обратная матрица и она вроде появляется, только их перемножение с исходной не дает единичную.

  Ответить  
 
 автор: DEM   (04.01.2012 в 01:28)   письмо автору
 
   для: cheops   (04.01.2012 в 01:17)
 

И у Вас там есть условие:
if($a[$icol][$icol] == 0) return "Матрица сингулярна";


А у моей матрицы все элементы диагонали будут всегда равны 0

  Ответить  
 
 автор: cheops   (04.01.2012 в 01:37)   письмо автору
 
   для: DEM   (04.01.2012 в 01:28)
 

>А у моей матрицы все элементы диагонали будут всегда равны 0
Это значения не имет, главное, чтобы детерминант не был равен 0, а метод Гаусса он же строки складывает и вычитает, там от этих нулей в первом же проходе ничего не останется.

Дайте вашу матрицу, если не сложно.

  Ответить  
 
 автор: DEM   (04.01.2012 в 01:45)   письмо автору
 
   для: cheops   (04.01.2012 в 01:37)
 

У меня такое условие задачи:
Есть файл вида:
2 4
1 5
2 7
2 8
3 1
1 7

Это координаты точек (только целые). Надо составить матрицу из расстояния от одной точки до других (первый ряд от первой точки, второй - от второй и т.д.), и ещё добавляется один ряд и столбец в которых элементы равны 1 (кроме диагонального, он равен единице)
Значения там могут быть какие угодно (только не повторяющиеся). В матрице которую я привёл были значения точек:
2 1
2 2


и с ней надо делать всякую фигню, но вот застопорился с ОБРАТНОЙ МАТРИЦЕЙ, всё остальное легко делается...

  Ответить  
 
 автор: DEM   (04.01.2012 в 01:57)   письмо автору
 
   для: DEM   (03.01.2012 в 23:14)
 

Взял, как Вы и сказали массив $b равный единице и постаивл, что бы возвращала матрицу $a. Всё посчиталось правильно.

СПАСИБО БОЛЬШОЕ!!!! :)

  Ответить  
 
 автор: cheops   (04.01.2012 в 02:07)   письмо автору
 
   для: DEM   (04.01.2012 в 01:57)
 

Ага, тоже вручную посчитал, и ваш, и мой алгоритмы дают одно и тоже на простейшей двухмерной матрице.

  Ответить  
 
 автор: cheops   (04.01.2012 в 02:54)   письмо автору
 
   для: DEM   (03.01.2012 в 23:14)
 

Немного вашу функцию облагорожу (в 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) ? 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
  }
?>

  Ответить  
 
 автор: cheops   (04.01.2012 в 03:03)   письмо автору
 
   для: DEM   (03.01.2012 в 19:23)
 

За одно и перемножение матриц сюда заброшу, чтобы уж все в одном месте было (это для квадратных матриц, для прямоугольных нужно проверять, что там с границами циклов).
<?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;
  }
?>

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования