МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ ФЕДЕРАЛЬНОЕ АГЕНСТВО ПО ОБРАЗОВАНИЮ МОСКОВСКИЙ ЭНЕРГЕТИЧЕСКИЙ ИНСТ...
12 downloads
247 Views
371KB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ ФЕДЕРАЛЬНОЕ АГЕНСТВО ПО ОБРАЗОВАНИЮ МОСКОВСКИЙ ЭНЕРГЕТИЧЕСКИЙ ИНСТИТУТ (ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ) АМОСОВА О.А., ВЕСТФАЛЬСКИЙ А.Е.
ПРИМЕНЕНИЕ ПАКЕТА MATHCAD К РЕШЕНИЮ ВЫЧИСЛИТЕЛЬНЫХ ЗАДАЧ Методическое пособие по курсу «Численные методы»
Москва
Издательский дом МЭИ
2007
УДК 519 А 623 Утверждено учебным управлением МЭИ Подготовлено на кафедре математического моделирования Рецензенты: д.т.н., проф. Фролов А.Б., к. ф.-м. н., ст. преп. Казенкин К.О.
Амосова О.А., Вестфальский А.Е. Применение пакета Mathcad к решению вычислительных задач : методическое пособие / М.: Издательский дом МЭИ, 2007. – 30 с. Пособие содержит краткие сведения о некоторых встроенных функциях, а также краткую характеристику встроенного языка программирования пакета Mathcad. Все описания сопровождаются примерами их использования. Тексты всех программ для большей наглядности продублированы на языке программирования Pascal. Предназначено для студентов всех направлений подготовки МЭИ и слушателей ФПКП, изучающих вычислительные методы.
© Московский энергетический институт (технический университет), 2007 2
Содержание Предисловие ..................................................................................................................4 Часть I. Встроенные средства ......................................................................................5 1.1 Символьные вычисления .............................................................................5 1.2 Работа с матрицами ......................................................................................6 1.3 Поиск корней нелинейных уравнений .......................................................8 1.4 Нормы и числа обусловленности матриц ................................................10 1.5 Решение СЛАУ ...........................................................................................11 1.6 Интерполяция функций .............................................................................11 1.7 Решение задачи Коши ................................................................................13 1.8 Блок Given – Find ........................................................................................16 Часть II. Встроенный язык программирования .......................................................18 Библиографический список .......................................................................................31
3
Предисловие Настоящее пособие является дополнением к циклу лабораторных работ по численным методам. Примерный вариант заданий лабораторных работ был ранее опубликован в изданиях [3, 4]. Данное пособие содержит минимально необходимые для выполнения лабораторных работ сведения о математическом пакете Mathcad и предназначено для тех студентов, которые не знакомы с этим математическим пакетом. Все содержащиеся в пособии описания справедливы для любой версии пакета Mathcad, начиная с версии Mathcad 6.0 Plus. Описания применяемых численных методов, а также необходимые теоретические сведения можно найти в [1], см. также [2]. Для более детального знакомства с пакетом Mathcad можно использовать любую литературу, например, [5]. В первой части пособия приводятся краткие сведения о некоторых встроенных функциях пакета Mathcad, используемых при решении линейных систем, поиске корней нелинейных уравнений, интерполяции функций, а также решении задачи Коши для обыкновенных дифференциальных уравнений. Описания всех встроенных функций сопровождаются примерами их использования, которые являются вставками рабочих файлов пакета Mathcad. Поскольку вычислительные процедуры, реализованные в пакете Mathcad, выходят за рамки стандартных курсов численных методов, для большинства встроенных функций не приводится информация об алгоритмах их работы. Вторая часть пособия содержит краткую характеристику встроенного языка программирования пакета Mathcad. На примерах задач из указанного лабораторного практикума разобраны основные конструкции встроенного языка и особенности их использования. Для большей наглядности тексты всех программ продублированы на языке программирования Pascal (предполагается, что студенты с ним уже знакомы). Также приводятся примеры вызова (и, соответственно, работы) всех написанных программ. Приведенное в пособии описание встроенного языка не является полным. Те возможности, которые не требуются для решения задач практикума, не описаны.
4
Часть I Встроенные средства 1.1. Символьные вычисления Математический пакет Mathcad может производить вычисления двух типов: численно и символьно. Численное вычисление – это получение результата (числа) при помощи вычислительного алгоритма, имеющего конечное число действий. Например, это – вычисление значения функции в точке, нахождение корня уравнения с помощью той или иной процедуры и т.п. Результатом символьного вычисления (символьного преобразования) является формула или число, которое нельзя получить за конечное число вычислительных операций. Таковы поиск предела последовательности, формулы для производной заданной функции или взятие неопределенного интеграла. Для Mathcad’а указанием к численному вычислению является знак равенства, а указанием к символьному преобразованию – стрелка вправо. Пример. Применение символьных преобразований 1. Вычислим производные функции. 3
Задаем функцию:
f ( x) := 3x + x⋅ln( x) − cos ( x)
Вычисляем первую производную:
d 2 f ( x) → 9 ⋅x + ln( x) + 1 + sin( x) dx 2
d
Вычисляем вторую производную:
2
f ( x) → 18 ⋅x +
dx
1 + cos ( x) x
2. Вычислим неопределенный интеграл. Задаем функцию:
Вычисляем интеграл:
2
g( x) := 9 ⋅x + ln( x) + 1 + sin( x) ⌠ 3 ⎮ g( x) dx → 3 ⋅x + x⋅ln( x) − cos ( x) ⌡
5
3. Вычислим предел последовательности (функции). Зададим формулу общего члена последовательности (как функцию 2
номера):
( n + 1) − ( n − 1) x( n) := 2n
lim
Вычислим предел:
2
x( n) → 2
n→ ∞
1.2. Работа с матрицами Все встроенные средства пакета Mathcad, предназначенные для работы с матрицами собраны на панели векторов и матриц (vector and matrix toolbar). Задавать матрицу можно либо вставив с панели матриц шаблон нужного размера и заполнив его числами, либо присваивая каждому элементу матрицы его значение (обычно это производится в цикле). Если элемент массива (матрицы) имеет несколько индексов, то они указываются через запятую. Для элементов матрицы первым идет номер строки, вторым – номер столбца. Индексация массивов по умолчанию начинается с нуля, однако есть возможность управлять этим процессом. Номер первого элемента хранится в предопределенной переменной ORIGIN, значение которой можно менять. Встретив присвоение ORIGIN := k, Mathcad будет все встречающиеся ниже массивы нумеровать, начиная с номера k. Любое обращение к элементу с меньшим номером будет вызывать сообщение об ошибке. Пример. Работа с матрицами Задаем диапазон изменения индексов:
i := 0 .. 2
Ai , j := i − j
Задаем элементы матрицы:
⎛0 1 2⎞ ⎜ ⎟ A= 1 0 1 ⎜ ⎟ ⎝2 1 0⎠
Выводим получившуюся матрицу:
6
j := 0 .. 2
A =4
Найдем определитель данной матрицы:
(Важно отметить, что знак модуля для вычисления определителя необходимо вводить с помощью панели матриц.) rank ( A) = 3
Найдем ранг данной матрицы:
⎛ −0.25 0.5 0.25 ⎞ −1 ⎜ ⎟ A = 0.5 −1 0.5 ⎜ ⎟ ⎝ 0.25 0.5 −0.25 ⎠
Найдем матрицу, обратную к данной:
Найдем собственные числа данной матрицы: ⎛ 2.732 ⎞ ⎜ −2 ⎟ z := eigenvals( A) z=
⎜ ⎟ ⎝ −0.732 ⎠
Найдем максимальное и минимальное из них: max( z) = 2.732
min( z) = −2 〈1〉 y := A
Вырежем из матрицы А средний столбец: Превратим его в строку:
⎛1⎞ ⎜ ⎟ y= 0 ⎜ ⎟ ⎝1⎠
T
y = ( 1 0 1)
Вырежем из матрицы А подматрицу, состоящую из первых двух строк: B := submatrix( A , 0 , 1 , 0 , 2)
⎛0 1 2⎞ ⎟ ⎝1 0 1⎠
B=⎜
Определим единичную матрицу: E := identity( 3)
7
⎛1 0 0⎞ ⎜ ⎟ E= 0 1 0 ⎜ ⎟ 0 0 1 ⎝ ⎠
1.3. Поиск корней нелинейных уравнений Корень нелинейного уравнения (функции) в пакете Mathcad можно отыскать с помощью встроенной функции root(f(x0), x0). Ее аргументами являются функция f(x), корень которой отыскивается, и начальное приближение x0 к этому корню. Результатом работы является значение корня, к которому сойдется метод. Следует также учитывать, что подобно другим встроенным функциям, функция root() работает с той точностью, которая содержится в предопределенной переменной TOL. По умолчанию она равна 0.001 (TOL = 0.001), однако может быть задана равной любому другому интересующему нас значению, но не меньшему, чем 10 -15. Пример. Найдем действительные корни функции-многочлена f ( x) := x4 − x − 2 4
f ( x) := x − x − 2
Зададим функцию:
Для начала построим график функции на отрезке [-5, 5] 1000 500 f( x) 5
0
5
500 x
Поскольку на этом графике ничего не видно, сузим отрезок построения до [-2, 2]
20 10 f( x) 2
1
0
1
2
10 x
Теперь ясно, что функция имеет два вещественных корня. Один из них расположен около -1, а другой около 1.3. Эти значения и зададим ниже в качестве начальных приближений. 8
Установим высокую точность работы встроенных методов:
−8
TOL := 10
Найдем сначала отрицательный корень x0 := −1
root ( f ( x0) , x0) = −1
А теперь положительный x0 := 1.3
root ( f ( x0) , x0) = 1.35320996
Следует отметить, что начальное приближение следует выбирать по возможности ближе к корню. В том случае, когда начальное приближение достаточно грубое, метод может сходиться не к ближайшему корню, а к другому. Если рассматриваемая функция является многочленом, т.е. n f ( x) = a0 + a1 x + K + an x , то для поиска корней можно также воспользоваться другой встроенной функцией polyroots(a). Ее единственным аргументом
является массив коэффициентов многочлена a = (a 0 , a1 , K , a n ) (начиная со свободного члена). Функция возвращает массив, содержащий все корни заданного многочлена, в том числе комплексные. T
Пример. Найдем корни того же многочлена f ( x) := x4 − x − 2
Задаем массив коэффициентов:
Находим корни:
⎛ −2 ⎞ ⎜ −1 ⎟ ⎜ ⎟ a := ⎜ 0 ⎟ ⎜ 0 ⎟ ⎜ ⎟ ⎝ 1 ⎠
−1 ⎛ ⎞ ⎜ ⎟ − 0.17660499 − 1.20282082i ⎟ polyroots( a) = ⎜ ⎜ −0.17660498 + 1.20282082i ⎟ ⎜ ⎟ 1.35320997 ⎝ ⎠
9
1.4. Нормы и числа обусловленности матриц В пакете Mathcad имеются встроенные функции norm1(A), norm2(A), A 2, A E и A ∞ norme(A) и normi(A), которые вычисляют величины A 1 , соответственно. Единственным аргументом этих функций является квадратная матрица A. Для матриц произвольного размера (прямоугольных) данные функции применить нельзя. В частности, в пакете Mathcad нет встроенных средств для вычисления норм векторов. Функции cond1(A), cond2(A), conde(A) и condi(A) вычисляют относительное число обусловленности квадратной матрицы A, используя −1 соответствующие нормы. (Напомним, что cond ( A) = A ⋅ A .)
Пример. Найдем норму ⋅ 1 и соответствующее число ⎛ 5
обусловленности матрицы A = ⎜⎜ ⎝− 7 Зададим матрицу: Вычислим норму:
− 3⎞ ⎟ 4 ⎟⎠
⎛ 5 −3 ⎞ ⎟ ⎝ −7 4 ⎠
A := ⎜
norm1(A) = 12
Вычислим число обусловленности: cond1(A) = 132 Теперь вычислим число обусловленности по определению. Для этого найдем норму обратной матрицы: norm1(A-1) = 11 Перемножая, получаем число обусловленности: 12·11 = 132 Как и следовало ожидать, оно совпало с результатом работы встроенной функции.
10
1.5. Решение СЛАУ Стандартным средством решения линейных систем является встроенная функция lsolve(A,b), которая решает систему на основе LU-разложения матрицы (с частичным выбором главного элемента). Ее аргументами являются квадратная невырожденная матрица A и вектор правых частей b.
Пример.
⎧2 x1 + x 2 − 3x3 = 4 ⎪ Решим систему ⎨ x1 + 2 x2 + x3 = 5 ⎪ 3 x − 2 x + 2 x = −1 2 3 ⎩ 1
⎛ 2 1 −3 ⎞ ⎜ ⎟ A := 1 2 1 ⎜ ⎟ 3 2 − 2 ⎝ ⎠
Зададим матрицу системы:
Зададим вектор правых частей:
Найдем решение:
⎛ 4 ⎞ ⎜ ⎟ b := 5 ⎜ ⎟ ⎝ −1 ⎠
x := lsolve( A , b)
⎛1⎞ ⎜ ⎟ x= 2 ⎜ ⎟ ⎝0⎠
⎛ 4 ⎞ Для проверки умножим матрицу A на найденное решение A⋅x = ⎜ 5 ⎟ ⎜ ⎟ ⎝ −1 ⎠ Произведение совпало с правой частью b.
1.6. Интерполяция функций В пакете Mathcad имеется возможность интерполяции кубическими сплайнами. Для этого предназначена пара функций cspline(…) – interp(…). Если заданы массивы узлов интерполяции X и соответствующих значений функции Y, то функция cspline(X,Y) возвращает массив коэффициентов для построения кубического сплайна. Этот массив должен быть первым аргументом функции interp(S,X,Y,t). Два следующих аргумента – это массивы исходных данных, 11
последний аргумент – точка, в которой вычисляется значение построенного интерполяционного сплайна. Пример. Построим интерполяционный сплайн для функции, заданной x y
таблицей значений
− 1 − 0 .5 3 2
Задаем исходные данные:
⎛ −1 ⎞ ⎜ −0.5 ⎟ ⎜ ⎟ x := ⎜ 0 ⎟ ⎜ 0.5 ⎟ ⎜ ⎟ ⎝ 1 ⎠
0 1
0 .5 2 .5
1 4
⎛ 3 ⎞ ⎜ 2 ⎟ ⎜ ⎟ y := ⎜ 1 ⎟ ⎜ 2.5 ⎟ ⎜ ⎟ ⎝ 4 ⎠
Получаем коэффициенты многочленов: s := cspline( x , y)
Задаем интерполяционный сплайн: g( t) := interp( s , x , y , t)
Строим график полученного сплайна и точечный график исходных данных:
g( t) y
4 2 1
0
1
t, x
Описанным образом можно построить кубический сплайн дефекта один с условиями отсутствия узла. Помимо этого, имеется возможность построения указанного сплайна с другими дополнительными условиями. А именно, использование функции pspline() для получения массива коэффициентов позволяет построить сплайн, у которого в граничных точках равна нулю третья производная. А функция lspline() дает указанный сплайн с равными нулю в граничных точках второй и третьей производными. 12
1.7. Решение задачи Коши Одной из простейших встроенных функций для решения задачи Коши для ⎧ y ' = f (t , y ) является функция rkfixed(y0,t0,tN,N,F), в ⎩ y (t 0) = y 0
ОДУ 1 порядка вида ⎨
которой реализован метод Рунге-Кутты 4-го порядка. Ее первый аргумент y0 – начальное значение решения, второй и третий аргументы t0, tN – начальное и конечное значения аргумента (начало и конец отрезка, на котором решается задача), четвертый аргумент N – количество точек на указанном отрезке, в которых будет найдено решение и последний аргумент F – имя функции – правой части дифференциального уравнения. Функция rkfixed(y0,t0,tN,N,F) возвращает матрицу из двух столбцов и N+1 строки. В первом (по счету) столбце содержатся узлы, на которые разбит отрезок [t0, tN], во втором столбце – значения искомого решения в соответствующих узлах отрезка.
⎧ y ' = sin(t ⋅ y ) Пример. Решим задачу Коши ⎨ ⎩ y (0) = 1 зададим начальные данные:
t0 := 0
y0 := 1
зададим правую часть ОДУ:
f ( t , y) := sin( t ⋅ y)
решим задачу на отрезке длины 2, разбитом на 10 шагов: y := rkfixed( y0 , t0 , t0 + 2 , 10 , f) 0
y=
1
0 1
0 0.2
1 1.02
2
0.4
1.082
3
0.6
1.189
4
0.8
1.343
5
1
1.534
6
1.2
1.727
7
1.4
1.868
8
1.6
1.923
9
1.8
1.9
10
2
1.822
Выделим из полученного результата массив аргументов (вырежем из матрицы y нулевой (первый по счету) 〈0〉 столбец): X := y 13
Выделим из полученного результата массив значений решения (вырежем из матрицы y первый (второй по счету) 〈1〉 столбец): Y := y Таким образом, получено решение: 0
X=
0
0
0
1
0.2
0 1
1 1.02
2
0.4
2
1.082
3
0.6
3
1.189
4
0.8
4
1.343
5
1
5
1.534
6
1.2
6
1.727
7
1.4
7
1.868
1.6
8
1.923
1.8
9
1.9
2
10
1.822
8 9 10
Y=
построим график найденного решения: 2
Y
1.5
1
0
1
2
X
Определим, например, значение y(1). Для этого найдем в массиве X соответствующее значение аргумента. Это X 5 = 1 Теперь возьмем из массива Y элемент с тем же номером: Y 5 = 1.534 Это и есть искомое значение.
14
Ту же самую функцию rkfixed(y0,t0,tN,N,F) можно использовать при решении задачи Коши для систем ОДУ 1-го порядка. В этом случае ее первый аргумент y0 должен быть вектором начальных приближений, а последний аргумент F(t,y) должен быть вектор-функцией правых частей (зависящей от скаляра t и вектора y). Возвращать же функция rkfixed(y0,t0,tN,N,F) будет матрицу с большим количеством столбцов. В первом (по счету) столбце опять будут содержаться узлы сетки, а в остальных – значения искомых функций в этих узлах (и количество таких столбцов будет совпадать с порядком системы). Пример.
Решим задачу Коши для системы
⎧u ' = sin(t ⋅ v) ⎪ ⎨v′ = u ⎪u (0) = 1, v(0) = 0.5 ⎩ t0 := 0
зададим начальные данные:
⎛ 1 ⎞ ⎟ ⎝ 0.5 ⎠
y0 := ⎜
⎛ sin( t ⋅ y1) ⎞ f ( t , y) := ⎜ ⎟ y 0 ⎝ ⎠
зададим правую часть ОДУ:
решим задачу на отрезке длины 2, разбитом на 10 шагов: y := rkfixed( y0 , t0 , t0 + 2 , 10 , f) 0
y=
1
2
0 1
0 0.2
1 1.02
0.5 0.611
2
0.4
1.082
0.746
3
0.6
1.189
0.911
4
0.8
1.343
1.113
5
1
1.534
1.359
6
1.2
1.727
1.66
7
1.4
1.868
2.028
8
1.6
1.923
2.476
9
1.8
1.9
3.025
10
2
1.822
3.694
〈〉 Выделим из полученного результата массив аргументов: X := y 0 〈〉 Выделим из полученного результата первую функцию: U := y 1 15
〈〉 Выделим из полученного результата вторую функцию: V := y 2
Построим графики найденного решения: Первая функция:
Вторая функция:
4
U
4
V
2
0
0
1
2
0
2
0
X
1
2
X
1.8. Блок Given -- Find Достаточно универсальным средством решения различных вычислительных задач является блок Given – Find. Покажем, как пользоваться данным средством на примере решения систем нелинейных уравнений. (К тому же, других способов решения таких систем Mathcad не имеет.) Между ключевыми словами записываются все уравнения системы, которую необходимо решить. При этом для знака равенства следует использовать «логическое равно» (набирается с помощью клавиш [Ctrl]= или выбирается с панели логических символов). После ключевого слова find в скобках указываются искомые величины. Пример. Найдем точки пересечения эллипса x2 + 2y2 прямой x − 2y 0 задаем исходные данные: given 2
2
x + 2y 6 x − 2y 0
вызываем функцию решения системы:
16
6и
⎛ 2 −2 ⎞ ⎟ ⎝ 1 −1 ⎠
find( x , y) → ⎜
В итоге получаем, что данная задача имеет два решения (они расположены в выданном ответе по столбцам): и x1 = 2 y1 = 1 x2 = −2 y2 = −1 Для проверки построим графики заданных кривых. Выражая y из каждого уравнения, получаем: 2
для эллипса y0 ( x) :=
для прямой
y2 ( x) :=
6−x 2
2
6−x y1 ( x) := − 2 ,
x 2
Теперь строим график 2 y0( x)
1
y1( x) y2( x)
3
2
1
0
1
2
3
1 2 x
По графику хорошо видно, что решений действительно два и они найдены правильно.
17
Часть II Встроенный язык программирования Пакет Mathcad обладает некоторым арсеналом средств, позволяющим создавать пользовательские функции и реализовывать таким образом практически любые алгоритмы вычислительной математики. Все соответствующие средства собраны на панели программирования (programming toolbar). Следует сразу подчеркнуть, что в текст программы все операторы, ключевые слова и т.д. должны вставляться только с панели программирования и ни в коем случае не вводиться посимвольно с клавиатуры. Никаких принципиальных отличий в использовании операторов во встроенном языке пакета Mathcad нет. Ниже для удобства восприятия все алгоритмы продублированы на языке Паскаль (предполагается, что он уже освоен читателем). С одной стороны, это позволяет лучше понять структуру и детали алгоритма, а с другой – увидеть те небольшие отличия, которые есть между двумя языками программирования. Любая программа состоит из заголовка и тела программы. Заголовок представляет собой название программы (произвольная последовательность стандартно допустимых символов) и параметров. Параметры программы задаются простым перечислением и не требуют явного указания их типа. Тип распознается автоматически по использованию того или иного параметра в теле программы. Это могут быть числа (целые, вещественные, комплексные), вектора (массивы), матрицы, функции и т.д. За заголовком следует оператор присваивания и начинается собственно тело (текст) программы. Оно ограничено жирной вертикальной чертой, которая создается по нажатию на кнопку Add Line и служит аналогом операторных скобок (begin ... end в Паскале, { ... } в Си и т.д.) Если необходимо, чтобы программа после завершения своей работы возвращала какое-либо значение, то имя переменной, в которой это значение хранится, необходимо указать в самой последней строке программы. Внутренние переменные в программе также не требуют предварительного описания с указанием типа данных. Фактически, определением переменной является первый оператор присваивания, в левой части которого она встречается. Теперь разберем на примерах основные конструкции встроенного языка. Начнем с оператора присваивания ( ← ) и цикла for. Для начала напишем простую программу, вычисляющую норму вектора, n
т.е. величину x 1 = ∑ xi (по сути дела, найдем сумму модулей n чисел). При i =0
этом не забываем, что нумерация массивов в пакете Mathcad по умолчанию ведется с нуля. 18
Вычисление x 1
Программа 1.
type vector = array[0..100] of double; function norma1(x: vector; n: word): double; var i: word; s: double; begin s := x[0]; for i := 1 to n do s := s + abs(x[i]); normа1 := s; end;
normа1 ( x , n) :=
s ← x0 for i ∈ 1 .. n s ← s + xi s
Пример вызова программы 1.
Зададим вектор x:
⎛ 2 ⎞ ⎜ ⎟ x := −3 ⎜ ⎟ ⎝ 1 ⎠
Так как нумерация начинается с нуля, то n := 2
(номер последнего элемента равен двум) Вызовем программу:
normа1 ( x , n) = 6
Ниже приведена еще одна простая программа, вычисляющая другую норму вектора
x
∞
= max xi (теперь ищется максимальное по модулю число 0≤i ≤ n
среди заданных). На этом примере хорошо видна особенность условного оператора во встроенном языке пакета Mathcad: перед ключевым словом if пишется выполняемый оператор (или последовательность операторов), а после ключевого слова – условие, в случае истинности которого эти операторы будут выполнены. 19
Программа 2.
Вычисление x
∞
type vector = array[0..100] of double; function normai(x: vector; n: word): double; var i: word; s: double; begin s := x[0]; for i := 1 to n do if s < abs(x[i]) then s := abs(x[i]); normаi := s; end;
normai( x , n) :=
s ← x0 for i ∈ 1 .. n s ← xi
if s < xi
s
Пример вызова программы 2.
⎛ 2 ⎞ ⎜ ⎟ x := −3 ⎜ ⎟ ⎝ 1 ⎠
Зададим тот же вектор x:
Так как нумерация начинается с нуля, то
n := 2
normai( x , n) = 3
Вызовем программу:
Теперь немного усложним задачу: будем искать максимум не среди элементов массива, а на множестве значений функции f(x) на заданном отрезке [a,b]. Для этого зададим на отрезке [a,b] множество точек, расположенных равномерно с шагом h, и найдем максимальное значение функции в этих точках. Необходимо, конечно, понимать, что такой алгоритм не ищет точное значение маскимума функции. Он возвращает лишь некоторое приближение к нему, точность которого тем выше, чем большее количество точек мы рассмотрим на отрезке [a,b]. В приведенной ниже программе количество точек фиксировано (и равно 100). Для увеличения точности следует увеличить этот параметр в тексте программы (при вычислении величины h), а еще лучше – ввести дополнительный аргумент, задающий количество рассматриваемых на отрезке [a,b] точек. 20
Программа 3.
Поиск максимума функции на отрезке.
type func = function(t: double): double; function maxf(f: func; a,b: double): double; var s,x,h: double; begin x := a; s := f(a); h := (b - a) / 100; while x < b do begin x := x + h; if s < f(x) then s := f(x); end; maxf := s; end;
maxf ( f , a , b) :=
x←a s ← f ( a) h←
b−a 100
while x < b x←x+h s ← f ( x) if s < f ( x) s
Пример вызова программы 3. Найдем максимум модуля
sin 2 ( x) + 1 на отрезке [1, 1.5] производной функции g ( x) = 4 Определим нужную функцию: 2
sin( x) g( x) := +1 4
Определим модуль ее производной: h ( x) :=
Зададим границы отрезка: a := 1
b := 1.5
Найдем максимум: maxf ( h , a , b) = 0.227 21
d g( x) dx
Для проверки построим график:
0.2 h( x) 0.1 1
1.1
1.2
1.3
1.4
1.5
x
По графику видно, что максимум h(x) достигается в левой границе отрезка. Вычислив это значение, убеждаемся, что оно совпадает с найденным максимумом: h ( 1) = 0.227
Если необходимо, чтобы программа возвращала не одно значение, а больше, следует составить массив возвращаемых значений и выдать в качестве результата этот массив (т.е. указать его имя в последней строке программы). Следующая программа уже может быть использована для решения серьезной задачи – поиска корня уравнения вида x = ϕ (x) методом простых итераций. При этом предполагается, что необходимая для работы метода величина q = max ϕ ' ( x) уже найдена. Напомним, что метод простой итерации заключается в последовательном вычислении приближений xn+1 = ϕ ( xn ) до тех пор, пока не выполнится условие xn+1 − xn ≤
1− q ε , гарантирующее нахождение q
решения с точностью ε . В качестве ответа приведенная ниже программа выдает массив из двух значений: корня уравнения и количества итераций. Входными параметрами являются функция - правая часть уравнения ϕ (x) (она обозначена через g), знаменатель метода q, начальное приближение x0 и точность e. Две переменные x и y в теле цикла отвечают за предыдущее и последующее приближения к корню соответственно, а их разность позволяет следить за выполнением критерия окончания. 22
Программа 4.
Метод простой итерации.
type func = function(t: double): double; vect2 = array[0..1] of double;
siter( g , q , x0 , e) :=
x ← x0 y ← g( x)
function siter(f: func; q, x0, e: double): vect2; var x,y: double; k: word; begin x := x0; y := g(x); k := 1; e1 := ((1 - q) / q ) * e; while abs(x - y) > e1 do begin x := y; y := g(x); k := k + 1; end; res[0] := y; res[1] := k; siter := res; end;
k←1 e1 ←
1−q ⋅e q
while x − y > e1 x← y y ← g( x) k←k+1
⎛ y⎞ ⎟ ⎝k⎠
res ← ⎜ res
sin 2 ( x) −1 = 0 Пример вызова программы 4. Найдем корень уравнения x − 4 Зададим функцию: 2
sin( x) f ( x) := x − −1 4 Оставляя x слева и перенося остальные слагаемые вправо, получим уравнение вида x = g (x) . Зададим полученную функцию g(x): 2
( sin( x) ) g( x) := +1 4 23
Построим график заданной функции f(x): 1 0.5 f( x) 1
1.2
1.4
1.6
1.8
0.5 x
По графику видно, что в качестве начального приближения можно выбрать значение 1.2, так как примерно там происходит пересечение графиком оси OX. Определим знаменатель метода q = max g ' ( x) . (Это подробно расписано в предыдущем примере). По графику функции f(x) видно, корень расположен на отрезке [1, 1.4] и, следовательно, можно ограничиться рассмотрением только этого отрезка. d h ( x) := g( x) q := maxf ( h , 1 , 1.4) dx Получили значение q = 0.227 Оно меньше единицы, следовательно метод должен сходиться. Зададим начальное приближение и точность:
−8
e := 10
x0 := 1.2
Вызовем функцию, реализующую метод простой итерации: y := siter( g , q , x0 , e)
Получим следующий результат:
⎛ 1.221 ⎞ ⎟ ⎝ 9 ⎠
y=⎜
Если нам нужно только значение корня, то вычленим его: Таким образом, ответом (корнем) является величина
X := y0 X = 1.22056858
(Поскольку корень был найден с точностью 10-8, то необходимо настроить формат вывода числа Х так, чтобы отображались все 8 верных знаков после десятичной точки.) 24
Внесем в написанную программу небольшое изменение: введем предельное количество итераций, по достижении которого программа будет прерывать свою работу. (Это может пригодиться, например, в том случае, когда знаменатель q определен неправильно, и метод может расходиться.) Используем для этих целей оператор break, который будет срабатывать при достижении счетчиком числа итераций значения 10000. В такой ситуации произойдет выход из цикла while и начнут выполняться следующие за ним операторы. Кроме того, программа должна возвращать информацию о том, по какой причине закончилась ее работа: по выполнению критерия окончания или по достижению предельного числа итераций. Для этого введем дополнительную переменную key, которая будет равна 1 при нормальной работе метода и становиться нулем при превышении предельного числа итераций. Соответственно, в массив возвращаемых значений необходимо добавить эту переменную. Во всем остальном новая программа работает так же, как предыдущая.
Программа 5.
Метод простой итерации с прерыванием. siter( g , q , x0 , e) :=
type func = function(t: double): double; vect2 = array[0..1] of double;
x ← x0 y ← g( x) k←1
function siter(f: func; q, x0, e: double): vect2; var x,y: double; k: word; begin x := x0; y := g(x); k := 1; key := 1; e1 := ((1 - q) / q ) * e; while abs(x - y) > e1 do begin x := y; y := g(x); k := k + 1; if k > 10000 then begin key := 0; exit; end; end; siter[0] := y; siter[1] := k; siter[2] := key; end;
key ← 1 e1 ←
1−q ⋅e q
while x − y > e1 x← y y ← g( x) k←k+1 if k > 10000 break key ← 0
⎛ y ⎞ ⎜ k ⎟ res ← ⎜ ⎟ key ⎝ ⎠ res
25
Чтобы набрать новый вариант программы, необходимо после того, как прописан оператор if, нажать кнопку Add Line. Тогда под оператором if появится вертикальная линия с несколькими полями ввода. Вызов программы 5 производится точно так же, как и программы 4, поэтому подробно он не прописан. Вернемся еще раз к условному оператору if. До сих пор нам требовалось выполнять некоторые действия только в случае истинности проверяемого условия. Однако часто требуется выполнить те или иные действия и в противоположном случае. Ключевым словом для этих действий является otherwise (иначе), которое должно быть написано на следующей строчке после оператора if. Проиллюстрируем это на примере метода бисекции, в котором в зависимости от истинности некоторого условия необходимо выбирать либо одну, либо другую половину отрезка локализации.
Программа 6.
Метод бисекции.
type func = function(t: double): double; vect2 = array[0..1] of double;
bisec( f , a , b , e) :=
an ← a bn ← b k←0 while ( bn − an) > 2 ⋅e
function bisec(f: func; a, b, e: double): vect2; var xn, an, bn: double; k: word; begin an := a; bn := b; k := 0; while bn - an > 2*e do begin xn := (an + bn) / 2; if f(an)*f(xn) <= 0 then bn := xn else an := xn; k := k + 1; end; xn := (an + bn) / 2; bisec [0] := xn; bisec [1] := k; end;
xn ←
an + bn 2
bn ← xn if f ( an) ⋅f ( xn) ≤ 0 an ← xn otherwise k←k+1 xn ←
an + bn 2
⎛ xn ⎞ ⎟ ⎝ k⎠
res ← ⎜ res
В приведенной выше программе входными параметрами являются функция (корень которой мы ищем), границы отрезка локализации и требуемая 26
точность, а возвращается массив из двух значений – корня функции и количества произведенных итераций. Внутренние переменные an и bn содержат границы текущего отрезка локализации, xn – середину этого отрезка. В том случае, когда знак функции на левом конце отрезка не совпадает с ее знаком в середине отрезка ( f ( an ) ⋅ f ( xn ) ≤ 0), в качестве нового отрезка локализации выбирается левая половина (т.е. правой границей отрезка становится предыдущая середина: bn ← xn). В противном случае выбирается правая половина (т.е. левой границей отрезка становится предыдущая середина: an ← xn).
Пример вызова программы 6. Найдем корень уравнения из предыдущего примера. 2
Зададим функцию:
sin( x) f ( x) := x − −1 4
Зададим точность:
e := 10
−8
Вызовем метод бисекции на отрезке локализации [1, 1.4] (см. график в предыдущем примере): y := bisec( f , 1 , 1.4 , e)
Получим результат:
⎛ 1.22056858 ⎞ ⎟ 25 ⎝ ⎠
y=⎜
Напоследок, остается еще раз сказать о возвращаемых значениях. Во всех приведенных выше программах возвращается либо одно значение, либо несколько однотипных. Однако, иногда бывает необходимо возвращать данные разных типов. Технически это делается точно так же: заполняется массив значений и возвращается этот массив. Единственным, на что здесь следует обратить внимание, является работа с массивами. А именно, если одним из элементов возвращаемого массива данных является также массив, то в выдаваемом векторе будет отображаться не содержимое этого массива, а размерность (взятая в фигурные скобки). Чтобы увидеть сами элементы, необходимо произвести разыменование. Проиллюстрируем сказанное на примере программы, определяющей оптимальное значение параметра для метода простых итераций (для СЛАУ). Напомним, что оптимальным параметром
27
2 , где m и M – минимальное и максимальное m+M собственные числа матрицы системы. Поскольку метод применим только для положительно определенных матриц (т.е. таких, у которых m > 0), то оптимальный параметр вычисляется только в этом случае. В противном случае будем выдавать ноль. Приведенная ниже программа возвращает массив из двух значений: нулевым элементом массива является вектор собственных чисел, первым элементом – оптимальный параметр.
является величина a =
Программа 7.
Определение оптимального параметра для метода простых итераций. param ( A) :=
z ← eigenvals( A) m ← min( z)
В языке Pascal создание типов данных, аналогичных массиву res из программы Mathcad’а невозможно.
M ← max( z) a←
2 if m > 0 m+M
a ← 0 otherwise
⎛z⎞ res ← ⎜ ⎟ ⎝a⎠ res
Пример вызова программы 7. Определим оптимальный параметр метода ⎛ 17 −5 6 −6 ⎞
⎜ ⎟ − 6 − 5 11 4 ⎟ . простых итераций для матрицы A = ⎜ ⎜ 6 −6 9 −8 ⎟ ⎜ ⎟ ⎝ −6 4 −8 13 ⎠
Зададим матрицу:
⎛ 17 ⎜ −5 A := ⎜ ⎜ 6 ⎜ ⎝ −6
−5 6
−6 ⎞
⎟
11 −6 4 ⎟ −6 9 −8 ⎟ 4
Вызовем написанную выше программу: 28
⎟
−8 13 ⎠ y := param ( A)
Получим результат:
⎛ {4,1} ⎞ ⎟ ⎝ 0.062 ⎠
y=⎜
Как видим, значение параметра выдается сразу:
y1 = 0.062
А вместо собственных чисел выдается шифрованная запись {4,1}. Это означает, что первым (по счету) элементом массива y является массив, состоящий из 4-х строк и 1-го столбца. Чтобы его увидеть, обратимся к соответствующему элементу массива y:
⎛ 30.4 ⎞ ⎜ ⎟ 1.928 ⎟ y0 = ⎜ ⎜ 9.825 ⎟ ⎜ ⎟ ⎝ 7.847 ⎠ Теперь все собственные числа видны. Чтобы обратиться к какому-либо из них, необходимо ставить скобки:
( y0) 2 = 9.825 Или вводить новую переменную: z := y0
z2 = 9.825
29
Библиографический список 1. Амосов А.А., Дубинский Ю.А., Копченова Н.В. Вычислительные методы для инженеров. М.: Изд-во МЭИ, 2003. 2. Самарский А.А., Гулин А.В. Численные методы. М.: Наука, 1999. 3. Амосова О.А., Григорьев В.П., Зайцева С.Б. Вычислительные методы с применением математического пакета MATHCAD. М.: Изд-во МЭИ, 2000. 4. Амосова О.А., Акимова И.Г., Зайцева С.Б. Сборник заданий к лабораторным занятиям по вычислительной математике. М.: Изд-во МЭИ, 2002. 5. Дьяконов В. Mathcad 8 / 2000: специальный справочник. СПб. Изд-во Питер, 2000.
30