авторефераты диссертаций БЕСПЛАТНАЯ БИБЛИОТЕКА РОССИИ

КОНФЕРЕНЦИИ, КНИГИ, ПОСОБИЯ, НАУЧНЫЕ ИЗДАНИЯ

<< ГЛАВНАЯ
АГРОИНЖЕНЕРИЯ
АСТРОНОМИЯ
БЕЗОПАСНОСТЬ
БИОЛОГИЯ
ЗЕМЛЯ
ИНФОРМАТИКА
ИСКУССТВОВЕДЕНИЕ
ИСТОРИЯ
КУЛЬТУРОЛОГИЯ
МАШИНОСТРОЕНИЕ
МЕДИЦИНА
МЕТАЛЛУРГИЯ
МЕХАНИКА
ПЕДАГОГИКА
ПОЛИТИКА
ПРИБОРОСТРОЕНИЕ
ПРОДОВОЛЬСТВИЕ
ПСИХОЛОГИЯ
РАДИОТЕХНИКА
СЕЛЬСКОЕ ХОЗЯЙСТВО
СОЦИОЛОГИЯ
СТРОИТЕЛЬСТВО
ТЕХНИЧЕСКИЕ НАУКИ
ТРАНСПОРТ
ФАРМАЦЕВТИКА
ФИЗИКА
ФИЗИОЛОГИЯ
ФИЛОЛОГИЯ
ФИЛОСОФИЯ
ХИМИЯ
ЭКОНОМИКА
ЭЛЕКТРОТЕХНИКА
ЭНЕРГЕТИКА
ЮРИСПРУДЕНЦИЯ
ЯЗЫКОЗНАНИЕ
РАЗНОЕ
КОНТАКТЫ


Pages:     | 1 | 2 || 4 | 5 |   ...   | 20 |

«Международная Академия Ноосферы Балтийское отделение В.З. Аладьев, Д.С. Гринь Расширение функциональной среды системы Mathematica ...»

-- [ Страница 3 ] --

При этом, пакет поддерживает арифметику не только с отдельными числами, но и с произвольными списками и множествами, а также символьными и алгебраическими формами. Пакет использует довольно эффективные платформо–оптимизированные алгоритмы для работы с точными и приближенными числами с количеством цифр до миллионов, а также с полиномами с миллионами слагаемых. Следующий простой фрагмент представляет арифметические Listable-операции над списками. Завершает этот фрагмент простая функция, вызов которой Nconcat[x] возвращает конкатенацию элементов списка x – целых чисел 0;

более того, рассматривается список Flatten[x], а не x, обеспечивая работу с вложенными списками любого уровня вложенности. Тогда как вызов процедуры ToString2[x] на аргументе x, отличном от списка, эквивалентен вызову ToString[x], а на списке x – вызову ToString[x] с ToString, наделенной Listable– В.З. Аладьев, Д.С. Гринь атрибутом. Фрагмент представляет исходные коды средств с примерами применения.

In[1615]:= n = {a, b, c};

m = {x, y, z};

{Plus[n, m], Power[n, m], Times[n, m]} Out[1615]= {{a + x, b + y, c + z}, {a^x, b^y, c^z}, {a x, b y, c z}} In[1616]:= L = {70, 65, 45};

{Mean[L], Accumulate[L}], Max[L], Min[L]} Out[1616]= {60, {70, 135, 180}, 70, 45} In[1617]:= {Commonest[L], Ratios[L], Differences[L], Subtract[L, 20], Length[L]} Out[1617]= {{70, 65, 45}, {13/14, 9/13}, {–5, –20}, {50, 45, 25}, 3} In[1711]:= Nconcat[h_ /;

PosIntQ[h] || PosIntListQ[h]] := If[PosIntQ[h], h, ToExpression[StringJoin[Map[ToString, Flatten[h]]]]] In[1712]:= Nconcat[{70, 65, 45, 50, 23, 16}] Out[1712]= In[1713]:= Nconcat[70] Out[1713]= In[1714]:= Nconcat[{{70, 65}, {45, 50}, {23, 16}}] Out[1714]= In[1717]:= ToString2[x_] := Block[{a}, If[ListQ[x], SetAttributes[ToString, Listable];

a = ToString[x];

ClearAttributes[ToString, Listable];

a, ToString[x]]] In[1718]:= ToString2[a + b/70 – Sin[750.75]] Out[1718]= "–0.0905201 + a + b/70" In[1719]:= ToString2[{{70, 65}, {45, 50}, {23, 16}}] Out[1719]= {{"70", "65"}, {"45", "50"}, {"23", "16"}} Если функция Nconcat иллюстрирует расширение арифметических функций путем определения числовой конкатенации списка PosInt–типа подобно случаю функции StringJoin, тогда как процедура ToString2 иллюстрирует довольно простой механизм, базирующийся на атрибутах стандартной функции ToString, для дифференциации применения ToString к выражениям List–типа и к отличным от данного типа.

Операции на векторах: Пакет представляет векторы как списки, не различая строки и столбцы. Элементы вектора могут быть как числовыми, так и символьными, пакет использует довольно эффективные алгоритмы для оптимизации работы с операциям на достаточно длинных, плотных, и редких векторах. Среди операций над векторами можно выделить математические: +, *, ^, и др., Dot, Cross, Norm, Total;

операции над векторами в векторном пространстве: VectorAngle, UnitVector, Normalize, Projection, Orthogonalize, KroneckerProduct и др.;

представление векторов: Row, Column, Arrow, GridListPlotArrayPlot;

векторно–ориентированные операции: Dot, Norm, Normalize, Projection, VectorQ и др.;

теоретико–множественные операции: Union, Complement, Intersection;

ряд операций над последовательностями: LongestCommonSubsequence, LongestCommonSubsequence, SequenceAlignment;

операции измерения расстояния и подобия: HammingDistance, SmithWatermanSimilarity, NeedlemanWunschSimilarity, DamerauLevenshteinDistance, EditDistance, Nearest, FindClusters и др.;

Операции для импортирования и экспортирования списков: Используются функции Import и Export с указанием соответствующих форматов данных;

Расширение функциональной среды системы Mathematica Представление списков: функции ListPlot, ArrayPlot и ряд других.

Так как списки составляют базовую структуру для многих важных объектов (векторы, массивы, матрицы, тензоры и др.), то поддерживающие с ними работу функции вполне можно рассматривать как средства работы со списками различной структуры. По этой причине здесь не имеет смысла сколько–нибудь детально останавливаться на всех из них (даже перечислять), приумножая сущности и изводя массу бумаги в электронный век. На наш взгляд, писать следует лишь то, что достаточно оригинально, инновативно и чего нет в другом широко распростаненном виде. Многостраничные же опусы, как правило, содержат пересказы уже имеющейся информации, например, в справочной базе, которая, в частности, и в Mathematica, и в Maple вполне пригодна для получения четких ответов на подавляющее число вопросов,возникающих в процессе применения этих средств. Поэтому мы адресуем заинтересованного читателя к соответствующим разделам хорошо организованной справочной базы Mathematica. Более того, в случае такой необходимости достаточно квалифицированный пользователь имеет хорошую возможность запрограммировать требуемое ему средство с использованием функций, предоставляемых программной средой Mathematica, а также средств пакета [90].

Например, в случае работы со списочными структурами NestList-типа в ряде случаев могут возникать задачи, не решаемые прямыми стандартными средствами, требуя в данных ситуациях программирования задач средствами, предоставляемыми пакетом Mathematica. Это можно весьма наглядно проиллюстрировать на примере довольно простой задачи, состоящей в определении количества элементов, отличных от списка, на каждом уровне вложенности списка как простого списка (уровень вложенности 0), так и вложенного. Данную задачу может решить процедура, вызов которой ElemLevelsN[x] возвращает вложенный список, элементами которого являются 2-х элементные списки, первый элемент которых определяет уровень вложенности, тогда как второй – число элементов данного уровня с типом, отличным от List. При этом, в программировании процедуры возникла целесообразность дополнительно к NestListQ-типу, ранее нами введенному, определить и тип NestListQ1, определяемый весьма простой функцией, чей вызов NestListQ1[x] возвращает True, если по меньшей мере один из элементов x списка является его подсписком, и False в противном случае. Фрагмент представляет исходные коды обоих средств с наиболее типичными примерами их применения.

In[1633]:= ElemLevelsN[x_ /;

ListQ[x]] := Module[{a = x, c = {}, m = 0, n, k = 0}, While[NestListQ1[a], n = Length[Select[a, ! ListQ[#] &]];

c = Append[c, {k++, n – m}];

m = n;

a = Flatten[a, 1];

Continue[]];

Append[c, {k++, Length[a] – m}]] In[1634]:= L = {a, b, a, {d, c, s}, a, b, {b, c, {x, y, {v, g, z, {70, {450, {}, 75}}, a, k, a}, z}, b}, c, b};

In[1635]:= ElemLevelsN[L] Out[1635]= {{0, 7}, {1, 6}, {2, 3}, {3, 6}, {4, 1}, {5, 2}, {6, 0}} In[1641]:= NestListQ1[x_] := If[ListQ[x] && Length[Select[x, ListQ[#] &]] != 0, True, False] In[1642]:= Map[NestListQ, {{}, {{}}, {a, b}, {a, b, {c}}, {{a, b}, {c, d}}}] Out[1642]= {False, True, False, False, True} В.З. Аладьев, Д.С. Гринь In[1643]:= Map[NestListQ1, {{}, {{}}, {a, b}, {a, b, {c}}, {{a, b}, {c, d}}}] Out[1643]= {False, True, False, True, True} In[1644]:= Map[ElemLevelsN, {{}, {a, b, c, d, r, t, y, c, s, f, g, h, 70, 75, 450, s, a, q, w}}] Out[1644]= {{{0, 0}}, {{0, 19}}} In[1674]:= ElemLevelsL[x_ /;

ListQ[x]] := Module[{a = x, c = {}, m = {}, n, k = 0}, While[NestListQ1[a], n = Select[a, ! ListQ[#] &];

c = Append[c, {k++, MinusList[n, m]}];

m = n;

a = Flatten[a, 1];

Continue[]];

Append[c, {k++, MinusList[a, m]}]] In[1675]:= ElemLevelsL[L] Out[1675]= {{0, {a, b, a, a, b, c, b}}, {1, {d, s, c, b, c, b}}, {2, {x, y, z}}, {3, {v, g, a, k, a, z}}, {4, {70}}, {5, {450, 75}}, {6, {}}} Завершает этот фрагмент довольно полезная модификация процедуры – процедура, чей вызов ElemLevelsL также возвращает вложенный список, элементы которого – 2-х элементные списки, первый элемент которых определяет уровень вложенности, тогда как второй элемент – список элементов такого уровня с типом, отличным от List. При этом, читатель в качестве довольно полезного упражнения может объединить данные процедуры в одну, например, возвращая один из результатов через необязательный аргумент. Это лишь один из многочисленных примеров, представленных в настоящей книге средств и расширяющих функциональную среду, в частности, для достаточно эффективного программирования ряда задач обработки списочных структур разной организации. Такие средства представлены в последующих главах настоящей книги.

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

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

"Набор символов" – строка, содержащая произвольный набор символов и знаков Любой набор символов и знаков (включая специальные), взятый в кавычки, Mathematica рассматривает в качестве строки. При этом, ограничивающие кавычки не видны при выводе/возврате строчной структуры. Между тем, данные кавычки визуализируются при применении к строке функции InputForm, как иллюстрирует простой пример:

In[3405]:= "avzagnvsvArtKr6" Out[3405]= avzagnvsvArtKr In[3406]:= % Out[3406]= avzagnvsvArtKr In[3407]:= InputForm[%] Out[3407]//InputForm = "avzagnvsvArtKr6" Расширение функциональной среды системы Mathematica Более того, в режиме документа кавычки будут появляться автоматически, как только начинается редактирование строки. Строка имеет заголовок String, распознаваемый по функциям Head и Part, тогда как шаблон _String соответствует произвольной строке:

In[3412]:= h = "avzagnvsvArtKr6";

{Head[h], Part[h, 0]} Out[3412]= {String, String} In[3413]:= Cases[{h, 70, a + b, "Art", "Kr"}, _String] Out[3413]= {"avzagnvsvArtKr6", "Art", "Kr"} In[3414]:= Map[StringQ, {h, 70, a + b, "Art", "Kr"}] Out[3414]= {True, False, False, True, True} Более того, по вызову функции StringQ[x] возвращается True, если x – строка, и False в противном случае, как иллюстрирует последний пример предыдущего фрагмента.

Попытка присвоения строке значения инициирует ошибочную ситуацию с выводом соответствующего сообщения. Функцией Quiet можно подавить вывод сообщения, но сути это, естественно, не меняет, например:

In[3416]:= "avzagnvsvArtKr6" = Set::setraw: Cannot assign to raw object avzagnvsvArtKr6.

Out[3416]= In[3417]:= Quiet["avzagnvsvArtKr6" = 70] Out[3417]= Mathematica обеспечивает пользователя достаточно большимй набором функций для разнообразной обработки строк. Большинство этих функций рассматривает строки, последовательности символов, однако многие из этих функций подобны тем, которые используются для обработки списочных структур. Не вдаваясь в детальное описание, представим лишь несколько ярко выраженных т.н. строчных функций, а именно:

"x1" "x2"... "xn";

StringJoin["x1", "x2",..., "xn"];

StringJoin[{["x1", "x2",..., "xn"}] – возвращает результат конкатенации строк "x1", "x2",..., "xn";

StringLength[x] – возвращает количество символов в строке x;

StringReverse[x] – возвращает результат обращения символов в строке x;

ToString[x] – возвращает результат конвертирования выражения x в строку;

ToExpression[x] – возвращает выражение, полученное, как результат интерпретации строки x как Input-параграфа;

имеет еще два формата кодирования;

в таком формате функцию ToExpression при весьма естественных допущениях вполне можно было бы рассматривать как обратную для предыдущей функции ToString, например:

In[3427]:= (a + b)/(c – d) === ToExpression[ToString[InputForm[(a + b)/(c – d)]]] Out[3427]= True В любом случае функция ToExpression оказывается весьма эффективным средством в контексте своих возможностей по организации динамической генерации выражений, программируемых в форме строчных конструкций средствами обработки строчных выражений и вычисляемых в процедурном режиме, активизируя в текущем сеансе, в частности, определения процедур/функций. Об этом будет идти речь несколько ниже.

Однако, здесь не все так просто, если не исключать выражения x, содержащие внутри В.З. Аладьев, Д.С. Гринь себя строчные подвыражения, как иллюстрирует следующий простой пример:

In[3419]:= ToString[{a, "b", c, "", d}] Out[3419]= "{a, b, c,, d}" In[3420]:= ToExpression[%] Out[3420]= {a, b, c, Null, d} В определенном смысле это недостаток функции ToString и для его устранения нами была предложена ее модификация – функция ToString1, его устраняющая и полезная во многих приложениях, имеющих дело с обработкой строчных структур. Следующий пример приведен для сравнения с предыдущим примером применения ToString, как видим, полученные результаты достаточно красноречивы.

In[3429]:= ToString1[{a, "b", c, "", d}] Out[3429]= "{a, \"b\", c, \"\", d}" In[3430]:= ToExpression[%] Out[3430]= {a, "b", c, "", d} Таким образом, между функциями ToString и Tostring1 существует принципиальное различие, определяемое тем, что функция Tostring1 при каждом новом применении к результату своего предыдущего применения производит обрамление его скобками. В следующем простом примере этот момент прослеживается весьма четко, а именно:

In[3433]:= {ToString["x"], ToString1["x"], ToString["\"x\""], ToString1["\"x\""]} Out[3433]= {"x", "\"x\"", "\"x\"", "\"\\\"x\\\"\""} Строки, генерируемые функцией ToString1, подобно случаю списков можно назвать StringString (строки строк) и для их тестирования может быть использована довольно простая функция, вызов которой StringStringQ[x] возвращает True, если выражение x представляет собой строку StringString-типа, и False в противном случае. Следующий фрагмент представляет исходный код функции с примерами ее применения.

In[3437]:= StringStringQ[x_] := If[! StringQ[x], False, If[SuffPref[x, "\"", 1] && SuffPref[x, "\"", 2], True, False]] In[3438]:= Map[StringStringQ, {"\"vsvartkr\"", "vsvartkr", a+b, "\"\\\"vsvartkr\\\"\""}] Out[3438]= {True, False, False, True} In[3703]:= StringLevels[x_String] := Block[{a = x, n = –1}, While[StringQ[a], a = ToExpression[a];

n++;

Continue[]];

n] In[3704]:= Map[StringLevels, {"agn", "\"vsv\"", "\"\\\"art\\\"\"", rans}] Out[3704]= {0, 1, 2, StringLevels[rans]} В определенном смысле функция ToString1 генерирует вложенные строки аналогично вложенным спискам, и уровень вложенности строки x можно определять процедурой StringLevels[x], возвращающей уровень вложенности строки x при условии, что нулевой уровень соответствует стандартной строке. Наряду с представленными средствами в дальнейшем изложении будет рассмотрен целый ряд средств как расширяющих, так и дополняющих стандартные средства пакета, ориентированные на обработку строк.

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

StringTake[x, n] – подстроку строки x, ограниченную позициями, заданными n;

имеет 6 форматов кодирования, обеспечивающих различные способы выделения подстрок;

StringDrop[x, n] – результат удаления из строки x подсроки, ограниченной позициями, заданными n;

располагает 5 форматами кодирования, обеспечивающими различные методы удаления подстрок. В определенном плане функции StringTake и StringDrop, которые предназначены для работы со строками, аналогичны функциям Take и Drop, которые предназначены для работы со списочными структурами;

StringInsert[x, y, n] – результат вставки строки y в строку x в позицию, определенную n;

имеет 4 формата кодирования, определяющие различные способы вставки;

StringReplacePart[x, y, n] – результат замены в строке x подстроки, заданной позициями n, на строку y;

имеет 3 формата кодирования, определяющие разные способы замены;

StringPosition[x, y] – список позиций, занимаемых непосредственно подстроками или подстроками, отвечающими шаблонам, определенным y, в строке x;

имеет 5 форматов кодирования, определяющих различные способы поиска вхождений подстрок;

StringCount[x,y] – число вхождений в строку x непосредственно подстрок или подстрок, отвечающих шаблонам, определенным y;

имеет 4 формата кодирования;

StringFreeQ[x, y] – True, если строка x не содержит непосредственно подстрок y либо подстрок, отвечающих шаблонам y, и False в противном случае;

функция имеет три формата кодирования;

StringReplace[x, y – z] – результат применения к строке x одиночного правила y – z либо их списка;

функция имеет три формата кодирования;

StringReplaceList[x, y – z] – список результатов применения к строке x одного правила y – z (для каждого вхождения y в x) либо их списка;

имеет 3 формата кодирования;

StringSplit[x, y] – список подстрок строки x, полученных разбиением ее разделителем, в качестве которого задана подстрока y непосредственно или подстрока, отвечающая шаблону y;

вызов функции в формате StringSplit[x] в качестве разделителя полагает пробел;

функция имеет 7 форматов кодирования;

Sort[x] или Sort[x, y] – результат сортировки списка строк x в стандартном словарном порядке либо в порядке, определенном сортирующей функцией y соответственно. В качестве довольно полезного расширения функции Sort на отдельные строки можно предложить функцию SortLS, вызов которой SortLS[x, y] в качестве первого аргумента x допускает список из элементов типа {Numeric, Symbol, String}, строку и целое число;

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

In[3452]:= SortLS[x_ /;

ListQ[x] || StringQ[x] || IntegerQ[x], y_] := If[ListQ[x], Sort[x, y], If[StringQ[x], Evaluate, ToExpression][StringJoin[Sort[Characters[If[StringQ[x], x, ToString[x]]], y]]]] В.З. Аладьев, Д.С. Гринь In[3453]:= Map[SortLS, {"Kr16Art23", {"9", "7", "5", "3"}, "avzransian", {75, 450, 70, 23, 16}}] Out[3453]= {"1236AKrrt", {"3", "5", "7", "9"}, "aaainnrsvz", {16, 23, 70, 75, 450}} In[3454]:= Map[SortLS, {"Kr16", {Art23, "9", 7, "5"}, "avzrans", {ian, "A"}, {75, 4, "70", 23, 16}}] Out[3454]= {"16Kr", {7, "5", "9", Art23}, "aanrsvz", {"A", ian}, {4, 16, 23, 75, "70"}} In[3455]:= Map[SortLS, {"Kr16", {Art23, "9", 7, "5"}, "avzrans", {ian, "A"}, 459, 7654, –63976}] Out[3455]= {"16Kr", {7, "5", "9", Art23}, "aanrsvz", {"A", ian}, 459, 4567, –36679} In[3456]:= Sort["avzransia"] Sort::normal: Nonatomic expression expected at position 1 in Sort[avzransia].

Out[3456]= Sort["avzransia"] StringTrim[x] и StringTrim[x, y] – результат усечения строки x на пробелы и подстроки, соответствующие шаблону y, соответственно с обоих концов строки.

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

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

Characters[x] – результат конвертирования строки x в список символов, составляющих данную строку;

все символы списка представляются в строчном формате;

StringJoin[x] – результат конвертирования списка x символов, указанных в строчном формате, в строку;

DigitQ[x] – True, если в строке x все символы – цифры, и False в противном случае;

LetterQ[x] – True, если в строке x все символы – буквы, и False в противном случае;

UpperCaseQ[x] – True, если в строке x все символы – прописные буквы (символы верхнего регистра), тогда как False в противном случае;

LowerCaseQ[x] – True, если в строке x все символы – строчные буквы (символы нижнего регистра), тогда как False в противном случае;

ToUpperCase[x] – результат конвертирования всех букв строки x в прописные;

ToLowerCase[x] – результат конвертирования всех букв строки x в строчные;

CharacterRange[x, y] – список символов в строчном формате в диапазоне x.. y, где x, y – символы в строчном формате.

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

StringExpression[x1, x2, …, xn] x1~~x2~~ … ~~xn или где x1, x2, …, xn – последовательность строк и символьных шаблонов. Такие шаблоны, в частности, достаточно широко используются в функции StringReplace, обеспечивая различного рода замены в строках составляющих их подстрок, например:

In[1723]:= StringReplace["123456789abc", "345" ~~ _ – "VGS_Art23Kr16"] Out[1723]= "12VGS_Art23Kr16789abc" Для тестирования строк на соответствие строчным шаблонам используется функция, имеющая три формата кодирования, простейший из которых имеет следующий вид, Расширение функциональной среды системы Mathematica а именно StringMatchQ[x, h], вызов которой возвращает True, если строка x отвечает h шаблону, и False в противном случае, как иллюстрирует следующий простой пример:

In[1725]:= StringMatchQ["avz7075agn", "avz" ~~ ~~ "agn"] Out[1725]= True In[1726]:= StringMatchQ["avz7075agn", "avz" ~~ _ ~~ "agn"] Out[1726]= False In[1727]:= StringMatchQ["avzagn", "avz" ~~ _ ~~ "agn"] Out[1727]= True In[1728]:= StringMatchQ["avzagn", "avzagn"] Out[1728]= True Следует иметь в виду, что одинарный символ "_" (подчеркивания) в строчном шаблоне отвечает отдельным символам, тогда как двойной символ "" – последовательности из одного либо нескольких символов, в то время как тройной символ "_" соответствует пустой последовательности или последовательности из нескольких символов, как это наглядно иллюстрирует представленный выше пример к функции StringMatchQ. Из часто используемых функций работы со строками, поддерживающими использование строчных шаблонов, можно отметить такие, как StringCases, StringReplace, StringSplit.

Подобно ранее рассмотренной темы по шаблонам, для строчных шаблонов приняты следующие соглашения, определяющие типы шаблонов и простых, и с условиями:

_ – одиночный символ;

– произвольная последовательность из одного или более символов;

_ – произвольная последовательность пустая либо из нескольких символов;

x_, x, x_ – подстроки с заданным именем x;

Шаблон /;

Условие – соответствие шаблону при истинности условия.

С другими вопросами подобной тематики возможно ознакомиться, например, в [116].

Дополнительно Mathematica поддерживает символьные спецификации для некоторых общих классов символов, содержащихся в строчных шаблонах, а именно:

NumberString – числовые символы;

DigitCharacter – десятичные цифры 0..9;

LetterCharacter – латинские буквы;

WhitespaceCharacter – символы пробела, перевода на новую строку, табуляции либо другого символа подобного типа;

WordCharacter – латинские буквы либо цифры;

Except[x] и Except[x, y] – шаблоны, которые исключают выражения, соответствующие x, и которые исключают выражения, соответствующие y, но не x, соответственно.

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

In[1752]:= StringCases[{"123abx", "abc", "x y", "avx\nagn"}, LetterCharacter] Out[1752]= {{"a", "b", "x"}, {"a", "b", "c"}, {"x", "y"}, {"a", "v", "x", "a", "g", "n"}} В.З. Аладьев, Д.С. Гринь In[1753]:= StringCases[{"123abx", "abc", "x y", "avx\nagn"}, NumberString] Out[1753]= {{"123"}, {}, {}, {}} In[1754]:= StringCases[{"123abx", "abc", "x y", "avx\nagn"}, WhitespaceCharacter] Out[1754]= {{}, {}, {" "}, {"\n"}} In[1755]:= StringCases[{"123abx", "abc", "x y", "avx\nagn"}, WordCharacter] Out[1755]= {{"1", "2", "3", "a", "b", "x"}, {"a", "b", "c"}, {"x", "y"}, {"a", "v", "x", "a", "g", "n"}} In[1756]:= StringCases[{"123ax", "a", "x y", "avz"}, Except[LetterCharacter, NumberString]] Out[1756]= {{"123"}, {}, {}, {}} In[1757]:= StringReplace["ab cd fg hk m n", WhitespaceCharacter – ""] Out[1757]= "abcdfghkmn" Строчные шаблоны довольно часто используются для извлечения некоторых структур из текстовых строк. В целом ряде случаев текстовые строки могут содержать символы пробела, перевода на новую строку, табуляции, которые не нужно учитывать, с такой целью в пакете определен шаблон Whitespace, определяющий последовательности из произвольной комбинации данных символов, как иллюстрирует следующий пример:

In[1723]:= StringReplace["ab \ncd fg hk \nm np\nagn", WhitespaceCharacter – ""] Out[1723]= "abcdfghkmnpagn" В котором обеспечивается уплотнение строки за счет удаления из нее всех указанных символов. В данном свете представляется довольно полезной процедура RedSymbStr, чей вызов RedSymbStr[x, y, z] возвращает результат замены всех подстрок, состоящих из символа y, строки x на символ либо строку z. В случае отсутствия вхождений y в x, вызов процедуры возвращает строку x неизменной. Следующий фрагмент приводит исходный код процедуры RedSymbStr наряду с примерами ее применения.

In[1802]:= RedSymbStr[x_String, y_ /;

SymbolQ1[y], z_String] := Module[{a = StringPosition[x, y], b}, If[StringFreeQ[x, y], x, b = Map[#[[1]] &, a]];

b = Sort[DeleteDuplicates[Map[Length, Split[b, #2 – #1 == 1 &]]], Greater];

b = Mapp[Rule, Map3[StringMultiple, y, b], z];

StringReplace[x, b]] In[1803]:= RedSymbStr["a b c d ef gh x y z", " ", " "] Out[1803]= "a b c d ef gh x y z" In[1804]:= RedSymbStr["a b c d ef gh x y z", " ", ""] Out[1804]= "abcdefghxyz" In[1805]:= RedSymbStr["a b c d ef gh x y z", " ", "GGG"] Out[1805]= "aGGGbGGGcGGGdGGGefGGGghGGGxGGGyGGGz" In[1806]:= RedSymbStr["a b c d ef gh x y z", "X", "GGG"] Out[1806]= "a b c d ef gh x y z" In[1849]:= SymbolQ1[x_] := If[Length[ToCharacterCode[ToString[x]]] == 1, True, False] In[1850]:= Map[SymbolQ1, {70, "G", "Kr", "6", "#", "!", ":", sv}] Out[1850]= {False, True, False, True, True, True, True, False} Завершает фрагмент простая, но в целом ряде случаев полезная, функция SymbolQ1, Расширение функциональной среды системы Mathematica чей вызов SymbolQ1[x] возвращает True, если x является одиночным символом, и False в противном случае. Функция используется в заголовке процедуры RedSymbStr.

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

In[1731]:= StringReplace[{"70avzagn", "4507570avzagn"}, StartOfString ~~ "70" – "VSV"] Out[1731]= {"VSVavzagn", "4507570avzagn"} In[1732]:= StringReplace[{"70avzagn", "4507570avzagnv"}, "agn" ~~ EndOfString – "VS"] Out[1732]= {"70avzVS", "4507570avzagnv"} Тогда как для обозначения конца строки в шаблонах используется EndOfString, как в последнем приведенном выше примере. Пакет располагает еще целым рядом средств программирования строчных шаблонов, здесь нами не рассматриваемым. Тогда как заинтересованный читатель отсылается к пособиям [100,116] или к справке по пакету.

Механизм шаблонов пакета обеспечивают достаточно серьезный метод производить разнообразную обработку строчных структур. При этом, знакомство со специальными языками обработки строк в ряде случаев позволяет определять строчные шаблоны с помощью нотации регулярных выражений, которые определяются в пакете на основе функции RegularExpression. Эта функция может использоваться для представления типов строк в функциях StringMatchQ, StringReplace, StringCases, StringSplit. Функция RegularExpression поддерживает стандартный синтаксис регулярных выражений вида, используемого в типичных языках программирования обработки строк, в частности, в языке Perl. В качестве основной особенности языка Perl можно полагать именно его достаточно широкие возможности для работы с текстовой информацией, в том числе работа с регулярными выражениями, встроенными в синтаксис языка. Использование в среде пакета регулярных выражений для расширения механизма строчных шаблонов здесь не рассматривается и читатель отсылается к изданиям, например, [100,116].

3.5. Выражения в программной среде пакета Mathematica Аналогично целому ряду программных систем и систем компьютерной математики пакет Mathematica под «выражением» понимает все, с чем он манипулирует (графики, списки, формулы, числа различного типа и т.д.). Не взирая на то, что все эти выражения на первый взгляд, порой, сильно различаются, пакет представляет их единым образом.

Приведем примеры представления некоторых выражений в полной форме, а именно:

Выражение Полная форма x+y+z Plus[x, y, z] x^n Power[x, n] !x Not[x] {{a, b, c}} List[List[a, b, c]] a – b Rule[a, b] a=b Set[a, b] В.З. Аладьев, Д.С. Гринь a && b And[a, b] a := b Null И лишь отложенное присвоение (:=) не имеет полной формы. С целью определения заголовка выражения (его определяющего типа) используется функция Head, чей вызов Head[expr] возвращвет заголовок выражения expr, например:

In[1629]:= Map[Head, {ProcQ, Sin, 70, a + b, Function[{x, y}, x + y], G[x], S[6], x*y, x^y}] Out[1629]= {Symbol, Symbol, Integer, Plus, Function, G, S, Times, Power} Для более точного определения заголовков нами была создана модификация Head1, расширяющая возможности стандартной функции Head, как иллюстрирует пример:

In[1630]:= Map[Head1, {ProcQ, Sin, 70, a + b, Function[{x, y}, x + y], G[x], S[6], x*y, x^y}] Out[1630]= {Procedure, System, Integer, Plus, Function, G, S, Times, Power} Между тем, и процедура Head1 имеет ряд ограничений при тестировании заголовков некоторых выражений, как показывают примеры фрагмента. В частности, относится это к тестированию операции отложенных вычислений. Поэтому дальнейшее развитие в виде процедуры Head2 расширяет процедуру Head1, прежде всего, на отложенные вычисления, возвращая на них значения RuleDelayed, SetDelayed || TagSetDelayed.

Следующий фрагмент представляет исходный код процедуры Head2 с примерами ее применения в сравнительном отношении с функцией Head и процедурой Head1. Ее вызов Head2[x] возвращает идентифицируемый заголовок выражения x.

In[755]:= Head2[x_] := Module[{a}, Off[MessageName[Definition, "ssle"]];

a = If[StringQ[x], String, If[If[FunctionQ[x] === True, Function, If[ProcQ[x], Procedure, If[SystemQ[x], System, If[HeadPF[x] === x, Symbol, Head[x]]]]]];

On[MessageName[Definition, "ssle"]];

If[SuffPref[ToString[DefFunc[ x]], "Attributes[Null]", 1], SetDelayed || TagSetDelayed, ReductRes[Head1, a]]] In[756]:= Map[Head, {ProcQ, Sin, 6, a + b, Function[{x}, x], G[x], G := S, x*y, x^y, G = S}] Out[756]= {Symbol, Symbol, Integer, Plus, Function, S, Symbol, Times, Power, Symbol} In[757]:= Map[Head1, {ProcQ, Sin, 6, a + b, Function[{x}, x], G[x], G := S, x*y, x^y, G = S}] Out[757]= {Procedure, System, Integer, Plus, Function, S, System, Times, Power, Symbol} In[758]:= Map[Head2, {ProcQ, Sin, 6, a + b, Function[{x}, x], G[x], G := S, x*y, x^y, G = S}] Out[758]= {Procedure, System, Integer, Plus, Function, S, SetDelayed || TagSetDelayed, Times, Power, Symbol} In[759]:= Flatten[{Quiet[Head2[a b]], Map[Head2, {a | b, a || b, a b, a = b, a : b}]}] Out[759]= {StringJoin, Alternatives, Or, Less, GreaterEqual, RuleDelayed} In[760]:= Map[Head2, {G /: F[G[x_]] := FG[x], G := S}] Out[760]= {SetDelayed || TagSetDelayed, SetDelayed || TagSetDelayed} В виду сказанного, процедура Head2 имеет вполне определенное значение для более точной (относительно стандарта) классификации выражений по типу их заголовков.

Язык пакета Mathematica базируется на соответствующей грамматике, определяющей алгоритм преобразования входа во внутреннюю форму. Так, грамматика определяет, Расширение функциональной среды системы Mathematica как будут группироваться компоненты входа. Например, при вводе выражения b^c + a грамматика пакета определяет, что его следует рассматривать как a+b^c. Mathematica выбирает именно такую группировку, т.к. рассматривает оператор (^), как имеющий более высокий приоритет, чем оператор (+). Итак, термы выражения с операторами с более высоким приоритетом располагаются перед термами выражения с операторами с более низким приоритетом. При этом, приоритеты определены не только обычным традиционным математическим операторам, но и формам таким как {–, :=, ;

и др.}. В свою очередь, символы, не являющиеся буквами, буквенные формы или структурные элементы рассматриваются пакетом в качестве операторов;

стандартные операторы в среде пакета поддерживаются встроенными функциями либо другими правилами. С приоритетами всех операторов и форм пакета Mathematica возможно ознакомиться в специальной таблице, которая доступна по фразе "Operator Input Forms" в справке по пакету;

таблица представляет все операторы пакета в порядке убывания приоритета.

Со всеми операторами среды Mathematica и их типами можно ознакомиться в справке.

Любое введенное в пакет выражение Expr конвертируется им в стандартную (полную) форму, вид которой можно получать по функции FullForm[Expr], например:

In[1638]:= Map[FullForm, {{a + b}, Sin[x], a^b, a – b, a || b, a && b, c := d}] Out[1638]= {List[Plus[a, b]], Sin[x], Power[a, b], Rule[a, b], Or[a, b], And[a, b], Null} Еще раз отметим, пакет рассматривает в качестве выражения все, что в него вводится.

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

In[1644]:= Map[Head, {G[x, y], Sin[x], Cos[450], V[70*x + S[x, y]], Head1}] Out[1644]= {S, Sin, Cos, V, Symbol} In[1645]:= Map[Head2, {G[x, y], Sin[x], Cos[450], V[70*x + S[x, y]], Head1}] Out[1645]= {S, Sin, Cos, V, Procedure} Таким образом, понятие выражения является важным объединяющим принципом в Mathematica, а тот факт, что каждый объект в Mathematica имеет ту же внутреннюю структуру, позволяет охватить много областей сравнительно небольшим количеством базовых операций. Между тем, несмотря на то, что все выражения имеют одинаковую базовую структуру, пакет предоставляет множество различных функций для работы как с выражением в целом, так и с отдельными его компонентами.

Средства тестирования выражений. Пакет располагает рядом средств тестирования корректности синтаксиса выражений, из которых пользователю доступны 2 функции SyntaxQ["x"] – возвращает True, если x – синтаксически корректное выражение, и False в противном случае;

SyntaxLength["x"] – возвращает число p символов, начиная с самого начала строки "x", которое определяет синтаксически корректное выражение StringTake["x", {1, p}];

при этом, в случае p StringLength["x"] пакет декларирует, что вся строка "x" корректна, но формирование корректного выражения требует ее продолжения. На наш взгляд, В.З. Аладьев, Д.С. Гринь это не совсем удобно при обработки выражений. Поэтому предложено расширение в виде процедуры SyntaxLength1, чей исходный код представляется в нижеследующем фрагменте с наиболее типичными примерами применения процедуры.

In[1988]:= SyntaxQ1[x_ /;

StringQ[x]] := If[Quiet[ToExpression[x]] === $Failed, False, True] In[1989]:= Map[SyntaxQ1, {"(a+b/", "d[a[1]] + b[2]"}] Out[1989]= {False, True} In[1990]:= SyntaxLength1[x_ /;

StringQ[x], y_] := Module[{a = "", b = 1, d, h = {}, c = StringLength[x]}, While[b = c, d = Quiet[ToExpression[a = a StringTake[x, {b, b}]]];

If[! SameQ[d, $Failed], h = Append[h, StringTrim[a]]];

b++];

h = DeleteDuplicates[h];

If[{y} != {} && ! HowAct[{y}[[1]]], {y} = {h}];

If[h == {}, 0, StringLength[h[[–1]]]]] In[1991]:= SyntaxLength["(a+b/"] Out[1991]= In[1992]:= SyntaxLength1["(a+b/"] Out[1992]= In[1993]:= {SyntaxLength1["(a+b", p], p} Out[1993]= {0, {}} In[1994]:= SyntaxLength["d[a[1]] + b[2]"] Out[1994]= In[1995]:= SyntaxLength1["d[a[1]] + b[2]"] Out[1995]= In[1997]:= {SyntaxLength1["d[a[1]] + b[2]", g], g} Out[1997]= {14, {"d", "d[a[1]]", "d[a[1]] + b", "d[a[1]] + b[2]"}} Вызов SyntaxLength1[x] возвращает максимальный номер p позиции в строке x такой, что ToExpression[StringTake[x, {1, p}]] – синтаксически корректное выражение, иначе возвращается 0;

вызов SyntaxLength1[x, y] через второй необязательный аргумент y – неопределенную переменную – дополнительно возвращает список подстрок строки x, представляющих корректные выражения. Выше приведены сравнительные примеры применения функции SyntaxLength и процедуры SyntaxLength1, которые достаточно наглядно иллюстрируют сказанное. Там же приведен простой пример программной реализации стандартной функции SyntaxQ в лице функции SyntaxQ1.

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

Expand[x] – раскрывает произведения и положительные целые степени в x;

ExpandAll[x] – по–возможности максимально раскрывает выражение x;

Factor[x] – представляет полином x в форме произведения сомножителей;

Together[x] – приводит выражение x к общему знаменателю;

Apart[x] – разделяет выражение x на термы с простыми знаменателями;

Cancel[x] – сокращает x на общие множители в числителях и знаменателях;

Расширение функциональной среды системы Mathematica Simplify[x] – алгебраическими преобразованиями пытается упростить выражение x.

Данные функции составляют основную группу средств форматирования выражений.

Приоритет упорядочивает термы выражения там, где это возможно, в соответствии со стандартными математическими соглашениями, позволяя минимизировать количество круглых скобок, которые, как правило, необходимы. Так, у оператора отношения {} приоритет более низкий, чем у арифметического оператора (+), что дает возможность корректно определять выражения типа G + V 135 без использования круглых скобок.

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

In[1715]:= {a && b || c, a && (b || c), (a + b)^c, (a + b)/(c – d)} Out[1715]= {(a && b) || c, a && (b || c), (a + b)^c, (a + b)/(c – d)} Средства обработки выражений на уровне их компонентов. Средства такой группы обеспечивают довольно эффективную дифференцированную обработку выражений.

Унифицированная символьная архитектура пакета Mathematica дает возможность по непосредственному обобщению элементно–ориентированных списочных операций на произвольные выражения, поддерживая операции как на отдельных термах, так и на наборах термов на заданных уровнях в деревьях выражений. Не вдаваясь детально во все средства, поддерживающие работу с составными частями выражений, приведем лишь список основных из них с кратким назначением. Тогда как с более детальным их описанием, включая допустимые форматы кодирования, можно познакомиться либо в справке по пакету, либо в соответствующей литературе по пакету, например, в [100].

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

Part[x, k] – получение k–й части произвольного выражения x;

Variables[p] – возвращает список всех независимых переменных полинома p;

тогда как ее применение к произвольному выражению p имеет определенные ограничения;

Тогда как для получения всех независимых переменных произвольного выражения x вполне можно использовать довольно несложную функцию, чей вызов UnDefVars[x] возвращает список всех независимых переменных произвольного выражения x. Ниже представлены исходный код функции с примерами ее применения в сравнительном контексте относительно стандартной функции Variables. В ряде случаев эта функция имеет определенные преференции относительно стандартной функции Variables.

In[1763]:= UnDefVars[x_] := Select[OP[x], Quiet[ToString[Definition[#]]] == "Null" &] In[1764]:= UnDefVars[(x^2 – y^2)/(Sin[x] + Cos[y]) + a*Log[x + y + z – G[h, t]]] Out[1764]= {a, G, h, t, x, y, z} In[1775]:= Variables[(x^2 – y^2)/(Sin[x] + Cos[y]) + a*Log[x + y + z – G[h, t]]] Out[1775]= {a, x, y, Cos[y], Log[x + y + z – G[h, t]], Sin[x]} In[1765]:= H := 70;

Map[UnDefVars, {a + 70*b, a*Sin[x]*Cos[y], {a, b}, a*F[h, g, s] + H}] Out[1765]= {{a, b}, {a, x, y}, {a, b}, {a, F, g, h, s}} В.З. Аладьев, Д.С. Гринь In[1766]:= {Variables[(x + y)^3 + 6 z^2 – y z + 70], UnDefVars[(x + y)^3 + 6 z^2 – y z + 70]} Out[1766]= {{x, y, z}, {x, y, z}} Length[x] – возвращает число частей выражения x;

эквивалентна простой функции:

MaxParts[x_] := Length[Op[x]] In[1709]:= X = (x^2 – y^2)*(Sin[x] + Cos[y])*a*Log[x + y]*c;

{Length[X], MaxParts[X]} Out[1709]= {5, 5} First[x] – возвращает первую часть выражения x;

эквивалентна Part[x, 1];

Last[x] – возвращает последнюю часть выражения x;

эквивалентна Part[x, –1];

Most[x] – возвращает выражение x без последней части;

эквивалентна x[[1 ;

;

–2]];

Rest[x] – возвращает выражение x без первой части;

эквивалентна x[[2 ;

;

–1]];

Take[x, n] – возвращает части выражения x, определенные аргументами, начиная со второго n;

имеет четыре формата кодирования и эквиваленты x[[m ;

;

n]];

Drop[x, n] – возвращает выражение x без частей, определенных аргументами, начиная со второго n;

имеет шесть форматов кодирования и эквиваленты x[[m ;

;

n]];

Extract[x, n] – извлекает из выражения x часть, определенную аргументами, начиная со второго n;

имеет три форматав кодирования и эквиваленты с Part;

Replace[x, r {, l}] – возвращает результат применения правила r типа a b или списка таких правил с целью преобразования выражения x как единого целого;

применение 3-го необязательного аргумента l определяет применение правил r к частям l–уровня выражения x. Между тем, функция Replace имеет ряд ограничений, ряд из которых в значительной мере снимает процедура, чей вызов Replace1[x, r] возвращает результат применения правил r к независимым (всем либо выборочно) переменным выражения x.

В случае обнаружения процедурой пустых правил печатается сообщение с указанием списка тех правил r, которые оказались пустыми, т.е. левые части которых не входят в список независимых переменных выражения x. Фрагмент представляет исходный код процедуры Replace1 наряду с примерами ее типичного применения. При этом, дано сравнение с результатом применения функции Replace на том же самом выражении.

In[1679]:= Replace1[x_, y_ /;

ListQ[y] && DeleteDuplicates[Map[Head, y]] == {Rule} || Head[y] == Rule] := Module[{a = x //FullForm //ToString, b = UnDefVars[x], c, p, l, h = {}, r, k = 1, d = ToStringRule[DeleteDuplicates[Flatten[{y}]]]}, p = Mapp[RhsLhs, d, "Lhs"];

c = Select[p, ! MemberQ[Map[ToString, b], #] &];

If[c != {}, Print["Rules " ToString[Flatten[Select[d, MemberQ[c, RhsLhs[#, "Lhs"]] &]]] " are vacuous"]];

While[k = Length[d], l = RhsLhs[d[[k]], "Lhs"];

r = RhsLhs[d[[k]], "Rhs"];

h = Append[h, {"[" l – "[" r, " " l – " " r, l "]" – r "]"}];

k++];

Simplify[ToExpression[StringReplace[a, Flatten[h]]]]] In[1680]:= X = (x^2 – y^2)/(Sin[x] + Cos[y]) + a*Log[x + y];

Replace[X, {x – a + b, a – 70, y – Cos[a], z – Log[t]}] Out[1680]= a Log[x + y] + (x^2 – y^2)/(Cos[y] + Sin[x]) Расширение функциональной среды системы Mathematica In[1681]:= Replace1[X, {x – a + b, a – 70, y – Cos[a], z – Log[t], t – c + d}] Rules {z – (Log[t]), t – (c + d)} are vacuous Out[1681]= 70 Log[a + b + Cos[a]] + ((a + b)^2 – Cos[a]^2)/(Cos[Cos[a]] + Sin[a + b]) In[1682]:= Replace1[X], {x – a + b, a – 70, y – Cos[a]}] Out[1682]= 70 Log[a + b + Cos[a]] + ((a + b)^2 – Cos[a]^2)/(Cos[Cos[a]] + Sin[a + b]) В ряде случаев при преобразованиях выражений посредством подстановок возникает необходимость конвертации в строчный формат левых и правых частей правил типа "a b". Данную задачу решает довольно простая процедура ToStringRule, чей вызов ToStringRule[x] возвращает правило либо список правил x, чьи левые и правые части имеют строчный формат. Более того, правая часть берется в круглые скобки. Именно эта процедура используется вышепредставленной процедурой Replace1. Следующий фрагмент представляет исходный код процедуры с примерами ее применения.

In[1689]:= ToStringRule[x_ /;

ListQ[x] && DeleteDuplicates[Map[Head, x]] == {Rule} || Head[x] == Rule] := Module[{a = Flatten[{x}], b = {}, c, k = 1}, While[k = Length[a], c = a[[k]];

b = Append[b, ToString[RhsLhs[c, "Lhs"]] – "(" ToString[RhsLhs[c, "Rhs"]] ")"];

k++];

If[ListQ[x], b, b[[1]]]]] In[1690]:= {ToStringRule[a – b], ToStringRule[{a – b, c – d, m – n}]} Out[1690]= {"a" – "b", {"a" – "b", "c" – "d", "m" – "n"}} ReplacePart[x, n – a] – простейший формат вызова возвращает результат замены n–й части выражения x на a;

функция располагает еще четырьмя форматами.

В целом ряде случаев обработки выражений, в частности, вычисления производных x по подвыражениям выражения x либо интегрирования выражения x, когда в качестве переменной интегрирования x вместо простой переменной выступает подвыражение и т.д. весьма полезной оказывается процедура Replace2, вызов которой Replace2[x,y,z] возвращает результат замены в выражении x все входящие в него подвыражения y на выражение z. При невозможности выполнить замену вызов Replace2[x,y,z] возвращает значение $Failed, что довольно удобно при необходимости обеспечения непрерывных вычислений. Следующий фрагмент представляет исходный код процедуры наряду с примерами ее применения. Там же представлены примеры процедур D1 и Integrate1, которые базируются на процедуре Replace2 и обеспечивают соответственно операции дифференцирования и интегрирования выражений по сложным переменным.

In[1690]:= Replace2[x_, y_, z_] := Block[{a = Map11[ToString, FullForm, {x, y, z}], b}, SetAttributes[ToString1, Listable];

b = ToExpression[StringReplace[a[[1]], a[[2]] – a[[3]]]];

If[DeleteDuplicates[StringFreeQ[ToString1[Flatten[{b}]], "\""]] == {True}, ClearAttributes[ToString1, Listable];

b, ClearAttributes[ToString1, Listable];

$Failed]] In[1691]:= Replace[1 + 1/a, 1/a – Sin[x]] Out[1691]= 1 + 1/a In[1692]:= Replace2[Sin[x + Cos[y]] + x^2*Log[x + y], x, h^2] Out[1692]= h^4 Log[h^2 + y] + Sin[h^2 + Cos[y]] В.З. Аладьев, Д.С. Гринь In[1691]:= Replace2[Sin[x + Cos[y]] + 1/a^2 + x^2*Log[x + y], 1/a, h] Out[1691]= $Failed In[1670]:= D1[x_, y_] := Module[{a, b, c}, c = Replace2[D[b = Replace2[x, y, a];

If[b === $Failed, Return[$Failed], b], a], a, y];

If[b === $Failed, $Failed, c]] In[1701]:= {D1[Sin[x + Cos[y]] + x^2*Log[x + y], Cos[y]], D1[Sin[x], x]} Out[1701]= {Cos[x + Cos[y]], Cos[x]} In[1686]:= {D1[Sin[x + Cos[y]] + 1/a^2 + x^2*Log[x + y], 1/a], D1[Sin[x], x]} Out[1686]= {$Failed, Cos[x]} In[1702]:= Integrate1[x_, y_] := Module[{a, b, c}, c = Replace2[Integrate[b = Replace2[x, y, a];

If[b === $Failed, Return[$Failed], b], a], a, y];

If[b === $Failed, $Failed, c]] In[1703]:= {Integrate1[Sin[x + Cos[y]] + x^2*Log[x + y], Cos[y]], Integrate1[Tan[x], x]} Out[1703]= {–Cos[x] Cos[Cos[y]] + x^2 Cos[y] Log[x + y] + Sin[x] Sin[Cos[y]], –Log[Cos[x]]} In[1705]:= Replace2[1/a^2 + 1/(1/a + Cos[x]), 1/a, Sin[x]] Out[1705]= $Failed In[1706]:= Subs[1/a^2 + 1/(1/a + Cos[x]), 1/a, Sin[x]] Out[1706]= Sin[x]^2 + 1/(Cos[x] + Sin[x]) Между тем, не взирая на простоту и изящность реализаций процедур Replace2, D1 и Integrate1, говорить об их универсальности не приходится именно из-за ограничений процедуры Replace2, здесь не обсуждаемых. Тогда как заинтересованному читателю в качестве весьма полезного упражнения рекомендуется рассмотреть этот вопрос. В то же время два последних примера фрагмента иллюстрируют ограниченность Replace и большие возможности процедуры Subs, рассматриваемой нами несколько ниже. В любом случае процедуры Replace2, D1 и Integrate1 в ряде случаев довольно полезны, включая примененные при их программировании некоторые полезные приемы. Так, весьма полезным оказывается прием временного изменения атрибутов у ToString1.

Append[x, a] – возвращает результат дополнения выражения x подвыражением a;

при этом, дополнение производится на основе конструкции Head[x][x, a];

Prepend[x, a] – вызов возвращает результат расширения выражения x подвыражением a слева;

при этом, дополнение производится на основе конструкции Head[x][a, x];

так как пакет использует упомянутый выше принцип полного представления выражений, то в целом ряде случаев имеет место соотношение Append[x, a] Prepend[x, a], как это весьма наглядно иллюстрируют следующие весьма простые примеры, а именно:

In[1664]:= X = (a + b)/(c + d);

{Append[X, Sin[x]], Prepend[X, Sin[x]]} Out[1664]= {((a + b) Sin[x])/(c + d), ((a + b) Sin[x])/(c + d)} In[1665]:= Y = {a + b + c + d};


{Append[Y, 70], Prepend[Y, 70]} Out[1665]= {{a + b + c + d, 70}, {70, a + b + c + d}} Insert[x, a, n] – простейший формат вызова возвращает результат вставки выражения a по месту n–й части выражения x, раздвигая его;

функция имеет еще два формата;

Delete[x, n] – простейший формат вызова возвращает результат удаления выражения n–й части выражения x, упрощая его;

функция имеет еще два формата кодирования;

Расширение функциональной среды системы Mathematica более того, в обоих функциях Insert и Delete вычисление n–й позиции производится, исходя из полной формы выражений, ранее упомянутой и принятой в пакете;

DeleteCases[x, p] – простейший формат вызова возвращает результат удаления всех частей выражения x, соответствующих шаблону p;

функция имеет еще два формата;

Position[x, p] – возвращает список позиций, на которых в выражении x появляются все подвыражения, соответствующие шаблону p;

функция имеет 3 формата кодирования;

при этом, возвращаемый функцией список позиций имеет форму, вполне пригодную для использования функциями Extract, ReplacePart и MapAt, но не Part, например:

In[1688]:= X = (a^b + Sin[x])/(c^d – Cos[x]);

Position[X, _^_] Out[1688]= {{1, 1, 1}, {1}, {2, 1}} In[1689]:= ReplacePart[X, {%[[1]] – agn, %[[3]] – agn}] Out[1689]= (agn + Sin[x])/(agn – Cos[x]) MapAt[F, x, n] – простейший из форматов вызова возвращает результат применения F к части выражения x, находящейся на позиции n;

функция имеет еще два формата;

и данном случае n–я позиция определяется, исходя из полной формы выражения x;

Map[F, x] – простейший формат вызова возвращает результат применения функции F ко всем частям выражения x, находящимся на первом уровне;

функция Map имеет еще один формат кодирования, достаточно полезный в целом ряде приложений;

MapAll[F, x] – вызов функции возвращает результат применения функции F ко всем подвыражениям выражения x;

достаточно полезна в целом ряде приложений;

Level[x, n] – простейший формат вызова возвращает список всех подвыражений для x выражения на уровнях от 1 до n;

функция имеет еще один формат кодирования;

В качестве полезного обобщения функции Level можно рассматривать и процедуру, чей вызов Levels[x, h] возвращает список всех подвыражений для x выражения на всех его возможных уровнях, тогда как через второй аргумент h – независимую переменную – возвращается максимальное число уровней выражения x. Вообще говоря, имеет место следующее определяющее соотношение Levels[x, h] Level[x, Infinity], однако в случае процедуры Levels дополнительно возвращается максимальный уровень выражения x.

Фрагмент представляет исходный код процедуры Levels с примером ее применения в сравнении с функцией Level со вторым Infinity–аргументом.

In[1768]:= Levels[x_, h_ /;

ToString[Definition[h]] == "Null"] := Module[{a = {}, b, k = 1}, While[k Infinity, b = Level[x, k];

If[a == b, Break[], a = b];

k++];

h = k – 1;

a] In[1769]:= {Levels[(x^2 – y^2)/(Sin[x] + Cos[y]) + a*Log[x + y + z – G[h, t]], g], g} Out[1769]= {{a, x, y, z, –1, h, 7, G[h, 7], –G[h, 7], x + y + z – G[h, 7], Log[x + y + z – G[h, 7]], a Log[x + y + z – G[h, 7]], x, 2, x^2, –1, y, 2, y^2, –y^2, x^2 – y^2, y, Cos[y], x, Sin[x], Cos[y] + Sin[x], –1, 1/(Cos[y] + Sin[x]), (x^2 – y^2)/(Cos[y] + Sin[x])}, 6} In[1770]:= Level[(x^2 – y^2)/(Sin[x] + Cos[y]) + a*Log[x + y + z – G[h, t]], Infinity] Out[1770]= {{a, x, y, z, –1, h, 7, G[h, 7], –G[h, 7], x + y + z – G[h, 7], Log[x + y + z – G[h, 7]], a Log[x + y + z – G[h, 7]], x, 2, x^2, –1, y, 2, y^2, –y^2, x^2 – y^2, y, Cos[y], x, Sin[x], Cos[y] + Sin[x], –1, 1/(Cos[y] + Sin[x]), (x^2 – y^2)/(Cos[y] + Sin[x])}, 6} В.З. Аладьев, Д.С. Гринь In[1779]:= ExprOnLevels[x_] := Module[{a = {}, k = 1}, While[k = Depth[x], a = Append[a, MinusList[Level[x, k], Level[x, k – 1]]];

k++];

a[[1 ;

;

–2]]] In[1780]:= X = (x^2 – y^2)/(Sin[x] + Cos[y]) + a*Log[x + y + z – G[h, t]];

ExprOnLevels[X] Out[1780]= {{a Log[x + y + z – G[h, t]], (x^2 – y^2)/(Cos[y] + Sin[x])}, {a, Log[x + y + z – G[h, t]], x^2 – y^2, 1/(Cos[y] + Sin[x])}, {x + y + z – G[h, t], x^2, –y^2, Cos[y] + Sin[x], –1}, {x, y, z, x, 2, –1, y^2, Cos[y], Sin[x], –1}, {G[h, t], y, 2, y, x, –1}, {h, t}} Тогда как вызов довольно простой процедуры ExprOnLevels[x] возвращает вложенный список, элементами которого являются списки подвыражений выражения x, которые расположены на каждом из его уровней с 1-го до последнего. Предыдущий фрагмент завершается исходным кодом процедуры наряду с примером ее применения.

Depth[x] – возвращает общее число уровней в выражении x. Относительно массивов, векторов и матриц функция анализирует их подобно соответствующим им спискам;

по сравнению с вышепредставленной процедурой Levels функция Depth определяет на том же самом выражении x максимальное число его уровней на единицу больше:

In[1680]:= Clear[t];

{Levels[a + b + c^2, t], t, Depth[a + b + c^2]} Out[1680]= {{a, b, c, 2, c^2}, 2, 3} Sow и Reap – обеспечивают удобный способ для накопления списка промежуточных результатов при вычислении выражений. Функции Sow и Reap имеют 3 и 4 формата кодирования соответственно, охватывая весьма существенный диапазон приложений при программировании как прикладных, так и системных задач.

Для удобной визуализации структуры выражения довольно удобной представляется функция, вызов которой TreeForm[x] возвращает структуру выражения x в виде дерева его составляющих, как весьма наглядно иллюстрируют простые примеры, а именно:

In[1670]:= X = (x^2 – y^2)/(Sin[x] + Cos[y]) + a*Log[x + y + z – G[h, t]];

TreeForm[X] Out[1670]//TreeForm = Plus Times Times a Log Plus Power Plus Plus Power Times 1 Power x y z Times x 2 Cos Sin 1 G y 2 y x h t In[1671]:= Y = {{a, b, c}, {c, d, g}, {x, y, z}};

TreeForm[Y] Out[1671]//TreeForm = List List List List a b c c d g x y z Расширение функциональной среды системы Mathematica В случае сложных выражений, порождающих большие малообозримые деревья, можно получать части дерева, начиная с первого и до заданного уровня n по вызову функции TreeForm[x, n]. Данное средство довольно полезно для структурного как анализа, так и представления выражений. Таким образом, любое выражение может рассматриваться как некоторая древовидная хорошо обозримая структура, облегчая его анализ. Итак, уровни в выражениях возможно представлять с точки зрения деревьев, когда уровень некоторой части выражения – просто расстояние вниз по дереву, в котором эта часть появляется с верхушкой дерева, рассматриваемой как уровень 0.

Reverse[x, {n}] – вызов функции в зависимости от фактических аргументов возвращает результат обращения подвыражений выражения x в целом либо подвыражений на n– уровне;

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

In[1678]:= X = (x^2 – y^2)/(Sin[x] + Cos[y]) + a*Log[x + y + z – G[h, t]];

Reverse[X] Out[1678]= a Log[x + y + z – G[h, t]] + (x^2 – y^2)/(Cos[y] + Sin[x]) In[1679]:= Reverse[X, 3] Out[1679]= (–1)^(Cos[y] + Sin[x]) (x^2 – y^2) + a Log[x + y + z – G[h, t]] In[1680]:= Y = {{a, b, c}, {c, d, g}, {x, y, z}};

Reverse[Y] Out[1680]= {{x, y, z}, {c, d, g}, {a, b, c}} В целом ряде случаев достаточно полезной оказывается глобальная переменная, вызов которой FullFormF[] возвращает список наиболее часто используемых эквивалентов функций и операторов, используемых в полной форме представления выражений. В первую очередь данная переменная полезна при анализе выражений, представленных в полной форме. Фрагмент представляет код переменной с примером ее применения.

In[1793]:= FullFormF[] := {And, AngleBracket, CapitalDifferentialD, CenterDot, Complex, Condition, Congruent, Decrement, DifferentialD, DoubleVerticalBar, DirectedEdge, Element, Equal, Equivalent, Exists, ForAll, Function, GreaterFullEqual, Greater, GreaterEqual, Implies, Increment, Infinity, Intersection, LeftArrow, LessEqual, Less, LessFullEqual, LessLess, MessageName, MinusPlus, Not, NotDoubleVerticalBar, NotCongruent, NotElement, NotExists, NotReverseElement, NotSubset, NotSuperset, Or, Part, Pattern, Plus, PlusMinus, Power, Product, Proportion, Proportional, Rational, Repeated, ReverseElement, RoundImplies, Rule, RuleDelayed, SameQ, Span, StringJoin, Subset, SubsetEqual, Sum, Superset, SupersetEqual, TildeEqual, TildeTilde, Times, UndirectedEdge, Unequal, Union, UpArrow, VerticalBar, VerticalSeparator} In[1794]:= FullFormF[] Out[1794]= {And, AngleBracket, CapitalDifferentialD, CenterDot, Complex, …, Infinity} In[1795]:= Map4[FreeQ2, Map[FullForm, {a + b*Cos[x], a^b, a – b}], {Plus, Power, Rule}] Out[1795]= {False, False, False} В.З. Аладьев, Д.С. Гринь In[1795]:= FreeQ2[x_, p_] := If[ListQ[p], If[DeleteDuplicates[Map10[FreeQ, x, p]] === {True}, True, False], FreeQ[x, p]] In[1796]:= L = {a, b, c, d, f, g, h};

{FreeQ[L, {a, d, h}], FreeQ2[L, {a, d, h}]} Out[1796]= {True, False} In[1797]:= {FreeQ[Cos[x] + Sin[x], {Sin, Cos}], FreeQ2[Cos[x] + Sin[x], {Sin, Cos}]} Out[1797]= {True, False} In[1798]:= {FreeQ[Cos[x] + Sin[x], Sin], FreeQ2[Cos[x] + Sin[x], Sin]} Out[1798]= {False, False} Завершает данный фрагмент функция FreeQ2, расширяющая стандартную функцию FreeQ дополнительно и на список в качестве второго фактического аргумента. Вызов функции FreeQ2[x, p] возвращает True, если выражение x не содержит подвыражения p либо подвыражений из списка p, в противном случае возвращается False. Фрагмент представляет исходный код функции с примерами применения и в сравнении с FreeQ.


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

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

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

3.6. Понятие шаблонов и манипуляции с ними в Mathematica Шаблоны используются в среде Mathematica для представления классов выражений.

Весьма простым примером шаблона является выражение h[x_], представляющее класс выражений типа h[Любое выражение]. Предпосылкой введения понятия «Шаблон» в среду Mathematica послужил тот факт, что довольно много операций поддерживают работу не только с отдельными выражениями, но и с шаблонами, представляющими целые классы выражений. Так, в частности, можно использовать шаблоны в правилах преобразования для указания того, как следует преобразовывать классы выражений.

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

Базовым идентификатором, определяющим, практически, все шаблоны в Mathematica является приписанный некоторому символу справа символ «_» (символ подчеркивания).

В этом случае Mathematica рассматривает такой символ как допускающий в качестве значения для него произвольное допустимое пакетом выражение. Ранее упомянутая функция Head[x] на шаблоне x возвращает значение Pattern, тогда как весьма простая функция PatternQ[x] возвращает True, если x – шаблон, и False в противном случае:

In[1689]:= PatternQ[x_] := If[Head[x] === Pattern, True, False] In[1690]:= {Map[PatternQ, {agn_, _, _a _, x_, _^_}], Map[Head, {agn_, _, _a _, x_, _^_}]} Out[1690]= {{True, False, False, True, False}, {Pattern, Blank, Times, Pattern, Power}} Расширение функциональной среды системы Mathematica Примеры применения функции PatternQ с ее исходным кодом представлены выше;

в частности, x_ определяет допустимость для x любого (anything) выражения, в то время как пакет Maple для этих же целей использует конструкцию формата «x::anything». В принципе, символ «_» можно помещать в любое место выражения, определяя таким образом некий шаблон, соответствующий некоторой группе выражений, получаемых посредством замены данного символа произвольным выражением, например:

In[1698]:= StringQ["agn" ToString[_] ToString[] ToString[_]] Out[1698]= True type(cat("G", convert(a::anything, string), convert(b::anything, string)), string);

true Последний пример иллюстрирует некоторый аналог применения шаблона в Maple.

Ниже представлены некоторые простые примеры шаблонов, а именно:

h[x_] – заголовок функции/процедуры с одним формальным аргументом x, в качестве которого допустимо произвольное выражение;

h[x_, y_] – заголовок функции/процедуры h с двумя формальными аргументами x и y, в качестве которых допустимы произвольные выражения;

h[x_, x_] – заголовок функции/процедуры h с двумя идентичными аргументами x, в качестве которых допустимы произвольные выражения;

x^n_ – определяет выражение x в произвольной степени n;

x_^n_ – определяет произвольное выражение x в произвольной степени n;

x_ + y_ + z_ – определяет сумму трех произвольных выражений x, y и z;

{x_, y_, z_} – определяет список из трех произвольных выражений x, y и z;

70 x_^y_ + 450 x_*y_ + z_ – определяет выражение с пятью шаблонами.

Базовыми шаблонами в среде Mathematica являются три следующих, а именно:

_ или Blank[] (в полной форме) – шаблон, определяющий произвольное выражение;

_t или Blank[t] (в полной форме) – шаблон, определяющий произвольное выражение с заголовком t;

(2 символа "_") или BlankSequence[] (в полной форме) – шаблон, который определяет одно произвольное выражение либо последовательность произвольных выражений;

t либо BlankSequence[t] (в полной форме) – шаблон, который определяет одно либо последовательность произвольных выражений, каждое из которых имеет заголовок t;

_ (3 символа "_") или BlankNullSequence[] (в полной форме) – шаблон, определяющий отсутствие выражений либо последовательность произвольных выражений;

_t либо BlankNullSequence[t] (в полной форме) – шаблон, определяющий отсутствие выражений либо последовательность произвольных выражений с заголовками t.

При этом, в полной форме выражений, содержащих шаблоны типов {«_», «», «_»}, они представляются в форматах, иллюстрируемых следующим простым примером:

In[98]:= Map[FullForm, {x_, x, x_}] Out[98]= {Pattern[x, Blank[]], Pattern[x, BlankSequence[]], Pattern[x, BlankNullSequence[]]} Достаточно простая функция ExprPatternQ обеспечивает тестирование выражения на предмет наличия в нем шаблонов типов {«_», «», «_»}, возвращая при своем вызове В.З. Аладьев, Д.С. Гринь ExprPatternQ[x] значение True, если выражение x содержит по меньшей мере один из шаблонов {«_», «», «_»}, и False в противном случае. Фрагмент приводит исходный код функции ExprPatternQ наряду с типичными примерами ее применения:

In[3379]:= ExprPatternQ[x_] := ! StringFreeQ[ToString[FullForm[x]], {"BlankSequence[]", "BlankNullSequence[]", "Blank[]"}] In[3380]:= Map[ExprPatternQ, {a + Sin[x], 70 x_^y_ + 450 x_*y_, x_^y_, x, z_}] Out[3380]= {False, True, True, True, True} Возможно создавать шаблоны для выражений с любой структурой, однако наиболее распространенным способом использования шаблонов является именно определение функции/процедуры, когда в ее заголовке указываются формальные аргументы. При этом, задание формальных аргументов без шаблонов не позволяет рассматривать эти объекты в качестве функций либо процедур, как иллюстрирует простой пример:

In[1690]:= G[x, y] := x^2 + y^2;

G1[x_, y_] := x^2 + y^2;

In[1691]:= {G[70, 75], G1[70, 75]} Out[1691]= {G[70, 75], 10525} Еще раз следует подчеркнуть, что шаблоны в среде Mathematica представляют собой классы выражений с заданной структурой, когда один шаблон соответствует некоему выражению и если структура шаблона совпадет со структурой выражения, т.е. путем заполнения шаблонов можно получить выражение. Более того, даже два выражения, математически эквивалентные, не могут быть представлены тем же шаблоном, если у них нет той же самой структуры. Так, (a + b)^2 эквивалентно a^2 + 2*a*b + b^2, но оба выражения не эквивалентны на уровне шаблонов, их представляющих, по причине, что оба имеют различную полную форму, как иллюстрирует простой пример:

In[1731]:= FullForm[(a + b)^2] Out[1731]//FullForm = Power[Plus[a, b], 2] In[1732]:= FullForm[a^2 + 2*a*b + b^2] Out[1732]//FullForm = Plus[Power[a, 2], Times[2, a, b], Power[b, 2]] Тот факт, что шаблоны определяют структуру выражений, очень важен для решения задачи определения правил преобразования, изменяющих структуру выражений без изменения их математической эквивалентности. Другим общим критерием, который позволил бы определить эквивалентность двух выражений, пакет не располагает. Для реализации алгоритма сравнения выражений пакет использует сведение их к полной форме, определяемой функцией FullForm. В справке по Mathematica обсуждается ряд важных механизмов создания шаблонов для довольно широкого класса выражений, в других справочных руководствах рассматриваются приемы, применяемые пакетом с целью расширения и ограничения классов выражений, представляемых шаблонами.

Для определения выражений, совпадающих с заданным шаблоном, можно применять функцию Cases, допускающую пять форматов кодирования, вызов первого из которых Cases[a, p] возвращает элементы–выражения списка a, структурно соответствующие Расширение функциональной среды системы Mathematica шаблону p, как весьма наглядно иллюстрирует следующий простой пример:

In[3373]:= Cases[{a + b*c^5, 5 + 6*y^7, a + b*p^m, a + b*m^(–p)}, a + b*x_^n_] Out[3373]= {a + b c^5, a + b p^m, a + b m^–p} Не отвлекаясь на детали, отметим только еще ряд функций, обеспечивающих работу с выражениями на уровне представляющих их шаблонов как в целом, так и на уровне составляющих их подвыражений, а именно:

Count[a, p] – возвращает число элементов–выражений списка a, которые структурно соответствуют шаблону p;

дополнительно располагает еще одним форматом;

Position[a, p] – возвращает список позиций подвыражений выражения a, структурно соответствующих шаблону p;

дополнительно располагает еще двумя форматами.

DeleteCases[a, p] – возвращает результат удаления из выражения a всех подвыражений, структурно соответствующих шаблону p;

располагает еще двумя форматами.

Пакет располагает еще рядом средств для обеспечения решения подобных задач, но в данном разделе не рассматриваемых, как имеющих и другие приложения. Читатель с ними может ознакомиться либо в справке по пакету, либо в литературе [100,104,116].

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

In[3395]:= EquExprPatt[x_, y_ /;

ExprPatternQ[y]] := Module[{c, d = {}, t, v = {}, k = 1, j, p, g = {}, s = {}, a = Map[FullForm, Map[Expand, {x, y}]], b = Mapp[MinusList, Map[OP, Map[Expand, {x, y}]], {FullForm}], z = SetAttributes[ToString, Listable], w}, {b, c} = ToString[{b, a}];

p = StringPosition[c[[2]], {"Pattern[", "Blank[]]"}];

While[k = 2*k – 1;

k = Length[p], d = Append[d, StringTake[c[[2]], {p[[k]][[1]], p[[k + 1]][[2]]}]];

k++];

{t, k} = {ToExpression[d], 1};

While[k = Length[t], v = Append[v, StringJoin[ToString[Op[t[[k]]]]]];

k++];

v = ToString[v];

v = Map13[Rule, {d, v}];

v = StringReplace[c[[2]], v];

b = Quiet[Mapp[Select, b, ! SystemQ[#] || ProcQ[#] || QFunction[ToString[#]] &]];

{b, k, j} = {ToString[b], 1, 1};

While[k = Length[b[[1]]], z = b[[1]][[k]];

g = Append[g, {"[" z "," – "[w", " " z "," – " w,", "[" z "]" – "[w]", " " z "]" – " w]"}];

k++];

While[j = Length[b[[2]]], z = b[[2]][[j]];

s = Append[s, {"[" z "," – "[w", " " z "," – " w,", "[" z "]" – "[w]", " " z "]" – " w]"}];

j++];

ClearAttributes[ToString, Listable];

z = Map9[StringReplace, {c[[1]], v}, Map[Flatten, {g, s}]];

If[z[[1]] === z[[2]], True, False]] In[3396]:= EquExprPatt[a*Sin[x] – 5*b*c^5, a*Sin[x] – 5*b*x_^n_] Out[3396]= True В.З. Аладьев, Д.С. Гринь In[3397]:= EquExprPatt[a*Sin[x] – 5*b*c^5, 75*Sin[x] – 70*b*x_^n_] Out[3397]= True In[3398]:= EquExprPatt[a^2 + 2*a*b + b^2, (x_ + y_)^2] Out[3398]= True In[3399]:= Cases[{a + b*c^5, 5 + 6*y^7, a + b*p^m, a + b*m^(–p)}, a + b*x_^n_] Out[3399]= {a + b c^5, a + b p^m, a + b m^–p} In[3400]:= Mapp[EquExprPatt, {a + b*c^5, 5 + 6*y^7, a + b*p^m, a + b*m^p}, a + b*x_^n_] Out[3400]= {True, True, True, True} In[3401]:= Mapp[Cases, {{a + b*c^5}, {5 + 6*y^7}, {a + b*p^m}, {a + b*m^p}}, a + b*x_^n_] Out[3401]= {{a + b c^5}, {}, {a + b p^m}, {a + b m^p}} In[3402]:= EquExprPatt1[a^2 + 2*a*b + b^2, (a + b)^2] Out[3402]= True Для решения данной задачи в ее более широком аспекте достаточно полезной может оказаться процедура EquExprPatt, чей вызов EquExprPatt[x, p] возвращает True, если выражение x соответствует заданному шаблону p, и False в противном случае. Выше представлен фрагмент и с исходным кодом процедуры EquExprPatt, и с типичными примерами ее применения. Последние примеры фрагмента иллюстрируют также и более широкие возможности процедуры EquExprPatt относительно функции Cases.

А так как алгоритм процедуры базируется на представлении выражений и шаблонов в полной форме (FullForm), то, в принципе, в качестве второго аргумента процедуры можно использовать произвольное выражение, закодировав второй аргумент как y_ в определении процедуры EquExprPatt, модифицировав ее в процедуру, EquExprPatt1, которая отличается от EquExprPatt лишь этим моментом. В данном случае возможно проводить тестирование двух произвольных выражений на предмет их структурной эквивалентности, что представляется достаточно важным в целом ряде задач анализа выражений. Отметим, что в реализации процедуры используется не только довольно полезный прием временного наделения функции ToString Listable–атрибутом, но и ряд средств из нашего FreeWare пакета AVZ_Package, а именно: Map13, Map9, Mapp, MinusList, OP, Op, ProcQ, QFunction, SystemQ [90], рассмотренных и в данной книге.

Необходимо иметь в виду, что при использовании правил преобразования возникает необходимось именования шаблонов. Так, согласно соглашению x_ будет обозначать произвольное выражение, однако каждый раз присваивая выражению имя x. Имеется возможность использования этого имени в правой стороне правила преобразования.

Однако пакет ограничивает использование шаблона x_ в одном и том же выражении только относительно уникального выражения. В частности, в приведенном примере In[1701]:= G[x_, y_, z_] := x + y + z In[1702]:= {G[70, 75, 2012], G[70, 70, 70]} Out[1702]= {2157, 210} In[1703]:= {G[70, 75], G[70, 70, 70, 70]} Out[1703]= {G[70, 75], G[70, 70, 70, 70]} шаблоны {x_, y_, z_} в общем случае определяют различные выражения, определяя в среде пакета уникальный объект – функцию G[x, y, z]. При этом, при вызове данной Расширение функциональной среды системы Mathematica функции ее фактические аргументы могут принимать произвольные значения, в том числе и равные. Однако вызов функции будет корректным лишь при кодировании фактических аргументов, при наличии числа фактических аргументов, отличного от трех, вызов возвращается невычисленным, т.е. в том же виде как был определен вызов с точностью до стандартных преобразований фактических аргументов в соответствии с соглашениями пакета. Предыдущий пример иллюстрирует сказанное. Более того, в случае использования выражения G[a, b, c], где {a, b, c} – произвольные выражения оно будет ассоциироваться именно с объектом G[x, y, z]. Так, определив простую функцию In[1709]:= V[x_, x_, x_] := Plus[x, x, x] In[1710]:= {V[70, 70, 70], V[70, 75, 450]} Out[1710]= {210, V[70, 75, 450]} In[1711]:= S[x_, y_, x_] := x + y In[1712]:= {S[45, 67, 45], S[45, 67, 6]} Out[1712]= {112, S[45, 67, 6]} также с 3 формальными аргументами x_, в качестве которых выступает один и тот же шаблон, корректно обращаться к такому объекту V[x, x, x] можно только при условии трех идентичных фактических аргументов, иначе вызов возвращается невычисленным.

Подобная же картина имеет место также и при указании частичного числа шаблонов идентичными, как иллюстрирует приведенный выше пример объекта S[x, y, x]. Итак, шаблон "_" определяет произвольное выражение, а x_ – любое выражение с именем x;

при этом, если выражение G[x_, x_] отвечает выражениям, для которых оба аргумента идентичны, то G[_, _] отвечает всем выражениям формы G[x, y], где x и y допускают и различные значения. Более того, конструкция формата "x:p" определяет выражение с именем x, отвечающее шаблону p;

вообще говоря, данная конструкция представляет собой шаблон, присвоенный символу x.

Определение типов выражения в шаблонах. С этой целью вполне можно использовать заголовки выражений x (определяются вызовом функции Head[x]), которые определяют их основную суть. Так, шаблоны _h и x_h будут представлять выражения с заголовком h, из которых наиболее часто используемыми являются следующие, а именно:

x_h – выражение x с заголовком h ==================================================== x_Integer – выражение x с заголовком Integer (целое число) x_Real – выражение x с заголовком Real (действительное число) x_Complex – выражение x с заголовком Complex (комплексное число) x_List – выражение x с заголовком List (список) x_String – выражение x с заголовком String (строка) x_Symbol – выражение x с заголовком Symbol (символ) x_Plus – выражение x с заголовком Plus (сложение, вычитание) x_Times – выражение x с заголовком Times (произведение, деление) x_Power – выражение x с заголовком Power (степень) В принципе, в качестве заголовка в составе шаблона может выступать произвольный заголовок, допустимый пакетом. Приведем примеры таких шаблонов, а именно:

В.З. Аладьев, Д.С. Гринь In[1711]:= G[x_Plus] := x^2;

S[x_Power] := x^2;

{G[70], G[a + b], S[75], S[a^b]} Out[1711]= {G[70], (a + b)^2, S[75], a^(2 b)} Между тем, в целом ряде случаев стандартно определенных заголовков не хватает для задания шаблонов, вполне естественно поднимая вопрос подключения к их списку и заголовкой, определенных пользователем. А так как для вычисления заголовка служит стандартная функция Head, естественным представляется модифицировать данную функцию на предмет тестирования ею более широкого класса заголовков. Поэтому, с этой целью определена процедура RepStandFunc, вызов которой RepStandFunc[x, y, z] возвращает вызов функции y, одноименной со стандартной y и определение которой задано в строчном формате аргументом x, на списке z ее фактических аргументов. В то же время такой вызов процедуры RepStandFunc является разовым в том смысле, что после него восстанавливается исходное состояние стандартной функции y. В начале следующего фрагмента представлен исходный код процедуры RepStandFunc наряду с примерами ее применения и тестированием последействия результата ее вызова. В остальной части фрагмента представлены средства, иллюстрирующие сказанное.

In[3381]:= RepStandFunc[x_String, y_Symbol, z_List] := Module[{b = Attributes[y], c, d, a = ToString[y] ".mx"}, DumpSave[a, y];

ClearAllAttributes[y];

Clear[y];

ToExpression[x];

d = y[Sequences[z]];

Clear[y];

Get[a];

SetAttributes[y, b];

DeleteFile[a];

d] In[3382]:= x = "Sin[x_, y_, z_]:=x^2 + y^2 + z^2";

RepStandFunc[x, Sin, {42, 70, 75}] Out[3382]= 12 In[3395]:= x = "Sin[x_] := x^5";

RepStandFunc[x, Sin, {42}] Out[3395]= 130 691 In[3383]:= Definition[Sin] Out[3383]= Attributes[Sin] = {Listable, NumericFunction, Protected} In[3384]:= Sin[70.45075] Out[3384]= 0. In[3390]:= Headd := "Head[x_] := Module[{b = {ListListQ, NestListQ, ProcQ, QFunction, SystemQ}, c = {ListList, NestList, Procedure, Function, System}, h = SetAttributes[SetAttributes, Listable], d = 70, k = 1}, SetAttributes1[c, Protected];

Quiet[For[k = 1, k = Length[b], k++, If[b[[k]][x], d = c[[k]];

Break[]]]];

ClearAttributes[SetAttributes, Listable];

If[d === 70, x[[0]], d]]" In[3391]:= RepStandFunc[Headd, Head, {{{a}, {b, c}, {d}}}] Out[3391]= NestList In[3392]:= Definition[Head] Out[3392]= Attributes[Head] = {Protected} In[3393]:= Head[{{a}, {b, c}, {d}}] Out[3393]= List In[3396]:= G[h_NestList] := Length[h] Расширение функциональной среды системы Mathematica In[3397]:= G[{{a}, {b}, {c}, {d, t}, {f}, {g}, {v}}] Out[3397]= G[{{a}, {b}, {c}, {d, t}, {f}, {g}, {v}}] In[3398]:= G[h_List] := Length[h] In[3399]:= G[{{a}, {b}, {c}, {d, t}, {f}, {g}, {v}}] Out[3399]= In[1705]:= ClearAllAttributes[Head];

Clear[Head];

ToExpression[Headd] In[1706]:= G[h_ListList] := Length[h] In[1707]:= G[{{a}, {b}, {c}, {d, t}, {f}, {g}, {v}}] Out[1707]= G[{{a}, {b}, {c}, {d, t}, {f}, {g}, {v}}] In[695]:= SetAttributes1[x_, y_] := ToExpression["SetAttributes[SetAttributes, Listable];

SetAttributes[" ToString[x] ", " ToString[y] "];

ClearAttributes[SetAttributes, Listable]"] In[696]:= t = {x, y, z};

SetAttributes1[t, Listable];



Pages:     | 1 | 2 || 4 | 5 |   ...   | 20 |
 





 
© 2013 www.libed.ru - «Бесплатная библиотека научно-практических конференций»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.