Главная страница

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


Скачать 4.43 Mb.
НазваниеНастоящий учебник посвящен системе Mathematica прикладному пакету компьютерной алгебры, при помощи которого можно решать любые задачи, в которых в той или иной форме встречается математика
АнкорМатематика
Дата11.05.2022
Размер4.43 Mb.
Формат файлаpdf
Имя файла106-108.pdf
ТипУчебник
#521834
страница9 из 38
1   ...   5   6   7   8   9   10   11   12   ...   38
Кстати, что это такое мы тут посчитали?
Численное интегрирование. Мы уже знаем, что в элементарных функциях интеграл
R
sin(sin(x)) dx не берется. Но, конечно, для любых конкретных a < b значение определенного интеграла
R
b
a
sin(sin(x)) dx мож- но найти с любой точностью. Для этой цели проще всего пользоваться командой численного интегрирования NIntegrate, синтаксис которой не отличается от синтаксиса команды Integrate вызываемой для вычисления определенного интеграла. По умолчанию NIntegrate проводит вычисле- ния с машинной точностью (чуть меньше 16 знаков после запятой). Вот пример ее использования:
In[169]:= NIntegrate[Sin[Sin[x]],
{x,1,2}]
Out[169]=0.81645
Команда NIntegrate не может, конечно, дать такие значения, как

π.
Обычно эта команда работает чрезвычайно быстро, так как по умолчанию она вначале компилирует программу вычисления подынтегральной функ- ции и использует небольшую глубину рекурсии. Разумеется, это значит,
что в случае часто осциллирующих функций (highly oscillatory func- tions) применение команды NIntegrate — как и вообще любое применение приближенных вычислений!!! — может приводить к очень серьезным по- грешностям. В частности, поэтому приближенные вычисления никогда не следует использовать внутри рекуррентных или итеративных процедур, где уже за несколько десятков итераций ошибка может достичь десятков процентов. Разумеется, в подобных случаях система обычно пре- дупреждает о возможных проблемах и для получения правильного ответа следует использовать символьные, а не численные вычисления, даже если соответствующие функции работают чуть дольше. Вот пример, когда при- менение функции NIntegrate без настройки опций приводит к ошибке уже в 7-ом знаке:
In[170]:= NIntegrate[Sin[1/x/10000],
{x,0,1}]
Это вычисление производится очень быстро, но дает, увы, неверный ответ
0.000963519. Разумеется, система сообщает о возможной ошибке:
NIntegrate:
NIntegrate failed to converge to prescribed accuracy after 9
recursive bisections in x near
{x} = {2.07884 10
8
}...
С нашей точки зрения правильная политика во всех подобных случаях состоит в проведении безошибочных вычислений, с вычислением приближенного значения на самом последнем шаге:
In[171]:= N[Integrate[Sin[1/x/10000],
{x,0,1}]]]
Это вычисление требут несколько большего времени, но зато дает правиль- ный ответ 0.000963312. Разумеется фанатики численных методов могут добиться такой же точности и другими способами, например, просто уве- личив глубину рекурсии:

130
In[172]:= NIntegrate[Sin[1/x/10000],
{x,0,1},MaxRecursion->20]]
В этом случае система так же вернет правильный ответ 0.000963312 и затратит на его нахождение почти столько же времени, как и в исходном примере.
§ 10. Вектора и матрицы
Как представитель комбинаторики, я идентифицирую реальность с матрицами из 0 и 1.
Дональд Кнут. Математическая типография
Сейчас мы совсем коротко обсудим основы представления, генерации и изображения векторов и матриц в системе Mathematica. При этом мы ограничиваемся лишь абсолютным минимумом, необходимым для решения простейших задач линейной алгебры.
Списки. Одной из объединяющих концепций, вокруг которых ор- ганизован язык Mathematica, является понятие списка (List). С точки зрения языка системы и внутреннего представления данных все на свете
— множества, наборы, последовательности, векторы, матрицы, тензоры, и т.д. — трактуется как список. Более того, грамотное программирование на языке Mathematica состоит в том, чтобы избегать явного использова- ния циклов, а вместо этого объединять переменные, команды, уравнения,
условия, подстановки, ... в списки.
В Mathematica список (x
1
, . . . , x
n
) с компонентами x
1
, . . . , x
n
обознача- ется
{x1,...,xn} или, в полной форме, List[x1,...,xn]. Подчеркнем,
что с математической точки зрения список длины n представляет собой упорядоченную n-ку (n-tuple) или, если мы не хотим явно упоминать ее длину
43
, тупель. По определению два списка равны, если равны их длины и все их соответствующие компоненты:
(x
1
, . . . , x
m
) = (y
1
, . . . , y
n
)
⇐⇒
m = n
и
x
i
= y
i
, i = 1, . . . , n
В программировании существует устойчивая традиция называть компонен- ты списка элементами этого списка. Как мы только что отметили, при определении равенства списков учитываются кратности и порядок их эле- ментов!
Комментарий. В русской учебной литературе нет единства по поводу того, как следу- ет переводить термин Tupel, tuple. Под влиянием программирования сегодня tuple и в математических работах чаще всего переводится как список. Некоторые авторы пред- лагали перевод кортеж, но работающие математики никогда им не пользуются. Поэтому мы пропагандируем термин тупель и его производные дупель, трипель, квадрупель, квин- тупель, секступель, септупель и октупель для обозначения упорядоченных пар, троек,
четверок, пятерок, шестерок, семерок и восьмерок.
Таким образом, список
{a,b,a,c} или, в полной форме, List[a,b,a,c]
представляет именно тупель (a, b, a, c), а вовсе не набор или множество с элементами a, b, a, c. Это значит, например, что в ответ на вопрос
43
Например, при n = k.

131
TrueQ[
{a,b,c}=={b,a,c}]
система возвратит False — если, конечно, переменным a, b не были ранее присвоены одинаковые значения!
Применение к списку команды Sort расставляет его элементы в неко- тором естественном порядке, связанном с их записью как выражений в языке Mathematica. Таким образом, эффективно применение Sort застав- ляет систему игнорировать порядок элементов списка, делая два списка равными, в том и только том случае, когда совпадают представленные ими наборы [x
1
, . . . , x
n
]. Напомним, что при определении равенства наборов учитываются кратности входящих в них элементов, но не их порядок:
In[173]:= TrueQ[Sort[
{a,b,a,c}]==Sort[{b,c,a,a}]]
Out[173]=True
In[174]:= TrueQ[Sort[
{a,b,a,c}]==Sort[{b,c,b,a}]]
Out[174]=False
С другой стороны, команда Union превращает список в множество, т.е.
заставляет систему игнорировать не только порядок элементов списка, но и их кратности:
In[175]:= TrueQ[Union[
{a,b,a,c}]==Union[{b,c,b,a}]]
Out[175]=False
В системе содержится несколько десятков операций над списками, отно- сящихся к следующим категориям:
теоретико-множественные операции;
манипуляции с частями списка: извлечения, вычеркивания, вставки,
замены, выборки, и т.д.
структурные манипуляции: сортировки, перестановки, выравнивания,
разбиения, и т.д.
применение функций к спискам и их частям: Map, Apply, Thread, Inner,
Outer и их многочисленные варианты.
Гибкое применение возможностей этих операций составляет йогу системы
Mathematica, однако овладение этим искусством требует некоторого мен- тального тюнинга и многомесячной практики. Вопросы функционального и списочного программирования требуют отдельного основательного рас- смотрения, поэтому здесь мы не будем обсуждать тонкие аспекты работы со списками, а ограничимся иллюстрацией применения нескольких простей- ших встроенных функций к решению стандартных задач линейной алгеб- ры.
Векторы. В простейшем варианте вектор (x
1
, ..., x
n
) с координата- ми x
1
, . . . , x
n
представляется списком
{x1,...,xn}. При этом координаты вектора могут быть любыми выражениями: числами, символами, списка- ми, матрицами и т.д.
При действиях над векторами все обычные операции трактуются как покомпонентные:

132
In[176]:=
{u,v,w}+{x,y,z}
Out[176]=
{u+x,v+y,w+z}
In[177]:=
{u,v,w}*{x,y,z}
Out[177]=
{u*x,v*y,w*z}
Более того, арифметические операции имеют атрибут Listable. Это зна- чит, что при выполнении этих операций скаляр x отождествляется с век- тором (x, . . . , x) подходящей длины. Иными словами,
In[178]:=
{w+{x,y,z},w*{x,y,z}}
Out[178]=
{{w+x,w+y,w+z},{w*x,w*y,w*z}}
Стоит подчеркнуть, что в такой форме записи не делается различия между строками и столбцами, и вычисление
{a,b,c}.{x,y,z} или, что то же самое, Dot[
{a,b,c},{x,y,z}], даст a*x+b*y+c*z. Тот же резуль- тат получится и при вычислении Inner[Times,
{a,b,c},{x,y,z}]. Однако,
интерпретировать этот результат можно совершенно по разному, в зависи- мости от того, как мы представляем себе исходные векторы и чем являются их элементы.
произведение строки (a, b, c) на столбец (x, y, z)
t
;
скалярное произведение строки (a, b, c) на строку (x, y, z);
скалярное произведение столбца (a, b, c)
t
на столбец (x, y, z)
t
;
линейную комбинацию строк/столбцов x, y, z с коэффициентами a, b, c;
и многими другими способами.
Комментарий.
В действительности,
{x,y,z} не является ни строкой, ни столбцом.
Интересно, что Вольфрам считает это достоинством: Because of the way Mathematica uses lists to represent vectors and matrices, you never have to distinguish between “row”
and “column” vectors.
Как мы сейчас увидим, вектор (x, y, z), рассматриваемый как строка, должен записываться в виде
{{x,y,z}}, а рассматриваемый как столбец — в виде
{{x},{y},{z}}. С нашей точки зрения это нарушение симметрии между строками и столбцами является одним из самых серьезных концептуальных дефектов системы.
Конечно, оно никак не сказывается на практических вычислениях. С другой стороны,
в данном случае Mathematica всего лишь следует обычной при элементарном подходе практике, когда не делается никакого различия между правыми и левыми векторными пространствами. В действительности, даже над полем необходимо тщательно различать правые векторные пространства, координаты векторов в которых записываются столбцами, а базисы, соответственно, строчками (состоящими из столбцов) и левые векторные пространства, координаты векторов в которых записываются строчка- ми, а базисы, соответственно, столбцами (состоящими из строчек). Стоит только на- чать различать столбцы и строки и все в линейной алгебре сразу становится на свои места. Например, из четырех матриц g, g
t
, g
1
и g
−t
, отвечающих за преобразование координат различных геометрических объектов, остаются всего две: ковариантная g и контравариантная g
1
Запись матриц. Матрица в языке Mathematica записывается как список , составленный из строк этой матрицы. Список, элементы которо- го сами являются списками, называется вложенным списком (nested list). Таким образом, матрица

a
b
c
d


133
изображается как
{{a,b},{c,d}}. Именно такая форма используется при вводе матриц, внутри себя система переводит это выражение в полную фор- му List[List[a,b],List[c,d]].
Симметрия между строками и столбцами восстанавливается при помощи команды Transpose, переводящей матрицу в транспонированную матрицу,
строки которой совпадают со столбцами исходной:
In[179]:= Transpose[
{{a,b},{c,d}}}]
Out[179]=
{{a,c},{b,d}}
По умолчанию команда Transpose переставляет два верхних уровня вло- женности списков. Таким образом, например, команда Transpose, приме- ненная к списку матриц будет переставлять строки этих матриц между собой, а вовсе не транспонировать сами эти матрицы. Для одновременного транспонирования списка матриц нужно применять Transpose к элемен- там этого списка при помощи команды Map:
In[180]:= Transpose[
{{{a,b},{c,d}},{{e,f},{g,h}}}]
Out[180]=
{{{a,b},{e,f}},{{c,d},{g,h}}}
In[181]:= Map[Transpose,
{{{a,b},{c,d}},{{e,f},{g,h}}}]
Out[181]=
{{{a,c},{b,d}},{{e,g},{f,h}}}
Из описанного представления матриц и того, что было сказано выше об операциях над векторами следует, что при действиях над матрицами все обычные операции тракутются как покомпонентные:
In[182]:=
{{a,b},{c,d}}+{{e,f},{g,h}}
Out[182]=
{{a+e,b+f},{c+g,d+h}}
In[183]:=
{{a,b},{c,d}}*{{e,f},{g,h}}
Out[183]=
{{a*e,b*f},{c*g,d*h}}
Таким образом,
(Times) это умножение матриц по Адамару, а вовсе не обычное произведение матриц, которое обозначается . (Dot).
Более спорным представляется применение того же правила к скаля- рам, которые при этом отождествляются не с кратными единичной, а с кратными пробной матрицы, состоящей из одних единиц! Изобразим для примера пробную матрицу степени 3:


1 1
1 1
1 1
1 1
1


В свете этого соглашения нас не должен удивлять следующий результат:
In[184]:=
{{{a,b},{c,d}}+x,{{a,b},{c,d}}*x}
Out[184]=
{{{a+x,b+x},{c+x,d+x}},{{a*x,b*x},{c*x,d*x}}}
Генерация векторов и матриц. Основной командой генерации век- торов, матриц и других списков в языке Mathematica является команда

134
Table. Вызванная с одним итератором команда Table[f[i],
{i,m,n}] по- рождает список значений функции f в точках i = m, m + 1, . . . , n. Вот типичный пример использования этой команды:
In[185]:= Table[x^i/i!,
{i,0,5}]
Out[185]=
{1,x,x^2/2,x^3/6,x^4/24,x^5/120}
А вот забавная вариация на тему этого примера, детально обсуждаемая
Анри Пуанкаре в “Новых методах небесной механики”:
In[186]:= Table[N[10^i/i!],
{i,1,30}]
Out[186]=
{10., 50., 166.667, 416.667, 833.333, 1388.89, 1984.13,
2480.16, 2755.73, 2755.73, 2505.21, 2087.68, 1605.9,
1147.07, 764.716, 477.948, 281.146, 156.192, 82.2064,
41.1032, 19.5729, 8.89679, 3.86817, 1.61174, 0.644695,
0.24796, 0.0918369, 0.0327989, 0.01131, 0.00376999
}
Из этой таблицы видно, что отношение 10
i
/i! вначале очень быстро рас- тет (“расходится в смысле астрономов”), а потом очень быстро убывает
(“сходится в смысле математиков”).
Вызванная с двумя итераторами команда
Table[f[i,j],
{i,k,l},{j,m,n}]
порождает вложенный список значений функции двух аргументов f в па- рах (i, j), где i = k, k + 1, . . . , l, j = m, m + 1, . . . , n. Этот список будет организован как матрица, причем итератор i считается внешним, а j
внутренним, иными словами, i нумерует строки, а j — позиции внут- ри строк. Таким образом, строки этой матрицы имеют вид (f
im
, . . . , f
in
).
Еще раз обратите внимание на следующие два ключевых момента в этом определении:
матрица трактуется как строка, составленная из строк,
внутренние итераторы пишутся последними.
Иными словами, если мы дадим два определения матрицы Forward
In[187]:= forwaa[n ]:=Table[If[j==i+1,1,0],
{i,1,n},{j,1,n}]
In[188]:= forwbb[n ]:=Table[If[j==i+1,1,0],
{j,1,n},{i,1,n}]
отличающиеся лишь порядком итераторов, то получившиеся матрицы бу- дут транспонированы друг к другу. Вот как, например, выглядят матрицы forwaa[4] и forwbb[4] в традиционной математической нотации



0 1
0 0
0 0
1 0
0 0
0 1
0 0
0 0






0 0
0 0
1 0
0 0
0 1
0 0
0 0
1 0



Иными словами, только одна из этих матриц в действительности окажет- ся матрицей Forward, вторая будет матрицей Backward!
Ну а, скажем,
упомянутая в предыдущем пункте пробная матрица задается командой test[n ]:=Table[1,
{i,1,n},{j,1,n}] .

135
В системе Mathematica существует большое количество других команд генерации списков и мтариц специального вида. Одной из таких команд яв- ляется DiagonalMatrix[
{d1,...,dn}], которая порождает диагональную матрицу с диагональными элементами d
1
, . . . , d
n
. Однако в тех простых ситуациях, которые мы здесь рассматриваем, вполне достаточно команды
Table. Кроме того, как мы обсуждаем ниже, матрицы можно создавать из векторов или, наоборот, более глубоких списков при помощи структурных команд таких, как Partition или Flatten.
Части матриц. Для выделения частей списков в языке Mathemati- ca используется специальный вид скобок — двойные квадратные скобки
[[]], являющиеся сокращением команды Part. При этом в соответствии с общими правилами спецификации уровня, детально обсуждаемыми в Мо- дуле 2, x[[i]] — или, что то же самое, Part[x,i] — обозначает i-ю часть списка x; x[[-i]] — i-ю часть с конца; x[[i,j]] — j-ю часть его i-части и т.д. При этом сами номера позиций тоже могут задаваться списком, а если мы хотим выбрать все части на каком-то уровне, то спецификацией All.
Приведем несколько примеров применения этих соглашений
1   ...   5   6   7   8   9   10   11   12   ...   38


написать администратору сайта