Официальный сайт студ.городка НГТУ
Программирование и БД » Нахождение определителя матрицы через разложение по столбцам [C++] 

#1  10.11.10 22:23

Нахождение определителя матрицы через разложение по столбцам [C++]

Привет всем, вот такой у меня код, решающий эту задачу-



double Matrix_A(double **table1,int razm)
{
extern int nom;
int n_fakt=1;
for (int v=1;v<razm;v++)
n_fakt=n_fakt*v;

double ***table = new double** [n_fakt];
for(int c=0;c<razm;c++){table[c]=new double*[razm];for(int x=0;x<razm;x++){table[c][x]=new double[razm];};};
for(int c1=0;c1<razm;c1++){for(int c2=0;c2<razm;c2++){table[0][c1][c2]=table1[c1][c2];};};
double A=Minor(table, razm, 0, 0);
return(A);};
//=============
double Minor(double ***table, int razm, int i_minor,int j_minor)
{
int znak=1;
int vnut_nom;
vnut_nom=nom;
double A=0;
if(razm==0)return(0);
if(razm==1)return(table[nom][0][0]);
for(int q=0;q<(j_minor+i_minor);q++){znak=znak*(-1);};
for(int M=0;M<razm;M++)
{
vnut_nom++;
    for(int b=1;b<razm;b++)
    {
        for(int c=0;c<razm;c++)
        {
            if(c==M)c++;
            int n=0;
            table[vnut_nom][b][n]=table[nom][b][c];
            n++;
            }
    }
}
for(int z=0;z<razm;z++)
A=A+znak*table[0][i_minor+1][j_minor+1+z]*Minor(table[nom-razm+1+z][0][0],razm-1,i_minor+1,j_minor+1+z);
return(A);
};



Немного опишу её, а то вникнуть сложно сразу - здесь функция Matrix_A получает двойной массив и его размерность (предполагается что матрица квадратная)и создаёт тройной массив, где по адресу table[0][][] хранится исходная матрица, а в остальных все возможные её миноры (матрица разбивается на n! миноров 1х1) потом эта функция вызывает подфункцию - Minor которая разбивает получиную матрицу поочерёдно исключая столбцы и строки на все возможные миноры и опять сама себя вызывает передавая эти миноры как параметры и так пока не получится матрица 1х1, когда получилось считается формула. Так вот у меня возникла проблема с передачей этих массивов...даже боюсь как бы не была эта проблема только верхушкой айсберга - ХЕЛП ПЛИЗ! Помогите довести подпрограмму до ума, ну или,накрай, предложите другой способ нахождения определителя матрицы (а лучше минора, чтобы можно было и обратную потом написать).

Исправлено NoobsEnslaver (10.11.10 22:24)

Offline

#2  11.11.10 03:09

Re: Нахождение определителя матрицы через разложение по столбцам [C++]

NoobsEnslaver, есть два алгоритма для нахождения обратной матрицы, сам ими полбзуюсь:

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Функции для работы с матрицами и векторами из библиотеки uBLAS
* Поиск обратной матрицы первый способ
* Поиск обратной матрицы второй способ*/

#ifndef INVERT_MATRIX_H
#define INVERT_MATRIX_H

#include "boost/numeric/ublas/vector.hpp"
#include "boost/numeric/ublas/vector_proxy.hpp"
#include "boost/numeric/ublas/matrix.hpp"
#include "boost/numeric/ublas/triangular.hpp"
#include "boost/numeric/ublas/lu.hpp"
#include "boost/numeric/ublas/io.hpp"

namespace ublas = boost::numeric::ublas;

/* Matrix inversion routine.
Uses lu_factorize and lu_substitute in uBLAS to invert a matrix */
template<typename T1, typename T2>
bool InvertMatrix (const ublas::matrix<T1>& input, ublas::matrix<T2>& inverse)
{
    using namespace boost::numeric::ublas;
    typedef permutation_matrix<std::size_t> pmatrix;

    // create a working copy of the input
    matrix<T2> A(input);

    // create a permutation matrix for the LU-factorization
    pmatrix pm(A.size1());

    // perform LU-factorization
    int res = lu_factorize(A,pm);
    if( res != 0 ) return false;

    // create identity matrix of "inverse"
    inverse.assign(ublas::identity_matrix<T2>(A.size1()));

    // backsubstitute to get the inverse
    lu_substitute(A, pm, inverse);

    return true;
};


/* Matrix inversion routine.
Uses lu_factorize and lu_substitute in uBLAS to invert a matrix */
template<typename T>
bool InvertMatrix (ublas::matrix<T>& inverse)
{
    using namespace boost::numeric::ublas;
    typedef permutation_matrix<std::size_t> pmatrix;

    // create a working copy of the input
    matrix<T> A(inverse);

    // create a permutation matrix for the LU-factorization
    pmatrix pm(A.size1());

    // perform LU-factorization
    int res = lu_factorize(A,pm);
    if( res != 0 ) return false;

    // create identity matrix of "inverse"
    inverse.assign(ublas::identity_matrix<T>(A.size1()));

    // backsubstitute to get the inverse
    lu_substitute(A, pm, inverse);

    return true;
};


/* Поиск обратной матрицы
используется метод Фаддеева для массивов значений */
template<typename T>
bool faddeev_method(T** R, T** A, int n)
{
    int i, j, k, m;
    T p, s;

    T** B = new T* [n];   
    T** U = new T* [n];   

    for(i = 0; i < n; ++i)
    {
        B[i] = new T[n];
        U[i] = new T[n];
    }

    for(i = 0; i < n; ++i)
    {   
        for(j = 0; j < n; ++j)
        {
            B[i][j] = 0.0;
        }
        B[i][i] = 1.0;
    }

    for(k = 1; k <= n; ++k)              // общий цикл вычислений
    {   
        for(i = 0; i < n; ++i)                       // U = A * B
        {
            for(j = 0; j < n; ++j)
            {   
                s = 0.0;
                for(m = 0; m < n; m++) s += A[i][m] * B[m][j];
                U[i][j] = s;
            }
        }

        s = 0;
        for(i = 0; i < n; ++i)
        {
            s += U[i][i];                       // след матрицы U
        }

        p = s / k;              // характеристический коэффициент
        if(k == n) break;   // на последней итерации не вычислять

        for(i = 0; i < n; ++i)                      // B = U - pE
        {   
            for(j = 0; j < n; ++j)
            {
                i != j ? B[i][j] = U[i][j] : B[i][j] = U[i][j]-p;
            }
        }
    }

    bool z = true;// предположим, что обратная матрица существует

    if(p == 0.0) z = false;     // обратная матрица не существует
    for(i = 0; i < n; ++i)                    // обратная матрица
    {
        for(j = 0; j < n; ++j)
        {
            R[i][j] = B[i][j] / p;
        }
    }

    for(i = 0; i < n; ++i)
    {
        delete [] U[i];                       // удалить строки U
    }
    delete [] U;             // удалить указатели строк матрицы U

    for(i = 0; i < n; ++i)
    {
        delete [] B[i];                          // удалить строки B
    }
    delete [] B;             // удалить указатели строк матрицы B

    return z;
};


/* Поиск обратной матрицы
используется метод Фаддеева для класса типа матрица из uBLAS */
template<typename T>
bool faddeev_method (ublas::matrix<T>& result, const ublas::matrix<T>& matr/*, int n*/)
{
    using namespace boost::numeric::ublas;
    typedef permutation_matrix<std::size_t> pmatrix;

    const int n = matr.size1();

    matrix<T> B(n,n);
    matrix<T> U(n,n);

    int i, j, k;
    T p, s;

    for(i = n; --i >= 0;)
    {   
        for(j = n; --j >= 0;)
        {
            B(i, j) = 0.0;
        };
        B(i, i) = 1.0;
    };

    for(k = 1; k <= n; ++k)              // общий цикл вычислений
    {
        axpy_prod(matr, B, U, true);              // U = matr * B

        s = 0;
        for(i = 0; i < n; ++i)
        {
            s += U(i, i);
        };

        p = s / k;              // характеристический коэффициент
        if(k == n) break;   // на последней итерации не вычислять

        B = U;                                        // B = U - pE
        for(i = 0; i < n; ++i)
        {
            B(i, i) = U(i, i) - p;
        };
    };

    bool z = true;// предположим, что обратная матрица существует

    if(p == 0.0) z = false;     // обратная матрица не существует
    result = B / p;

    return z;
};


/* Поиск обратной матрицы
используется метод Фаддеева для класса типа матрица из uBLAS */
template<typename T>
bool faddeev_method (ublas::matrix<T>& matr)
{
    using namespace boost::numeric::ublas;
    typedef permutation_matrix<std::size_t> pmatrix;

    const int n = matr.size1();

    matrix<T> B(n,n);
    matrix<T> U(n,n);

    int i, j, k;
    T p, s;

    for(i = n; --i >= 0;)
    {   
        for(j = n; --j >= 0;)
        {
            B(i, j) = 0.0;
        };
        B(i, i) = 1.0;
    };

    for(k = 1; k <= n; ++k)              // общий цикл вычислений
    {
        axpy_prod(matr, B, U, true);              // U = matr * B

        s = 0;
        for(i = 0; i < n; ++i)
        {
            s += U(i, i);
        };

        p = s / k;              // характеристический коэффициент
        if(k == n) break;   // на последней итерации не вычислять

        B = U;                                        // B = U - pE
        for(i = 0; i < n; ++i)
        {
            B(i, i) = U(i, i) - p;
        };
    };

    bool z = true;// предположим, что обратная матрица существует

    if(p == 0.0) z = false;     // обратная матрица не существует
    matr = B / p;

    return z;
};

#endif //INVERT_MATRIX_H

первая вторая четвертая и пятая шаблоны для матриц из uBLAS.
третий шаблон для обычных массивов например double**. первый параметр - результат второй - исходная матрица третий - размерность. можешь изменить функцию так чтобы результат хранился на  месте исходной матрицы.

все функции работают отлично, предпочитаю метод фаддеева - и работает вроде пошустрее и матрица обратная считается поточнее.

Исправлено Flinn (11.11.10 03:11)

Offline

#3  11.11.10 14:17

Re: Нахождение определителя матрицы через разложение по столбцам [C++]

NoobsEnslaver, а зачем именно искать обратную матрицу? Может в твоей задаче всё-же можно решать СЛАУ?

Offline

Программирование и БД » Нахождение определителя матрицы через разложение по столбцам [C++] 

ФутЕр:)

© Hostel Web Group, 2002-2025.   Сообщить об ошибке

Сгенерировано за 0.190 сек.
Выполнено 11 запросов.