Смекни!
smekni.com

Программирование и разработка приложений в Maple (стр. 15 из 135)

> assume(x, 'odd', y::integer, z >= 0), is(x + y, 'integer'); ⇒ true

> x:= 'x': unassign('y'), map(is, [x, y], 'integer'), is(z, 'nonnegative'); ⇒ [false, false], true

До 7-го релиза включительно оперативно переопределять режим идентификации переменных assume можно было переключателями функции Assumed Variables группы Options GUI.

По тестирующей процедуре is(x, Свойство) возвращается true-значение, если х-переменная обладает указанным вторым фактическим аргументом свойством, и значение false в противном случае. При невозможности идентифицировать для х-переменной свойство (например, если она по assume-процедуре свойствами не наделялась) возвращается FAIL-значение. Наконец, отменять приписанные х-переменной свойства можно посредством выполнения простой конструкции x:= 'x' либо вызовом процедуры unassign('x'); сказанное иллюстрируют последние примеры предыдущего фрагмента. При этом, проверять можно как конкретную отдельную переменную, так и выражение по нескольким ведущим переменным и набору искомых свойств.

Maple-язык поддерживает работу со свойствами шести основных групп, а именно:

1) имя свойства, например, continuous, unary;

2) большинство имен типов, например, integer, float, odd, even;

3) числовые диапазоны, например, RealRange(a, b), RealRange(-infinity, b),

RealRange( a, infinity), где a и b могут быть или числовыми значениями или Open(a), где a – числовое значение

4) AndProp(a, b, ...) – and-выражение свойств <a and b and ...>, где a, b, ... – свойства, оп- ределенные выше

5) OrProp(a, b, ...) – or-выражение свойств, где объект может удовлетворять любому из a, b, ... свойств

6) диапазон свойств p1 .. p2, где p1 и p2 - свойства. Данное свойство означает, что объект удовлетворяет по меньшей мере p2, но не более, чем p1; например, integer .. rational удовлетворяется integers/2.

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

Механизм свойств, определяемый процедурой assume и сопутствующей ей группой процедур coulditbe, additionally, is, about, hasassumptions и addproperty, использует специальную глобальную _EnvTry-переменную для определения режима как идентификации у переменных приписанных им свойств, так и их обработки. При этом, данная переменная допускает только два значения: normal (по умолчанию) и hard, из которых указание второго значения может потребовать при вычислениях существенных временных затрат. В текущих реализациях пакета значение глобальной _EnvTry-переменной, определяющей режим обработки переменных, наделенных assume-свойствами, не определено, что иллюстрирует следующий достаточно прозрачный фрагмент:

> _EnvTry, about(_EnvTry); ⇒ _EnvTry

_EnvTry: nothing known about this object

> assume(V >= 64): about(V);

Originally V, renamed V~: is assumed to be: RealRange(64, infinity)

> `if`(is(V, RealRange(64, infinity)), ln(V) + 42, sqrt(Art + Kr)); ⇒ ln(V~) + 42 > assume(47 <= G, G <= 59): about(G);

Originally G, renamed G~: is assumed to be: RealRange(47, 59)

> `if`(is(G, RealRange(47, 59)), [10, 17, Sv, Art, Kr], Family(x, y, z)); ⇒ [10, 17, Sv, Art, Kr]

> assume(x >= 0), simplify(sqrt(x^2)), simplify(sqrt(y^2)); ⇒ x~, csgn(y) y

> sqrt(a*b), sqrt(a^2), assume(a >= 0, b <= 0), sqrt(a*b), sqrt(a^2); ⇒ a b, a2, −a~ b~ I a~,

Механизм приписанных свойств является достаточно развитым и мощным средством как числовых вычислений, так и символьных вычислений и преобразований. Использование его оказывается весьма эффективным при программировании целого ряда важных задач во многих приложениях. Последние примеры предыдущего фрагмента иллюстрируют некоторые простые элементы его использования в конкретном программировании. Тогда как конкретный assume-механизм базируется на алгоритмах Т. Вейбеля и Г. Гоннета. С интересным обсуждением принципов его применения, реализации и ограничений можно довольно детально ознакомиться в интересных работах указанных авторов, цитируемых в конце справки по пакету (см. ?assume), и цитируемых в них многочисленных источниках различного назначения.

В ряде случаев требуется выполнить обмен значениями между переменными. Например, переменные х, у и z, имеющие значения 64, 59 и 39 должны получить значения 39, 59 и 64 соответственно. Следующая процедура varsort решает данную задачу.

varsort := proc() local a b c d k, , , , ; `if`(nargs = 0, RETURN( ), assign(c = [ ])); d := proc(x y, ) try if evalf( )x < evalf( )y then true else false end if catch : `if`(map(type, {x, y}, 'symbol') = {true}, lexorder(x, y), true) end try

end proc ;

a := [seq `if` type(( ( args[ ]k , 'boolproc'), assign(' 'b = args[ ]k ), `if`(type(args[ ]k , 'symbol'), op(args[ ]k , assign(' 'c = [op( )c , k])), NULL)), k = 1 .. nargs)];

a := sort(a, `if`(type(b, 'boolproc'), ,b d)); for k to nops(a) do assign(args[c k[ ]] = a k[ ]) end do

end proc

> x:=64: y:=59: z:=39: m:=vsv: n:=avz: p:=agn: varsort('x', 'z', 'y', 'm', 'p', 'n'), x, y, z, m, n, p;

39, 64, 59, agn, vsv, avz

> x:=64: y:=59: z:=39: m:=vsv: n:=avz: p:=agn: varsort('x', 'y', 'z', 'm', 'n', 'n'), x, y, z, m, n, p;

39, 59, 64, avz, vsv, agn

Вызов varsort('x', 'y', 'z', …) возвращает NULL-значение, обеспечивая обмен значениями между переменными x, y, z, … в порядке возрастания. Подробнее с возможностями данной процедуры можно ознакомиться в [41-43,103,109].

1.4. Типы числовых и символьных данных Mapleязыка пакета

Средства Maple-языка поддерживают работу как с простыми, так и сложными типами данных числового или символьного (алгебраического) характера. В первую очередь рассмотрим типы простых данных числового характера, предварив краткой информацией по очень важным встроенным функциям nops и op, непосредственно связанных со структурной организацией Maple-выражений. Первая функция возвращает число операндов выражения, заданного ее единственным фактическим аргументом. Тогда как вторая имеет более сложный формат кодирования следующего вида: op({ |n,|n..m,|<Список>,} <Выражение>)

где первый необязательный фактический аргумент определяет возврат соответственно: n-го операнда, с n-го по m-й операнды или операнды согласно Списка их позиций в порядке возрастания уровней вложенности Выражения. При этом, при n = 0 возвращается тип самого выражения, а в случае отсутствия указанного первым аргументом операнда инициируется ошибочная ситуация. Для случая n<0 выполняется соотношение op(n,V) ≡ op(nops(V) + n + 1, V), где V – выражение, а для неопределенного Id-идентификатора имеют место соотношения: op(0, Id) ⇒ symbol и op(1, Id) ⇒ Id. Отсутствие первого аргумента op-функции аналогично вызову вида op(1 .. nops(V), V). Для вывода структурной организации произвольного выражения может оказаться полезной конструкция вида: op('k', <Выражение>) $'k'=0 .. nops(<Выражение>)

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

> Art:= 3*sin(x) + 10*cos(y)/AV + sqrt(AG^2 + AS^2)*TRG: op('k', Art)$'k'=0 .. nops(Art);

10 cos(y) 2 + AS2 TRG

+, 3 sin( )x , , AG

AV

Ниже будет рассмотрено достаточно средств Maple-языка, ориентированных на задачи символьной обработки выражений, включая и те, которые базируются на их структурном ана-изе. Целый ряд средств для решения подобных задач предоставляет и наша Библиотека [103]. Нам же для дальнейшего будет пока вполне достаточно информации по встроенным функциям nops и op пакета.

Целые (integer); представляют собой цепочки из одной или более цифр, максимальная длина которых определяется используемой платформой ЭВМ: так для 32-битной она не превышает 524280 цифр, а для 64-битной – 38654705646 цифр. Целые могут быть со знаком и без: 1999, -57, 140642. На числах данного типа функции op и nops возвращают соответственно значение числа и значение 1, тогда как функция type идентифицирует их тип как integer, например:

> op(429957123456789), nops(429957123456789); ⇒ 429957123456789, 1

> type(429957123456789, 'integer'); ⇒ true

Действительные (float) с плавающей точкой; представляют собой цепочки из десятичных цифр с десятичной точкой в {начале|середине|конце} цепочки; числа данного типа допускают следующие два основных формата кодирования:

[<знак>]{<целое>.<целое>|.<целое>|<целое>.}

Float([<знак>]<мантисса>, [<знак>]<экспонента>) ≡

[<знак>]<мантисса>.{E|e}[<знак>]<экспонента>

В качестве мантиссы и экспоненты используются целые со знаком или без; при этом, мантисса может иметь любую длину, но экспонента ограничивается длиной машинного слова: для 32-битной платформы значение экспоненты не превышает целого 2147483647, а для 64-битной платформы – целого значения 9223372036854775807. Тогда как максимальное допустимое число цифр мантиссы аналогично максимальному допустимому числу цифр целого (integer) числа. Число цифр мантиссы, участвующих в операциях арифметики с плавающей точкой, определяется предопределенной Digits-переменной ядра пакета, имеющей по умолчанию значение 10. В книге [103] представлен ряд полезных средств, позволяющих оформлять числовые значения в принятых для документирования и печати форматах.

Второй способ кодирования действительных чисел применяется, как правило, при работе с очень большими или очень малыми значениями. Для конвертации значений в действительный тип используется evalf-функция, возвращающая значение float-типа. В вышеприведенных примерах применение данной функции уже иллюстрировалось; функция имеет простой формат кодирования evalf(<Выражение> [, n]) и возвращает результат float-типа вычисления выражения (действительного или комплексного) с заданной n-точностью (если она определена вторым фактическим аргументом). Maple испытывает затруднения при вычислениях уже целого ряда простых радикалов с рациональными степенями от отрицательных значений, если знаменатель экспоненты – нечетное число. В этом случае даже стандартная функция evalf оказывается бессильной совместно с использованием пакетного модуля RealDomain, что очень хорошо иллюстрируют довольно простые примеры, а именно: