|
Персональные инструменты |
|||
|
Maxima — различия между версиямиМатериал из CustisWiki
Версия 19:47, 23 октября 2008Maxima — система компьютерной алгебры, реализованная на языке 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
Например, вычислим , а затем возьмем корень 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; →
Разложение на простые дроби: шаг за шагомОтветы 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(%)); → Напомним, мы использовали следующие функции:
Вычисление пределов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); → Внешние ссылки
Любые правки этой статьи будут перезаписаны при следующем сеансе репликации. Если у вас есть серьезное замечание по тексту статьи, запишите его в раздел «discussion». Репликация: База Знаний «Заказных Информ Систем» → «Maxima» |
||||||