Смекни!
smekni.com

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

Базовые объекты модуля LinearAlgebra. В качестве таких объектов выступают Array, Matrix, Vector[row] и Vector[column], кратко рассмотренные выше в связи с rtable-функцией, на основе которой они формируются. Между тем, пользователь имеет возможность непосредственно создавать указанные объекты на основе встроенных функции Array и процедур Matrix или Vector, кратко рассматриваемых ниже.

По функции Array(ИФ, D, НЗ, <Опции>) создается массив с заданными характеристиками, определяемыми ее фактическими аргументами. Каждый из аргументов функции не является обязательным; если же вызов функции Array определен без фактических аргументов, то возвращается пустой 0-мерный массив. Смысл и форматы кодирования аргументов функции (ИФ - индексирующая функция, D - размерность, НЗ - начальные условия и <Опции>) довольно прозрачны и особых пояснений не требуют. Поэтому на данном вопросе детальнее останавливаться не будем, а приведем несколько примеров на прямое определение массивов Array-типа.

> A:= Array(1..6, [42, 47, 67, 62, 89, 96], datatype=integer, readonly): Ao:=Array(): A, Ao;

[42, 47, 67, 62, 89, 96], Array({}, datatype = anything, storage = rectangular, order = Fortran_order)

> A[4]:= 2006;

Error, cannot assign to a read-only Array

> ArrayOptions(A);

datatype = integer, storage = rectangular, order = Fortran_order, readonly

> B:=Array(symmetric, 1..3, 1..3, datatype=integer): B[1, 1]:=42: B[2, 2]:=47: B[3, 3]:=67: B[1, 2]:= 64: B[1, 3]:=59: B[2, 3]:=39: B, ArrayIndFns(B), ArrayOptions(B);

426459 644739 593967, symmetric, datatype = integer, storage = triangularupper,

order = Fortran_order

> op(1, B), ArrayOptions(B, order=C_order), ArrayOptions(B);

symmetric, datatype = integer, storage = triangularupper, order = C_order

> ArrayDims(B), ArrayNumDims(B); ⇒ 1 .. 3, 1 .. 3, 2

> ArrayElems(B);

{(1, 1) = 42, (1, 2) = 64, (1, 3) = 47, (2, 2) = 59, (2, 3) = 39, (3, 3) = 67}

> ArrayNumElems(B, NonZeroStored), ArrayNumElems(B, All); ⇒ 6, 9

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

Для работы с Array-объектами Maple-язык располагает рядом полезных функций, детально рассмотренных в наших книгах [13,14,29,30,33]. Примеры предыдущего фрагмента иллюстрируют создание посредством Array-функции одномерного А-массива и двумерного В-массива, а также применение к ним ряда функций работы с массивами, которые ввиду их простоты не требуют дополнительных пояснений.

Вызов процедуры Matrix(n, m, НЗ, <Опции>) возвращает матричную структуру данных (матрицу), являющуюся одной из базовых структур, с которыми работают функциональные средства LinearAlgebra-модуля. Первые два формальных аргумента процедуры определяют число строк и столбцов матрицы соответственно; при этом, фактические значения для аргументов могут кодироваться или целыми неотрицательными числами, или диапазонами вида 1 .. h (h – целое неотрицательное). Третий аргумент определяет начальные значения, тогда как опции - дополнительные характеристики создаваемого матричного объекта. Все аргументы процедуры необязательны и при их отсутствии возвращается матрица (0х0)-размерности. В общем же случае при создании матричного объекта вызов Matrix-процедуры должен содержать достаточное количество информации о его структуре и элементах. Сказанное по начальным значениям относительно rtable-функции в полной мере переносится и на третий аргумент Matrix-процедуры. Среди допустимых опций (четвертый аргумент) многие аналогичны общему случаю rtable-функции, рассмотренной выше. Однако, среди них имеются и специфические для матричной структуры. Детальнее с описанием опций функции можно ознакомиться по справке пакета. Приведем примеры на создание некоторых простых матричных объектов и их тестирование.

> M1:=Matrix(3,[[42,47,67],[64,59,39],[89,96,62]],readonly): M2:=Matrix([[a,b],[c,d]]): M1,M2;

426489 475996 673962, ac bd

> M1[3, 3]:= 47;

Error, cannot assign to a read-only Matrix

> M3:= Matrix(3, (j, k) -> 4*j^2+11*k^2-89*j-96*k+99*j*k, datatype=integer[2]): M4:= Matrix(1..3,1..3,rand(42..99,0.58)): M5:= <<42,47,67>| <64,59,39>|<10,17,44>>: M3, M4, M5;

-49 86 243 , 44

-71-19 215-35 47123 617167 5898 538699, 424767 645939 101744

> map(type, [M1, M2, M2, M5], 'Matrix'); ⇒ [true, true, true, true]

> M6:= Matrix(2, {(1, 1)=64, (1, 2)=59, (2, 1)=10, (2, 2)=17}): type(M5,'matrix'), whattype(M5), type(M6, 'Array'), type(M6, 'Matrix'); ⇒ false, Matrix, false, true

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

M := <M11, M21, M31>|<M12, M22, M32>|<M13, M23, M33>

недостатком которой является невозможность указания для матрицы в точке определения других ее характеристик. Более того, последний пример фрагмента иллюстрирует тот факт, что type-функция не распознает Matrix-объект в качестве Maple-матрицы, тогда как тестирующая whattype-процедура определяет его как Matrix-объект. Детальнее с описанием и применением функции Matrix можно ознакомиться в книгах [13,14,42] и в справке по пакету. С учетом сказанного Matrix-объекты (NAG-матрицы) довольно прозрачны, но за более подробной информацией по их определению можно обращаться к справке по пакету (например, оперативно по конструкции ?Matrix).

Наконец, по функции Vector[T](n,НЗ, <Опции>) возвращается векторная структура данных (вектор), являющаяся одной из основных структур, с которыми работают функциональные средства LinearAlgebra-модуля пакета. Индекс Т определяет сам тип вектора (column – столбец, row – строка, по умолчанию полагается column). Первый формальный аргумент функции определяет число элементов вектора; при этом, фактические значения для аргумента могут кодироваться или целым неотрицательным числом, либо диапазоном вида 1..h. Второй аргумент определяет начальные значения, тогда как опции – дополнительные характеристики создаваемого векторного объекта. Все аргументы функции необязательны и при их отсутствии возвращается вектор 0-размерности, т.е. элемент 0-мерного векторного пространства. В общем же случае при создании векторного объекта вызов Vector-функции должен содержать достаточное количество информации о его структуре и элементах. Сказанное выше по начальным значениям относительно rtable-функции в полной мере переносится и на второй аргумент Vector-функции. Среди допустимых опций (третий аргумент) многие аналогичны общему случаю rtable-функции, рассмотренной выше. Однако допускаемые ими значения имеют векторную специфику. Детальнее с описанием опций Vector-функции можно познакомиться в справке по пакету. Приведем простые примеры на создание векторных объектов.

> V1:= Vector(1..4, [42, 47, 67, 89]): V2:= Vector[row](4, {1=64, 2=59, 3=39, 4=17}): V3:= Vector(1..4): V1, V2, V3;

 42476789, [64 59 39 17, , , ],  0000

 > VectorOptions(V2); shape = [], datatype = anything, orientation = row, storage = rectangular, order = Fortran_order > V4:= <Sv, Ar, Art, Kr>: V5:= <Sv|Ar|Art|Kr>: V4, V5, VectorOptions(V4, readonly);

ArtKrArSv , [Sv Ar Art Kr, , , ], false

> V6:= Vector[row](6, rand(42..99)): V7:=Vector(): V6, type(V6, vector), whattype(V6), V7;

[57, 89, 80, 52, 48, 71], false, Vector[row], []

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

V := <V1, V2, V3, …, Vn> или V := <V1|V2|V3| … |Vn>

недостатком которых является невозможность задания для вектора в точке его определения других характеристик. При этом, первый формат определяет вектор-столбец, тогда как второй – вектор-строку. Более того, последний пример фрагмента иллюстрирует тот факт, что type-функция не распознает Vector-объект в качестве Maple-вектора, тогда как тестирующая whattype-процедура определяет его как Vector-объект. С учетом сказанного Vector-типа объекты (NAG-векторы) довольно прозрачны и за более детальной информацией по их определению можно обращаться к справке (например, оперативно по конструкции ?Vector).

Как уже отмечалось выше, между Maple-объектами (array, vector и matrix) и NAG-объектами (Array, Vector и Matrix) имеются принципиальные различия. Более того, классификация вторых относительно тестирующих функции type и процедуры whattype выгодно отличается однозначностью, тогда как первые распознаются whattype-процедурой как объекты array-типа. В приведенном ниже фрагменте этот момент иллюстрируется весьма наглядно:

> a:=array(1..2, 1..2, [[42,47], [64,59]]): A:=Array(1..3, 1..3): v:=vector([1,2,3]): V:=Vector([1,2,3]): m:=matrix([[G, S, Vic], [47, 67, 42]]): M:=Matrix([[G, S, Vic], [47, 67, 42]]):

> type(a, 'array'), type(a, 'matrix'), type(v, 'vector'), type(v, 'array'), type(m, 'matrix'), type(m,'array'); ⇒ true, true, true, true, true, true

> type(A, 'Array'), type(A, 'Matrix'), type(V, 'Vector'), type(V, 'Array'), type(M, 'Matrix'), type(M, 'Array'); ⇒ true, false, true, false, true, false

> map(whattype, map(eval, [a, v, m])), map(whattype, [A, V, M]);

[array, array, array], [Array, Vector[column], Matrix]

> convert(a, 'listlist'), convert(A, 'listlist'); ⇒ [[42, 47], [64, 59]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]] > a[1]:= [x, y, z];

Error, array defined with 2 indices, used with 1 indices

> A[1]:= [x, y, z]; ⇒ A[1] := [x, y, z]

> convert(A, 'listlist'); ⇒ [[[x, y, z], [x, y, z], [x, y, z]], [0, 0, 0], [0, 0, 0]]

> Ar:=Array(1..2, 1..2, 1..4, [[[64, 59, 39, 10], [47, 67, 42, 6]], [[c2, b2, a2, 17], [c3, b3, a3, 6]]]): > convert(Ar, 'listlist'); ⇒ [[[64, 59, 39, 10], [47, 67, 42, 6]], [[c2, b2, a2, 17], [c3, b3, a3, 6]]] > Ar[1, 2]:= AVZ; ⇒ Ar[1, 2] := AVZ

> convert(Ar, 'listlist'); ⇒ [[[64,59,39,10], [AVZ,AVZ,AVZ,AVZ]], [[c2,b2,a2,17], [c3,b3,a3,6]]]

> A1:= Array(1..3, 1..3, [[a, b, с], [x, y, z], [42, 47, 6]]); ⇒ A1 :=

42ax 47by ñ6z

> A1[2]:= [Grodno, Tallinn]: A1;

[Grodno Tallinn42a, ] [Grodno Tallinn47b, ] [Grodno Tallinnñ6, ]

В целом ряде случаев точная идентификация rtable-объектов тестирующими средствами пакета играет весьма существенную роль. Еще на одном моменте данного фрагмента имеет смысл обратить внимание, а именно. Если 2-мерный Maple-массив (array) не допускает возможности замены своих строк путем присвоения, инициируя ошибочную ситуацию, то массив NAG (Array) такую операцию допускает, однако присваиваемое значение дублируется по числу элементов строки. Соответствующим образом это обобщается и на n-мерные массивы, как показано выше. В ряде случаев это может представить практический интерес при программировании ряда приложений в среде пакета.