28 января 2021 года    
Четверг | 03:28    
Главная
 Новости
Базы данных
Безопасность PC
Всё о компьютерах
Графика и дизайн
Интернет-технологии
Мобильные устройства
Операционные системы
Программирование
Программы
Связь
Сети
 Документация
Статьи
Самоучители
 Общение
Форум







 

Формирование матрицы

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

//====== Глобально заданная размерность системы

int n;

//====== Граничные условия

double UO, UN;

//====== Функция вычисления коэффициентов

//====== трехдиагональной матрицы

double f ()

{

//====== Разовые начальные установки

static int raw = -1, k = -1, col = 0;

//====== Сдвигаемся по столбцам

col++;

//====== k считает все элементы

//====== Если начинается новая строка

if (++k % n == 0)

{

col =0; // Обнуляем столбец

raw++; // Сдвигаемся по строкам

}

//====== Выделяем три диагонали

return col==raw ? -2.

: col == raw-1 И col==raw+l ? 1.

: 0.;

}

double fu()

{

//==== Вычисления вектора правых частей по формуле (5)

static double

dU = (UN-UO)/(n+1),

d = U0; return d += dU;

}

В функции main создается valarray с трехдиагональной матрицей и производится умножение матрицы на вектор решений. Алгоритм умножения использует сечение, которое вырезает из valarray текущую строку матрицы:

void main()

{

//======= Размерность задачи и граничные условия

n =4;

UO = 100.;

UN = 0 . ;

//======= Размерность valarray (вся матрица)

int nn = n*n;

//======= Матрица и два вектора

valarray<double> a(nn), u(n), v(n);

//======= Генерируем их значения

generate (&а[0], &a[nn], f); generate (&u[0], &u[n], fu);

out ("Initial matrix", a); out ("Initial vector", u);

//======= Умножение матрицы на вектор

for (int i=0; i<n; i++) {

//======= Выбираем i-ю строку матрицы

valarray<double> s = a[slice (i*n, n , 1)];

//======= Умножаем на вектор решений

//======= Ответ помещаем в вектор v <

transform(&s[0], &s[n], &u[0], &v[0], multiplies<double>());

//======= Суммируем вектор, получая

//======= i-ый компонент вектора правых частей

cout « "\nb[" « i « "] = " « v.sum(); }

cout«"\n\n";

}

Так как мы знаем структуру вектора правых частей, то, изменяя граничные условия и порядок системы, можем проверить достигнутую технику работы с сечениями.

Тестирование обнаруживает появление численных погрешностей (в пределах Ю"15), обусловленных ограниченностью разрядной сетки, в случаях когда диапазон изменения искомой величины не кратен размеру расчетной области. Стоит отметить, что сечения хоть и являются непривычным инструментом, для которого хочется найти наилучшее применение, но в рамках нашей задачи вполне можно обойтись и без него. Например, алгоритм умножения матрицы на вектор можно выполнить таким образом:

for (int i=0, id=0; i<n; i++, id+*n)

{

transform(&a[id], &a[id+n], &u[0], &v[0],

multiplies<dovible> () ) ;

cout « "\nb[" « i « "] = " « v.sum();

}

Эффективность этой реализации, несомненно, выше, так как здесь на один valarray меньше. Я думаю, что вы, дорогой читатель, сами найдете достойное применение сечениям.

 

Лента новостей


2006 (c) Copyright Hardline.ru