​​




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

Список имен используемых встроенных функций и символов в порядке их появления в коде: Manipulate | Graphics | List ({...}) | Part ([[…]]) | Span (;;) | EdgeForm | AbsoluteThickness | Darker | Gray | White | Disk | Inset | Image | CompressedData | Rule (->, →) | ColorSpace | ColorProfileData | Interleaving | True | Scaled | Times (*, ×) | Power (^) | Axes | False | PlotRange | ImageSize | RuleDelayed (:>, :→) | Initialization | CompoundExpression (;) | SetDelayed (:=) | Pattern (:) | Blank (_) | If | Inequality | Pi (π) | LessEqual (<=, ≤) | Less (<) | Text | Style | Bold | FontFamily | Cos | Sin | Plus (+) | Set (=) | Length | Table | Blend | Orange | Paneled | ControlPlacement | Top | AppearanceElements | None | ImageDimensions | Opacity | Red | LineSpacing | Reduce | Equal (==) | N | Out (%) | PDF | MultivariateHypergeometricDistribution | Beta | Gamma | DiscretePlot3D | CDF | ExtentSize | Right | PlotLabel | Row | PlotStyle | Directive | Black | HoldForm | Integer | Names | Select | Function (&) | StringLength | ToString | FullForm | Slot (#) | D (∂) | E ( | I ( | Reals | DSolve | Derivative (') | Series | SeriesData | MatrixForm | Det | Apply (@@) | Subscript | ReplaceAll (/.) | Precision | NSolve | WorkingPrecision | TableForm | FullSimplify | FunctionExpand | MeijerG | Small | Clear | Timing | Do | Append | ListPlot | Map (/@) | Range | Zeta | Block | Accumulate | ClearSystemCache | RandomChoice | Factorial (!) | RandomReal | Integrate (∫) | Minimize | AppendTo | Solve | Plot | MaxRecursion | PlotPoints | Cell | Notebook | CellGroupData | BoxData | RowBox | Graphics3DBox | CuboidBox | Open | WindowSize | WindowMargins | Automatic | FrontEndVersion | StyleDefinitions

Многие начинающие пользователи в начале своего знакомства с системой Mathematica и ее языком, который называется языком Wolfram (Wolfram Language), делают обычно ряд весьма распространенных ошибок, рассмотрению которых посвящена эта статья. Язык Wolfram является крайне мощным и красивым языком программирования, но он имеет ряд необычных для других языков особенностей, которые могут вызвать трудности, а также ряд тонкостей, на которые стоит обратить внимание уже с первого знакомства с системой, для того чтобы писать в дальнейшем быстрый и изящный код.

2.1 РАСПРОСТРАНЁННОЕ ЗАБЛУЖДЕНИЕ, ГЛАСЯЩЕЕ: “Mathematica только для математики”

Многие начинающие пользователи Mathematica думают, что эта система служит в основном для чисто математических расчетов. Виной тому служит несколько обстоятельств, во первых само название Mathematica, созвучное русскому слову “Математика”, во вторых то, что на протяжении нескольких первых версий (примерно до 5-й) язык системы Mathematica содержал действительно крайне много функций для символьной математики и приближенных вычислений и гораздо меньше функций из других областей знаний.

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

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




2.2 КАК МОЖНО ЧАЩЕ ИСПОЛЬЗОВАТЬ DOCUMENTATION CENTER

Documentation Center — Центр Документации — языка Wolfram это по истине одно из огромнейших достоинств системы Mathematica. Открыть Documentation Center можно через меню Help -> Documentation Center.


После открытия вы увидите документ, представленный на рис. ниже, в котором структурированы основные разделы справки. Также существует идентичная встроенной, онлайн версия Documentation Center.


Встроенная документации содержит свыше 100000 интересных и красивых примеров кодов на языке Wolfram, её печатная версия заняла бы более 6500 печатных страниц. Все документы полностью интерактивны, что понятно, так как это все те же знакомые документы Mathematica, а это означает, что можно пробовать свои коды и модифицировать готовые примеры непосредственно в справке.

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





2.3 НЕ БОЯТЬСЯ СООБЩЕНИЙ ОБ ОШИБКАХ, тем более, что иногда это просто предупреждения

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

Скажем, в коде ниже система предупреждает нас о том, что было произведено деление на 0:





А здесь о том, что в списке {a,1,1} нет 4-го элемента:





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





Эту проблему можно решить, скажем так:





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

Крайне важно помнить о том, что все встроенные функции ВСЕГДА начинаются с заглавной буквы и всегда называются в соответствии с тем, что они делают.

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

Скажем, ясно что следующий код не вычисляет синус числа 1.32:




Синус 1.32 можно вычислить с помощью функции Sin:




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

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




Или построить дискретную функцию распределения:




2.5 Какие символы нельзя использовать в своих переменных?

Предупреждение относительно наличия пробелов в имени функции

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




Начинать переменную с цифры

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




Заканчивать переменную символом $ и особенно $$

Важно помнить, что Mathematica использует символ $ в конце символа для создания уникальных имен временных переменных:




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







Нижнее подчеркивание _

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







Однобуквенные заглавные буквы английского алфавита

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




Символ D — дифференцирование:




Символ E — число e, N — приближенное вычисление выражения с заданным количеством значащих цифр:




Символ I — мнимая единица:




Символ C — зарезервирован для создания произвольных констант, скажем при решении тригонометрических уравнений:




Символ K — зарезервирован для произвольной переменной интегрирования в решениях, скажем, дифференциальных уравнений:




Символ O — по сути заменяет понятие о-малое, а также может использоваться для компактности вычислений без использования функции Series для разложения в ряд Тейлора.







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

2.6 Использование скобок и комментирование кода

В Mathematica есть четыре типа скобок:

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




Круглые — служат для группировки объектов, выделения логических фрагментов кода.




Фигурные — служат для создания списков объектов, которые могут интерпретироваться как коллекции (множества) объектов, векторы, матрицы, тензоры.




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







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




или же группировать объекты фигурными (квадратными) скобками вместо круглых:




Для того, чтобы оставить комментарий к коду используется специальный синтаксис вида (*комментарий*). Интересной особенностью комментариев в языке Mathematica является то, что он может быть оставлен буквально в любом месте кода и может содержать не только текст, но и графику, картинки, интерактивные объекты:






2.7 Использование форматирующих функций

Одной из распространенных ошибок пользователей является присваивание переменной некоторого “отформатированного” значения с последующей попыткой вычислить нечто от него.

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




Однако, при вычислении определителя от матрицы m получает верное значение — число 0, а во втором случае все остается в еквычисленном виде:




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




Так как на вход функции Det подается не матрица (список списков), а функция MatrixForm от некоторого аргумента, то вычисления не могут быть произведены. Эта ситуация была бы более очевидна, если бы была применена не форматирующая функция MatrixForm, а скажем просто функция F:






Однако, гибкость языка Mathematica позволяет выйти из этой ситуации, скажем с помощью функции Apply (@@), которая работает следующим образом:




Таким образом, решение проблемы имеет вид:




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





2.8 Задание переменных с нижним индексом

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

Предположим, мы задали переменной y с нижним индексом 1 значение равное 4-м:




После этого эту переменную можно использовать в вычислениях:




Однако, если взять список из набора переменных и попробовать, скажем, подставить в этом списке вместо y число 3, то на первый взгляд должен получиться список вида , однако, мы получим список вида:




Это связано с тем, что нижний индекс в Mathematica задаётся с помощью функции Subscript, в чём легко убедиться:




Именно поэтому всюду вместо x мы получаем число 3.

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

В качестве переменной с нижним индексом можно рассматривать объект вида, скажем, y[2]. Ничто не мешает такого рода переменным быть именами функций:




А при необходимости их можно превратить легко в переменные с нижним индексом (скажем для копирования результатов в статью):




Верно и обратное:




2.9 Разница между точными и приближенными числами

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

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




В то время как число будет иметь бесконечную точность:




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

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






Однако, просто изменив форму записи уравнения на тождественную ей аналитическую , поиск корня с этой точностью станет простым делом:





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




Однако, если вам нужно вы можете упрощать те же выражения дальше:




Система также способна работать с любыми специальными функциями:







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







2.10 Использование процедурной парадигмы программирования

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

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




С помощью функциональной, так:







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

2.11 “Изобретение колеса”

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

Скажем, пусть у нас есть список {α, β, γ, δ, ε, ζ, η} и мы хотим получить из него последовательные суммы элементов {α, α + β, α + β + γ, ...}.

Можно создать функцию, которая делал бы это:






Либо же воспользоваться встроенной функцией Accumulate:




При этом важно также то, что созданная функция accumulateMy уступает встроенной функции Accumulate в скорости (как видно в данном случае, более чем в 250 раз):






2.12 Понимание того, что такое ячейка и что такое документ Mathematica

Документ Mathematica состоит из ячеек, которые имеют разные стили и в зависимости от стиля ведут себя совершенно по-разному. Есть ячейки содержащие текст, скажем это ячейки в стиле “Text”, есть вычисляемые ячейки в стиле “Input”, ячейки содержащие результаты вычислений (стиль “Output”) и многие многие другие. Ячейки выделяются квадратной скобкой справа:


Эта скобка может быть, если необходимо, скрыта.

Ячейки могут группироваться вместе, иметь сложную структуру вложенности.

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

Каждой строке соответствует свой Output (результат вычислений), скажем, в ячейке ниже три строки:






При этом можно производить вычисления в строке, но не выводить их результат, для это служит функция CompoundExpression, которая имеет краткую форму “;”:




Безусловно можно держать разные фрагменты кода в разных ячейках, единственное всё же стоит группировать ячейки в одну, если это возможно, скажем вместо ячейки приведенной выше не стоит писать три:








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

Что касается самого документа Mathematica то о нём стоит помнить несколько вещей:

на самом деле это текстовый документ, не важно есть в нём какая-либо графика, динамическое содержимое и пр. или нет;

всё что вставляется в документ Mathematica автоматически преобразуется к представлению на языке Mathematica;

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

документ является функцией Notebook, а ячейки Cell являются его аргументами (или их группы), его настройки — его опциями (подробнее см. п. 2.16);

всё в документе хранится в так называемом формате боксов.

2.13 Четкое понимание того, что такое = и :=

В Mathematica есть два основных типа присваивания:

абсолютное, с помощью функции Set (=);

отсроченное, с помощью функции SetDelayed (:=).

Важно понимать какой из типов присваивания стоит использовать и в какой момент:

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

абсолютное присваивание (=) — универсально; будет работать не верно, если результат вычисления правой части напрямую завит от аргумента, к которому применяется функция; однако, в некоторых случаях способно заметно ускорить работу кода

Скажем, задав переменные a и b мы можем вычислить значения их квадратов и всё будет работать корректно:





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







При работе с функциями также важно использовать разные типы присваиваний.

Скажем, если правая часть выражения зависит от аргумента функции очень сильно, то нужно использовать отсроченное присваивание (здесь вычисляется длина списка, который подаётся на вход функций f1 и f2):







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







2.14 Знание трёх важных идей Mathematica относительно результатов вычислений

Если Mathematica не может вычислить результат,
она выдаст исходное выражение в качестве ответа

Mathematica не выдает результат, в котором не уверена. Это означает, что если выражение нельзя упростить или получить аналитическое (приближенное) решение, то на выходе вы увидите тот-же результат, что подавался на входе.

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




Однако, “упростить” его всё же можно:




Еще один пример — поиск глобального минимума функции, который нельзя найти аналитически:




Однако на заданном отрезке это вполне возможно:




По умолчанию, Mathematica НЕ МЕНЯЕТ исходные выражения

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

Скажем, можно переменной list присвоить значение — список {1,2,3,4,5}, после чего добавить в его конец элемент 6, и, как легко заметить, выдается результат добавления — новый список, но при этом оригинальный список list не изменяется:






Чтобы после добавления к списку list он изменился, это нужно указать явно:






Или же использовать специальную функцию:






Документы, созданные в предыдущих версиях Mathematica, работают корректно в новых

Язык системы Mathematica строится так, что “старые” функции работают в новых версиях системы, поэтому документы старых версий системы, за редким исключением, вычисляются в новых версиях достаточно легко. На самом деле верно и обратное: документы, созданные в новых версиях системы можно открывать в более старых. Это достигается за счет стройности языка и четкого следования идеям и парадигмам, разработанным основателем языка Mathematica — Стивеном Вольфрамом.

2.15 Нужно вовремя очищать переменные

Очень важно вовремя очищать переменные, так как “лишние” определения могут сыграть с вами злую шутку.

Скажем, присвоим переменной x значение 2:



Теперь можно вычислить, например её квадрат:




Позже, спустя много времени, вам может понадобиться решить уравнение с переменной x и тут вас может ожидать необычный результат:





Результат связан с тем, что вместо x всюду была подставлена двойка, что привело к ошибке. Избавиться от проблемы можно просто вовремя очистив переменную x, скажем:





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



2.16 Осознание того, что все что есть в системе является функцией или их композицией

Одна из фундаментальных особенностей системы Mathematica заключается в том, что абсолютно все что в ней есть, является некоторой функцией или их композицией. Совершенно не важно с чем вы работаете: с каким-то выражением вроде a+b, с ячейкой или целым документом — все это функции. Посмотреть на полную форму любого выражения можно с помощью функции FullForm:

Любое выражение является функцией:








Любая ячейка документа является функцией, скажем этой ячейке соответствует код:



А документу, изображенному на рисунке:


соответствует код: