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

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

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


Pages:     | 1 || 3 | 4 |   ...   | 20 |

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

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

Прежде всего необходимо отметить, что Maple–языку, не взирая на общеописательный характер изложения, было уделено столько внимания лишь по той причине, что язык пакета Mathematica обладает многими из черт, что и пакет Maple. Поэтому далее мы рассмотрим на содержательном уровне некоторые принципиальные отличия, которые присущи именно языку пакета Mathematica (в дальнейшем просто Math–языку пакета).

Прежде всего, с полным основанием можно сказать, что Mathematica – это и система компьютерной алгебры, и язык программирования сверхвысокого уровня. В качестве языка программирования Math–язык имеет ряд атрибутов, характерных для языков объектно-ориентированного типа, являясь процедурно–функциональным языком. А в качестве назначения Math–язык с полным основаниям возможно отнести к проблемно ориентированным языкам сверхвысокого уровня, предназначенным, прежде всего, для обеспечения аналитических и численных вычислений. При этом, функциональность Math–языка весьма существенно отличает его от Maple–языка. Функциональные языки программирования делают акцент на правилах и сравнении образцов. В то время как они представляются не обладающими интуицией для пользователей, которые имеют опыт работы лишь с процедурными языками, функциональные языки обеспечивают краткие и естественные структуры программирования для тех, кто получил немного опыта. Функциональное программирование особенно полезно для математических приложений, где «функция» – достаточно хорошо определенное базовое понятие. В среде пакета Maple также можно использовать некоторые элементы функционального программирования, в частности, создавать чистые функции, однако это всего лишь его симуляция в достаточно ограниченных пределах. Следующий простой фрагмент Расширение функциональной среды системы Mathematica довольно наглядно иллюстрирует реализацию в среде Maple функции Select пакета Mathematica, которая использует в качестве второго фактического аргумента чистую функцию (pure function) короткого формата, а именно:

L := [k$k = 1.. 42]: x := 68: map(proc(x) if type(x, prime) then x end if end proc, L);

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41] select(isprime, L);

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41] In[547]:= L = Range[42];

Select[L, PrimeQ[#] &] {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41} Действительно, функциональные программы, вообще говоря, выполняются медленнее, чем процедурные программы, однако время выполнения – не самое главное в терминах эффективности.

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

Двухуровневая лингвистическая поддержка Mathematica обеспечивается языком С и Math–языком. Подобно ситуации с Maple, в Mathematica можно выделить два уровня языковой среды – язык реализации (С + Math-язык) и встроенный язык программирования (Math–язык). Mathematica аналогично пакету Maple реализована в основном на языке Math, т.е. собственном встроенном языке программирования, однако часть ее ядра и ряд важных функций в целях оптимизации написаны на языке программирования C.

Таким образом, языком реализации Mathematica является и язык программирования C, показавший свою высокую эффективность как язык системного программирования.

По нашей оценке доля программных средств пакета, написанных на С, не превышает 8 – 10%. Тогда как остальная масса программных средств Mathematica, находящихся в различных библиотеках и пакетах, написана на собственном Math–языке. Это и дает основание рассматривать С и Math в качестве языков реализации пакета. При этом, с довольно определенными допущениями возможно говорить о входном Math–языке и языке программирования пакета Mathematica. Между тем, в отличие от пакета Maple, входной Math–язык, практически, совпадает со встроенном Math–языком пакета, что, в отличие от Maple, позволяет говорить о встроенном языке программирования, как о едином целом. Именно на встроенном Math–языке пишутся и выполняются в среде пакета Mathematica–документы и пакеты {nb, m, mx}–файлы. В отличие от Maple, все (за очень редким исключением) конструкции Math-языка допустимы как в процедурных конструкциях, так и на входе пакета Mathematica, как это иллюстрирует следующий достаточно простой фрагмент, представляющий эквивалентную реализацию в среде Mathematica в Input–режиме ранее представленного фрагмента для среды Maple:

In[523]:= {n, m} = {0, 0};

Label[A];

n = n + 1;

If[n = 72, m = m + n^2;

Goto[A], m] Out[523]= В.З. Аладьев, Д.С. Гринь In[524]:= {n, m} = {0, 0};

Label[A];

n = n + 1;

If[n = 72, m = m + n^2;

Goto[A], Return[m]] Out[524]= Return[127020] In[525]:= P[] := Module[{n = 0, m = 0, A}, Label[A];

n = n + 1;

If[n = 72, m = m + n^2;

Goto[A], Return[m]]] In[526]:= P[] Out[526]= In[527]:= F[n_, m_] := If[n + m = 72, m^2 + n^2, Return[{m, n}]] In[528]:= {F[14, 22], F[42, 47]} Out[528]= {680, {47, 42}} In[628]:= RETURN[x_, res_ /;

! HowAct[res]] := If[SuffPref[ToString[x], "Return[", 1], res = ToExpression[StringTake[ToString[x], {8, –2}]];

Abort[];

, Return[x]] In[629]:= {n, m} = {0, 0};

Label[A];

n = n + 1;

If[n = 72, m = m + n^2;

Goto[A], RETURN[Return[m], res];

2011];

res Out[629]= In[630]:= F1[n_, m_] := If[n + m = 72, m^2 + n^2, RETURN[Return[{m, n}]]] In[631]:= {F1[14, 22], F1[42, 47]} Out[631]= {680, {47, 42}} Из представленного фрагмента следует, что Goto–функция может использоваться и в Input-режиме пакета, и в процедуре;

при этом, в процедуре метка может определяться локальной, тогда как в случае пакета Maple это недопустимо. Правда, использование Return–функции в Input–режиме пакета хоть и не вызывает ошибочной ситуации, но ее вызов возвращается невычисленным, если Return использована вне тела процедуры/ функции. Таким образом, если вне контекстное использование return–предложения в среде Maple инициирует ошибочную ситуацию, то в среде Mathematica аналогичное использование Return–функции возвращает ее вызов невычисленным. Между тем, эту ситуацию вполне можно исправить обрамлением вызова Return–функции RETURN– функцией, как это иллюстрируют последние примеры представленного фрагмента.

Подобно пакету Maple, пакет Mathematica является довольно сложным программным обеспечением, реализованным миллионами строк исходного кода, написанного в C/C ++, Java и Mathematica. Программный код пакета на языке C фактически написан на специальном расширении языка C, которое поддерживает определенное управление памятью и объектно–ориентированные возможности. При этом, код оптимизирован, используя Share и DumpSave. При этом, программный код ядра пакета Mathematica по основным его функциональным составляющим процентуально можно охарактеризовать с определенной степенью погрешности как: поддержка встроенного Math-языка – 30%, алгебраические вычисления – 20%, числовые вычисления – 20%, графика и функции выхода – 30%. Исходный код ядра сохраняет процентуальное распределение данных составляющих независимо от используемой пакетом операционной платформы, тогда как объем исходного кода интерфейса пакета, написанного на языке C++, достаточно существенно зависит от используемой пакетом операционной платформы.

Пакет Mathematica использует вычислительную модель типа «client-server», в которой Расширение функциональной среды системы Mathematica графический пользовательский интерфейс (GUI) и ядро пакета связываются между собой через протокол MathLink;

с другими внешними средствами пакет поддерживает связь также по этому протоколу. Протокол MathLink поддерживает мульти–транспортные уровни (OSI), включая один, базирующийся на протоколе TCP/IP, и один, совместно использующий память. Наряду с указанным пакет использует ряд других протоколов.

Вполне уместно упомянуть о такой весьма существенной характеристике для любого программного средства, как совместимость «снизу-вверх». Несмотря на то, что с самого начала исходный код Mathematica изменялся весьма существенно от версии к версии, вплоть до того, что относительно самых первых версий остались неизменными лишь несколько процентов, а функциональные возможности пакета просто несопоставимы с первыми версиями, однако почти все программы, созданные в среде первых версий пакета Mathematica корректно выполняются и в старших версиях пакета. Тогда как в отношении пакета Maple это всегда было довольно острой проблемой. И не только на уровне версий пакета, но даже на уровне клонов одной и той же версии (например, для Maple 9 режимов стандартный и классический). Именно для решения данной проблемы и был нами разработан комплекс процедур, обеспечивающий в значительной степени решение проблемы несовместимости. Естественно, в данном отношении Mathematica в большей степени отвечает требованиям к качественному программному продукту.

Следует отметить, особое неприятие у многих пользователей математических пакетов вызывает не весьма привычный синтаксис Math–языке. Действительно, его называют по разному – и «нечеткий», и «странный», и «архаичный», и т.д., акцентируя внимание на том, что в противовес ему структура Maple–языка легко воспринимаема для тех, у кого имеется даже небольшой опыт работы с процедурными языками. Частично с этим вполне можно согласиться, однако здесь следует иметь ввиду, что «нечеткость» Math– языка во многом обусловлена как целым рядом причин исторического характера, так и его процедурно–функциональным гибридом, определив в нем ряд специфических парадигм, например, сравнение по образцам и т.д., что, однако, в целом ряде случаев оказывается весьма полезным при программировании в его среде как прикладных, так и системных средств. Правда, здесь имеются и не вполне убедительные решения как, например, кодирование функций с заглавных букв, скобки квадратные там, где для подавляющего большинства привычны круглые скобки, и т.д. И в этом отношении с определенной долей уверенности можно констатировать, что весь предыдущий опыт программирования не только не полезен, но и вступает в противоречие с парадигмой программной среды пакета Mathematica. Непривычность синтаксиса Maple–языка в течение довольно продолжительного времени будет портить настроение при наборе исходных кодов программ, правда, здесь имеются и свои плюсы в виде привычной для многих приложений прокрутки страниц текущего документа колесом мыши (в Maple это не поддерживается) и весьма удобной системы синтаксического анализа вводимого в Input-параграф текста, выполняемой в динамическом режиме, т.е. непосредственно в процессе посимвольного ввода. Подобной системой синтаксического анализа пакет Maple не располагает. Для пользователей Maple немало непривычного имеется и при наборе даже весьма элементарных выражений, например, если кодирование пробела между именем функции и скобкой, открывающей список фактических аргументов, в В.З. Аладьев, Д.С. Гринь обоих языках допустимо, не вызывая ошибок, то кодирование за десятичной точкой пробела в Maple инициирует ошибочную ситуацию, тогда как в Mathematica пробел воспринимается как знак умножения, приводя зачастую к неожидаемым результатам, как это очень наглядно иллюстрирует простой фрагмент, в котором пробел затенен:

sin(42.47);

–0. sin (42.47);

–0. sin(42. 47);

Error, unexpected number In[1537]:= Sin[42.47] Out[1537]= –0. In[1538]:= Sin [42.47] Out[1538]= –0. In[1539]:= Sin[42. 47] Out[1539]= 0. Между тем, при всей первоначальной непривычности синтаксиса Maple–языка с ней вполне можно справиться в довольно непродолжительный срок, учитывая краткость и логичность его конструкций, выполняемых достаточно эффективно. Синтаксис его конструкций (прежде всего значительных по объему) требует определенного навыка для их восприятия. Привычному к синтаксису традиционных языков программирования пользователю читабельность Math–программ может оказаться весьма затруднительна.

Многие примеры представленных в настоящей книге процедурных реализаций одной и той же задачи позволяют достаточно наглядно сравнивать такие два показателя, как удобочитаемость и краткость. В данном отношении, если исходный код Mathematica довольно явно отличается в сторону краткости, то исходный код Maple–процедуры в сторону большей удобочитаемости. И так как основу модульного программирования в обоих языках составляют базовые компоненты – процедуры/функции, здесь следует отдельно отметить существенно больший уровень читабельности Maple-процедур по отношению к Mathematica–процедурам. Резюмируя краткую характеристику языка Math, его синтаксис в целом можно объяснить тем обстоятельством, что Mathematica поддерживает процедурно–функциональный язык, сочетающий парадигмы 2 таких языков программирования, как C++ и APL. Язык APL базируется на математической нотации и оказал весьма существенное влияние на разработчиков функциональных языков, электронных таблиц и ряда математических пакетов, включая Mathematica.

Не детализируя более синтаксис Math–языка, с которым пользователь знакомится на первых шагах освоения пакета, отметим лишь, что если в Maple одной из важнейших базовых структур является последовательность выражений (просто последовательность), создаваемая на основе оператора запятой {,}, и составляет основу для создания многих типов структур (вызовы функций, списки, множества и др.), в Mathematica, практически, аналогичную роль играет список, являющийся удобной структурой функциональной парадигмы. И хотя в среде пакета Maple в определенной мере возможно реализовать функциональную парадигму, однако в большинстве случаев это потребует довольно серьезных усилий от пользователя, даже от достаточно искушенного пользователя.

Расширение функциональной среды системы Mathematica Реальная мощь Math–языка обусловлена не только его управляющими структурами и структурами данных, но и всем богатством его функциональных средств (встроенных, библиотечных, пакетных) и прикладных средств (в виде Math-пакетов), которые созданы к настоящему времени пользователями из различных прикладных областей, прежде всего, математических. К их числу можно с полным основанием отнести и пакет [90], содержащий более 500 средств, как дополняющих средства пакета, так и устраняющих некоторые его недостатки наряду с расширением некоторых его стандартных средств.

Представленные в [90] средства использовались достаточно широко как при работе с Mathematica в интерактивном режиме, так и в программировании различных задач в его среде, зарекомендовав себя в качестве достаточно полезных и эффективных.

Протокол MathLink пакета обеспечивает интерфейс не только между ядром и GUI, но и с другими языками: С, AppleScript, Haskell, Visual Basic и др. Ряд других протоколов обеспечивают интерфейс с рядом важных приложений. Между тем, интегрированная среда разработки (IDE) на основе Eclipse служит для работы с большими проектами в среде пакета, тогда как пакет Maple подобной IDE не имеет. Учитывая программный аспект, отметим, что Mathematica Player позволяет просматривать Math–документы (файлы в cdf-формате) без загрузки лицензионных версий Mathematica, тогда как для Maple необходима загрузка самого лицензионного пакета, достаточно существенно затрудняя просмотр даже доступных кодов. Правда, на основе файлов с документами {mws, mw} Maple и m-файлов с пакетами, в принципе, не составляет особенного труда создавать перлюстраторы программных кодов, некоторые будут представлены ниже.

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

Сравнение систем программирования обоих пакетов производилось на основе Maple 8–11 и Mathematica 7,8. Учитывая, что внутренний язык программирования, который составляет основу программирования пакетов, подвергается временным изменениям, как правило, в незначительной степени, то данный материал можно рассматривать в качестве достаточно пролонгированного. Между тем, преследовались цели не только сравнительного характера, но также попытка в данном аспекте представить основные элементы систем модульного программирования обеих пакетов наряду с представлением ряда достаточно полезных средств как расширяющих программные средства пакетов, так и устраняющих обнаруженные недостатки и ошибки стандартных средств. Более того, рассмотрение и сравнительный анализ проводились лишь в рамках встроенных языков пакетов без привлечения средств, обеспечивающих интерфейс с внешними по отношению к пакетам программными средами. Итак, сравнение языков обеих пакетов проводилось лишь в рамках их встроенных средств, исключая средства, позволяющие В.З. Аладьев, Д.С. Гринь использовать программные средства извне, что повышает уровень объективности;

т.е.

производилось сравнение замкнутых программных сред обоих пакетов [97-99].

Пакет Mathematica в плане процедурного программирования в определенной степени уступает пакету Maple, хотя и декларирует его как особую свою отличительную черту.

Между тем, именно пакет Maple поддерживает встроенный язык ярко выраженного процедурного типа, тогда как пакет Mathematica использует смешанный процедурно– функциональный язык, в основе которого лежит комбинирование элементов таких языков как C++ и APL. Для более детального ознакомления с возможностями среды пакета Mathematica ниже рассматриваются его основные элементы процедурного и функционального программирования. При этом, нами не рассматриваются средства программирования собственно Math–документов, а лишь средства, обеспечивающие процедурно-функциональное программирование на уровне процедур и функций.

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

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

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

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

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

Со временем работа с этими алгоритмами и приемами дойдет у вас до автоматизма.

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

Его функциональные средства расширяют программную среду пакета Mathematica, в ряде случаев устраняя ошибки и ограничения стандартных средств пакета.

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

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

более того, во многих случаях старые версии средств сохранялись в прилагаемом к книге пакете AVZ_Package [90], как содержащие ряд довольно полезных подходов и приемов, ориентированных на программирование различных приложений в среде пакета Mathematica. Надеемся, что настоящая книга представит вполне определенный интерес для тех пользователей пакета Mathematica, которые в своей профессиональной деятельности намереваются использовать пакет с максимальной степенью отдачи. И прежде всего для тех, которые в его среде решают задачи, требующие нетривиального программирования.

При этом, в связи с разработкой нестандартных программных средств, подобных тем, которые составляют наш пакет AVZ_Package, могут возникать вопросы, относящиеся к проблеме совместимости программного обеспечения. Однако, по нашему мнению такого типа вопросы являются надуманными. Действительно, разработка подобного типа приложений, включая расширяющие стандартную программную среду, совсем не нарушает принцип совместимости как и разработка любого приложения. Наличие такого приложения все равно требует версии, предполагается, лицензионной данной (Mathematica) либо иной среды, под которую оно было разработано. Поэтому, пакет AVZ_Package, доступный по FreeWare-лицензии, также совершенно не нарушает этот принцип совместимости, предоставляя пользователю более развитую в программном отношении среду Mathematica + AVZ_Package. Вопрос сводится к целесообразности использования чистой среды Mathematica или с применением расширений, впрочем, данный вопрос является вопросом именно целесообразности, а не совместимости. Он обусловлен лишь как теми задачами, которые стоят перед пользователем, его уровнем владения стандартной средой, так и потребностью в дополнительных средствах. Наш опыт использования пакета AVZ_Package в сочетании с Mathematica 8 при разработке целого ряда приложений различного назначения достаточно однозначно подтвердил эффективность такого симбиоза – лишним хорошее программное средство не бывает.

К данному выводу приводит нас и многолетний опыт программирования в целом на различных вычислительных платформах и в различных программных средах.

В.З. Аладьев, Д.С. Гринь Глава 3. Исходные сведения по программной среде Mathematica 3.1. Вводные данные по режиму текущего документа Подобно программной среде пакета Maple, документы (то содержимое экрана, которое пользователь видит в процессе работы с пакетом) пакета Mathematica имеют секционную структуру, каждая секция которой в общем случае идентифицируется входом In[n] и выходом Out[n], когда на вход подается выражение, которое требуется вычислить, а на выходе отражается результат такого вычисления. При этом, между этими точками могут появляться различного рода сообщения, связанные с данным вычислением. В частности, возможно появление сообщений об обнаруженных пакетом ошибках при вычислении, как это весьма наглядно иллюстрирует следующий простой пример:

In[1499]:= x = 0;

Sin[x]/x Power::infy: Infinite expression 1/0 encountered.

Infinity::indet: Indeterminate expression 0 ComplexInfinity encountered.

Out[1499]= Indeterminate При этом, через гиперссылку «» обеспечивается выход на справочную страничку с более детальной информацией по возникшей ошибочной или особой ситуации. При этом, конструкция формата «Out[n]= », говорит о том, что в результате вычисления выражения пакет ничего не возвращает, а конструкция «Out[n]= Null» говорит о том, что в процессе вычисления выражения возвращается Null, т.е. ничего. Более того, при вычислении определений процедур/функций также ничего не возвращается, включая и конструкцию «Out[n]= », как весьма наглядно иллюстрирует следующий пример:

In[1503]:= G[x_Integer, y_Integer, z_Integer] := Plus[x, y, z] In[1504]:= {G[42, 70, 2012], G[42, 450.75, 2012]} Out[1504]= {2124, G[42, 450.75, 2012]} Комментируя данный пример, отметим, что вычисления в среде пакета полагают два уровня присвоения значений, а именно: непосредственный (x = a) и отложенный (x := a).

В первом случае x получает значение a сразу после вычисления данного выражения, во втором – только в момент использования (ображения к) x. И здесь сразу же отметим, что в процессе работы с процедурами/функциями результаты их вызовов могут быть невычисленными, т.е. возвращаются вызовы только с упрощением значений, которые используются в качестве их фактических аргументов (упрощения, допускаемые пакетом).

Итак, в примере проиллюстрировано отсутствие «Out[n]= » в результате вычисления определения простой функции G[x, y, z] и возврат вызова G невычисленным в случае получения ею второго фактического аргумента, недопустимого по типу Integer. При этом, имеет смысл отметить, что в дополнение к целому ряду других принципиальных отличий Mathematica от Maple в полной мере можно отнести и способ оперативного вычисления ее входов – Input–параграфов в принятой нами терминологии в изданиях по пакетам, восходящей еще к первым книгам по обоим пакетам (клавиши Shift + Enter), вместо клавиши «Enter» в Maple. Правда, использование для этой цели контекстного Расширение функциональной среды системы Mathematica меню, открываемого по щелчку правой кнопки мыши идентично, различаясь только названием требуемой вычисляющей функции Evaluate Cell и Execute соответственно.

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

В процессе работы с текущим документом во многих случаях возникает потребность в использовании ранее вычисленных выражений в предыдущих Input-параграфах. Для этой цели служит %–оператор, формат кодирования которого имеет вид, а именно:

%, %%, %%... %% (k раз), %k определяющий возврат последнего, предпоследнего и k–го предыдущего результата вычислений в текущем сеансе. При этом, пакет Mathematica поддерживает 2 весьма полезные глобальные переменные, а именно:

$Line – определяет номер последнего In–параграфа текущего сеанса;

$HistoryLength – определяет число предыдущих In–параграфов и Out–параграфов, сохраняемых в текущем сеансе пакета.

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

In[450]:= {$Line, $Line = 0, $Line} Out[0]= {450, 0, 0} In[451]:= {$HistoryLength, $HistoryLength = 0, $HistoryLength} Out[451]= {, 0, 0} Для переменной $HistoryLength значением по умолчанию является бесконечность ();

используя для этой переменной меньшие установки, можно существенно экономить размер требуемой оперативной памяти для пакета Mathematica.

Достаточно простая процедура HelpPrint обеспечивает вывод на печать содержимого справочной базы загруженного в текущий сеанс пакета пользователя, где 1-й записью выводится контекст, приписанный пакету. Фрагмент представляет как исходный код процедуры HelpPrint, так и пример ее использования. Вызов процедуры HelpPrint[n] выводит справки в строчном формате по всем средствам пользовательского пакета с соответствующим контекстом. Механизм использования процедуры довольно прост, а именно: в процессе работы с Mathematica в режиме документа на некотором шаге, в частности, Out[n] выполняется загрузка в текущий сеанс пакета, находящегося в файле формата {"cdf", "nb", "m"} либо перезагрузка загруженного пакета, после чего следует обеспечить вызов HelpPrint[n+1], в результате которого на выходе получаем контекст, ассоциированный с пакетом наряду с упомянутой выше информацией.

In[1494]:= HelpPrint[n_Integer] := Block[{a = Out[n], b, k = n + 1}, Print[ToString[a]];

While[k Infinity, b = ToString[ToExpression["%" ToString[k]]];

If[! StringFreeQ[b, a], Return["End of HelpBase on context " a], Print[b]];

k++]] ================================================================== In[2999]:= G[x_Integer, y_Integer, z_Integer] := Plus[x, y, z] В.З. Аладьев, Д.С. Гринь In[3000]:= G[42, 70, 2012] Out[3000]= Активизация в текущем сеансе пакета из файла AVZ_Package.nb In[3001]:= HelpPrint[3001] "AladjevProceduresAndFunctions`" "The call UprocQ[x] returns the False if x is not a procedure;

otherwise, two-element list of the format {True, {Module|Block}} is returned."

"The call SymbolQ[x] returns the True if x is a symbol;

otherwise, the False is returned."

================================================================== "The call `$Help` prints the list of objects names contained in this package and recommendation regarding obtaining help about them."

Out[3001]= "End of HelpBase on context AladjevProceduresAndFunctions`" Следующая процедура ActUcontexts также базируется на механизме %–оператора, ее вызов ActUcontexts[] возвращает список всех контекстов, ассоциированных с пакетами пользователя, загруженными в текущий сеанс из файлов форматов {"cdf", "nb", "m"}. В то время как вызов ActUcontexts[h] возвращает список всех контекстов, порожденных загруженными пакетами из файлов вышеуказанного формата. Следующий фрагмент представляет исходный код процедуры ActUcontexts с примерами ее применения.

In[1516]:= ActUcontexts[h_] := Block[{a = {}, b = "", c = "Out[", k = 1}, For[k, k Infinity, k++, b = ToString[Out[k]];

If[b == c ToString[k] "]", Return[DeleteDuplicates[a]]];

If[ContextQ[b] && If[{h} != {}, True, StringCount[b, "`"] == 1], a = Append[a, b]]]] In[1517]:= ActUcontexts[] Out[1517]= {"AladjevProceduresAndFunctions`", "Aladjev`"} In[1518]:= ActUcontexts[70] Out[1518]= {"AladjevProceduresAndFunctions`", "AladjevProceduresAndFunctions`Help`", "AladjevProceduresAndFunctions`ExtrExpr`", "AladjevProceduresAndFunctions`ExtrCall`" ================================================================= "AladjevProceduresAndFunctions`PackNames`", "Aladjev`", "Aladjev`UprocQ`"} В свою очередь глобальная переменная $Line1 в отличие от стандартной глобальной переменной $Line определяет общее число Out–параграфов текущего сеанса пакета, включая результаты вычисления загруженных в него пакетов пользователя из файлов формата {"cdf", "nb"}. Фрагмент представляет исходный код и примеры применения.

In[13]:= $Line1 := Block[{a = "", c = "Out[", k = 1}, For[k, k Infinity, k++, a = ToString[Out[k]];

If[a == c ToString[k] "]", Return[k]]];

k] In[14]:= $Line Out[14]= In[15]:= $Line Out[15]= Расширение функциональной среды системы Mathematica Приведенные примеры достаточно наглядно иллюстрируют ситуацию, когда после загрузки пакета пользователя значения $Line1 и $Line могут достаточно существенно различаться: первое, определяя общее число сохраненных Out–параграфов, тогда как второе – число реально полученных Out–параграфов в текущем сеансе пакета.

Следует отметить, что %–операторы в пакете Mathematica и в пакете Maple являются концептуально различными. Так, если в первом случае %–оператор непосредственно ассоциирован только с Out–параграфами текущего сеанса на глубину, допускаемую пакетом, что в целом ряде случаев работы в режиме документа представляется очень полезным, то во втором случае %–оператор имеет глубину не более 3 и ассоциирован с результатами выполнения как предыдущих Out–параграфов, так и предложений. В данном контексте в первом случае использование %-оператора в процедуре/функции, в целом, не имеет особого смысла, тогда как во втором – применение %–оператора в процедурах имеет вполне определенный смысл. Следующий пример весьма наглядно иллюстрирует вышесказанное, а именно:

In[1026]:= $HistoryLength = Out[1026]= In[1027]:= G[x_, y_] := Module[{a = 70, b}, b = a*(x + y);

{%, Out[1026]};

G[42, 2012] Out[1027]= {3000, 3000} G := proc(x, y) local a, b;

a := 70;

b := a*(x + y);

% end proc: G(42, 2012);

Итак, реальной областью применимости %–оператора в Mathematica является текущий сеанс, исключая область процедур/функций, в то время как областью применимости %–оператора в среде Maple является текущий сеанс в целом, вместе с тем, на глубину, не большую трем. Таким образом, %–операторы (Ditto operators), имея в Mathematica и Maple различные реальные области применимости, вместе с тем, обладают как своими недостатками, так и существенными преимуществами. Выше отмечалось, что путем изменения значения для переменной $HistoryLength (сохраняется до переопределения, если установка размещена в инициализационном файле init.m) можно весьма существенно экономить размер оперативной памяти, требуемой для рабочей области Mathematica.

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

Вероятно, пользователь заметил, что после некоторой попытки обновить определение процедуры оно остается прежним. Это обстоятельство следует учитывать при отладке процедур и функций, периодически применяя к ним функцию Clear или ClearAll.

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

В.З. Аладьев, Д.С. Гринь In[1520]:= ClearOut[x_ /;

PosIntQ[x] || PosIntListQ[x]] := Block[{a = Flatten[{x}], k = 1}, Unprotect[Out];

For[k, k = Length[a], k++, Out[a[[k]]] =. ];

Protect[Out];

] In[1517]:= {Out[1508], Out[1510], Out[1511], Out[1515]} Out[1517]= {42, 70, 2012, 450} In[1525]:= ClearOut[{1508, 1510, 1511, 1515}] In[1526]:= {Out[1508], Out[1510], Out[1511], Out[1515]} Out[1526]= {%1508, %1510, %1511, %1515} Исходный код достаточно прозрачен и каких-либо особых пояснений не требует.

С другой стороны, в ряде случаев работы в режиме документа появляется надобность замены Out–параграфов иным содержимым, что обеспечивает достаточно несложная процедура ReplaceOut, чей успешный вызов ReplaceOut[x, y] ничего не возвращает, в то же время выполняя замену содержимого существующих Out–параграфов, которые заданы целым положительным или их списком x, на новое выражение, определенное y-аргументом. Вызов предполагает паритет числа заменяемых Out-параграфов числу выражений, заменяющих их текущие значения;

в противном случае вызов процедуры ReplaceOut[x, y] возвращается невычисленным. Следующий фрагмент представляет исходный код процедуры ReplaceOut с типичными примерами ее применения.

In[1525]:= Agn = Out[1525]= In[1526]:= ReplaceOut[x_ /;

PosIntQ[x] || PosIntListQ[x], y_] := Module[{a = Flatten[{x}], b = Flatten[{y}], k = 1}, If[b != {}, If[Length[a] != Length[b], Defer[ReplaceOut[x, y]], Unprotect[Out];

For[k, k = Length[a], k++, Out[a[[k]]] = b[[k]]];

Protect[Out]];

, ClearOut[x]]] In[1527]:= ReplaceOut[1535, 70] In[1528]:= Out[1535] Out[1528]= In[1531]:= ReplaceOut[1535] In[1532]:= Out[1535] Out[1532]= % Вообще говоря, процедура ReplaceOut обобщает предыдущую процедуру ClearOut.

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

In[1517]:= vs = 70;

vg = Out[1517]= In[1518]:= res = vs^2 + vg^3 + Out[1518]= Расширение функциональной среды системы Mathematica In[1519]:= Out[1518] Out[1519]= По оператору присваивания «=» производится немедленное присвоение одной либо нескольким переменным требуемого значения, тогда как по конструкции x =. либо функциям Clear, ClearAll переменная x очищается от приписанного ей значения:

In[1522]:= t = 2012;

x = y = z = Out[1522]= In[1523]:= {t, x, y, z} Out[1523]= {2012, 2012, 2012, 2012} Для определения типа присвоения, примененного к символу (имени), можно применять достаточно простую процедуру DefOp, чей вызов DefOp[w] возвращает в строчном формате тип присвоения, примененного к имени x, закодированному тоже в строчном формате: (1) "Undefined" – имя w не определено, (2) "=" – к имени w было применено немедленное присвоение и (3) ":=" – к имени w применено отложенное присвоение. В приведенном фрагменте представлен исходный код процедуры с примерами.

In[1532]:= DefOp[x_ /;

StringQ[x] && SymbolQ[x] || SymbolQ[ToExpression[x]], y_] := Module[{a = DefOpt[x], b = {y}, c, d}, If[a == "Null", Return["Undefined"], c[h_] := StringTake[a, {Flatten[StringPosition[a, h]][[2]] + 1, –1}]];

If[SuffPref[a, x " = ", 1], d = "=", d = ":="];

If[b != {} && ! HowAct[y], y = c[d]];

d] In[1533]:= v = 70;

g = 65;

s := 45;

Kr = 16;

Art := 23;

Res := a + b + c;

In[1534]:= Map[DefOp, {"v", "g", "s", "Kr", "Art", "Res", "Avz"}] Out[1534]= {"=", "=", ":=", "=", ":=", ":=", "Undefined"} In[1535]:= Clear[y];

{DefOp["Art", y], y} Out[1535]= {":=", "23"} In[1536]:= Clear[y];

{DefOp["Res", y], y} Out[1536]= {":=", "a + b + c"} In[1537]:= {x, y, z, h, g, v, s} := {a1, b1, c1, d1, f1, g1, h1};

In[1538]:= Map[DefOp, {"x", "y", "z", "h", "g", "v", "s"}] Out[1538]= {":=", ":=", ":=", ":=", ":=", ":=", ":="} In[1539]:= {x, y, z, h, g, v, s} = {a2, b2, c2, d2, f2, g2, h2};

In[1540]:= Map[DefOp, {"x", "y", "z", "h", "g", "v", "s"}] Out[1540]= {"=", "=", "=", "=", "=", "=", "="} Тогда как вызов DefOp[w,y] через необязательный второй аргумент – неопределенная переменная y – возвращает выражение, присвоенное символу w.

Значение, присвоенное переменной x, остается ассоциированным с ней до его удаления по x =., по функциям Clear, ClearAll, Remove либо ее переопределения, например:

In[1522]:= t = 2012;

x = y = z = In[1541]:= x =.;

Remove[y];

z = Out[1541]= В.З. Аладьев, Д.С. Гринь In[1542]:= {x, y, z} Out[1542]= {x, y, 450} In[1558]:= h = 70;

Clear[h];

h Out[1558]= h Во избежание возможных ошибок при работе с большим документом рекомендуется очищать переменные сразу же по мере отсутствия в них необходимости. Имя может иметь любую длину, но не может начинаться с цифры. В имени допустимы заглавные и строчные буквы;

при этом, по соглашению встроенные объекты пакета начинаются с заглавных букв, поэтому рекомендуются пользовательские идентификаторы, которые начинаются со строчных букв. Однако, создавая свои библиотеки или пакеты, вполне допустимо для процедур/функций пользователя использовать имена, начинающиеся с заглавных букв. Именно такой подход использован нами в пакете AVZ_Package [90].

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

1) x y эквивалентно x*y;

2) xy – переменная с именем xy.

Тогда как для замены в выражениях подвыражений используется правило замены «–», как иллюстрирует простой пример, а именно:

In[1552]:= x y /. {x – 42, y – 70} Out[1552]= In[1553]:= (70 x + y) /. {70 x – vgs, y – vsv} Out[1553]= vgs + vsv Если к выражению применяется несколько правил, то они кодируются в виде списка.

Наряду с (=)–оператором присваивания Math–язык использует также и (:=)–оператор отложенного присваивания, суть которого состоит в том, что реальное присваивание x:=y значения y объекту x производится только при конкретном использовании x, как это имеет место, например, при определении процедуры либо функции. При каждом использовании x каждый раз производится замена x на y, например:

In[1578]:= x := In[1579]:= ToString[%] Out[1579]= "Null" При этом, в отличие от немедленного присвоения отложенное присвоение возвращает Null, т.е. ничего, как иллюстрирует последний пример. Для вычисления присвоений Mat–язык располагает функцией Definition, вызов которой Definition[x] возвращает все определения, приписанные символу (имени) x. Между тем, применение к данной функции функции Map либо использование ее в списочной структуре (In–параграфы с номерами 1581, 1582, 1584, 1585 и 1586) визуализирует результаты некорректно, как это иллюстрируют приеры нижеследующего фрагмента. В качестве выхода здесь можно использовать применение функции Definition к именам по отдельности, применять к результату InputForm–функцию либо нашу процедуру DefOpt, рассматриваемую в настоящей книге ниже. Фрагмент достаточно наглядно иллюстрирует сказанное.

Расширение функциональной среды системы Mathematica In[1580]:= x = 70;

y := 2012;

In[1581]:= {Definition[x], Definition[y]} Out[1581]= {x = In[1582]:= {Definition[y], Definition[x]} Out[1582]= {x := In[1583]:= InputForm[{Definition[x], Definition[y]}] Out[1583]//InputForm= {x = 70, y := 2012} In[1584]:= Map[Definition, {x, y}] Definition::ssle: Symbol, string, or HoldPattern[symbol] expected at position in Definition[70].

Definition::ssle: Symbol, string, or HoldPattern[symbol] expected at position in Definition[2012].

Out[1584]= {, } In[1585]:= Map[Definition, {"x", "y"}] Out[1585]= {x = In[1586]:= % Out[1586]= {x = In[1587]:= Map[Definition, {"y", "x"}] Out[1587]= {y := In[1588]:= Definition[x] Out[1588]= x = In[1589]:= Definition[y] Out[1589]= y := In[1590]:= Map[DefOpt, {"x", "y"}] Out[1590]= {"x = 70", "y := 2012"} В целом ряде случаев возникает необходимость очистки переменных текущего сеанса от поученных в результате динамической генерации значений. С этой целью можно использовать механизм, состоящий в аккумулировании в списке значений, переменные с которыми впоследствие должны быть удалены из текущего сеанса или очищены как от своих значений, так и атрибутов. Для этого можно воспользоваться функцией, вызов которой ClearValues[x] возвращает пустой список, одновременно удаляя из текущего сеанса все переменные, имеющие значения из списка x;

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

In[1858]:= ClearValues[x_ /;

ListQ[x], y_] := Select[Map[If[{y} == {}, Remove, ClearAll], Select[Names["`*"], MemberQ[x, ToExpression[#]] &]], # != "Null" &] In[1859]:= {a = 42, b = 75, c := 75, d = 450, h5 := 65, Kr = 16, Art = x + Sin[y]} Out[1859]= {42, 75, Null, 450, Null, 16, x + Sin[y]} В.З. Аладьев, Д.С. Гринь In[1860]:= ClearValues[{42, 75, 75, 450, 65, 16, x + Sin[y]}] Out[1860]= {} In[1861]:= Names["`*"] Out[1861]= {"ClearValues"} In[1862]:= {a, b, c, d, h5, Kr, Art} Out[1862]= {a, b, c, d, h5, Kr, Art} In[1887]:= {a = 42, b = 75, c := 75, d = 450, h5 := 65, Kr = 16, Art = x + Sin[y]} Out[1887]= {42, 75, Null, 450, Null, 16, x + Sin[y]} In[1888]:= ClearValues[{42, 75, 75, 450, 65, 16, x + Sin[y]}, 70] Out[1888]= {} In[1889]:= Names["`*"] Out[1889]= {"a", "Art", "b", "c", "ClearValues", "d", "h5", "Kr"} In[9]:= VarsValues[x_ /;

ListQ[x]] := Select[Names["`*"], MemberQ[x, ToExpression[#]] &] In[10]:= {a = 42, b = 75, c := 75, d = 450, h5 := 65, Kr = 16, Art = x + Sin[y]} Out[10]= {42, 75, Null, 450, Null, 16, x + Sin[y]} In[11]:= VarsValues[{42, 75, 75, 450, 65, 16, x + Sin[y]}] Out[11]= {"a", "Art", "b", "c", "d", "h5", "Kr"} Во второй части фрагмента представлена довольно простая функция VarsValues, чей вызов VarsValues[x] возвращает список переменных в строчном формате, имеющим значения из списка x. Обе функции представляют определенный интерес при работе с переменными текущего сеанса пакета. Прежде всего, в целом ряде случаев возникает задача очистки памяти от большого числа динамически сгенерированных значений, в то время как в целом ряде случаев требуется определить переменные, получившие в текущем сеансе значения по любому оператору присваивания. Если в первом случае вопрос имеет самое прямое отношение к задаче оптимизации использования памяти, в то время как во втором важен с точки зрения адресного использования значений.

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

– круглые скобки для группировки подвыражений в выражениях «()»;

– фигурные скобки для определения списочных структур «{}»;

– квадратные скобки для процедур и функций (вызовы, заголовки и т.д.) «[]»;

– двойные квадратные скобки для организации индексных структур «[[]]».

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

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

»

(точкой с запятой). При этом, если последнее выражение в In–параграфе завершается данным разделителем, возвращается Null, т.е. ничего, без создания Out–параграфа, в случае отсутствия возвращается результат вычисления последнего выражения, пример достаточно наглядно иллюстрирует вышесказанное, а именно:

In[1601]:= x = 70;

y := 42;

z = Out[1601]= In[1602]:= x = 70;

y := 42;

z = 2012;

In[1603]:= {x, y, z} Out[1603]= {70, 42, 2012} Более того, завершением последнего (либо единственного) выражения в In–параграфе разделителем «;

», возвращающим Null в Out–параграфе, одновременно выполняется вычисление всех выражений In–параграфа, как это довольно наглядно иллюстрирует предыдущий весьма простой пример.

При программировании многих приложений является целесообразным использовать не отдельные выражения, а их совокупности, оформляемые в форме списков, формат которых очень прост, а именно: последовательность выражений, разделенных знаком запятая «,», берется в фигурные скобки, например, {a, b, c, d}. При такой организации вместо выполнения вычислений над отдельными выражениями имеется возможность выполнять требуемые операции как над списками, как едиными объектами, так и над их отдельными элементами. Списки различных типов представляют собой важную и одну из наиболее часто используемых структур в программной среде Mathematica. В программной среде пакета многие функции имеют атрибут Listable, говорящий, что процедура, функция либо оператор F с таким атрибутом автоматически применимы ко всем элементам списка, используемого соответственно в качестве их аргумента или операнда. Для тестирования наличия данного атрибута может использоваться весьма простая функция, чей вызов с примерами применения представляет фрагмент:


In[1550]:= ListableQ[x_] := MemberQ[Quiet[Check[Attributes[x], {}]], Listable] In[1551]:= Map[ListableQ, {70, Sin, Power, Plus, Log, a + b}] Out[1551]= {False, True, True, True, True, False} In[1552]:= a = N[{70, 42, 2012}];

{a, Sin[a]} Out[1552]= {{70., 42., 2012.}, {0.773891, –0.916522, 0.981986}} In[1553]:= {a^2, a + 70, a + {x1, y1, z1}} Out[1553]= {{4900, 1764, 4048144}, {140, 112, 2082}, {70 + x1, 42 + y1, 2012 + z1}} In[1569]:= a = {70, 42, 2012};

a + {x1, x2} Thread::tdlen: Objects of unequal length in {70, 42, 2012} + {x1, x2} cannot be combined.

Out[1569]= {x1, x2} + {70, 42, 2012} In[1570]:= a^{x1, x2} Thread::tdlen: Objects of unequal length in {70, 42, 2012}^{x1, x2} cannot be combined.

В.З. Аладьев, Д.С. Гринь Thread::tdlen: Objects of unequal length in {Log[70], Log[42], Log[2012]} {x1, x2} cannot be combined.

Out[1570]= {70, 42, 2012}^{x1, x2} In[1571]:= ListOp[a, {x1, x2}, Power] Out[1571]= {70^x1, 42^x2, 2012} In[1572]:= ListOp[{x1, x2}, a, Plus] Out[1572]= {70 + x1, 42 + x2, 2012} Между тем, для ряда операций, имеющих Listable-атрибут, требуется соответствие по длине списков-операндов, в противном инициируются соответствующие ошибочные ситуации, как иллюстрируют примеры предыдущего фрагмента. И лишь процедура ListOp, рассматриваемая несколько ниже, позволяет устранять подобные ситуации.

Вызов функции ListableQ[x] возвращает True, если объект x имеет Listable–атрибут, и False в противном случае. В принципе, любой процедуре/функции арности 1 можно приписать Listable–атрибут, обеспечивая ее корректный вызов на списках в качестве ее фактического аргумента, как наглядно иллюстрирует следующий фрагмент:

In[1569]:= ProcQ[{ProcQ, ListOp, DefOp, Globals, DirName, Mapp, Attrib}] Definition::ssle: Symbol, string, or HoldPattern[symbol] expected at position 1 in Definition[{ProcQ, ListOp, DefOp, Globals, DirName, Mapp, Attrib}].

Out[1569]= False In[1570]:= SetAttributes[ProcQ, {Listable}] In[1571]:= ProcQ[{ProcQ, ListOp, DefOp, Globals, DirName, Mapp, Attrib}] Out[1571]= {True, True, True, True, False, True, True} Если вызов процедуры ProcQ (рассматривается ниже) без Listable–атрибута на списке x инициирует ошибку, в результате присвоения ей данного атрибута вызов ProcQ[x] на списке x в качестве аргумента процедуры возвращает вполне ожидаемый результат, как весьма наглядно иллюстрирует предыдущий фрагмент. На формальном уровне для процедуры/функции F арности 1 можно отметить нижеследующее определяющее соотношение, а именно: Map[F, {a, b, c, d,…}] {F[a], F[b], F[c], F[d],…}, где в левой части процедура F может быть как с Listable–атрибутом, так и без оного, тогда как в правой части предполагается наличие Listable–атрибута для процедуры/функции F. Таким образом, для процедур/функций без Listable–атрибута используется функция Map.

Для обеспечения наличия Listable–атрибута для процедуры/функции пользователя, стандартной функции h может оказаться достаточно полезной достаточно несложная процедура ListableC, чей вызов ListableC[h] возвращает список атрибутов h–объекта, обеспечивая установку атрибута Listable–атрибута для объекта h (процедура/функция пользователя или стандартная функция). Следующий фрагмент представляет исходный код процедуры наряду с наиболее типичными примерами ее применения, а именно:

In[1549]:= ListableC[x_ /;

SystemQ[x] || ProcQ[x] || QFunction[ToString[x]]] := Module[{b = If[MemberQ[Attributes[x], Protected], "Protected", "Null"]}, a = Attributes[x], If[MemberQ[a, Listable], a, Unprotect[x];

SetAttributes[x, Listable];

If[b == "Protected", Protect[x]];

Attributes[x]]] Расширение функциональной среды системы Mathematica In[1543]:= Attributes[FromCharacterCode] Out[1543]= {Protected} In[1550]:= ListableC[FromCharacterCode] Out[1550]= {Listable, Protected} In[1555]:= ListableC[ProcQ] Out[1555]= {Listable} In[1559]:= ProcQ[{ProcQ, ListableC, Def, Def1, Definition1}] Out[1559]= {True, True, True, True, True} В Mathematica для группировки выражений наряду с простыми списками используются и более сложные списочные структуры – вложенные списки, чьими элементами также являются списки (подсписки). В этом отношении особый интерес представляют списки ListList-типа, чьи подсписки имеют одинаковую длину. При этом, для простых списков пакет располагает тестирующей функцией, чей вызов ListQ[x] возвращает True, если x – список, и False в противном случае. Тогда как для тестирования вложенных списков нами определены функции NestListQ и ListListQ, рассматриваемые несколько ниже.

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

Матричные объекты непосредственно представляются вложенными списками ListList– типа, для обработки которых пакет располагает целым рядом средств, включая также работу с матрицами специального типа. Каждый список L ListList–типа может быть представлен соответствующей матрицей размерности Length[L] * Length[L[[1]]]. Итак, вектора и матрицы могут быть представлены простыми списками и списками ListList– типа соответственно. Для обеспечения работы с вложенными списками был предложен ряд полезных средств, представленных ниже. В качестве лишь одного из этих средств рассмотрим процедуру, чей вызов TransListList[x] возвращает результат транспозиции списка x ListList–типа. Процедура TransListList работает по принципу переключателя;

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

In[1563]:= TransListList[L_ /;

ListListQ[L]] := Module[{a = Length[L], b = Length[L[[1]]], c = {}, d = {}, k = 1, j}, For[k, k = b, k++, For[j = 1, j = a, j++, d = Append[d, L[[j]][[k]]]];

c = Append[c, d];

d = {}];

c] In[1564]:= L = {{a0, b0, c0, d0}, {a1, b1, c1, d1}, {a2, b2, c2, d2}, {a3, b3, c3, d3}, {a4, b4, c4, d4}};

In[1565]:= L1 = TransListList[L] Out[1565]= {{a0, a1, a2, a3, a4}, {b0, b1, b2, b3, b4}, {c0, c1, c2, c3, c4}, {d0, d1, d2, d3, d4}} In[1566]:= Map[MatrixForm, {L, L1}] a0 b0 c0 d d1 a0 a1 a2 a3 a a1 b1 c d2, b0 b1 b2 b3 b : a2 b2 c d3 c0 c1 c2 c3 c a3 b3 c d4 d0 d1 d2 d3 d Out[1566]= a4 b4 c Наряду к таким объектам, группирующим данные, как списки и матрицы, в полной В.З. Аладьев, Д.С. Гринь мере можно отнести таблицы (Table) и массивы (Array), для которых пакет предлагает целый ряд функциональных средств обработки как над объектами в целом, так и над их отдельными элементами. Вопросы этого типа здесь не рассматриваются, читатель отсылается к соответствующей литературе либо к справочной системе пакета. Здесь же делается акцент на списочные структуры, как основу группирующих объектов.

Между тем, для целого ряда функций и выражений Listable-атрибут не работает, и в этом случае пакет предоставляет специальные две функции Map и Thread, которые в определенном отношении вполне можно отнести к структурным средствам, которые обеспечивают применение функций к частям выражений. В данном плане нами был создан целый ряд довольно простых и вместе с тем достаточно полезных процедур и функций Mapp, Map1 Map16, довольно существенно расширяющих функцию Map.

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

In[548]:= TableForm[{{1, Vic, 70}, {2, Gal, 65}, {3, Sv, 45}, {4, Art, 23}, {5, Kr, 16}, {6, Arn, 50}}] Out[548]//TableForm = 1 Vic 2 Gal 3 Sv 4 Art 5 Kr 6 Arn Аналогичным образом дело обстоит с матрицами/векторами, также базирующимися на простых и вложенных списках ListList-типа. Со стандартными функциями, которые служат как для генерации таблиц, матриц и векторов, так и для их обработки можно ознакомиться в справке по пакету. Следующий фрагмент представляет функции для представления вложенного списка ListList–типа в форме таблицы и матрицы:

In[1610]:= Map15[TableForm, MatrixForm, {{1, Vic, 70}, {2, Gal, 65}, {3, Sv, 45}, {4, Art, 23}, {5, Kr, 16}, {6, Arb, 50}}] 1 Vic 70 1 Vic 2 Gal 65 2 Gal 3 Sv 45 3 Sv Out[1610]= ;

?

, 4 Art 23 4 Art 5 Kr 16 5 Kr 6 Arb 50 6 Arb In[1619]:= Map15[x /;

DeleteDuplicates[Map[SymbolQ, {x}]] == {True}, y_] := Module[{a = Length[{x}], b = {}, с={x}, k = 1}, While[k = a, b = Append[b, ToString[с[[k]]] "[" ToString1[y] "]"];

k++];

ToExpression[b]] In[1620]:= Map15[F, G, H, P, Q, X, Y, Z, (a + b)] Out[1620]= {F[a + b], G[a + b], H[a + b], P[a + b], Q[a + b], X[a + b], Y[a + b], Z[a + b]} С целью компактного представления списка ListList-типа в двух указанных форматах используется полезное обобщение функции Map в виде процедуры Map15, которая представлена последним примером предыдущего фрагмента. Процедура Map15, чей Расширение функциональной среды системы Mathematica вызов Map15[F1, F2, …, Fp, t], где Fj – символы, тогда как t – произвольное выражение, возвращает результат формата: {F1[t], F2[t], F3[t], F4[t], …, Fp[t]}, не требуя каких–либо дополнительных пояснений ввиду ее вполне достаточной прозрачности.

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

Для идентификации конкретного элемента списка L используются индекс L[[n]] либо функция Part[L, n], позволяющая выделять отдельный элемент списка или их группы.

Из операций над списками, как едиными объектами, можно отметить арифметические операции при условии, что списки имеют одинаковую длину, например:


In[1531]:= L = {a1, b1, c1, d1};

L1 = {a2, b2, c2, d2};

In[1532]:= L + L Out[1532]= {a1 + a2, b1 + b2, c1 + c2, d1 + d2} In[1533]:= L*L Out[1533]= {a1 a2, b1 b2, c1 c2, d1 d2} In[1534]:= L^L Out[1534]= {a1^a2, b1^b2, c1^c2, d1^d2} In[1535]:= L/L Out[1535]= {a1/a2, b1/b2, c1/c2, d1/d2} Работа со списками разной длины обсуждалась выше и детальнее рассмотрена ниже.

Отметим некоторые из наиболее часто используемых функций работы со списками.

Range – генерирует числовой список на основе числовых аргументов числом от 1 до 3;

CharacterRange – генерирует символьный список на основе двух строчных аргументов;

в качестве аргументов выступают буквы латинского алфавита в строчном формате.

Как и во многих иных случаях вполне целесообразно модифицировать стандартные функции, обеспечивающие как более удобное использование, так и расширяющие их функциональные возможности. Многочисленные примеры такого рода представлены и в настоящей книге. Так для функции Range приводятся 3 полезные модификации – Range1, Range2 и Range3. Здесь лишь приведем процедуру Range4, сочетающую обе стандартные функции Range и CharacterRange с расширением возможностей второй.

Вызовы Range4[x], Range4[x, y], Range4[x, y, z] на числовых аргументах эквивалентны вызовам Range[x], Range[x, y], Range[x, y, z] стандартной функции соответственно, в то же время как вызов Range4[x,y] на строчных символах с кодами 32 4096 эквивалентен вызову CharacterRange[x, y], вызов Range4[x] возвращает список символов с кодами, меньшими либо равными ToCharacterCode[x]. Фрагмент представляет исходный код процедуры Range4 с наиболее типичными примерами ее применения.

In[1543]:= Range4[x_, y_] := Module[{a = Select[Flatten[{x, If[{y} != {}, {y}, Null]}], # != "Null" &], b}, If[DeleteDuplicates[Map[NumberQ, a]] == {True}, Range[Sequences[a]], b = Map[FromCharacterCode, Range[32, 4096]];

If[Length[{x, y}] == 2 && MemberQ3[b, {x, y}] == True, CharacterRange[x, y], If[Length[{x, y}] == 1 && StringQ[x], Select[b, ToCharacterCode[#][[1]] = ToCharacterCode[x][[1]] &], $Failed]]]] В.З. Аладьев, Д.С. Гринь In[1544]:= Range4["2"] Out[1544]= {" ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2"} In[1545]:= Range4["9", "H"] Out[1545]= {"9", ":", ";

", "", "=", "", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H"} In[1546]:= Range4[42, 70, 2] Out[1546]= {42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70} In[1547]:= Range4[52, 70] Out[1547]= {52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70} In[1548]:= Range4[22] Out[1548]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22} In[1549]:= MemberQ3[x_ /;

ListQ[x], y_ /;

ListQ[y]] := Block[{h = StringTake[ToString1[Map3[MemberQ, x, y]], {2, –2}]}, ToExpression["And[" h "]"]] In[1550]:= Map3[MemberQ3, {a, b, c}, {{c, a}, {c, d}, {m, n}}] Out[1550]= {True, False, False} In[1551]:= MemberQ3[x_ /;

ListQ[x], y_ /;

ListQ[y]] := DeleteDuplicates[Map3[MemberQ, Flatten[x], Flatten[y]]] == {True} С целью упрощения алгоритма процедуры Range4 используется процедура/функция MemberQ3[x, y], вызов которых возвращает True, если список y – подсписок списка x, и False в противном случае, но без учета вложенности. Представлены обе реализации.

Как отмечалось выше, многие функции работают со списками как едиными объектами, однако в целом ряде случаев имеется настоятельная необходимость оперирования с отдельными их элементами, что достигается или упомянутой функцией Part формата, соответствующего задаче, либо с использованием индексации, имеющей следующий формат, а именно: L[[k]], L[[k]][[j]] … [[p]];

при этом, использование функции Part при значительной глубине индексации представляется более компактным и наглядным.

Вложенные списки могут представлять достаточно широкий спектр структур данных (векторы, таблицы, массивы, матрицы и др.). Между тем, в целом ряде случаев требуется сведение их к более простым спискам, имеющим меньший уровень вложенности. Эту задачу решает функция Flatten, располагая четырьмя форматами кодирования. Так, на ее основе можно создавать достаточно эффективные средства обработки списочных структур. В качестве примера приведем процедуру MaxLevel, чей вызов MaxLevel[x] возвращает максимальный уровень вложенности списка x (при этом, уровень вложенности простого списка полагается равным 0). Следующий фрагмент представляет и исходный код процедуры MaxLevel, а также типичные примеры ее применения, а именно:

In[1562]:= MaxLevel[x_ /;

ListQ[x]] := Module[{a = x, k = 0}, While[NestListQ[a], k++;

a = Flatten[a, 1];

Continue[]];

k] In[1563]:= Map[MaxLevel, {{a, b}, {a, {b, c, d}}, {{{a, b, c}}}, {a, {{c, {d}, {{h, g}}}}}}] Out[1563]= {0, 1, 2, 4} In[1564]:= MaxLevel[{a, b, c, d, f, g, h, s, r, t, w, x, y, z}] Out[1564]= Расширение функциональной среды системы Mathematica In[1581]:= ListLevels[x_ /;

ListQ[x]] := Module[{a = x, b, c = {}, k = 1}, If[! NestListQ[x], {0}, While[NestListQ[a], b = Flatten[a, 1];

If[Length[b] = Length[a], c = Append[c, k++], c = Append[c, k]];

a = b;

Continue[]];

c]] In[1582]:= ListLevels[{a, b, c, d, f, g, h, s, r, t, w, x, y, z}] Out[1582]= {0} In[1583]:= ListLevels[{a, b, c, {d, f, g, {h, s, {z, y, g}, r}, t}, w, {x, {{{a, b, c}}}, y}, z}] Out[1583]= {1, 2, 3, 4} В представленном примере определение процедуры MaxLevel использует функцию, чей вызов ListQ[x] возвращает True, если x – список, и False в противном случае, в то время как вызов функции NestListQ[x] возвращает True, если x – вложенный список, и False в противном случае. Для более детального тестирования объектов на List–тип нами были дополнительно определены тестирующие функции ListListQ, NestListQ, NestQL и PosIntListQ, рассматриваемые ниже. В случае необходимости пользователь имеет возможность существенно расширять этот список с учетом потребности своих приложений либо системных задач. Завершает фрагмент процедура, вызов которой ListLevels[x] возвращает список уровней вложенности списка x;

при этом, на простом списке вызов процедуры возвращает {0}. Более того, между упомянутыми функциями имеют место следующие определяющие соотношения, а именно:

Flatten[x] Flatten[x, MaxListLevel[x]] MaxListLevel[x] ListLevels[x][[–1]] Представимм еще две простые функции, тестирующие списочные структуры. Вызов функции ListNumericQ[x] возвращает True, если x, включая все его подсписки любого уровня вложенности, является числовым списком, и False в противном случае. Более того, рассматривается не сам список x, а список N[x], что в целом ряде случаев весьма актуально. В то время как вызов ListExprHeadQ[w, h] возвращает True, если список w содержит лишь элементы, удовлетворяющие условию Head[a] = h, и False в противном случае. Фрагмент представляет коды обеих функций с примерами их применения.

In[1574]:= ListNumericQ[x_ /;

ListQ[x]] := If[DeleteDuplicates[Map[NumericQ, N[Flatten[x]]]] == {True}, True, False] In[1575]:= Map[ListNumericQ, {{42, 450.75, 15/23, Sqrt[2]}, {42, 450.75, a, Sqrt[2]}}] Out[1575]= {True, False} In[1576]:= ListExprHeadQ[x_ /;

ListQ[x], h_] := If[DeleteDuplicates[Map[Head, x]] === {h}, True, False] In[1577]:= {ListExprHeadQ[{(a + b), (c – d)}, Plus], ListExprHeadQ[{a*b, c/d}, Times]} Out[1577]= {True, True} Перечисленные и ряд других средств часто используются при обработке списочных структур. Более того, многие из них используются и средствами пакета AVZ_Package.

В отличие от Maple, в пакете Mathematica средства для работы с индексированными выражениями отсутствуют. Для устранения этого недостатка могут быть предложены достаточно простые процедуры, а именно IndexedQ,Index и ArrayInd, рассмотренные ниже. Тогда как здесь представим весьма простую процедуру IndexQ, вызов которой В.З. Аладьев, Д.С. Гринь IndexQ[x] возвращает True, если x – индексированное выражение, и False в противном случае;

при этом, аргумент x задается в строчном формате, где под индексированным понимается любое выражение в приведенной форме, которое завершается индексной скобкой "]]". Следующий фрагмент представляет исходные коды процедуры IndexQ с наиболее типичными примерами ее применения.

In[1623]:= IndexQ[x_String] := If[! SuffPref[x, "[[", 1] && StringDependQ[x, {"[[", "]]"}] && EvenQ[StringCount[x, {"[[", "]]"}]] && StringTake[x, {–2, –1}] == "]]", True, False] In[1624]:= Map[IndexQ, {"{a, {b, x, y}, c}[[2, 4]]", "(a + b)", "V[[70]]", "G[[47, 65]] + Sv", "V[[a[[b]] + c[[d]]]][[a + b]]", "Sin[x] + V[[70]]", "G*L[[47]][[65]]", "L[[47]][[65]] + S"}] Out[1624]= {True, False, True, False, True, True, True, False} In[1625]:= IndexQ[x_String] := If[StringTake[x, {–2, –1}] != "]]", False, True] In[1626]:= Map[IndexQ, {"{a, {b, x, y}, c}[[2, 4]]", "(a + b)", "V[[70]]", "G[[47, 65]] + Sv", "V[[a[[b]] + c[[d]]]][[a + b]]", "Sin[x] + V[[70]]", "G*L[[47]][[65]]", "L[[47]][[65]] + S"}] Out[1626]= {True, False, True, False, True, True, True, False} Как следует из фрагмента, под индексированными в контексте процедуры/функции IndexQ понимается достаточно широкий круг выражений, предполагая дальнейшую детализацию данного понятия, что представляется важным для ряда приложений. В частности, на основе этой функции довольно несложно программируется достаточно полезная в целом ряде задач работы с индексированными выражениями процедура с исходным кодом и примерами применения, представленными фрагментом.

In[1675]:= Indices[x_ /;

IndexQ[x]] := Module[{a = "]]", b = "[[", h = x, c, d = {}, g, t, k, y, p = StringLength[x]}, While[p = 4, For[k = p – 2, k = 1, k––, c = StringTake[h, {k, p}];

If[StringCount[c, a] == StringCount[c, b], d = Append[d, {k, c}];

Break[]]];

k = d[[–1]][[1]];

h = StringTake[h, {1, k – 1}];

If[IndexQ[h], p = StringLength[h];

Continue[], Break[]]];

g = Reverse[Map[{#[[1]], #[[2]], #[[1]] + StringLength[#[[2]]]} &, d]];

y = g[[–1]][[2]];

For[k = Length[g] – 1, k = 1, k––, If[g[[k]][[3]] == g[[k + 1]][[1]], y = g[[k]][[2]] y]];

y] In[1676]:= Indices["(Art[[23]] + Kr[[16]])*a[[a + b]][[b[[k]] + j]][[c, d]]"] Out[1676]= "[[a + b]][[b[[k]] + j]][[c, d]]" In[1677]:= Indices["a[[a + b]][[b[[k]] + j]][[c, d]]"] Out[1677]= "[[a + b]][[b[[k]] + j]][[c, d]]" In[1678]:= Indices["a[[a + b]][[b[[k]] + j]][[c, d]] + Sin[x]"] Out[1678]= Indices["a[[a + b]][[b[[k]] + j]][[c, d]] + Sin[x]"] Вызов процедуры Indices[x] возвращает индексную составляющую индексированного выражения x, заданного в строчном формате, в противном случае вызов возвращается невычисленным, как наглядно иллюстрируют примеры предыдущего фрагмента. В то же время рассмотрение всех функций, поддерживаемых Mathematica для работы с массивами, таблицами, векторами и матрицами, нами здесь не обсуждается равно как и множество функций по работе со списочными структурами, как самостоятельными Расширение функциональной среды системы Mathematica объектами. Заинтересованный читатель отсылается к справочной информации либо к соответствующей литературе по пакету Mathematica. Пакет рассматривает список, как объект, допускающий кратные вхождения элементов и сохраняющий тот порядок элементов, который был задан при его определении. Между тем, пакет, не определяя отдельно такого объекта как множество, обеспечивает ряд теоретико–множественных операций над списками аналогично множествам, а точнее, имитируется работа над множествами. Для сведения кратности элементов списка к 1 используется функция DeleteDuplicates, тогда как упорядочивание элементов списка обеспечивает функция Sort пакета. Наряду с сортировкой пакет предоставляет ряд весьма полезных средств для различного типа переупорядочиваний элементов списка. С другими функциями, поддерживающими теоретико–множественные операции, можно ознакомиться как в справке по пакету, так и в соответствующей литературе. Более того, несколько ниже будет представлен целый ряд довольно полезных средств для работы со списочными структурами, включая их теоретико–множественный аспект.

Здесь еще раз вполне уместно отметить естественный механизм создания и развития собственного программного инструментария пользователя, работающего в той либо иной программной среде. В процессе программирования того либо другого средства, либо целого проекта вполне реальна ситуация, когда весьма целесообразно написать дополнительные средства, отсутствующие среди стандартных, или эффективнее, или удобнее их. Во многих случаях применимость таких средств может носить довольно массовый характер, позволяя сформировать инструментарий достаточно широкого спектра применимости. Именно во многом благодаря описанному механизму и были созданы наши достаточно известная библиотека для Maple и пакет для Mathematica, содержащие более 850 и 500 средств соответственно [45,90]. В частности, в написании процедуры SortNestList для расширения области ее применимости как на числовые, так и на символьные вложенные списки оказалось весьма целесообразным определить три новые функции, а именно: SymbolGreater и SymbolLess, как аналоги операций Greater и Less соответственно, и функцию ListSymbolQ[x], возвращающую True, если все элементы списка x, включая его подсписки любого уровня вложенности, имеют тип Symbol, в противном случае возвращается False. Вызов процедуры SortNestList[x, p, y] возвращает результат сортировки вложенного числового либо символьного списка x по p-му элементу его подсписков согласно сортирующей функции Greater (), Less () для числовых списков и SymbolGreater (), SymbolLess () для символьных списков. При этом, в обоих случаях в качестве фактического аргумента x предполагается вложенный список с уровнем вложенности 1, иначе возвращается исходный список x. Тогда как в случае символьных списков сравнение элементов производится на основе их кодов. В следующем фрагменте представлены исходные коды всех вышеупомянутых средств с примерами их наиболее типичного применения.

In[1636]:= SortNestList[x_ /;

NestListQ[x], p_ /;

PosIntQ[p], y_] := Block[{a = DeleteDuplicates[Map[Length, x]], b}, b = If[DeleteDuplicates[Map[ListNumericQ, x]] == {True} && MemberQ[{Greater, Less}, y], y, If[DeleteDuplicates[Map[ListSymbolQ, x]] == {True} && В.З. Аладьев, Д.С. Гринь MemberQ[{SymbolGreater, SymbolLess}, y], y], Return[Defer[SortNestList[x, p, y]]]];

If[Min[a] = p = Max[a], Sort[x, b[#1[[p]], #2[[p]]] &], Defer[SortNestList[x, p, y]]]] In[1637]:= SortNestList[{{42, 47, 67}, {70, 65, 45}, {23, 16}}, 16, Greater] Out[1637]= SortNestList[{{42, 47, 67}, {70, 65, 45}, {23, 16}}, 16, Greater] In[1638]:= SortNestList[{{42, 47, 67}, {70, 65, 45}, {23, 16}}, 2, Greater] Out[1638]= {{70, 65, 45}, {42, 47, 67}, {23, 16}} In[1639]:= SortNestList[{{42, 47, 67}, {70, 65, 45}, {23, 16}}, 2, Less] Out[1639]= {{23, 16}, {42, 47, 67}, {70, 65, 45}} In[1640]:= SortNestList[{{"a", Avz, b1}, {x4, Agn65, y3}, {V70, G65}}, 2, SymbolGreater] Out[1640]= {{x4, Agn65, y3}, {"a", Avz, b1}, {V70, G65}} In[1641]:= SortNestList[{{"a", Avz, b1}, {x4, Agn65, y3}, {V70, G65}}, 2, SymbolLess] Out[1641]= {{V70, G65}, {"a", Avz, b1}, {x4, Agn65, y3}} In[1596]:= SortNestList[{{42, 47, 67}, {70, {67, 89}, 65, 45}, {23, {16, 6}}}, 2, Greater] Out[1596]= {{42, 47, 67}, {70, {67, 89}, 65, 45}, {23, {16, 6}} In[1597]:= SortNestList[{{"a", Avz, b1}, {x4, {x, y}, Agn65, y3}, {V70, G65}}, 2, SymbolLess] Out[1597]= {{"a", Avz, b1}, {x4, {x, y}, Agn65, y3}, {V70, G65}} In[1636]:= SymbolGreater[x_ /;

SymbolQ[x], y_ /;

SymbolQ[y]] := If[ToExpression[StringJoin[Map[ToString, ToCharacterCode[ToString[x]]]]] ToExpression[StringJoin[Map[ToString, ToCharacterCode[ToString[y]]]]], True, False] In[1637]:= Map11[SymbolGreater, Sequences, {{Avz, Agn}, {Rans, Ian}, {"a", "c"}, {"x", "z"}}] Out[1637]= {True, True, False, False} In[1638]:= SymbolLess[x_ /;

SymbolQ[x], y_ /;

SymbolQ[y]] := If[ToExpression[StringJoin[Map[ToString, ToCharacterCode[ToString[x]]]]] ToExpression[StringJoin[Map[ToString, ToCharacterCode[ToString[y]]]]], True, False] In[1639]:= Map11[SymbolLess, Sequences, {{Avz, Agn}, {Rans, Ian}, {"a", "c"}, {"x", "z"}}] Out[1639]= {False, False, True, True} In[1645]:= ListSymbolQ[x_ /;

ListQ[x]] := If[DeleteDuplicates[SymbolQ /@ Flatten[x]] == {True}, True, False] In[1646]:= ListSymbolQ[{Avz, Agn, "a", "b", Ian, "Rans", "x", "y"}] Out[1646]= True Списочная структура – одна из важнейших в Mathematica, поэтому существует целый ряд способов ее определения и большое число функций манипулирования с такого типа структурами. Естественно, весь спектр функций данного типа здесь рассмотреть не представляется возможным, перечислим лишь основные группы данных функций, отправляя заинтересованного читателя к справочной информации по пакету либо к соответствующей довольно многочисленной и зачастую превосходной литературе, и, прежде всего, англоязычной. В последней на сегодня мы имеем целый ряд довольно квалифицированных как с писательской, так и профессионально–ориентированной точки зрения авторов. Кратко охарактеризуем здесь наиболее массовые стандартные Расширение функциональной среды системы Mathematica функции, поддерживаемые Mathematica, сгруппировав их по основному назначению (между тем, носящему довольно условный характер), а именно:

Создание списков: Mathematica поддерживает целый ряд функций, обеспечивающих создание списков различного размера и структуры. Среди данных функций следует отметить такие, как: Range, Table, Array, Tuples, Subsets, Permutations, RandomChoice, RandomInteger, NestList, FixedPointList, NestWhileList, Append, IntegerDigits, Import, RealDigits, Characters, CharacterRange, ReplaceList, BinaryReadList и ряд других;

Обработка элементов списка: Mathematica обеспечивает отлично выбранный набор функций для доступа к отдельным либо группам элементов списков, либо используя индексы, либо их позиции, либо на основе шаблонов, либо на основе их значений. К данным функциям можно отнести такие, как: Part, Span, First, Last, Rest, Take, Select, Drop, Prepend, Insert, Delete, AppendTo, Position, Extract, ReplacePart, Ordering, Cases, Length, Count, ArrayQ, MatrixQ, MemberQ, FreeQ, VectorQ и целый ряд других. При этом, Mathematica обеспечивает существенный набор встроенных функций, которые связаны с анализом элементов списков любых допустимых размеров и структуры;

Реструктуризация списков: Mathematica обеспечена рядом высокоэффективных для реструктуризации списков любых структуры и числа элементов функций, из которых следует отметить такие, как: Flatten, Partition, Join, ArrayFlatten, FlattenAt, Sort, SortBy, Reverse, RotateLeft, RotateRight, Transpose, Riffle, PadLeft, PadRight, Gather, SplitBy, Union, DeleteDuplicates, Intersection, Complement и целый ряд других;

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

К данным функциям можно отнести следующие, а именно: Map, Apply, MapIndexed, MapAt, Scan, FoldList, ComposeList, Outer, Thread, MapThread и целый ряд других;

Арифметические операции над списками: Как было отмечено ранее, математические функции, обеспечиваемые Mathematica, снабжены Listable-атрибутом, позволяющим применять их к элементам списка параллельно. Между тем, Listable–атрибутом также снабжены и арифметические операции Length, Plus, Subtract, Divide, Power, Times, BinCounts, Commonest, Ratios, Total, Mean, Accumulate, Differences, Max, Min, и др.



Pages:     | 1 || 3 | 4 |   ...   | 20 |
 





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

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