Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

pmi432 / LR05 / Books / Аладьев - Основы программирования в Maple, 2006

.pdf
Скачиваний:
200
Добавлен:
18.03.2015
Размер:
3.41 Mб
Скачать

По root-процедуре, имеющей два эквивалентных формата кодирования следующего вида:

root(V, n {, symbolic})

или

root[n](V {, symbolic})

вычисляется n-й корень из алгебраического V-выражения, в качестве которого могут выступать также действительные и комплексные константы. В случае кодирования необязательного symbolic-аргумента подкоренное выражение полагается положительным и производятся определенные упрощения. В ряде случаев целесообразно по assume-процедуре налагать определенные условия на компоненты V-выражения, например:

> assume(a > 0, b > 0, y > 0): root(a + b*y + 10*y^2, 3); (a~ + b~ y~ + 10 y~2)1/3

> assume(y < 2, y >= 0): root[5](x^5*(y - 2)^4, 'symbolic');

x (2 - y~)4/5

 

x ((x2

( 1/3 )

> root[3](x^3*(x^2 + n)/(z^3 - m)^2, 'symbolic');

+ n) (z3 − m))

 

z3 − m

 

 

> map(root, [64 + 42*I, 10, 20.06, 19.47 - 59*I, gamma, Catalan], 2);

[ 64 + 42 I , 10, 4.478839135, 6.3874701304.618416900I, γ, Catalan ]

Весьма полезной при работе с символьными тригонометрическими выражениями может оказаться и trigsubs-процедура, работающая с тригонометрической таблицей (trig-таблицей) пакета, входы которой содержат известные для функции тригонометрические конструкции. По вызову процедуры trigsubs(0) возвращается множество распознаваемых процедурой тригонометрических функций. Вызов процедуры trigsubs(V) возвращает список тригонометрических выражений, эквивалентных тригонометрическому V-выражению, находящемуся в trig- таблице. При этом следует иметь в виду, что на V-выражениях, не распознаваемых процедурой trigsubs(V) в качестве входов в trig-таблицу, инициируются ошибочные ситуации, поэтому в качестве V-выражения допускаются только известные процедуре тригонометрические конструкции. При этом упрощения фактического V-аргумента не производится, что может вызывать ошибочные ситуации на очевидных выражениях. Поэтому, во избежание некорректных даже с точки зрения Maple-языка ситуаций рекомендуется использовать конструкции следующего вида trigsubs(simplify(V, 'trig')), как это хорошо иллюстрирует нижеследующий достаточно простой фрагмент:

> trigsubs(0); trigsubs(AVZ);

 

{tan, sec, sin, cos, cot, csc}

 

 

 

 

 

 

 

 

 

 

 

 

Error, (in trigsubs) unknown expression

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

> trigsubs(x*sin(x));

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Error, (in trigsubs) expecting a product of two functions but got x*sin(x)

 

 

 

 

 

> trigsubs(sin(x) + cos(x));

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Error, (in trigsubs) sum not found in table

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

> trigsubs(simplify(F(x), 'trig'));

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Error, (in trigsubs) unknown function - try trigsubs(0)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

> trigsubs(simplify(tan(x)*cos(x), 'trig'));

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

x

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2 tan

 

 

 

 

 

 

 

 

 

 

 

 

 

x

 

 

x

 

 

1

 

1

 

2

 

 

 

-1

 

 

 

 

 

 

 

 

 

 

 

 

 

( x I)

( I x )

 

 

 

 

 

 

 

 

 

 

, −

 

,

 

 

 

 

,

 

 

I (e

e

 

sin(x), −sin(−x), 2 sin

 

cos

 

,

csc(x)

csc(−x)

 

 

 

 

 

 

2

2

 

)

 

2

 

2

 

 

 

 

x

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1 + tan

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

 

 

 

 

 

 

 

 

В общем случае, trig-таблица пакета характеризуется относительно ограниченным представительством тригонометрических соотношений, что существенно снижает возможности процедуры trigsubs по обработке символьных выражений.

По вызову процедуры trigsubs(<Уравнение>), где уравнение должно быть строго тригономет- рическим, определяется факт его вхождения в trig-таблицу. В зависимости от {наличия|отсутствия} уравнения в таблице возвращается строчное значение {`found`|`not found`}. По вызову процедуры trigsubs(<Уравнение>, <Выражение>) в случае принадлежности уравнения, заданного первым аргументом функции, trig-таблице производится подстановка его в заданное вторым аргументом выражение и возвращается результат такого редактирования; в противном

131

случае выводится соответствующее диагностическое сообщение с рекомендациями. Следующий простой фрагмент иллюстрирует вышесказанное:

> trigsubs(cot(Pi + a*x));

 

 

 

 

 

 

a x

 

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

− 1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

cot

 

 

 

 

 

 

 

 

cos(a x)

 

 

1 + cos(2 a x)

 

 

 

sin(2 a x)

 

 

 

 

 

 

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

cot(a x),

−cot(−a x),

 

 

 

 

 

 

 

 

 

 

 

 

 

,

 

 

 

 

 

 

,

 

 

 

 

 

 

 

,

 

 

 

 

 

 

,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

 

a x

 

 

sin(a x)

 

 

 

 

sin(2 a x)

 

 

 

 

1 − cos(2 a x)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

cot

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

a x 2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1 − tan

 

 

 

 

 

 

 

 

a x

 

 

 

 

 

 

 

 

a x

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

, −

 

 

 

1

 

 

 

1

 

 

 

 

 

2

 

 

 

 

1

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

,

 

 

cot

 

 

 

 

 

tan

 

,

 

 

 

 

tan(a x)

tan(−a x)

2

 

 

 

 

a x

 

 

2

 

2

 

 

 

 

 

 

 

 

 

 

 

 

 

2

 

 

 

 

 

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

tan

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(e(a x I)

+ e( I a x ) ) I

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

,

 

sin(2 a x)

 

,

 

((e(a x I) )(1 + cos(2 a x)) − (e( I a x ) )(1 + cos(2 a x))) sin(2 a x)

1 − cos(2 a x)

csc(2 a x) + cot(2 a x)

> map(trigsubs, [sec(x)^2 = 1 + tan(x)^2, sin(x)^2 = 1 - cos(x)^2]); [`found`, `found`] > trigsubs(sin(2*t) = 2*cos(t)*sin(t), sin(2*t)*t + tan(t)); 2 cos(t) sin(t) t + tan(t)

> trigsubs(cos(x + y) = cos(x)*cos(y) - sin(x)*sin(y), cos(x + y)*t - 57*cos(x + y) + 2006);

Error, (in trigsubs) not found in table - use subs to over ride

Как видно из приведенного фрагмента, в случае невозможности выполнить преобразование выводится сообщение с рекомендацией воспользоваться subs-функцией.

Относительно использования eval-функции, имеющей следующий формат кодирования:

eval(<Выражение> {, n})

следует сделать отдельное пояснение. Под вычислением понимается подстановка вместо идентификатора приписанного ему значения, а каждый шаг в данном процессе определяет отдельный вычислительный уровень. По функции eval производится вычисление определенного ее первым фактическим аргументом выражения на его n-ом вычислительном уровне или пол- ное вычисление выражения, если второй аргумент отсутствует. В интерактивном режиме с пакетом при вводе выражений производится их полное вычисление, как если бы к входящим в них идентификаторам применялась eval-функция. Иная ситуация имеет место, в частности, для Maple-процедур, для которых локальные переменные вычисляются только на первом уров- не, как это иллюстрирует следующий весьма наглядный пример:

> Proc:=proc() local a, b, c; a:= b; b:= c; c:= d: a*b*c end proc: Proc(), eval(Proc()); b c d, d3

Из приведенного примера видно, что при вызове Proc-процедуры вычисление локальных переменных {a, b, c} производится на первом уровне, о чем свидетельствует возвращаемый процедурой результат. Тогда как применение к вызову процедуры eval-функции обеспечивает полное вычисление процедуры. При этом, следует иметь в виду, что для полного вычисления локальных переменных могут потребоваться достаточно длинные цепочки присвоений, требующих затрат основных ресурсов ПК.

По subs-функции можно эффективно производить модифицирующие подстановки и в процедуры либо функции, однако данный механизм действует только на подвыражения тела процедуры, не содержащие локальных переменных, как это иллюстрирует следующий достаточно простой фрагмент:

> Proc:= proc(x, y) local a, b, c; sqrt(a*x^2 + b*y^2 + c)*sin(a*x) + cos(b*y) + 2006 end proc:

132

> Proc1:= proc(x, y) global a, b, c; sqrt(a*x^2 + b*y^2 + c)*sin(a*x) + cos(b*y) + 2006 end proc:

> subs([a=Pi, b=sigma, c=gamma], Proc1(x, y));

 

π x2 + σ y2 + γ sin(x π) + cos(σ y) + 2006

> subs([a=Pi, b=sigma, c=gamma], Proc(x, y));

 

a x2 + b y2 + c sin(a x) + cos(b y) + 2006

> subs([a=sin(z), b=x*Pi], (x, y) -> sqrt(a*x + b*y) + a*b); (x, y) sin(z) x + x π y + sin(z) x π

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

компонент идентификаторы при определении процедур следует указывать глобальными.

По вызову процедуры applyrule(R, V) обеспечивается применение к V-выражению правил подстановки, определяемых ее первым фактическим R-аргументом (одно правило либо их список) до тех пор, пока они допустимы. При этом, правила подстановки можно определять как уравнениями, так и в форме сложных шаблонов, допускаемых patmatch-процедурой. Процедура applyrule эффективнее средств {subs, algsubs}, но подобно algsubs-процедуре не производит математических преобразований обрабатываемого выражения, требуя для этих целей eval-функции. Следующий фрагмент иллюстрирует применение applyrule-процедуры для преобразования выражений:

> algsubs(x*h(x)=a*x, x*h(x));

Error, (in algsubs) cannot compute degree of pattern in x

> applyrule(x*h(x) = a*x^2 + b*x^2, x*h(x) + b*(d + x*h(x))); a x2 + b x2 + b (d + a x2 + b x2 ) > applyrule((a::float*x + b::integer*y)/c::function = Avz(h), (10.17*x + 64*y)/sin(x)); Avz(h)

> applyrule((a::float*x + b::integer*y)/c::function = 4, sqrt((10.17*x + 64*y)/G(x)));

4

> applyrule([a=b, b=c, c=d, d=e, e=f, f=g, g=h], sqrt(Art^a+Kr^b+V*c));

 

Arth + Krh + V h

> T:= function: applyrule([a=b, b=a], a);

Прерванный бесконечный цикл

 

Warning, computation interrupted

 

 

 

 

> applyrule([a^2 + b^2 = Art + Kr, c::function = W(t)], sqrt(a^2+b^2)*G(x));

 

Art + Kr W(t )

> applyrule([a::T^b::T = Art(x), c::T/d::T = Kr(t)], S(x)^G(y) + V(x)/H(y));

Art(x) + Kr(t)

Для исключения зацикливаний, следует уделять особое внимание определению правил подстановок. Один из примеров фрагмента иллюстрирует простую ситуацию по зацикливанию вызова applyrule-процедуры. Вместе с тем совместное использование средств subs, applyrule, asubs, powsubs и algsubs в сочетании с рядом других функциональных средств позволяют достаточно эффективно производить весьма интересные и важные символьные преобразования различного типа выражений.

Функциональные конструкции Maple-языка. Под функцией в Maple-языке понимается невы- числяемая конструкция следующего общего вида:

<Идентификатор>(<Последовательность формальных аргументов>)

где идентификатор определяет уникальное имя функции, а последовательность допустимых Maple-выражений - список ее формальных аргументов. Примерами функций являются: exp(x), sin(x), sqrt(x), AGN(x, y, z) и др. Maple-язык в качестве функций понимает любую из конструкций указанного типа, независимо от того, является ли она определенной. Рассмотренная выше функция type(<Выражение>, function) тестирует произвольное Maple-выражение на предмет отношения его к типу функция”. Как видно уже из следующего простого примера

> map(type, [F(x,y,z), sin(x), H(x, G(y), z)], 'function'); [true, true, true]

к данному (функциональному) типу Maple-язык относит как процедуру sin, так и неопределен- ную в его среде конструкцию, указанного вида. Наряду с этим, тестирующая type-функция позволяет идентифицировать не только собственно функциональный тип выражения, указанного ее первым фактическим аргументом, но и детализировать математический тип выра- жения-функции согласно значению ее второго фактического аргумента, а именно:

133

algfun алгебраическая функция; допускается тестировать по типу коэффициентов и ведущим переменным;

{arctrig|arctrigh} – обратная {тригонометрическая|гиперболическая} функция; допускается тестирование по ведущим переменным;

{evenfunc|oddfunc} – {четная|нечетная} функция; допускается тестировать по ведущим переменным;

radalgfun алгебраическая функция, определенная в терминах RootOf и радикалов; допускается тестирование по ведущим переменным и типам коэффициентов;

radfunextn – алгебраическое функциональное расширение в терминах радикалов;

radfun радикальная функция; допускается тестирование по ведущим переменным и типам коэффициентов;

mathfunc математическая функция; тестируется любая функция из приложения 8 [12]; {trig|trigh} – {тригонометрическая|гиперболическая} функция; допускается тестирование по ведущим переменным.

При этом, алгебраическим полагается Maple-выражение одного из следующих типов:

integer fraction float string indexed `+` `*` `^` `**` series function `!` `.` uneval

а под ведущей xj-переменной произвольной F(x1, ..., xn)-функции такая переменная, на которой имеет место следующее определяющее соотношение:

( x`j)( x``j)(x`jx``j F(x1, ..., x`j , ..., xn) F(x1, ..., x``j ,..., xn)) (j = 1 .. n)

Следующий фрагмент иллюстрирует применение данных значений в качестве 2-го аргумента type-функции для тестирования типов функций, указанных ее 1-м аргументом:

> G:= 64*y*z + 10*RootOf(x^5 – y + 59*y - 99*x^3/y, x):

 

> [type(G, algfun(rational)), type(G, algfun(rational, z))];

[true, false]

> S:= arcsin(x*y): [type(S, arctrig(x)), type(S, arctrig(y))];

[true, true]

> [type(sin(x)*cos(y) ,oddfunc(x)), type(sin(x)*cos(y), oddfunc(y))]; [true, false]

> type((64^(1/5)*z^3 + 10*sqrt(x))^(1/6), 'radfunext');

true

> typematch(GS(x, y, z, Art(h), Kr(t)), function, 't');

true

> map(type, [WeierstrassSigma, InverseJacobiSD, MeijerG], 'mathfunc'); [true, true, true]

Как следует из последнего примера фрагмента, для тестирования математических функций указываются только их идентификаторы. Наряду с рассмотренными выше возможностями {type|typematch}-функции по тестированию Maple-выражений, частным случаем которых является функция, представленные здесь новые возможности позволяют проводить достаточно детальную (насколько это вообще на сегодня возможно) апробацию как функционального типа выражений, так и математического типа собственно самих тестируемых функций.

В качестве весьма полезной тестирующей представляется также и процедура:

hasfun(<Выражение>, <IdF> {, <Ведущая переменная>})

позволяющая определять факт вхождения (true) в заданное первым аргументом выражение функции (или функций в случае их списка/множества), заданной вторым IdF-аргументом, возможно, по ведущей (ведущим в случае их списка/множества) переменным, заданным ее необязательным третьим аргументом, например:

> G:=(L(x) + AG(x+y)/Art(z) + Kr(t))/(V(x) + W(y)): hasfun(G, [W, AG, Art, Kr], {y, z, t}); true

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

Функциональная структура анализируется рассмотренными выше функциями op и nops, возвращающими результаты согласно следующим соотношениям:

nops(F(x1, ..., xn))

n

op(F(x1, ..., xn))

x1, ..., xn

op(0, F(x1, ..., xn))

F

op(k, F(x1, ..., xn))

xk

(k > 0)

134

Следующий простой фрагмент иллюстрирует вышесказанное:

> [op(0, G(x,y,z,h))], [op(G(x, y, z, h))], [nops(G(x, y, z, h))]; [G], [x, y, z, h], [4] > [op(k, G(x, y, z, h))]$'k' = 0 .. nops(G(x, y, z, h)); [G], [x], [y], [z], [h]

При решении целого ряда математическиих задач определенный интерес представляет тип arity, отсутствующий в Maple релизов 6-10. Вызов процедуры type(F, arity(n)) [103] возвращает true-значение, если F является функцией либо процедурой n-арности; в противном случае возвращается false-значение. Более того, через глобальную переменную 'n-arity' возвращается реальная арность произвольной функции/процедуры F, например:

> F:= f(x1, x2, x3, x4, x5, x6): G:= g(x): S:= s(x1, x2, x3, x4, x5, x6): V:=v(a, b, c, d, e, f, h):

> Art:= proc(x, y, z) [y, x, z] end proc: Kr:= proc(a, b, c, d, e, h) {a, b, c, d, e, h} end proc: > seq([type(k, arity(6)), `n-arity`], k = [F, G, S, V, Art, Kr]);

[true, 6], [false, 1], [true, 6], [false, 7], [false, 3], [true, 6]

Идентификаторы пакетных функций имеют protected-атрибут, защищающий их от модификации со стороны пользователя; для обеспечения подобной защиты пользовательских функций/процедур следует использовать protect-процедуру, рассмотренную выше, либо следующие две функции, обладающие более широкими возможностями, а именно:

attributes(B) тестирование наличия и типа атрибутов у В-выражения; setattribute({B, A|B}) присвоение A-атрибутов В-выражению либо их отмена.

где в качестве В-выражения допускаются: идентификаторы, списки, множества, невычисляемые

вызовы функций либо float-значения, тогда как А-атрибутом может быть любое корректное Maple-выражение либо их последовательность, определяющая набор атрибутов для В-выра- жения. По attributes-функции возвращается последовательность приписанных В-выражению атрибутов либо NULL-значение при их отсутствии. Тогда как по setattrubute-функции либо приписываются А-атрибуты В-выражению, либо отменяются приписанные ему при отсутствии у функции второго аргумента. Приписанные В-выражению атрибуты переносятся и на объект W (W:= B;), которому оно присваивается; при этом отмена атрибутов для одного из этих объектов автоматически отменяет их и для другого. Следует иметь в виду, что по предложению restart отменяются все атрибуты, приписанные выражениям в текущем сеансе. Следующий фрагмент иллюстрирует использование механизма атрибутов:

> [attributes(sin), protect(GS), attributes(GS)]; [protected, _syslib, protected] > Vasco = H(x, y): setattribute('Vasco', protected, 'float'); Vasco

> attributes('Vasco'); protected, float

 

> W:= Vasco: attributes(W); protected, float

 

> setattribute(W): [attributes(W), attributes(Vasco)]; []

(пустой список атрибутов)

> [setattribute(V, 64), setattribute(G, 59)]; [V, G]

 

> [attributes(V), attributes(G)]; [64, 59]

 

> setattribute('Vasco', 'protected', 'float'): restart;

 

> [attributes(V), attributes(G), attributes(Vasco)]; []

(пустой список атрибутов)

Механизм атрибутов позволяет не только проводить пакетную их обработку, например по распознаваемому ядром protected-атрибуту, но и пользователь имеет возможность организовывать достаточно интересные условные обработки выражений на основе приписанных им атрибутов, пример чему может дать следующий весьма простой пример:

> V:= 64: setattribute('V', 'integer'): [V, attributes('V')]; [64, integer] > V:= `if`(attributes('V') <> 'integer', 1995, 2006): V; 2006

Вместе с тем следует отметить, что аналогичный механизм атрибутов, поддерживаемый пакетом Mathematica [6,7], представляется нам существенно более развитым.

Функциональный идентификатор может использоваться в алгебраических скобочных конструкциях в сочетании с @-оператором, определяющим композицию функций, образуя новые

135

функциональные выражения. Следующие достаточно прозрачные функциональные правила поддерживаются Maple-языком, а именно:

> (S + G)(x, y, z), (S - G)(x, y, z),

(-G)(x, y, z), (S@G)(x, y, z);

S(x,y,z) + G(x,y,z), S(x,y,z) - G(x,y,z), -G(x,y,z), S(G(x,y,z))

> (S@G)(x, y, z), (G@@5)(x, y, z);

S(G(x,y,z)), (G(5))(x,y,z)

>expand(%[2]); G(G(G(G(G(x, y, z)))))

>(S + G)(x[k]$k=1 .. n), (S@G)(x[k]$k=1 .. n);

S(xk $ (k = 1 .. n )) + G(xk $ (k = 1 .. n)), S(G(xk $ (k = 1 .. n)))

> (10*G@S@@2 + 17*S^2@G - S@G@H)(x, y, z)/(G@S@V@@2 - M^3@V + A@N@O)(x, y, z);

10 G((S(2 ) )(x, y, z)) + 17 S(G(x, y, z))2 S(G(H(x, y, z)))

G(S((V( 2 ) )(x, y, z))) M(V(x, y, z))3 + A(N(O(x, y, z)))

> (sqrt@cos^2@ln + H@exp - G@(sin + cos)/(Art + Kr))(x);

cos(ln(x))2 + H(ex )

G(sin(x) + cos(x))

Art(x) + Kr(x)

 

где “@@n” обозначает n-кратную композицию функции, определяемую соотношением:

(G@@n)(...) = G(n)(...) = G(G(G...G(...)...))

иллюстрируемым примерами предыдущего фрагмента. В терминах @-оператора для функции seq имеют место (в ряде случаев весьма полезные) соотношения:

seq(A(k), k =[B(x)]) seq(A(k), k ={B(x)}) (A@B)(x) A(B(x)) seq(A(k), k =x) seq(A(k), k =B(x)) A(x)

Активные и пассивные формы функций. Наряду с вычисляемыми в указанном выше смысле функциями, идентификаторы которых начинаются со строчных букв, Maple-язык располагает т.н. пассивными (inert) функциями (операторами), идентификаторы которых начинаются с заглавной буквы. Maple-язык различает более 50 таких пассивных функций/процедур (Diff, Int, Limit, Sum, Produc, Normal и др.), суть которых нетрудно усмотривается из самого их названия. В общем случае Maple-язык рассматривает идентификаторы видов Abb...b и abb...b

(b - любой допустимый для имени символ) как имена соответственно пассивной и вычисляемой

функции/процедуры одного и того же назначения. Пассивные функции/процедуры имеют два основных назначения: (1) для символьных вычислений и преобразований и (2) для вывода в Maple-документах конструкций в математической нотации. Для вычисления пассивных функций/процедур и выражений в целом служит процедура value(Выражение), например:

> Int(sqrt((1 + x)/(1 - y)), x); simplify(value(%));

 

1

+ x

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

dx

 

 

 

 

 

 

 

1

y

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1 + x

 

 

 

 

 

 

2 (1 + x)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

y 1

 

 

 

 

 

 

 

3

 

 

 

 

 

 

 

 

 

 

 

 

10

 

 

 

 

 

 

 

 

 

> Product((1 + x)^k, k = 1 .. 10); value(%);

(1 + x)k

 

 

 

 

 

 

k = 1

 

 

 

 

 

 

 

 

 

 

(1 + x)55

 

 

 

 

 

 

 

 

> Limit((1 + 1/j)^j, j = infinity); value(%);

 

 

 

+

 

1

 

j

e

lim

1

 

 

 

 

 

 

 

 

 

 

 

 

j → ∞

 

 

 

j

 

 

> Sum(k^4*ithprime(k), k=1..17)/Product(ithprime(k), k=1..10); value(%);

17

 

 

 

k4 ithprime(k)

 

2568338

 

k = 1

 

1078282205

10

ithprime(k)

 

 

 

k = 1

 

 

 

136

Активная функция/процедура, начинающаяся со строчного символа, инициирует немедлен- ное вычисление результата, тогда как пассивная функция/процедура, начинающаяся с пропи- сного символа, возвращает невычисленный результат в стандартной математической нотации, для окончательного вычисления которого требуется применение value-процедуры. При этом следует отметить, что value-процедура может быть распространена и на случай пользовательских функций. В случае невозможности вычислить выражение функция возвращает его в исходном виде. Многие из пассивных функций/процедур Maple-языка широко используются в конъюнкции с evala-процедурой и операторами mod, modp1 модульной арифметики.

Пассивные функции/процедуры тестируются и нашей процедурой ParProc [103], как это иллюстрирует следующий весьма простой фрагмент:

>map(ParProc, [Int, Diff, Product, Sum, Limit, Normal]);

Warning, <Int> is inert version of procedure/function <int> Warning, <Diff> is inert version of procedure/function <diff> Warning, <Product> is inert version of procedure/function <product> Warning, <Sum> is inert version of procedure/function <sum> Warning, <Limit> is inert version of procedure/function <limit> Warning, <Normal> is inert version of procedure/function <normal>

[inert_function, inert_function, inert_function, inert_function, inert_function, inert_function]

>ParProc(AVZ); ParProc(avz); ParProc(Avz); ParProc(Mkdir);

Error, (in ParProc) <AVZ> is not a procedure and not a module

Error, (in ParProc) <avz> is not a procedure and not a module

Error, (in ParProc) <Avz> is not a procedure and not a module

Error, (in unknown) <Mkdir> is not a procedure and not a module

По установке infolevel[<Функция>]:=n (n=1..3) можно определять уровень протокола выполнения указанной функции, а по infolevel[<Функция>, _debug]:=3 установке определять уровень вывода отладочной информации. По умолчанию infolevel-таблица пакета содержит только один вход hints = 1 {print(infolevel); TABLE([hints = 1])}, определяя вывод ошибочных и предупреждающих сообщений. По приведенным установкам для указанной функции в таблице infolevel определяется соответствующий вход, обеспечивающий необходимый уровень мониторинга выполнения функции, например:

> infolevel[int]:= 3: int(sqrt((1 + x^2)/(1 - x^2)), x); int/indef1: first-stage indefinite integration int/indef1: first-stage indefinite integration int/indef1: first-stage indefinite integration int/algebraic2/algebraic: algebraic integration int/indef1: first-stage indefinite integration int/indef1: first-stage indefinite integration int/indef1: first-stage indefinite integration int/algebraic2/algebraic: algebraic integration int/elliptic: trying elliptic integration int/ellalg/ellindefinite: indefinite elliptic integration

3

_X

2

_X 1

_X

 

 

 

 

 

 

 

 

d_X

 

 

 

 

 

 

 

1

_X4

 

 

 

 

 

int/ellalg/ellindefinite: Step 2 -- partial fraction decomposition of 0 giving

 

 

0 d_X = 0 d_X

 

int/ellalg/ellindefinite: Step 3

-- Hermite Reduction.

int/ellalg/ellindefinite: Step 4

-- Symbolic partial fraction reduction to Hj1's.

int/ellalg/ellindefinite: Step 5

-- Reduction of polynomial part to I0, I1, I2.

137

int/ellalg/ellindefinite: result of indefinite elliptic integration 1/2*(1-_X^4)^(1/2)-(1-_X^2)^ (1/2)*(1+_X^2)^(1/2)/(1-_X^4)^(1/2)*EllipticF(_X,I)+1/2*I*ln(I*_X^2+(1-_X^4)^(1/2))+(1-_X^2)^ (1/2)*(1+_X^2)^(1/2)/(1-_X^4)^(1/2)*(EllipticF(_X,I)-EllipticE(_X, I))

int/indef1: first-stage indefinite integration

 

 

 

int/indef1: first-stage indefinite integration

 

 

 

int/algebraic2/algebraic: algebraic integration

 

 

 

int/elliptic: trying elliptic integration

 

 

 

 

 

int/ellalg/ellindefinite:

indefinite elliptic integration

 

3

+ _X

2

− _X + 1

 

−_X

 

 

 

 

 

 

 

 

 

d_X

 

 

 

 

 

 

 

 

 

1 − _X4

 

 

 

 

 

 

int/ellalg/ellindefinite:

Step 2 -- partial fraction decomposition of 0 giving

 

 

 

 

 

 

0 d_X

= 0 d_X

 

 

 

 

int/ellalg/ellindefinite: Step 3 -- Hermite Reduction.

int/ellalg/ellindefinite: Step 4 -- Symbolic partial fraction reduction to Hj1's.

int/ellalg/ellindefinite: Step 5 -- Reduction of polynomial part to I0, I1, I2.

int/ellalg/ellindefinite:

result of indefinite elliptic integration 1/2*(1-_X^4)^(1/2)+(1-_X^2)^

(1/2)*(1+_X^2)^(1/2)/(1-_X^4)^(1/2)*EllipticF(_X,I)+1/2*I*ln(I*_X^2+(1-_X^4)^(1/2))-(1-_X^2)^ (1/2)*(1+_X^2)^(1/2)/(1-_X^4)^(1/2)*(EllipticF(_X,I)-EllipticE(_X,I))

 

1 + x2

(1 + x2 ) 1 x2

1 + x2 EllipticE(x, I )

1

+ x2

 

 

 

 

 

 

(1 + x2 ) (1 + x2 ) 1 x4

 

 

 

 

> infolevel[simplify]:= 3: simplify(%%);

 

 

simplify/do:

applying simplify/sqrt function to expression

simplify/do:

applying commonpow function to expression

simplify/do:

applying power function to expression

 

 

 

EllipticE(x, I ) 1 x2

1 + x2

 

1 + x2

 

 

 

1+ x2

>infolevel[dsolve]:= 3: dsolve(diff(y(x), x$3) - y(x) + sin(x)*cos(x)^2);

Methods for third order ODEs:

--- Trying classification methods ---

trying a quadrature

trying high order exact linear fully integrable

trying differential order: 3; linear nonhomogeneous with symmetry [0,1] trying high order linear exact nonhomogeneous

trying linear constant coefficient

checking if the LODE has constant coefficients

<- constant coefficients successful

y(x) =

 

1

 

sin(3 x) −

27

 

cos(3 x) +

1

 

sin(x) −

1

cos(x) + _C1 ex

2920

 

 

8

 

 

 

 

 

 

 

 

 

2920

 

 

 

 

 

 

8

 

 

 

 

 

 

 

x

 

 

 

 

 

 

 

x

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3 x

 

 

 

 

 

 

3 x

 

 

 

 

 

 

 

2

 

 

 

2

+

_C2 e

 

 

 

 

sin

 

 

 

+ _C3 e

 

 

 

 

 

cos

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

> eval(infolevel); table([dsolve = 3, int = 3, simplify = 3, hints = 1])

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

Преобразования математических функций. Различного рода преобразования выражений составляют один из краеугольных камней многих разделов современных математических дис-

138

циплин и в этом отношении пакет Maple обеспечивает пользователя достаточно развитыми средствами, в большинстве своем рассматриваемыми на протяжении книги. Здесь мы представим основные средства Maple-языка по преобразованию известных пакету математических функций, играющему чрезвычайно важную роль, прежде всего, в прикладной математике и ряде физических дисциплин, имеющих важные физико-технические приложения [8-14].

Для целей преобразования математических функций (известных ядру пакета) из одного типа в другой служит многоаспектная convert-функция, рассмотренная в разделе 1.7. Здесь мы акцентируем наше внимание на ее возможностях по конвертации одного типа математических функций в другой. В данном случае convert-функция имеет формат кодирования вида:

convert(<Выражение>, <Тип функции>)

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

*Bessel{ |I|J|K|Y} - преобразование волновых Айри-функций в функции Бесселя указанного типа либо функций Бесселя одного типа в функции Бесселя другого типа;

*Hankel - преобразование волновых Айри-функций и/или функций Бесселя в функции Ханкеля. В обоих случаях преобразованию подвергаются как собственно сами функции Айри и Бесселя, так и их производные. Простейший случай Bessel-аргумента всегда возвращает результат, тогда как в остальных случаях возможно возвращение невычисленного выражения, т. е. выражения в его исходном виде;

*binomial - преобразование GAMMA-функций и факториалов в биномиалы;

*erf - преобразование дополнительной erfc-функции ошибок, ее итеративных интегралов и интегралов Доусона в основную erf-функцию ошибок;

*erfc - преобразование основной erf-функции ошибок в ее erfc-дополнительную;

*GAMMA - преобразование факториальных и биномиальных функций в GAMMA-функцию; при этом, кодирование необязательного третьего вргумента convert-функции позволяет определять ведущие переменные, по которым производится преобразование;

*StandartFunctions - преобразование функций Мейера и гипергеометрических в стандартные специальные и элементарные функции согласно классификации [12] (ссылка [65]).

Прежде чем представить следующий тип преобразования, представим средство Maple-языка по заданию в его среде кусочно-определенных функций, играющих чрезвычайно важную роль во многих прикладных областях математики. Для этой цели Maple-язык располагает функцией piecewise, имеющей следующий формат кодирования:

piecewise(<ЛУ_1>, <В1>, <ЛУ_2>, <В2>, ..., <ЛУ_n>, <Вn> {, <Z>, <Вf>})

сущность которого соответствует условной конструкции (в терминах if_then_else-конструк- ций) следующего весьма прозрачного вида:

if <ЛУ_1> then <В1> else if <ЛУ_2> then <В2> else ... if <ЛУ_n> then <Вn> else <Вf>

По умолчанию значение Вf полагается нулевым; в качестве логических условий (ЛУ) могут выступать отношения либо булевы выражения из неравенств. Тогда как в случае Z-выражения, отличного от условного, оно помещается в возвращаемом результате в качестве условия типа иначе(otherwise), как это иллюстрирует пример задания кусочно-определенной функции:

> R:=piecewise(x <= 0, x*a^x, (x>0) and (x<=59 ), x*log(x), (x > 59) and (x <= 64), x*exp(x), exp(x)*

 

 

 

x ax

x ≤ 0

 

 

 

 

 

 

cos(x) + sqrt(Art + Kr));

 

 

x ln(x)

x < 0 and 59 + x 0

 

 

 

R :=

 

 

x

 

 

 

 

 

 

 

 

 

x e

 

x < -59 and x 64 0

 

 

 

 

 

 

 

 

 

 

 

 

x

cos(x) + Art + Kr

otherwise

 

e

 

> convert(R, Heaviside);

139

x ax - x ax Heaviside(x) + x ln(x) Heaviside(x) - x ln(x) Heaviside(-59 + x) + x ex Heaviside(-59 + x) - x ex Heaviside(x - 64) + Heaviside(x - 64) ex cos(x) + Heaviside(x - 64) (Art + Kr)^(1/2)

По convert-функции предоставляется возможность преобразования кусочно-определенных функций в функции Хэвисайда и наоборот; тогда как функции abs, sign и signum-процеду- ру можно преобразовывать в функции Хэвисайда и кусочно-определенные функции.

*Heaviside - преобразование кусочно-определенной функции, а также функций sign, abs и процедуры signum в функцию Хэвисайда;

*piecewise - преобразование функций sign, abs, процедуры signum и функции Хэвисайда в кусочно-определенные функции (см. прилож. 1 [12]); однако, уже csgn-процедура определения знака для действительных и комплексных чисел не преобразуется ни в функцию Хэвисайда, ни в кусочно-определенную, хотя именно таковой и является;

*hypergeom - преобразование любого суммирования по процедурам sum и Sum в гипергеометрические функции, однако Maple не гарантирует их сходимости.

Следующий фрагмент иллюстрирует использование представленных средств convert-функ- ции для преобразования математических функций из одного вида в другой:

> convert(3*Pi*x^3*AiryAi(x) + y*BesselY(x^2, 1), 'BesselK');

3 π x3 AiryAi(x) + y BesselY(x2, 1)

> convert(2*BesselK(2*x^2, 1) + BesselJ(x^2, 1), 'Hankel');

π e( x2 π I) HankelH1(2 x2, I ) I + 12 HankelH1(x2, 1) + 12 HankelH2(x2, 1)

> convert(GAMMA(k + 3/2)/(k!*sqrt(Pi)*GAMMA(k + 10)), 'binomial');

 

 

1

 

 

binomial k +

 

, k

 

 

1

 

2

 

2Γ(k + 10)

>simplify(convert(sqrt(x^2 + erfc(x))/dawson(x)*sqrt(Pi), 'erf'));

2

2 I x2 + 1 erf(x) e( x )

> convert(sqrt(x^2 + erf(x) - 1)/erf(x), 'erfc');

x2 erfc(x)

1erfc(x)

>convert((x! + y! + z!)/(m! + (m - n)!/m!), GAMMA, {x, y, m, n});

Γ(x + 1) + Γ(y + 1) + z!

Γ(m + 1) + Γ(m n + 1)

Γ(m + 1)

> simplify(convert(abs(x) + sign(y)*z + signum(z)*y, 'Heaviside'));

-x + 2 x Heaviside(x) + z - y + 2 y Heaviside(z)

> R:= piecewise(g <= 42,64, (g <= 47) and (g > 42),59, (g <= 67) and (g > 47), 39, 2006);

 

64

g 42

 

59

g 47 0 and g < -42

 

 

 

 

R :=

39

g 67 0 and g < -47

 

 

 

 

 

 

otherwise

2006

> convert(R, 'Heaviside');

64- 5 Heaviside(-42+g) - 20 Heaviside(g-47) + 1967 Heaviside(g-67)

>convert(%, 'piecewise');

 

64

 

 

 

 

undefined

 

59

 

 

 

 

 

 

 

undefined

 

 

 

39

 

 

 

 

 

undefined

 

2006

 

g < 42 g = 42 g < 47 g = 47 g < 67 g = 67 67 < g

> convert(Heaviside(t), 'piecewise');

140

Соседние файлы в папке Books