национальный исследовательский ядерный университет «мифи

advertisement
НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙ ЯДЕРНЫЙ УНИВЕРСИТЕТ «МИФИ»
Кафедра информатики и процессов управления (№17)
Дисциплина «Прикладное ПО»
для студентов факультета КиБ,
3-й курс, 5-й семестр.
Методические указания
Занятие 3
Решение СЛАУ в среде Octave.
Основы программирования.
Содержание
Решение СЛАУ в среде Octave. Основы программирования. . 1
Решение СЛАУ с помощью обращения матрицы ...................................... 2
Решение СЛАУ методом Гаусса ................................................................... 3
Хранимые программы (процедуры) ............................................................ 4
*.m – файлы ............................................................................................................. 4
Проверка входных данных ................................................................................... 5
Циклы в программах.............................................................................................. 6
Итоговое задание (8 баллов) ........................................................................ 6
Приложение. Экстремальное тестирование задания ............................... 7
1
Решение СЛАУ с помощью обращения матрицы
Будем решать систему линейных алгебраических уравнений (СЛАУ),
которая в векторно-матричном виде записывается как A*x=b , где A – матрица
n x n , b – вектор-столбец свободных членов длиной n, а x – вектор-столбец
неизвестных.
Введем матрицу А, размером 3 х 3 :
> A=[2 -1 5 ; 3 2 -5;1 1 -2]
Введем вектор-столбец свободных членов:
> b=[ 0 ; 1 ; 4 ]
Есть несколько способов записи решения с помощью обратной матрицы.
Наиболее компактная форма записи использует операцию обратного
деления (x=A\b). Эта же форма является наиболее правильной, поскольку не
использует в явном виде промежуточное вычисление обратной матрицы.
Поэтому такая форма записи будет работать даже для вырожденных матриц и
для неквадратных матриц (для недоопределенных и переопределенных СЛАУ).
> x=A\b
Альтернативный вариант – наиболее интуитивно понятная форма записи.
Здесь используется обратная матрица, такую форму можно использовать только
для квадратных невырожденных матриц:
> x=A^(-1)*b
Octave выдаст тот же ответ
x =
-2.8333
15.1667
4.1667
Тот же алгоритм и тот же ответ получится еще при двух альтернативных
формах записи:
> x=A^-1*b
> x=inv(A)*b
2
Выполним проверку, перемножим A*x, сравним с введенным значением b:
> A*x
Полученный ответ визуально совпадает с введенным значением b:
ans =
-0.0000
1.0000
4.0000
Хотелось бы определить погрешность расчетов, для этого рассчитаем невязку
( A*x – b ):
> A*x-b
Мы видим, что существует незначительная погрешность, сравнимая с точностью
представления чисел:
ans =
1.0e-014 *
Ответ начинается с общего масштабного множителя, показывающего, что речь
идет о невязках в четырнадцатом знаке после запятой.
Решение СЛАУ методом Гаусса
Обращение
матриц
большого
размера
требует
значительных
вычислительных ресурсов. Для СЛАУ с большим количеством уравнений
предпочтительнее использовать метод Гаусса, причем это справедливо не
только для Octave, но для любых других средств.
В методе Гаусса вводится понятие «Расширенная матрица» n x n+1,
которая образуется, если к матрице A справа присоединить вектор свободных
членов b. В Octave это записывается как [ A b ].
Метод Гаусса состоит из двух этапов. Первый этап – это прямой ход, в
результате которого расширенная матрица системы путём элементарных
преобразований (перестановка уравнений системы, умножение уравнений на
число отличное от нуля и сложение уравнений) приводится к виду, когда в
первых n столбцах - верхнетреугольная матрица.
На втором этапе (обратный ход) получившуюся матрицу преобразовывают
так, чтобы в первых n столбцах получилась единичная матрица. Последний, n+1
столбец этой матрицы содержит решение первоначальной СЛАУ.
Octave
содержит
встроенный
механизм,
который
полностью
автоматизируют вышеописанный алгоритм. Оба этапа реализуются одной
функцией rref( ) :
> C=rref([A b])
> x= C( : , end )
3
В описанном выше примере мы выбираем последний столбец (на это
указывает служебное слово end в качестве второго индекса) и берем в нем все
элементы (символ двоеточие в качестве первого индекса).
Рассчитаем невязку ( A*x – b ) для получившегося решения:
> A*x-b
Ошибка по-прежнему в 14-ом разряде:
ans =
1.0e-014 *
Теоретически, для СЛАУ с большим количеством уравнений (более чем 200),
метода Гаусса должен работать быстрее. Однако в некоторых версиях Octave
это не так, вследствие того, что обратное деление в этих версиях реализовано
на языке низкого уровня, а rref( ) - на языке высокого уровня.
Хранимые программы (процедуры)
Если одну и ту же последовательность команд предполагается
использовать многократно, то ее можно запомнить в файле и вызывать при
появлении необходимости.
*.m – файлы
Можно создавать текстовые файлы, содержащие код Octave. Если такой
файл сохранить в рабочей директории с расширением .m , то его можно будет
вызвать, набрав в командной строке имя файла без расширения.
В качестве Примера создайте в рабочей директории при помощи
редактора файл hello.m следующего содержания:
% эта строка -просто комментарий
disp('Моя первая программа')
date_time = fix(clock)
year = input('Введите (полностью) Ваш год рождения: ') ;
age = date_time(1) - year ;
fprintf('Ваш возраст примерно %u лет.\n', age) ;
Сохраните этот файл и запустите на выполнение, набрав в командном
окне:
> hello
4
Проверка входных данных
В программах можно осуществлять проверки условий при помощи
операторов if, elseif, else, switch, case, otherwise, end. Также
полезно использовать операторы return и error для прерывания программы.
Заметим, что не существует оператора goto.
Исследуйте особенности работы этих операторов, вставив фрагмент (6
дополнительных строк) между вводом года и вычислением возраста (age):
% эта строка -просто комментарий
disp('Моя первая программа')
date_time = fix(clock)
year = input('Введите (полностью) Ваш год рождения: ');
if (year < 0) | (year > date_time(1) ) error('неверный год')
elseif year < 14 year = year +2000
elseif year < 100 year = year +1900
elseif year < 1900 disp('неверный год'), return
else disp('Спасибо, что ввели без ошибок ')
end
age = date_time(1) - year;
fprintf('Ваш возраст примерно %u лет.\n', age);
Немного пояснений по поводу добавленных строк. Здесь представлен
наиболее полный вариант if, в других случаях отдельные куски конструкции
могут быть пропущены, например можно убрать блок else, или блок elseif,
или оба.
Вертикальная черточка, которая соединяет два условия в первой проверке,
означает логическую связку ИЛИ.
Вторая и третья проверка позволяет исправить ошибку ввода, если
пользователь ввел только последние две цифры года рождения.
Сохраните этот файл и запустите несколько раз на выполнение.
Исследуйте все ветки if, то есть попробуйте разные варианты ввода, например:
-5
11
96
1896
1996
2116
Сделайте заключение о действии использованных конструкций elseif,
else, end, disp, return, error.
5
Циклы в программах
Octave имеет встроенные средства для обработки матриц и векторов, не
прибегая к циклам для перебора индексов. Тем не менее, возможность
организовывать циклы также имеется.
Циклы, повтор группы команд, обеспечиваются при помощи операторов
for, while, break, end . Циклы могут быть вложенными.
В качестве Примера будем искать и обнулять в магическом квадрате
простые числа.
Создайте в рабочей директории при помощи редактора файл prime.m
следующего содержания, структурировав циклы и условия отступами, чтобы
было видно, что закрывает каждый end :
A=magic(4)
for m=1:4
for n=1:4
if isprime(A(m,n))
A(m,n) = 0 ;
end
end
end
A
Немного пояснений. Встроенная функция isprime() проверяет, является
ли число простым. Точка с запятой в конце оператора обнуления предотвращает
вывод результатов внутри цикла. Итоговый результат выводится вне цикла, для
этого в конце программы набрано имя получившейся матрицы A.
Запустите созданный файл на выполнение, набрав: prime
Как уже говорилось, в Octave можно много сделать, не прибегая к циклам.
Например, тот же результат можно получить, используя механизм логической
индексации:
> A=magic(4) ;
> A(isprime(A))=0
Итоговое задание (8 баллов)
Используя полученные навыки и знания, напишите программу для решения
произвольной СЛАУ. Программа должна запросить и ввести исходные данные,
проверить их корректность, например, квадратность и соответствие
размерностей.
Перед решением СЛАУ необходимо ее проверить. В частности, если
матрица вырожденная, то надо выдать соответствующее сообщение и
завершить программу. Детерминант вычисляется встроенной функцией det() .
Также предварительно надо проверить существование решения. Согласно
теории, для этого надо, чтобы ранг матрицы равнялся рангу расширенной
матрицы и равнялся размерности матрицы. Ранг вычисляется встроенной
функцией rank() .
6
Приложение. Экстремальное тестирование задания
Здесь приведены некоторые тестовые СЛАУ для проверки экстремальных
случаев. Самый высокий балл получает программа, которая правильно
реагирует на все проверки.
Баллы A
+1 б
1 1
2 1
+1 б
2 1
2 1
+1 б
2 1
2 1
+1 б
+1 б
+1 б
+1 б
+1 б
+1б
2
2
1
0
1
1
0 1
1 1
1
0
1
1
0
1
1
0
1
2
2
0
1
1
0
1
1
0
1
1
1
1
b
1
2
2
2
2
2
2
2
Должно получиться: текст (если нужен), и ответ:
х
1
0
Бесчисленное множество решений. Например, 1
одно из них:
0
Задача некорректна. Вектор b слишком длинный
Задача некорректна. Вектор b слишком короткий
2 Бесчисленное множество решений. Например, 0
2 одно из них:
0
2
2
2
2
2
4
2 Решений нет. Минимальной невязка равна
2.333
2 (0.333, 0.333, -0.333) при следующем х:
2.333
5
2 Задача некорректна. Вектор b слишком короткий
2
2 Решений нет. Минимальной невязка равна
3 (0.5, -0.5) при следующем х:
7
1
0.5
Download