Лекция 4. Детализация.

Выражения - универсальный конструктор в Mathematica
f[x,y,...] - универсальный (канонический) вид выражения
x, y... могут быть выражениями или атомарными объектами (числами, символами, строками)

Последовательность аргументов x, y, ... называется Sequence

f[Sequence[x,y,z]]

f[x,Sequence[y,z],w]

f называется заголовком (Head) выражения f[x, y, ...]
f может быть как символом, так и более сложным выражением

(в приведенных примерах заголовки - это f[2], (a+b) и ((#)^2)&)

f[2][x,y]
(a+b)[x]
((#)^2)&[x]

еще один пример : заголовком является InterpolatingFunction[{{0.,3.}},<>]

(First - взятие первого элемента списка)

f=y/.First[NDSolve[{y''[x]== -y[x],y[0]==y'[0]==2},y,{x,0,3}]]
f[x]
f[2.3]
Plot[f[x],{x,0,3}]

Команда FullForm позволяет представить выражение в каноническом виде

FullForm[((x+y-z w)/(a+(((b -c))^(1/2))))]

Выражения имеют структуру дерева

TreeForm[((x+y-z w)/(a+(((b -c))^(1/2))))]

Список, как частный случай выражения, имеет форму дерева

TreeForm[{a,{b,c},d}]

Когда в одной скобке стоит последовательность выражений (Subscript[expr, 1]);(Subscript[expr, 2]);..., разделенных ";", на самом деле там имеется одно выражение CompoundExpression[(Subscript[expr, 1]),(Subscript[expr, 2]),...]

Последовательность выражений

x=2; y=(x^2);
y

представляет собой одно выражение

CompoundExpression[x=2,y=(x^2),y]

Clear[x,y]

Уровни выражения expr: 
Level[expr,levelspec], где levelspec описывает интересующие уровни

TreeForm[((x+y-z w)/(a+(((b -c))^(1/2))))]

Table[Level[((x+y-z w)/(a+(((b -c))^(1/2)))),{i}],{i,0,7}]

levelspec = {n} - только n - ый уровень (нулевой уровень - само выражение)

Level[((x+y-z w)/(a+(((b -c))^(1/2)))),{3}]

levelspec = n - все уровни от 1-ого до n-ого (нулевой уровнень не включен)

Level[((x+y-z w)/(a+(((b -c))^(1/2)))),3]

levelspec = {n, m} - уровни с номерами между n и m

Level[((x+y-z w)/(a+(((b -c))^(1/2)))),{3,5}]

levelspec = {n, Infinity} - уровни с номерами, больше или равными n

Level[((x+y-z w)/(a+(((b -c))^(1/2)))),{0,Infinity}]

Заголовок выражения f[x, y, ...] - это f
Заголовки атомарных объектов называются их типами

Head[f[x,y]]

Head[x+y]

Типы атомарных объектов
целые числа - Integer
рациональные числа - Rational
вещественные числа - Real
комплексные числа - Complex
символы - Symbol
строки - String

{Head[1],FullForm[1]}
{Head[1/2],FullForm[1/2]}
{Head[1.1],FullForm[1.1]}
{Head[1+I],FullForm[1+I]}
{Head[x],FullForm[x]}
{Head["abc"],FullForm["abc"]}

Интересный пример (сравните с {Head[1 + i], FullForm[1 + i]})

{Head[x+I],FullForm[x+I]}

Замена заголовка, команда Apply или @@

Apply[g,f[x,y]]

Head[{a,b,c,d}]

Apply[Plus,{a,b,c,d}]

Plus@@{a,b,c,d}

Apply не действует на атомарных объектах

x=Apply[List,1]

Head[x]

x=Apply[List,1/2]

Head[x]

x=.

Head[x]

Преобразование типов атомарных объектов

IntegerString[integer] - преобразует целое число integer в строку (знак игнорируется)

IntegerString[25361]//InputForm

FromDigits[str] - преобразует строку цифр в целое число
(также преобразует список цифр в целое число; чтобы преобразовать число в список цифр, можно использовать IntegerDigits)

FromDigits["43476"]
FromDigits[{5,2,3,8}]
IntegerDigits[374632]

ToString[expr] - преобразует выражение expr в строку
ToString[expr,form] - преобразует выражение expr в строку, соответствующую типу вывода

ToString[(x^2)]
ToString[(x^2)]//InputForm

ToString[(x^2),InputForm]
ToString[(x^2),InputForm]//InputForm

ToExpression[str] - преобразует строку в соответствующее выражение
ToExpression[str,form] - преобразует строку в соответствующее выражение, используя при этом правила, соответствующие форме вывода form

ToExpression["Sin[x]"]

ToExpression["sin(x)",TraditionalForm]

ToExpression["\sin(x)",TeXForm]

Symbol[str] превращает строку в символ

Symbol["x"]

Строка из 10 символов:

Table[Symbol["x"<>ToString[i]],{i,10}]

Table[ToExpression["x"<>ToString[i]],{i,10}]

SymbolName[symbol] превращает symbol в строку - имя этого символа

SymbolName[x]//InputForm

Доступ к фрагментам выражения - как к списку (Заголовок Head - нулевой элемент)

TreeForm[((x+y-z w)/(a+(((b -c))^(1/2))))]

{(((x+y-z w)/(a+(((b -c))^(1/2)))))[[0]],(((x+y-z w)/(a+(((b -c))^(1/2)))))[[1]],(((x+y-z w)/(a+(((b -c))^(1/2)))))[[2]],(((x+y-z w)/(a+(((b -c))^(1/2)))))[[3]]}

TreeForm[(((x+y-z w)/(a+(((b -c))^(1/2)))))[[2]]]

{(((x+y-z w)/(a+(((b -c))^(1/2)))))[[2,1]],(((x+y-z w)/(a+(((b -c))^(1/2)))))[[2,2]],(((x+y-z w)/(a+(((b -c))^(1/2)))))[[2,3]],(((x+y-z w)/(a+(((b -c))^(1/2)))))[[2,4]]}

Символы и контексты (Contexts)

Полное имя кажодго символа состоит из двух частей : контекста (context) и короткого имени (short name)
Полное имя пишется в виде context`short 
Обратная кавычка ` называется меткой контекста (context mark)

abc`x
abc`x=10
(abc`x^2)

Символы с одинаковым именем, но разными контекстами - различны

x==x
a`x==b`x
a`x==a`y

В каждый момент времени фиксирован текущий контекст, имя которого находится в переменной $Context

$Context

Символы с текущим контекстом можно называть их короткими именами

x==Global`x

Контексты аналогичны директориям (папкам) с файлами
 1) текущий контекст - текущая папка, к файлам которой можно обращаться по их именам, не указывая полный путь
 2) папки могут содержать другие папки, как и контексты могут быть сложными

a`b`x==a`c`x

Отметим, что в момент запуска Mathematica устанавливается контекст Global`. Пользовательские символы относятся именно к этому контексту. Однако Pi имеет контекст System`. Чтобы в этом убедиться, примените к Pi команду Contex[].

Context[x]
Context[Pi]

В Mathematica реализована возможность пользоваться краткими именами символов, относящимися к разным контекстам: все такие контексты перечислены в списке $ContextPath. Полный список имеющихся контекстов можно получить, выполнив команду Contexts[].

$ContextPath//InputForm

Если в $ContextPath встречаются два контекста, содержащих один и тот же символ, скажем x, то при обращении к x он интерпретируется в соответствии с тем контекстом, который встречается первым в списке $ContextPath (все остальные одноименные символы "затеняются")

$ContextPath={"a`","b`"}~Join~$ContextPath
{a`x,b`x}
Context[x]

Таким образом, x воспринимается как a`x. Если такой x больше не нужен, можно выполнить команду Remove[x], и символ a`x будет уничтожен. Теперь x  будет восприниматься как b`x.

Remove[x]
Context[x]

Remove[x]
Context[x]

$ContextPath=Drop[$ContextPath,2]

Пакеты (Packages)

Пакеты - расширение Mathematica, написанные на языке Mathematica и содержащие определения, которые "учат" Mathematica работать в соответствующих областях.
Загрузить такой пакет можно командой
<<package
или
Needs[packege]
где packege имеет такой же формат, как context

<<VectorAnalysis`

Одной из функций, реализованных в этом пакете, является вычисление дивергенции Div[ξ] (в заданной координатной системе) или Div[ξ, coordsystem] (в координатной системе coorsystem)

SetCoordinates[Cartesian[x,y,z]] (* задает текущую систему координат*)
Div[{(x^2),(y^2),(z^2)}]

SetCoordinates[Spherical[r,θ,φ]]
Div[{(r^2),(θ^2),(φ^2)}]

CoordinateSystem (* выдает название текущей системы координат *)
Div[{(r^2),(φ^2),(z^2)},Cylindrical[r,φ,z]]

Текущий список загруженных пакетов присвоен переменной $Packages

$Packages

Типичная ошибка при загрузке пакета : попытка выполнить до загрузки пакета некоторую функцию f, короткое имя которой имеется у одной из функций пакета. Если такое произошло, то выполняемой функции автоматически присваивается контекст Global`. После загрузки пакета одноименная функция из этого пакета начинает затенять функцию Global`f, о чем сообщается в диагностике. Если Вам не нужна функция из пакета, а нужна определенная Вами, выполните команду Remove[f] (см. выше)

Отличие << (Get) от Needs: Needs загружает пакет только если он еще не был загружен, что определяется по тому, есть ли его имя в списке $Packages или нет

Просмотр определений (Definitions)
В чем разница между Unset (=.) и Clear

Definition[x] или ?x - посмотреть определения для x (?x дает больше информации), заданные с помощью команд = и :=

x=a-2;
x

Definition[x]

?x

Clear[x]
Definition[x]

Продемонстрируем разницу между Unset ( =. ) и Clear
(Unset работает только для выражения, точно соответствующего тому, которому присваивали; Clear работает для всех ассоциированных выражений)

f[x_]:=(x^2);
f[x_,y_]= x+y;
Definition[f]

f=.
Definition[f]

f[y_]=.
Definition[f]

f[x_]:=(x^2);
Definition[f]

Clear[f]
Definition[f]

Шаблон (Pattern)

"_" (Blank[]) - любой объект
"x_" - любой объект, которому, для обращения к нему, присвоено имя "x"

f[x_] := (x^2)

"_h"  - любой объект, имеющий заголовок h

fint[x_Integer] := (x^2)
{fint[2],fint[1/2],fint[x]}

"s : obj"  - объекты вида obj, которым приписано имя s

fobj[x:{_,_}] := x[[1]]+x[[2]]
{fobj[{1,2}],fobj[{1,2,3}],fobj[x]}

"_ _" (BlankSequence[]) - любая последовательность, состоящая из одного или более выражений

fseq[x_]:=(({x})^2)
fseq[3]
fseq[3,5]

Clear[fseq]
fseq[x__]:= (({x})^2)
fseq[3]
fseq[3,5]

"_ _ _" (BlankNullSequence[]) - любая последовательность, состоящая из нуля или более выражений

(в приводимом ниже примере <> обозначает объединение (конкатинацию) строк, а ToString[expr] превращает выражение expr в соответствующую строку)

fnulseq[x___]:="число аргументов равно "<>ToString[Length[{x}]]
fnulseq[]
fnulseq[3]
fnulseq[3,5]

Repeated[p] или "p.." обозначает последовательность (Sequence) из одного или более аргументов, каждый из которых соответствует шаблону (Pattern) p
RepeatedNull[p] или "p..." обозначает последовательность (Sequence) из нуля или более аргументов, каждый из которых соответствует шаблону (Pattern) p

fpat[x:{_,_}..]:=Plus@@{x}

fpat[{x1,x2},{y1,y2},{z1,z2}]

fpat[{x1,x2},y,{z1,z2}]

fpat[{x1,x2},{y1,y2},{{z11,z12},z2}]

Аргументы, которые могут быть пропущены
x_: v     - если пропущен, то v - его значение по умолчанию (Default)
x_h: v   - если пропущен, то v - его значение по умолчанию (Default)
x_.         - если пропущен, то его значение по умолчанию (Default) ассоциировано с функцией, в которой он находится, а именно, если имя этой функции f, то умолчание присвоено Default[f] (отметим, что Default[f] нужно задавать ДО ОПРЕДЕЛЕНИЯ функции)

f[x_:10]:= (x^2);
f[5]
f[5,7]
f[]

Clear[f]
Default[f]= 9;
f[x_.]:=(x^2);
f[5]
f[5,7]
f[]

Команда Clear не очищает значение Default. Чтобы очистить его, воспользуйтесь либо Default[f] =., либо ClearAll[f]

Clear[f]
Definition[f]

Default[f]=.
Definition[f]

Default[f]=9;
f[x_.]:=(x^2);
Definition[f]
ClearAll[f];
Definition[f]

Выбор объектов по шаблону

Выбор из списка объектов {e1,e2,...} по шаблону pattern, команда cases[{e1,e2,...},pattern]

Cases[{1,{2,(x^2)},(y^3),2},_^_]

Выбор из объектов {e1,e2,...} по шаблону pattern на уровнях, заданных levelspec, команда cases[{e1,e2,...},pattern,levelspec]

Cases[{1,{2,(x^2)},(y^3),2},_^_,{2}]

Команда cases[expr,pattern,levelspec] применима к произвольным выражениям expr

Cases[fexp[1,{2,(x^2)},(y^3),2,g[y,(z^(1/2))]],_^_,{0,Infinity}]

Clear[f,fint,fobj,fexp,fseq,fnulseq]

Опции

Каждому объекту s можно приписать опции, выполнив команду Options[s] = rhs

Options[s]={a,b,c}

Меняя Options можно управлять процессом вычисления выражения. В приведенном ниже примере
команда MemberQ[Options[s], a] проверяет, входит ли объект a в список Options[s]

s[x_]:=If[MemberQ[Options[s],a],Print["a входит в Options"],Print["a НЕ входит в Options"]]
s[2]

Options[s]={b,c};
s[2]

У многих встроенных функций и констант имеются заранее заданные опции. Обычно они имеют вид правил lhs->rhs
Чтобы посмотреть опции у обекта s, выполните команду Options[s]

Options[Plot]

Чтобы посмотреть значение конкретной опции объекта s, выполните команду Options[s,name], где name - имя опции

Options[Plot,PlotStyle]

Plot[{Sin[x],Cos[x]},{x,0,1}]

Чтобы изменить опции объекта s с именами name1, name2 , ..., выполните команду Options[s, {name1 -> values1, name2 -> value2, ...}]

SetOptions[Plot,PlotStyle->Dashing[{.05,.01}]];
Options[Plot,PlotStyle]

Plot[{Sin[x],Cos[x]},{x,0,1}]

SetOptions[Plot,PlotStyle->abc];
Options[Plot,PlotStyle]
Plot[{Sin[x],Cos[x]},{x,0,1}]

Для опций, определенных в виде правил замены, имеются удобные способы их использования и изменения в пользовательских функциях. 
OptionsPattern[] используется в качестве последовательности опций определяемого выражения
OptionValue[name] -  значение (правая часть rhs) name -> rhs из списка опций OptionsPattern[]

Clear[s]
Options[s]={u->u0,v->v0};
s[x_,OptionsPattern[]]:={x,OptionValue[u],OptionValue[v]}
s[1]
s[1,u->4]
s[1,u->4,v->7]
s[1]

список OptionsPattern[s] позволяет использовать в качестве аргумента выражения f опции другого выражения s, не меняя при этом опции самого выражения f

f[x_,OptionsPattern[s]]:={x,OptionValue[u],OptionValue[v]}
Options[f]

f[1]
f[1,u->4]
f[1,u->4,v->7]
f[1]

Правила в опциях могут быть как в виде Rule (lhs -> rhs), так и в виде RuleDelayed (lhs :> rhs)

В этом примере значение опции с именем "u" равно  10 и не меняется при изменении x

x=10;
Options[s]={u->x};
s[]

x=8;
s[]

А в этом примере значение опции с именем "u" равно текущему значению выражения x

x=12;
Options[s]={u:>x};
s[]

x=9;
s[]

В этом примере значение опции с именем "u" также равно текущему значению выражения x

Clear[s]
Options[s]={u->x};
s[OptionsPattern[]]:=OptionValue[u]
s[]
s[u->1]

x=5;
s[]

x=7;
s[]

Команда Clear[s] не очищает опции для s. Чтобы очистить s полностью, вместе с  определениями (и еще некоторыми связанными с s объектами), воспользуйтесь командой ClearAll[s]

Clear[s,f]
Definition[s]

ClearAll[s]
Definition[s]

Атрибуты

Служат для задания некоторых специальных неявных свойств функций, таких как коммутативность (Orderless), ассоциативность (Flat) и др. Имеется 19 типов возможных атрибутов (см. справку)
Посмотреть атрибуты можно командой Attributes[x]

Attributes[Plus]

Задать атрибуты объекту x можно командой Attributes[x] = {attr1, attr2, ...}

ClearAll[f,x]

f[{1,2,3}]

Attributes[f]={Listable}
f[{1,2,3}]

Добавить атрибут attr к объекту x можно командой SetAttributes[x,attr]

f[f[x,y],z]

SetAttributes[f,Flat]
f[f[x,y],z]

Удалить атрибут attr из списка атрибутов объекта x можно командой ClearAttributes[x, attr]

ClearAttributes[f,Flat]
f[f[x,y],z]

f::gt="Аргумент больше или равен нулю";
f::lt="Аргумент меньше нуля";

Полный список атрибутов символов в пакете Mathematica

1) Orderless - коммутативная функция

f[x,y]==f[y,x]

SetAttributes[f,Orderless]
f[x,y]==f[y,x]

f[f[x,y],z]

2) Flat - "обобщенная" ассоциативная функция  (обобщенная в том смысле, что f[f[...[x]]] отождествлятся с f[x])

f[f[x,y],z]
f[f[f[x]]]

SetAttributes[f,Flat]
f[f[f[x]]]
f[f[x,y],z]

{f[f[a,a,a],a],f[f[f[a],f[a],f[a]],a]}

Аргумент Flat и замены

f[a,b,c,d,e]/.f[b,c,d]->x

здесь f[a, b, c, d, e] отождествляется с f[a, f[b, c, d], e] и после делается замена

f[a,b,c,d,e]/.f[b,c,d]->f[x,y]

после замены f[a, b, c, d, e] на f[a, f[x, y], e] последнее выражение отождествляется с  f[a, x, y, e]

3) OneIdentity - наличие этого атрибута приводит к тому, что f[f[...f[a]]] сопоставляется (Match) a внутри другой функции
Работает обычно совместно с атрибутом Flat

SetAttributes[f,Flat]
f[a,a,a,a]/.f[x_,x_,x_]-> g[x]

f[a,b,c,d]/.f[x_,y_,z_]-> g[z]

Attributes[f]

В предыдущем примере атрибут Flat позволяет отождествить f[a, a, a, a] как с f[f[a, a, a], a], так и с  f[f[f[a], f[a], f[a]], a]. Если нет атрибута OneIdentity, то происходит отождествление с f[f[f[a], f[a], f[a]], a], таким образом внутрення функция f[f[a], f[a], f[a]] заменяется по правилу f[x_, x_, x_] -> g[x] на g[f[a]].

SetAttributes[f,OneIdentity]
f[a,a,a,a]/.f[x_,x_,x_]-> g[x]

Теперь установлен атрибут OneIdentity, поэтому выбирается отождествление с f[f[a, a, a], a], что приводит к замене f[a, a, a] на g[a]

4) Listable - функция, примененная к списку, автоматически применяется к каждому аргументу списка

f[{1,2,3}]

SetAttributes[f,Listable]
f[{1,2,3}]

5) Constant - все производные функции равны нулю

Dt[f]

SetAttributes[f,Constant]
Dt[f]
Dt[f g]

Attributes[π]
Dt[π]

6) NumericFunction - предполагается, что функция принимает числовые значения при условии, что ее аргументы - числа

В приводимом ниже примере NumericQ[expr] дает True, если выражение expr числовое, и False в противном случае

NumericQ[f[x]]
NumericQ[f[2]]

SetAttributes[f,NumericFunction]
NumericQ[f[x]]
NumericQ[f[2]]

7) Protected - значения функции не могут изменяться

f[x_]:=(x^2)
f[2]
SetAttributes[f,Protected]

f[x_]:=(x^3)
f[2]

ClearAttributes[f,Protected];
f[x_]:=(x^3)
f[2]

8) Locked - атрибуты функции не могут изменяться до конца текущей сессии Mathematica. Использование одновременно Protected и Locked запрещает менять функцию до конца сессии.

SetAttributes[f,Locked]
ClearAttributes[f,Locked]

9) ReadProtected - определение функции скрыто

f[x_]:=(x^2)
?f

f[x_]:=(x^2)
SetAttributes[f,ReadProtected]
?f

f[x_]:= (x^3)
?f

ClearAttributes[f,ReadProtected]
?f

10) HoldFirst - первый аргумент функции не вычисляется

SetAttributes[h,HoldFirst]
h[1+1,2+2,3+3]

SetAttributes[f,HoldFirst]
f[sym_,val_]:=(sym=val^2)
x=17;
f[x,5]
x

Аргумент все-таки можно вычислить, если применить к нему функцию Evaluate

h[Evaluate[1+1],2+2,3+3]

11) HoldRest - все аргументы функции, кроме первого, не вычисляется

12) HoldAll - все аргументы функции не вычисляется

13) HoldAllComplete - все аргументы функции не вычисляется ни при каких обстоятельствах, например, даже при применении функции Evaluate

SetAttributes[h,HoldAllComplete]
h[1+1,2+2,3+3]
h[Evaluate[1+1],2+2,3+3]

14) NHoldFirst - первый аргумент функции не подвергается обработки функцией N, переводящей числа в числа в десятичной записи

SetAttributes[f,NHoldFirst]
N[f[π,E]]
N[f[3,π]]

15) NHoldRest - все аргументы функции, кроме первого, не подвергаются обработки функцией N

16) NHoldAll - все аргументы функции не подвергаются обработки функцией N

17) SequenceHold - объекты типа последовательность (Sequence) не встраиваются в функцию

h[a,Sequence[b,c]]

SetAttributes[h,SequenceHold]
h[a,Sequence[b,c]]

18) Temporary - локальная переменная уничтожается как только перестает использоваться

Module[{x},Print[x];Attributes[x]]

19) Stub - если функция явно вычисляется, автоматически вызызвается Needs

DeclarePackage["ErrorBarPlots`","ErrorListPlot"]

Теперь, если будет выполнена функция с именем ErrorListPlot, до ее вычисления будет загружен пакет ErrorBarPlots, в котором она определяется. DeclarePackage приписывает функции ErrorListPlot атрибут Stub.

Attributes["ErrorListPlot"]

ErrorListPlot[Table[{i,RandomReal[0.5]}, {i, 10}]]

ClearAll[f,h]

Сообщения

В пакете Mathematica предусмотрен механизм выведения сообщений при выполнении вычислений. Обычно это сообщения об ошибках и предупреждения. Имеется возможность приписывать сообщения любым символам.

Чтобы приписать сообщение с именем tag символу symbol, выполните команду symbol::tag = "сообщение"

f::lt="Аргумент меньше нуля"

Чтобы вывести сообщение, выполните команду Message[symbol::tag]

Message[f::lt]

Теперь в определении функции можно задать вывод сообщения при выполнении некоторых условий

f[x_]/;If[x<0,Message[f::lt];False,True]:=(Sqrt[x])

f[1]

f[-1]

В сообщение можно вставить значение выражений expr1,expr2,..., выполнив команду Message[symbol::tag, expr1,expr2,...], при этом ссылка на выражение expri внутри текста сообщения должна иметь вид  `i`

f[x_]/;If[x<0,Message[f::lt,x];False,True]:=(Sqrt[x])
f::lt="Аргумент `1` меньше нуля";
f[-2]

Отключить сообщение можно командой Off[symbol : tag]

Off[f::lt]
f[-1]

Включить сообщение можно командой On[symbol : tag]

On[f::lt]
f[-1]

Вывести список всех сообщений, приписанных символу symbol можно выполнив команду Messages[symbol]

Messages[f]

Messages[General]