• Векторы (vector); в среде Maple-языка вектор представляется в виде 1D-массива, нумерация строк и столбцов которого производится, начиная с единицы. Вектор определяется либо явно через рассмотренную выше array-функцию, например V:= array(1..n), или посредством процедуры vector, имеющей следующие два простых формата:
vector([X1, X2, ..., Xn]) и vector(n, { |Fn|[X1, X2, ..., Xn]})
где Xk - элементы вектора, n - число его элементов и Fn - функция генерации элементов вектора аналогично случаю определения матриц. По тестирующей же функции type(V, {'vector'(K)| vector}) возвращается значение true, если V-выражение является вектором; при этом, допускается проверка на принадлежность значений его элементов заданной К-области. В противном случае функцией возвращается false-значение. Так как вектор является одним из типов общего понятия массив, то функция type(V, 'array') также возвращает true-значение, если V – вектор. Обратное в общем случае неверно, например, в случае списка. По convert(L, 'vector')-функции возвращается вектор, если L – соответствующая ему списочная структура.
Следует отметить, что в силу специфики организации базовых структур, на которых основываются векторы, массивы, и матрицы, они не вполне однозначно тестируются пакетными процедурой whattype и функцией type, как иллюстрирует фрагмент ниже:
> v:=vector(3,[]): m:=matrix(3,3,[]): a:= array(1..2,1..3,[]): map(whattype, map(eval, [v,m,a]));
[array, array, array]
> map(type, [v,m,a], 'array'), map(type, [v,m,a], 'vector'), map(type, [v,m,a], 'matrix');
[true, true, true], [true, false, false], [false, true, true]
Так, если процедура whattype отождествляет все типы {array, matrix, vector} как обобщающий array-тип, то функция type обеспечивает более дифференцированное тестирование, хотя и в этом случае типы array и matrix ею не различаются. Предыдущий фрагмент хорошо иллюстрирует сказанное.
• Основные характеристики матриц и векторов. Прежде всего, среди класса матричных объектов выделим квадратные (square) матрицы, которые будут основным объектом нашего рассмотрения и для работы с которыми Maple-язык располагает довольно широким набором функциональных средств. Поэтому, если не оговаривается противного, то под понятием «матрица» в дальнейшем понимается именно квадратная матрица. Для работы с такого типа матрицами Maple располагает большим набором средств, находящихся в пакетных модулях linalg и LinearAlgebra.
Прежде всего, по функции indices(M) возвращается последовательность 2-элементных списков, определяющих индексное простанство М-матрицы, а по функции entries(M) – последовательность 1-элементных списков, содержащих значения элементов М-матрицы. В случае использования в качестве М-аргумента таблицы функция {indices|entries} возвращает соответственно ее входы и выходы. При этом, следует иметь в виду, что в случае матриц обе функции возвращают последовательности списков, имеющих внутреннее взаимно-однозначное соответствие (при отсутствии оного в их выходных порядках), не управляемых пользователем. Вместе с тем, на основе несложной Pind-процедуры [103], в качестве единственного фактического аргумента использующей выражение типа {array, matrix, table}, можно получать (nxp)-размерность произвольной М-матрицы в виде [n, p]списка, как это иллюстрирует следующий весьма простой фрагмент:
> Fn:= (k, j) -> k^2+3*k*j: M:= matrix(3, 10, Fn): M1:= matrix(3,3,[]): map(evalm, [M, M1]); 18104 16277 223610 284513 543416 634019 467222 815225 285890 649931, M1M1M1132,,, 111 M1M1M1321,,, 222 M1M1M1123,,, 333 > indices(M); [1, 3], [3, 2], [2, 1], [3, 6], [1, 6], [2, 5], [3, 10], [1, 2], [1, 4], [3,3], [1, 7], [1, 9], [3, 7], [2, 9], [1,5], [2,10], [2, 4], [1, 1], [3, 4], [2, 7], [1, 8], [3, 8], [2, 6], [2, 2], [1, 10], [2, 8], [3, 1], [3, 5], [2, 3], [3, 9] > entries(M); ⇒ [10], [27], [10], [63], [19], [34], [99], [7], [13], [36], [22], [28], [72], [58], [16], [64], [28], [4], [45], [46], [25], [81], [40], [16], [31], [52], [18], [54], [22], [90] > Pind(M), Pind(M1); ⇒ [3, 10], [3, 3] > assign(Kr=matrix(3,3,[[a,e*ln(x),c],[d,e*ln(x),f],[e*ln(x),h,k]])), eval(Kr), Mem1(Kr,e*ln(x)); e lnad( )x ee lnlnh(( )xx) ckf, ,3 [1, 2], [2, 2], [3, 1] |
Во фрагменте иллюстрируется определение М-матрицы на основе matrix-функции с использованием Fn-функции генерации элементов матрицы. Представлено применение Pind-процедуры для определения размерности матриц. Процедура Mem1(M, h) возвращает последовательность, первый элемент которой определяет число вхождений в Mматрицу элементов, заданных вторым h-аргументом функции, а последующие определяют списки-координаты искомых элементов. В нашей Библиотеке [103] представлен целый ряд других полезных процедур для работы с матрицами. Можно определять целый ряд других полезных процедур как на основе представленных, так и других функций Maple-языка, что оставляется читателю в качестве весьма полезного практического упражнения. В реальной работе с пакетом это вполне возможные ситуации.
Как таблица, так и общая функция array({<ИФ>}{, <Размерность>}{, <НЗ>}) допускает 3 необязательных ключевых аргумента: ИФ – индексная функция, размерность, кодируемая в виде диапазонов (..) изменения значений индексов, и НЗ – список начальных значений для определения элементов массива. Два последних из них достаточно просты и неоднократно обсуждались при рассмотрении массивов и таблиц. Несколько детальнее остановимся на индексной функции, имеющей для матриц особое значение, определяя общего уровня их классификацию. В общем случае индексная функция определяет правило присваивания значений элементам массива или таблицы, или их обработки. При отсутствия ИФ-аргумента используется стандартный метод индексации элементов массива (матрицы). Индексная функция может определяться пользовательской процедурой, принцип организации которой здесь не рассматривается, но общий подход был указан выше. Для этих целей может использоваться, например, процедура indexfunc пакетного модуля linalg. Язык Maple располагает пятью основными встроенными ИФ с идентификаторами symmetric, antisymmetric, sparse, diagonal и identity для функций table и array. Мы рассмотрим вкратце данные индексные функции.
Индексная symmetric-функция применима в качестве первого фактического аргумента для определения симметричности элементов матрицы/таблицы относительно ее главной диагонали, т.е. для М-матрицы предполагается определяющее соотношение M[k,j] = M[j, k]. В свою, очередь antisymetric-аргумент определяет М-матрицу с соотношением M[k, j] = -M[j, k], следовательно ∀(k)∀(j)(k=j)(M[k, j]=0). Если же при определении такого типа матрицы были заданы ненулевые начальные значения для ее диагональных элементов, то они получают нулевые значения с выводом соответствующей диагностики. Аргумент diagonal определяет диагональную М-матрицу, для которой справедливо соотношение ∀(k)∀(j)(k≠j)(M[k, j]=0). Посредством sparse-аргумента определяется М-матрица, чьи неопределенные входы получают нулевые значения. Например, по вызову array(sparse, 1..n, 1..p) возвращается нулевая матрица (nxp)-размерности. Наконец, по identity-аргументу возвращается единичная матрица, для которой имеет место соотношение ∀(k)∀(j)[(k=j) → (M[k, j] = 1)] & [(k≠j) → (M[k,j] = 0)]. Следующий пример иллюстрирует получение рассмотренных выше пяти типов матриц:
> MS:=array(symmetric, 1..3, 1..3): MS[1, 1]:=10: MS[1, 2]:=17: MS[1, 3]:=39: MS[2, 2]:=64:
MS[2, 3]:=59: MS[3, 3]:=99: MD:=array(diagonal, 1..3, 1..3): MD[1, 1]:=2: MD[2, 2]:=10:
MD[3, 3]:=32: MAS:= array(antisymmetric, 1..3, 1..3): MAS[1, 2]:=10: MAS[1, 3]:=32:
MAS[2, 3]:=52: MI:= array(identity, 1..3, 1..3): MSp:=array(sparse, 1..3, 1..3): map(evalm,
[MS, MAS, MD, MI, MSp]);
39 59 99, -10-320 -52100 52320, 200 1000 3200, 100 100 100, 000 000 000 1017 6417 5939
Так как вектор представляет собой (1xn)-матрицу, то к нему применим и целый ряд сугубо матричных функций, например evalm-функция, позволяющая возвращать вычисленные векторные выражения в векторной (списочной) нотации. Более того, все имеющее силу относительно матриц в полной мере (с поправкой на размерность) относится и к векторам. В частности, это относится и к (&*)-оператору матрично/векторного произведения. Длину V-вектора, подобно случаю матриц, можно вычислять, в частности, посредством конструкции вида nops([{indices|entries}(V)]); при этом, нулевое значение возвращается, если элементам V-вектора не присваивалось значений. Следующий простой фрагмент иллюстрирует некоторые способы определения, тестирования и вычисления простых векторных выражений в среде Maple-языка:
> V1:= array(1..9): V2:= array(1..6, [64, 59, 39, 10, 17, 44]): V3:= vector(5, [42, 47, 67, 89, 96]): V4:= vector(5, [64, 59, 39, 17, 10]): Fn:= k -> 3*k^2 + 10*k + 99: V5:= vector(5, Fn):
V6:= vector(6, [V, G, S, Art, Kr, Ar]): map(type, [V1, V2, V3, V4, V5, V6], 'vector');
[true, true, true, true, true, true]
> map(evalm, {V5, V6}); ⇒ {[112, 131, 156, 187, 224], [V, G, S, Art, Kr, Ar]}
> map(nops, [[indices(V6)], [entries(V6)]]); ⇒ [6, 6]
> V:=vector(6, []): map(nops, [[indices(V)], [entries(V)]]); ⇒ [0, 0]
> [type(V4, 'vector'(integer)), type(V6, 'vector'(symbol))]; ⇒ [true, true]
> Z:= vector([W, G, S]): M:= array(1..3, 1..3, [[1, 2, 3], [4, 5, 6], [7, 8, 10]]): evalm(M&*Z);