Maxima
Maxima — система компьютерной алгебры, реализованная на языке Lisp.
Maxima имеет широчайший набор средств для проведения аналитических вычислений, численных вычислений и построения графиков. По набору возможностей система близка к таким коммерческим системам как Maple и Mathematica. В то же время она обладает высочайшей степенью переносимости. Это единственная из существующих систем аналитических вычислений, которая может работать на всех современных операционных системах, на компьютерах, начиная от самых мощных, заканчивая наладонниками.
Содержание
[убрать]История
Maxima произошла от системы «Macsyma», разрабатывавшейся в MIT (Massachusetts Institute of Technology) с 1968 по 1982.
Вариант продукта (известный как DOE Macsyma) сопровождался профессором Уильямом Шелтером в Техасском Университете с 1982 до своей смерти в 2001.
В 1998, Шелтер получил от Департамента энергии разрешение опубликовать исходный код DOE Macsyma под лицензией GPL, и в 2000 он создал проект «Maxima» на SourceForge для поддержания и развития «DOE Macsyma», переименованного в Maxima.
Введение
Обзор
Maxima может использоваться как мощный калькулятор:
(%i13) 144*17 - 9; (%o13) 2439
Maxima поддерживает точные вычисления с большими числами,
размер которых ограничен только ресурсами вашего компьютера.
Например, вычислим , а затем возьмем корень 25-степени из результата:
(%i14) 144^25; (%o14) 910043815000214977332758527534256632492715260325658624 (%i15) %^(1/25); (%o15) 144
Знак «%» ссылается на специльную переменную, хранящую результат последней операции. Знак «^» — оператор возведения в степень.
Однако основное назначение компьютерной алгебры — не численные вычисления, а скорее, символьные операции. Поиграем с полиномом :
expand((x + 2*y)^4); → factor(%); →
Вычисление производных:
diff(sin(x)*cos(x), x); → trigsimp(%); → diff(%, x); → diff( sin(x)*cos(x), x, 2); →
и первообразных (неопределенных интегралов):
integrate((x + 1)/(x^3 - 8), x); →
Maxima может преобразовывать тригонометрические выражения в канонические конечные тригонометрические ряды (Fourier sums):
trigreduce (sin(x)^5); →
Первые шаги
Maxima ориентирована на минималистический интерфейс командной строки — т. е. сеанс работы состоит из последовательных команд пользователя и полученных на них ответов.
Команда — это некое выражение, возможно многострочное, оканчивающееся точкой с запятой «;». Например на команду:
(%i1) 14*(7 + 3);
будет получен ответ:
(%o1) 140
Если вы забудете ввести «;» — Maxima будет терпеливо (т. е. без каких-либо сообщений об ошибках) продолжать ввод ввод, пока вы ее не введете «;».
Можно вместо точки с запятой завершить команду знаком доллара «$», тогда вывод этой команды будет заглушён, то есть, команда будет обработана и результат будет вычислен, но не выведен на экран.
Введем какое-нибудь выражение с переменной:
(%i2) (x + 2)*(x - 3);
Ответ Maxima содержит то же выражение, в неупрощенной форме:
(%o2) (x - 3) (x + 2)
Maxima выдает выражение-результаты, используя минималистические средства — текстовую отрисовку формул. Так в ответе «(%o2)» мы видим,
что за счет исключения «*» из ответа, выражение выглядит «математическим», а не программистким.
Теперь раскроем скобки:
(%i3) expand(%); 2 (%o3) x - x - 6
Т.е. человек вполне способен прочесть эту ASCII-формулу, однако, есть возможность получить эту формулу (c помощью функции «tex») в формате TeX:
(%i38) tex( expand( (x + 2)*(x - 3) ) ); $x^2-x-6$ (%o38) false
Что, если отрисовать через TeX будет выглядеть так: .
Пользуясь этой возможностью, далее в этом введении, все математические формулы, получаемые от Maxima мы будем отрисовывать через TeX, что будет гораздо удобней для чтения, чем ASCII-графика, особенно в случае «многоэтажных» формул.
Итак, возведение в степень:
x^3^4; →
Обратите внимание на приоритет операций: x^3^4 есть
Дифференцирование и интегрирование
Возьмем неопределенный интеграл для :
integrate(x/(x^3 + 1), x); →
Продифференцируем результат для проверки:
diff(%, x); →
И чтобы, не пугаться, упростим сумму рациональных выражений:
ratsimp(%); →
Повторим тоже самое для :
integrate(exp(a*x)*sin(x)*cos(x), x); → diff(%, x); → ratsimp(%); → trigexpand(%); →
Если Maxima не смогла взять интеграл — она возвращает интеграл в «исходной форме»:
(%i4) integrate(1/((x-3)^4+1/2), x); / [ 1 (%o4) I ------------ dx ] 4 1 / (x — 3) + - 2
Разумеется, в TeX-форматировании интеграл будет выглядеть красивее:
В таком случае, можно помочь системе, выполнив замену переменных:
changevar (%, x - 3 - y ,y ,x); →
а затем проинтегрировав:
ev (%, integrate)
выполним обратную подстановку
sfx: %, y=x-3;
Т.к. подынтегральное выражение — всюду определенная положительная функция, мы можем вычислить определенный интеграл , используя вычисленную первообразную «sfx»:
ratsimp(subst (1, x, sfx) - subst(0, x, sfx));
или переходя к значениям в плавающей арифметике:
float(ratsimp(subst (1, x, sfx) - subst(0, x, sfx))); → 0.028806333852738
Для проверки выполним численное интегрирование методом Ромберга:
romberg(1/((x-3)^4+1/2), x,0, 1); → 0.028806333924554
Результаты аналитического и численного интегрирования совпадают с точностью 1e-10.
Проинтегрируем .
integrate(((6*x^5 + 7*x^4 - 36*x^3 + 18*x - 21)*(x^4 + 1)^(2/3) + (2*x^6 - 20*x^4 - 40*x^3 + 18*x^2 + 12)*(x^4 + 1)^(1/3)) /(3*x^8 +6*x^4 + 3), x);
Осталось «сократить» экспоненты с логарифмами, перейдя к каноническому радикалу:
radcan(%);
Решение полиномов
Нахождение нулей у полиномов от одной переменной — задача известная со школы. Поиграем с ней для демонстрации некоторых возможностей Maxima. Определим переменную poly:
poly: x^2 - x - 12; →
Вычислим нули, используя функцию «solve»:
solutions: solve (poly=0, x); → [ x=-3, x=4 ]
Мы получили ответ в виде двух равенств (с левыми и правыми частями) — если их преобразовать в множители, то мы должны получить исходный полином, в виде их произведения.
Воспользуемся механизмом лямбда-функций (по сути, безымянных функций). Лямбда функция
lambda ([eq], lhs(eq) - rhs(eq))
очевидным образом преобразует выражение-равенство, в множитель, равный нулю в точке равенства. Итак, применим функцию «map», применяющую нашу лямбда-функцию для всех элементов нашего списка уравнений:
map( lambda( [eq], lhs(eq) - rhs(eq)), solutions); → [x+3,x-4]
Перемножим этот список:
apply("*", %); → (x-4)(x+3)
И, раскрыв скобки, получаем исходный полином:
expand(%); →
Тригонометрические преобразования
Чтобы преобразовать произведения синусов-косинусов, в триногометрический ряд Фурье, используется функция «trigreduce»:
trigreduce(sin(x)^3*cos(x)); →
Теперь избавимся от произведений в аргументах тригонометрических функций:
trigexpand(%); →
И наконец, упрощаем выражение, используя функцию «trigsimp», знающую тождество :
trigsimp(%); →
Упрощение тригонометрических выражений не всегда получается просто и быстро, как в приведенном примере, и в почтовых рассылках часто раздаются вопросы, «как мне упростить XXX?» или «почему Maxima не упрощает YYY?».
Рассмотрим пример:
result:integrate(9/cos(7*x)^2, x); →
А пользуясь любым матсправочником с таблицей основных первообразных (например, справочником Бронштейна-Семендяева), легко получить более красивый результат: .
Попробуем упростить «влоб»:
simp1: trigsimp(result); →
Но применять дальше «trigexpand», для раскрытия sin(14*x) и cos(14*x) через sin(x) и cos(x) бесполезно — выражение сильно усложнится. Надо бы выразить sin(14*x) и cos(14*x) через sin(7*x) и cos(7*x), а для этого надо сделать подстановку, заменив 14*x на 2*y.
simp2: simp1, 14*x=2*y; →
И далее:
trigexpand(simp2); → trigsimp(%); →
и наконец:
trigreduce(%); →
возвращаемся к исходным переменным:
%, y = 7*x; →
Итак, мы показали на примере этой задачки, как важно использовать подстановки переменных при упрощении через «trigexpand». А вообще, это выражение можно было упростить одним действием:
trigrat(result); → trigreduce(%); →
Проверим результат интегрирования:
deriv: diff(result, x); trigrat(deriv); →
Выглядит просто, но чтобы сравнить с исходным выражением, надо выразить всю «тригонометрию» через 7x.
%, 14*x = 2*y; → trigexpand(%); → trigsimp(%); → %, y = 7*x; →
Итак, напомним еще раз назначение рассмотренных функций:
- trigreduce
- преобразует тригонометрическое выражение как сумма слагаемых, каждое из которых содержит один синус или косинус.
- trigexpand
- «раскрывает» аргументы тригонометрических функций, согласно правилам тригонометрических функций от суммы углов.
- trigsimp
- упрощает тригонометрическое выражение, используя тождество .
- trigrat
- мощная функция — упрощение рационального тригонометрического выражения.
Разложение на простые дроби: шаг за шагом
Ответы Maxima всегда показывают готовый результат (если, конечно, системе удалось его получить), но не путь его вычисления.
Например, разложение на простые дроби выполняется функцией «partfrac»:
partfrac ( 1/(x^2*(x^2 + 1)), x); →
Обычно этого достаточно, ибо полученный результат вполне можно проверить. Однако, иногда требуется получить последовательность вычислений (например, если это часть домашней работы, и проверяющему недостаточно предьявить ответ).
Итак, попробуем вычислить разложение в «полуавтоматическом» (или «полуручном») режиме.
В данном случае, разложение на простые дроби — это сумма следующих элементарных дробей:
p1: a/x; → p2: b/x^2; → p3: (c*x + d)/(x^2 + 1); →
т. е.
p1 + p2 + p3; →
Приводим к общему знаменателю, и поименуем числитель этой дроби, как «n»:
ratsimp(p1 + p2 + p3); → n: num(%); →
Теперь осталось решить уравнение, «приравняв» числитель исходной дроби и числитель «n»:
solve ([coeff (n, x, 3) = 0, coeff (n, x, 2) = 0, coeff (n, x, 1) = 0, → [[a=0,b=1,c=0,d=-1]] coeff (n, x, 0) = 1], [a, b, c, d]);
Наконец, подставляем полученные коэффициенты:
at(p1 + p2 + p3, first(%)); →
Напомним, мы использовали следующие функции:
- num
- возвращает числитель дроби.
- coeff
- возвращает коэффициент при переменной в заданной степени.
- solve
- решает систему линейных уравнений.
Вычисление пределов
Maxima может вычислять пределы для широкого спектра как рациональных, так и трансцедентных функций.
Для рациональных функций, часто интересно посмотреть поведение функции на бесконечности:
limit ((x^2 - 1)/(x^2 + 1), x, inf); →
Можно раскрыть и предел типа «0/0»:
limit ((x^2 + x - 6)/(x^4 + x^3 - 19*x^2 + 11*x + 30), x, 2); →
Maxima умеет вычислять пределы «справа» и «слева», и честно сообщает, когда предел в заданной точке не определен:
limit (tan(x), x, %pi/2, plus); → minf limit (tan(x), x, %pi/2, minus); → inf limit (tan(x), x, %pi/2); → und
Вычисление рядов — конечных и бесконечных
Конечные суммы считаются сразу:
sum(i, i, 1, 100); → 5050
Но бесконечные ряды, по умолчанию не суммируются, выражение остается в исходном символьном виде:
sum1:sum(1/x^2, x, 1, inf); → sum2:sum(1/x^2, x, 1, inf); →
Чтобы выполнить суммирование, нужно указать опцию «simpsum=true»:
sum(1/x^2, x, 1, inf), simpsum=true; →
Впрочем, над «непросуммированными суммами» можно выполнять операции, только операторы суммирования не будут сокращаться:
sum1+sum2; →
Для сокращения сумм, нужно использовать функцию «sumcontract»:
sc:sumcontract(sum1+sum2); →
Версия 5.9.3. содержит баг 1517061
Далее, можно просуммировать, как мы уже делали выше:
ev (sc, simpsum=true); →
Внешние ссылки
- Домашняя страница Maxima
- Maxima в Википедии.
- Вадим Житников-Компьютеры, математика и свобода
- Maxima – максимум свободы символьных вычислений
- Maxima: максимум удобства и функциональности
- WxMaxima — оконный интерфейс к Maxima.
- GNU TeXmacs - набор маттекстов в TeX, с плагинами доступа к различным CAS-системам, типа Axiom, Reduce, и в частности Maxima.
Любые правки этой статьи будут перезаписаны при следующем сеансе репликации. Если у вас есть серьезное замечание по тексту статьи, запишите его в раздел «discussion».
Репликация: База Знаний «Заказных Информ Систем» → «Maxima»