2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки


Правила форума


В этом разделе нельзя создавать новые темы.

Если Вы хотите задать новый вопрос, то не дописывайте его в существующую тему, а создайте новую в корневом разделе "Помогите решить/разобраться (М)".

Если Вы зададите новый вопрос в существующей теме, то в случае нарушения оформления или других правил форума Ваше сообщение и все ответы на него могут быть удалены без предупреждения.

Не ищите на этом форуме халяву, правила запрещают участникам публиковать готовые решения стандартных учебных задач. Автор вопроса обязан привести свои попытки решения и указать конкретные затруднения.

Обязательно просмотрите тему Правила данного раздела, иначе Ваша тема может быть удалена или перемещена в Карантин, а Вы так и не узнаете, почему.



Начать новую тему Ответить на тему
 
 Приведение к Хессенбергу с помощью Гивенса
Сообщение27.06.2012, 19:00 


20/11/11
46
Помогите разобраться! Мне нужно написать программу на $C++$ для приведения матрицы 6 на 6 к матрице Хессенберга с помощью преобразований Гивенса.
Не могу до конца понять, каким образом нужно в матрице $T$ расставлять значения $c$ и $s$. И что делать в последствии с матрицей $G$. Нужно ли ее куда-то записывать после очередного получения путем умножения $T_{kj}^T \cdot A \cdot T_{kj}$ и, если да, то куда именно? Сколько промежуточных матриц $G$ (т.е. сколько шагов) мы должны получить?Большое спасибо!

 Профиль  
                  
 
 Re: Приведение к Хессенбергу с помощью Гивенса
Сообщение29.06.2012, 17:51 


13/01/12
317
Петербург
Kirillko93 в сообщении #589845 писал(а):
Помогите разобраться! Мне нужно написать программу на $C++$ для приведения матрицы 6 на 6 к матрице Хессенберга с помощью преобразований Гивенса.
Не могу до конца понять, каким образом нужно в матрице $T$ расставлять значения $c$ и $s$. И что делать в последствии с матрицей $G$. Нужно ли ее куда-то записывать после очередного получения путем умножения $T_{kj}^T \cdot A \cdot T_{kj}$ и, если да, то куда именно? Сколько промежуточных матриц $G$ (т.е. сколько шагов) мы должны получить?Большое спасибо!

Вращение обнуляет один элемент матрицы, а в форме Хессенберга нужно обнулить $N_0=(n-1)(n-2)/2$ элементов. Отсюда понятно число вращений.

Для обнуления элемента (индексы нумеруются, как массивы в С) $a_{20}$ составим матрицу:
$$R_{12} =
\begin{pmatrix}
c_{11} & -s_{12} \\
s_{21} &  c_{22}
\end{pmatrix}
$$
которая в остальных местах единичная, а индексы обозначают расстановку коэффициентов $(c, s)$.

Коэффициенты $(c, s)$ вычисляются как $c=a_{10}/\sqrt{a_{10}^2+a_{20}^2}$ и $s=-a_{20}/\sqrt{a_{10}^2+a_{20}^2}$.

Остальные вращения вычисляются аналогично. Для каждого вращения берутся элементы активной подматрицы.

Хранить нужно $N_0$ пар коэффициентов $(c, s)$, т.е. $2N_0$ вещественных переменных.

А вообще, перед тем, как начинать что-то программировать, про это что-то хорошо бы и в учебнике почитать. Например, Х.Д.Икрамов, Численное решение матричных уравнений. Ортогональные методы. М., Наука, 1984, стр. 26-28. Обратите внимание на окончание - на стр. 28.

Код:
// ---------------------------------------------------------------------------
// Copyright (C) 2012 <andrew dot nesterov at techemail dot com>
// This code is not in public domain. Use it for educational purposes
// only.
// ---------------------------------------------------------------------------

// transform matrix to upper hessenberg form using givens rotations

#include <math.h>

#define N       5
#define sqr(x)  ((x)*(x))

// construct givens rotations R(k,i) to zero a[i][k-1]
// and possibly a[k-1][i], if matrix is symmetric
void crot (float akl, float ail, float *c, float *s)
{
    float b;

    b = 1.0e0f / sqrt (sqr (akl) + sqr (ail));
    *c =  akl * b;
    *s = -ail * b;

    return;
}

// apply left and right givens rotations R(k,i) to zero a[i][k-1]
// and possibly a[k-1][i], if matrix is symmetric
void grot (int n, int k, int i, float c, float s, float a[N][N])
{
    int j;
    float ai[N], ak[N];

    // left multiply (two dot products with two terms)
    for (j = 0; j < n; j++)                 // all cols
    {
        // k-th row
        ak[j] = c * a[k][j] - s * a[i][j];
        // i-th row
        ai[j] = s * a[k][j] + c * a[i][j];
    }

    // copy temp arrays
    for (j = 0; j < n; j++)                 // all cols
    {
        // k-th row
        a[k][j] = ak[j];
        // i-th row
        a[i][j] = ai[j];
    }

    // right multiply (two dot products with two terms)
    for (j = 0; j < n; j++)                 // all rows
    {
        // k-th col
        ak[j] = c * a[j][k] - s * a[j][i];
        // i-th col
        ai[j] = s * a[j][k] + c * a[j][i];
    }

    // copy temp arrays
    for (j = 0; j < n; j++)                 // all rows
    {
        // k-th col
        a[j][k] = ak[j];
        // i-th col
        a[j][i] = ai[j];
    }

    return;
}

#include <stdio.h>

// debug output
void printm (int n, float a[N][N])
{
    int i, k;

    for (i = 0; i < n; i++)                 // row cycle
    {
        for (k = 0; k < n; k++)             // col cycle
        {
            printf ("%14.7f ", a[i][k]);
        }

        printf ("\n");
    }

    printf ("\n");

    return;
}

// transform matrix to upper hessenberg form
void hessen (int n, float a[N][N], float *cs)
{
    int i, j, k, l;
    float c, s, b;

    j = 0;

    for (k = 1; k < n - 1; k++)             // col cycle
    {
        for (i = k + 1; i < n; i++)         // row cycle
        {
            // construct givens rotations R(k,i) to zero a[i][k-1]
            // and a[k-1][i] if matrix is symmetric
            l = k - 1;
            crot (a[k][l], a[i][l], &c, &s);

            // store givens rotation (i,k)
            cs[2*j+0] = c;
            cs[2*j+1] = s;
            j += 1;

            // apply givens rotations R(k,i) to zero a[i][k-1]
            // if A is symmetric, a[k-1][i] is zeroed as well
            grot (n, k, i, c, s, a);

            // printm (n, a);                  // debug phase
        }
    }

    return;
}

// test givens rotations

#include <stdlib.h>

// initialize generic matrix
void minit (int n, float a[N][N])
{
    int i, k;

    // init generic matrix
    for (i = 0; i < n; i++)                 // row cycle
    {
        for (k = 0; k < n; k++)             // col cycle
        {
            a[i][k] = (float) rand () / (float) RAND_MAX;
        }
    }

    return;
}

// initialize symmetric matrix
void sinit (int n, float a[N][N])
{
    int i, k;

    // init symmetric matrix
    for (i = 0; i < n; i++)                 // row cycle
    {
        for (k = i; k < n; k++)             // col cycle
        {
            a[i][k] = (float) rand () / (float) RAND_MAX;
            if (i < k) a[k][i] = a[i][k];
        }
    }

    return;
}

// global data
float A[N][N];
// storage for up to 10 x 10 matrix transform
float cs[9*8/2];

void main (void)
{
    int i, k, n;

    n = N;

    minit  (n, A);                          // init generic matrix
    // sinit  (n, A);                          // init symmetric matrix

    printm (n, A);

    hessen (n, A, cs);

    printm (n, A);

    exit (0);
}

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 2 ] 

Модераторы: Модераторы Математики, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group