Смекни!
smekni.com

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

> seq(H[s], s = 1 .. 11); ⇒ x, y, z, h, r, t, k, p, w, z, d

С учетом сказанного приведенный фрагмент весьма прозрачен и особых пояснений не требует. Более детально вопросы, связанные с $-оператором и seq-функцией, будут рассмотрены в связи с обсуждением функциональных средств языка. Здесь лишь отметим, что при всей близости обоих средств между ними существует различие, выражающееся в более универсальном характере seq-функции в плане ее применимости для генерации последовательностей, что будет проиллюстрировано ниже на примерах и детально рассмотрено в [12,41-43,103].

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

List := [B1, B2, B3, ..., Bn], где Bj (j=1 .. n) – любое допустимое выражение Maple-языка

Длина списка определяется числом входящих в него элементов, а идентичными полагаются списки, имеющие одинаковую длину и одинаковые значения соответствующих элементов. По конструкции вида List[n] можно получать значение n-го элемента списка с List-идентификатором, а на основе вызова функции nops(List) – число его элементов. При этом, по вызову функции op(List) можно конвертировать списочную List-структуру в последовательность. Замена к-го элемента списка L выполняется по конструкции L[k] := <Выражение>, тогда как для его удаления используется конструкция subsop(k = NULL, L). Функция type идентифицирует тип списочных структур как list. Следующий простой пример иллюстрируют вышесказанное:

> L:=[sqrt(25),September,2,2006,GS]: [L[4],nops(L)],op(L); ⇒ [2006,5], 5,September,2, 2006,GS

> L[2]:= October: L; L:= subsop(3 = NULL, L): L, type(L, 'list'); ⇒ [5, October, 2, 2006, GS] [5, October, 2006, GS], true

Между тем, для удаления к-го элемента списка L с последующим обновлением списка «на месте» можно использовать конструкцию вида L[k] := 'NULL', весьма удобную в целом ряде приложений. Однако данный подход, корректно работая в одиночных вычислениях, не дает искомого результата в циклических. Поэтому во втором случае после каждого вычисления вида L[k]:= 'NULL' следует использовать операцию присвоения L:= L. Следующий весьма простой фрагмент иллюстрирует вышесказанное:

> restart; L:= [q, w, e, r, t, y, u, j, o, p, a, d, g, h, k, z, x]: L[10]:= 'NULL': L;

[q, w, e, r, t, y, u, j, o, a, d, g, h, k, z, x]

> L:=[q,w,e,r,t,y,u,j,o,p,a,d,g,h,k,z,x]: while L <> [] do L[1]:= 'NULL': L:= L end do: L ⇒ []

На основе предложенного приема можно предложить несложную процедуру mlist, обновляющую список на месте. Ее исходный текст и примеры применения даются ниже.

> L:= [q,w,e,r,t,y,u,j,o,p,d,a,s,k,x,z,y]: subsop(5 = VSV, L), subsop(10 = NULL, L), L;

[q, w, e, r, VSV, y, u, j, o, p, d, a, s, k, x, z, y], [q, w, e, r, t, y, u, j, o, d, a, s, k, x, z, y],

[q, w, e, r, t, y, u, j, o, p, d, a, s, k, x, z, y]

> mlist:= proc(L::uneval, a::posint, b::anything) if type(eval(L), 'list') then if belong(a, 1 ..

nops(eval(L))) then L[a]:= b; L:=eval(L); NULL else error "in list <%1> does not exist

element with number %2", L, a end if else error "1st argument should be a list but had received <%1>", whattype(eval(L)) end if end proc;

mlist := proc(L::uneval, a::posint, b::anything) if type(eval(L), 'list') then if belong(a, 1 .. nops(eval(L))) then L a[ ] := b; L := eval(L); NULL

else error "in list <%1> does not exist element with number %2", L a,

end if

else error

"1st argument should be a list but had received <%1>"whattype(, eval(L)) end if

end proc

> mlist(L, 10, 'NULL'), L; ⇒ [q, w, e, r, t, y, u, j, o, d, a, s, k, x, z, y]

> mlist(L, 16, 'NULL'), L; ⇒ [q, w, e, r, t, y, u, j, o, d, a, s, k, x, z]

> mlist(L, 3, AVZ), L; ⇒ [q, w, AVZ, r, t, y, u, j, o, d, a, s, k, x, z]

> L:= [q,w,e,r,t,y,u,j,o,p,d,a,s,k,x,z,y]: while L <> [] do mlist(L,1,'NULL') end do: L; ⇒ [] > mlist(L, 64, AGN), L;

Error, (in mlist) in list <L> does not exist element with number 59 > mlist(B, 64, AGN), L;

Error, (in mlist) 1st argument should be a list but had received <symbol>

Вызов процедуры mlist(L, a, b) возвращает NULL-значение, заменяя a-й элемент списка L на Maple-выражение b; при этом, обновление списка производится «на месте». Тогда как вызов процедуры mlist(L, a, 'NULL') также возвращает NULL-значение, удаляя a-й элемент из списка L и обновляя список «на месте». В ряде приложений процедура mlist представляется достаточно полезной.

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

> Avz:= [[[1, 2, 3], [5, 6]], [6, G], V, S]: op(Avz), nops(Avz); ⇒ [[1, 2, 3], [5, 6]], [6, G], V, S, 4

Для вложенных списков, чьи элементы имеют одинаковую длину, Maple определяет тип listlist, играющий весьма важную роль при организации индексированных структур (матрица, массив и др.). Нами дополнительно определен тип nestlist [103], характеризующий более общий тип вложенности списков, например:

> Avz:= [[[1, 2, 3], [5, 6]], [6, G], V, S]: type(Avz, 'listlist'), type(Avz, 'nestlist'); ⇒ false, true > Agn:= [[1, 2, 3], [a, b, c], [x, y, z]]: type(Agn, 'listlist'), type(Agn, 'nestlist'); ⇒ true, true Пустой список обозначается как L0:=[] и nops(L0); ⇒ 0, op(L0); ⇒ NULL. Maple-язык располагает весьма обширным набором функциональных средств для работы со списочными структурами, которые будут рассматриваться нами довольно детально ниже. Пакетный модуль ListTools содержит набор средств для работы со списками. В свою очередь, наша Библиотека [103] также содержит ряд полезных средств для такого типа структур.

Списочные структуры являются весьма широко используемыми пакетом объектами (исходные и выходные данные, управление порядком вычислений, представление массивов, матриц и тензоров и др.). При этом, в достаточно широких пределах допускается сочетание их с другими типами данных и структур данных.

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

Set := {B1, B2, B3, ..., Bn}, где Bj (j=1 .. n) – любая допустимая конструкция Maple-языка

Мощность множества определяется числом входящих в него элементов, а идентичными полагаются множества, имеющие одинаковый набор вычисленных значений элементов без учета их кратности. По конструкции вида Set[n] можно получать значение n-го элемента множества с Set-идентификатором, а на основе вызова функции nops(Set) - число его элементов. Более того, по вызову функции op(Set) можно конвертировать Set-множество в последовательность. При этом, функция type идентифицирует тип множественных структур как set. Следующий пример иллюстрируют вышесказанное:

> Set1:= {q,6/3,e,r,5,t,w}: Set2:= {q,w,e,r,2,t,w,sqrt(25),r,q,q}: [op(Set1)], [op(Set2)],

[nops(Set1)], [nops(Set2)], Set2[5]; ⇒ [2, 5, r, q, e, t, w], [2, 5, r, q, e, t, w], [7], [7], e

Из приведенного примера можно заметить ряд особенностей применения функций op и nops к структуре данных set-типа. Прежде всего, производится вычисление элементов множества и их упорядочивание согласно соглашениям пакета, поэтому порядки элементов исходного множества и результата его вычисления могут не совпадать. Это же относится и к мощности множества - в результате вычисления его элементов одинаковые результаты сводятся к одному, например: S := {56/2, 7*4, 28, 7*2^2}: nops(S); ⇒ 1. Пустое множество обозначается как S0:= {} и nops(S0); ⇒ 0, op(S0); ⇒ NULL.

Maple-язык поддерживает ряд операций над множествами, аналогичных классическим теоретико-множественным операциям, включая базовые операции объединения (union), разности (minus) и пересечения (intersect) множеств, например:

> S1:= {q,r,64,t,w,x,h,z}: S2:= {h,n,v,x,59,z,k,s}: S1 union S2, S1 intersect S2, S2 minus S1;

{59, 64, x, h, s, z, n, r, v, q, t, w, k}, {x, h, z}, {59, s, n, v, k}

Множества могут иметь различный уровень вложенности, определяя различного рода структуры данных и конструкции. Нами дополнительно определен тип setset [103], аналогичный стандартному типу listlist для случая списков, например:

> map(type, [{{}}, {{},{}}, {{{7}}}, {{a, b}, {c, d}}, {{a, b}, {c}}, {{10, 17}, {64, 59}, {39, 44}}], 'setset');

[true, true, true, true, false, true]

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

(1) S := S minus {S[k]} union {<Выражение>} (2) S := subs(Sk = <Выражение>, S) где S – произвольное множество и S[k], Sk – его к-й элемент и значение к-го элемента соответственно. Конкретные примеры иллюстрируют применение обоих способов:

> S:= {q, r, 64, t, w, x, h, z}; ⇒ S := {64, x, h, z, r, q, t, w}

> S:= S minus {S[4]} union {Avz}; ⇒ S := {64, x, h, r, q, t, w, Avz}

> S:= subs(Avz = Agn, S); ⇒ S := {64, x, h, r, q, t, w, Agn}

> S:= subs(Agn = NULL, S); ⇒ S := {64, x, r, h, q, t, w}

Одной из наиболее полезных и часто используемых над объектами типов set и list является map-функция Maple-языка, имеющая в общем виде формат кодирования:

map(F, f(x, y, z, ...), a, b, c, …) ⇒ f(F(x, a, b, c, …), F(y, a, b, c, …), F(z, a, b, c, …), ...)

где F – некоторая функция или процедура, f – выражение от переменных x, y, z, ... и a, b, c, … – некоторые выражения, и возвращающая результат применения функции или процеду-ры F к каждому аргументу f(x, y, z, ...)-конструкции (а в более общей постановке, к каждому операнду выражения), как это иллюстрирует следующий простой фрагмент:

> map(F, [x, y, z], a, b, c, d); ⇒ [F(x, a, b, c, d), F(y, a, b, c, d), F(z, a, b, c, d)]

> map(F, {x, y, z}, a, b, c, d); ⇒ {F(x, a, b, c, d), F(y, a, b, c, d), F(z, a, b, c, d)}

> map(F, f(x, y, z), a, b, c, d); ⇒ f(F(x, a, b, c, d), F(y, a, b, c, d), F(z, a, b, c, d))

> Seq:= x, y, z: map(F, Seq, a, b, c, d); ⇒ F(x, y, z, a, b, c, d)

Между тем, если по map(F, V, a1, ..., an)-функции применяется определенная ее первым фактическим F-аргументом функция к каждому операнду V-выражения с передачей ей дополнительных фактических aj-аргументов (j=1..n), то по ее модификации – функции map2 вида map2(F, a1, V, a2, ..., an) производится применение к V-выражению F-функции со специфическим a1-аргументом и возможностью передачи ей дополнительных aj-аргументов (j=2 .. n), что является существенным расширением map-функции. Следующий пример иллюстрирует принцип формального выполнения map2-функции: