четверг, 18 мая 2023 г.

Maxima — Tips&Tricks, или собираем по крохам инфо, как на ней работать

 

Резервная копия. Изначально опубликовано 26 сентября 2014 г. https://habr.com/ru/articles/238347/

 

Человеческая память для меня загадка. Являясь обладателем слабой памяти с детства, вечно забываю о некоторых нюансах окружающего меня мира. Тем не менее, эти данные должны быть под рукой. И когда не хватает блокнота, на помощь приходят текстовые файлы. Один из таких файлов содержит небольшую сборку повседневных и обыденных команд <i>Maximа</i>.

Я думаю, всем из нас известна данная система компьютерной алгебры. Она не является конкурентом <i>Wolfram Mathematica</i>, но она обладает именно тем функционалом, который я требую от математического софта. Если говорить проще и доступнее - считать можно на всём, от палочек до суперкомпьютеров, и далеко не всегда задачи инженерной практики целиком переносятся с бумаги в программный код. Одним из примеров, который я честно говоря, еле-еле застал, является сегодня забытая поделка нашего конверсионного производства - цельнометаллический бытовой вакуумный гражданский термос, который выпускался ранее ещё в СССР на Урале. Чтобы наладить его производство институт, в котором я учусь, де-факто вручную на счётных машинках высчитал все необходимые параметры рабочего оборудования. Поэтому лицензия на Mathematica - не показатель и не ценз пригодности к практике. Считать, повторюсь, можно на всём.

От слов к делу. Ниже разбиты на категории те моменты в документации <i>Maxima</i>, которые желательно знать  для начинающего пользователя данной СКА.
<habracut>

<h4>Общий функционал</h4>
** или ^ - возведение в степень;
% - последняя ячейка вывода;
_ - последняя ячейка ввода;
%th(n) - возвращает n-ю с конца ячейку вывода;
$ - глушение вывода результата;
kill(all) - очистить сеанс;
describe(name) или ? name - помощь по конкретным словам;
example(name) - пример использования;
demo() - выполняет программы из демонстрационных файлов, поставляемых с системой;
'выражение - предотвращает вычисление выражения;
''выражение - аналог ev (принудительное вычисление выражения);
num(%) - числитель дроби;
denom(%) - знаменатель дроби;
coeff(n,x,3) - возвращает коэффициент при переменной в заданной степени;
depends([m,y],[x,z]) - устанавливает зависимость m(x,z) и y(x,z);
second(y = 14) - извлечёт 14;
subst - подстановка одного выражения в другое;
changevar (%, x - 3 - y ,y ,x); - замена переменных в выражении;
%, y=x-3 - обратная подстановка;
float(%) - преобразовать к вещественной форме;
nouns(%) - раскрывает вообще все несовершённые формы – и производные в том числе;
eval – напротив, проводит дополнительно ещё один процесс вычисления. в выражения тоже могут входить некоторые символы, которые тоже могут иметь свои значения; и такая цепочка  «вложенных значений» может продолжаться сколь угодно глубоко. Один вызов функции ev (без опции eval) опускается по этой цепочке в глубину на один уровень: noeval блокирует сам этап вычисления как таковой; т.е. её можно использовать для того, чтобы применить к выражению другие опции функции ev, не перевычисляя его;
lhs(eq) - rhs(eq) - левая и правая части некоторого выражения;
eliminate([x+y+z=1,x+y=2,x+z=3],[z]) - исключить из системы уравнений переменную или несколько переменных, то есть уменьшить размерность системы;
gcd(420,1176) - НОД;
mod(x,y) - остаток от деления x на y со знаком x;
signum(x) - вернёт +1 если x >0, -1 если x <0;
max/min;
log(x) - НАТУРАЛЬНЫЙ логарифм ("ln(x)");
floor(4.445) - округление вниз;
ceiling(4.445) - округление вверх;
listofvars(%) превращает исходное выражение в список содержащихся в нем переменных;
numer:true (или numeric:true) - проведение расчётов только с плавающей точкой, а не с рациональными числами;
bindtest - запрещает использовать символ в выражениях до присвоения ему значения;
batch() загружает Maxima-файл с расширением  .mac или .mc (от первоначального названия программы – Macsyma) и выполняет содержащиеся в нем выражения.
batchload(), подгружает пакетный файл «молча»: все назначенные в нем функции и переменные становятся доступны, но результаты не видны, и весь хранимый ввод-вывод, включая значения символов % и _ и результаты, возвращаемые функцией %th(), остается тем же, что и до вызова.
file_search_maxima - переменная, содержащая каталоги пользовательских файлов и файлов самой СКА;
~/.maxima - стандартный каталог системы;
file_search_lisp и file_search_demo - функции для поиска соответствующих файлов;
load() - обертка над двумя функциями загрузки файлов, просто короче;
loadfile() -загружает файл с исходным кодом Lisp (парна к save());
stringout()-  выгружает в файл любые выражения и функции Maxima;
declare() - внести факт в базу фактов;
facts(name) или facts() - узнать текущее состояние базы;
remove() - удалить свойства из базы;
assume() - в качестве аргументов принимает в любом количестве самые обыкновенные равенства и неравенства в логической форме, то есть не  «a=b»,  «a#b», а  «equal(a,b)»,  «not equal (a,b)». Из логических операторов допускается также использование and (по сути assume(x>0 and x<1) это то же самое, что и assume(x>0, x<1)), но не or – база фактов не поддерживает информацию вида «или»; и речь не о синтаксисе, а именно о конструкциях, то есть выражения типа not(a>b and a<c) тоже недопустимы. Факты, добавленные assume(), также видны функции facts():

<h4>Производные, пределы, ряды...</h4>
diff(выражение) — находит полный дифференциал выражения, который является суммой всех частныхпроизводных по переменным выражения;
diff(выражение, переменная) — находит частную производную первого порядка;
diff(выражение, переменная, N) — находит частную производную N-го порядка;
diff(выражение, х_1, N_1, х_2, N_2, …) —находит сумму частных производных;
derivlist(x, y, ..., v) – производные относительно переменных, заданных в качестве аргументов, а также полные дифференциалы (так как они не зависят ни от каких переменных);
integrate(%,x) - интегрирование;
romberg(cos(sin(x+1)), x, 0, 1) - численное интегрирование методом Ромберга;
limit ((x^2 - 1)/(x^2 + 1), x, inf) - вычисление пределов;
limit ((x^2 - 1)/(x^2 + 1), x, minf);
limit (tan(x), x, %pi/2, plus) - предел справа;
limit (tan(x), x, %pi/2, minus) - слева;
tlimit(...) - попытка найти предел с поднятым флагом tlimswitch (см. ниже);
sum(i, i, 1, 100) - сумма ряда;
product - произведение ряда (синтаксис аналогично sum);
sum(1/x^2, x, 1, inf), simpsum=true; - чтобы выполнить суммирование, нужно указать опцию «simpsum=true»;
sumcontract(sum1+sum2) - сокращение сум;
taylor(sin(x), x, 0, 8) - ряды;
niceindices(powerseries(sin(x), x, 0)) - ряды с упрощением;

<h4>Упрощения</h4>
simp: false - отключить принудительное упрощение "на лету";
ratdenomdivide - по умолчанию системная переменная имеет значение "true". В этом случае каждая дробь, в которой числитель является суммой, раскладывается на сумму дробей с одинаковым знаменателем. Если же присвоить этой опции значения "false", то тогда все дроби с одинаковым знаменателем будут объединены в одну дробь с числителем в виде суммы числителей начальных дробей;
expand() - раскрыть скобки, упростить;
distrib() – expand(), но только на один уровень в глубину;
combine() - функция, собирающая воедино дроби с одинаковыми знаменателями;
trigsimp(%) - тригонометрические упрощения через основное тригонометрическое тождество;
trigrat(%) - аналогично, посильнее;
trigreduсe(%) - преобразовать тригонометрические выражения в канонические конечные тригонометрические ряды (Fourier sums) [преобразует тригонометрическое выражение как сумма слагаемых, каждое из которых содержит один синус или косинус];
trigexpand(%) - «раскрывает» аргументы тригонометрических функций, согласно правилам тригонометрических функций от суммы углов;
partfrac(%) - разложение на простые дроби;
ratsimp(%) - быстро упростить сумму рациональных выражений;
fullratsimp(выражение) - последовательно применяет к выражению функцию ratsimp, а также некоторые нерациональные преобразования и повторяет эти действия в цикле до тех пор, пока выражение не перестанет в процессе преобразования изменяться (медленнее, зато дает более надежный результат);
ratexpand(%) - приводит дроби к общему знаменателю;
radcan(%) - «сократить» экспоненты с логарифмами, перейдя к каноническому радикалу [упрощение показательных, логарифмических и степенных (с рациональными степенями) функций];
factor - максимально сворачивает выражение в скобки;
factorsum() - если многочлен не может быть представлен в виде произведения нескольких сомножителей, его можно попытаться преобразовать в сумму таких произведений;
0. Также имеются такие функции как: atensimp, foursimp, fullratsimp, logarc, rootscontract, scsimp, simplify_sum, vectorsimp.
1. После ratexpand() и в числителе, и в знаменателе дроби все скобки будут раскрыты, в случае же rat() слагаемые, где имеются, например, две переменные, будут сгруппированы, и одна из них будет вынесена за скобки.
2. expand раскрывает скобки на всех уровнях вложенности, а ratexpand раскрывает рациональное выражение только первого уровня, при этом подвыражения, которые не являются рациональными, не обрабатываются;
3. ratexpand приводит дроби-слагаемые к общему знаменателю, а expand этого не делает;
4. На expand не влияет системная опция ratdenomdivide;
5. expand не преобразует в рациональные числа конечную десятичную запись независимо от значения системной опции keepfloat.
6. maxposex и maxnegex - переменные, управляющие раскрытием возведения в целую степень - максимальные положительный и отрицательный показатель степени, которые будут раскрываться этой функцией expand ( По умолчанию 1000), переназначить можно прямо в функции expand();
7. expop и expon - переменные, задают максимальные положительную и отрицательную степени, которые будут раскрываться автоматически, без вызова функций группы  expand (по умолчанию 0, то есть автоматически степени не раскрываются вообще);
8. Флаг – halfangles – управляет раскрытием формул половинных углов;
Два флага –  trigexpandplus и  trigexpandtimes – отвечают соответственно за применение формул сумм углов и кратных углов (по умолчанию установлены);
9. Флаги  trigsign и  triginverses - первый принимает традиционные два значения (по умолчанию – true) и регулирует вынос знака за пределы тригонометрической функции. Флаг  triginverses – трехзначный, и умолчательное его значение равно  all. Он отвечает за обработку сочетаний вида  sin(asin(x)) или atan(tan(x)). Значение all позволяет раскрывать эти сочетания в обоих направлениях (напомню, что при этом часть корней будет теряться); значение true оставляет разрешенным раскрытие только вида sin(asin(x)), то есть блокирует вариант с потерями периодических значений; а случай false запрещает оба направления преобразований;
10. Флаг  tlimswitch. По умолчанию он тоже выключен, а если его включить, функция  limit будет, при невозможности найти предел другими способами, пытаться его найти путем разложения подпредельной функции в ряд Тейлора в окрестности заданной точки;
11. Единственный флаг, имеющий прямое отношение к самой функции diff  – это флаг derivabbrev, который влияет на отображение производных в ячейках вывода Maxima. По умолчанию он равен  false, и производные обозначаются в виде дробей с буквой d; если же его выставить в true, производные будут отображаться в сокращенном виде, с переменными дифференцирования записанными в виде индексов.
12. solveradcan - флаг, по умолчание false, а выставив этот флаг в  true, мы заставим solve применять  radcan, что в некоторых случаях может помочь разрешить проблемы, которые без этого ключа приведут к невозможности найти точное решение.

<h4>Матрицы</h4>
A: matrix([1,2],[3,4]);
Определитель матрицы. Функция determinant(matrix).
Транспонирование матрицы. Функция transpose(matrix).
Вычисление обратной матрицы. Функция invert(matrix).
Построение характеристического многочлена матрицы. Функция charpoly(matrix, var).
Сложение матриц (знак «+»). Почленно складывает все элементы двух матриц.
Вычитание (знак «-»). Совершенно аналогичен сложению, но элементы матриц вычитаются.
Деление матриц (знак «/»). Деление слабо отличается от сложения, каждый элемент одной матрицы делится на соответствующий элемент другой матрицы.
Перемножение матриц почленно (знак «*»). Этот оператор работает также как и сложение: элементы первой матрицы умножаются на соответствующие элементы второй матрицы. Это не то умножениематриц, которое обычно подразумевается в курсе линейной алгебры!
Умножение матриц (знак «.», точка).
addcol(V1,[9,10]) - добавление столбца к матрице;
addrow(V1,[9,10]) - добавление строки к матрице;
V1: submatrix(V1, 6,7) - удалить из матрицы V1 6-й и 7-й столбец;
submatrix(начальный номер удаляемой строки, конечный номер удаляемой строки; Имя
матрицы;) - уменьшение количества строк;
M[j, i] - обращения к конкретному элементу массива М;
zeromatrix(m, n) - создание нулевой матрицы размерностью m*n;
ident(n) - создание единичной квадратной матрицы;
diagmatrix(n, x) - создание диагональной квадратной матрицы размерностью n*n;
transpose(M)  - транспонирование матрицы M;
matrix_size(M) - определение количества столбцов и строк матрицы;
rank(M) - определение ранга матрицы;
mattrace(M) - определение следа (суммы диагональных элементов) квадратной матрицы (* приложению предшествует загрузка пакета для работы с матрицами: load ("nchrpl"));
determinant(М) - вычисление определителя (детерминанта) квадратной матрицы;
invert(M) -вычисление матрицы, обратной к М.

<h4>Обыкновенные дифференциальные уравнения</h4>
1)
ode2(уравнение, функция, переменная). Функцией обычно является у, а переменной — х;
Помимо решения дифференциального уравнения в общем виде, можно решать уравнения с начальными условиями (краевая задача). Для этого необходимо решить уравнение в общем виде при помощи функцииode2, а затем воспользоваться одной из функций поиска начальных условий:
ic1(решение, точка х, значение у в точке х) —для решения дифференциальных уравнений 1-го порядка с начальным условием;
ic2(решение, точка х, значение у в точке х, значение y' в точке х) — для решения дифференциальных уравнений 2-го порядка с начальным условием;
bc2(решение, точка х1, значение у в точке х1, точка х2, значение у в точке х2) — для решения дифференциальных уравнений 2-го порядка с начальными условиями в виде двух точек;
2)
desolve(дифференциальное уравнение, переменная);
Если осуществляется решение системы дифференциальных уравнений или есть несколько переменных, то уравнение и/или переменные подаются в виде списка:
desolve([список уравнений], [переменная1, переменная2,...]);
Так же как и для предыдущего варианта, для обозначения производных в дифференциальных уравнениях используется функция diff, которая имеет вид 'diff(f(x), x);
atvalue(функция, переменная = точка, значение в точке) - начальные значения.

<h4>Графики</h4>
plot2d(sin(x), [x,0,6]);
plot2d(sin(x), [x,0,1], [y,0,1]);
plot2d([parametric, realpart(W(%i*t)), imagpart(W(%i*t))], [t,0,100], [nticks,1000])$
Параметрические графики строятся так:
[parametric, x(t), y(t)]. Поэтому из приведенной формулы были подставлены параметрические функции. Далее, [t,0,100] - это диапазон точек, в котором рисовать годограф. Тут у каждого получается по-разному, ясно, что кривая уходит либо в 0, либо в бесконечность, тут главное не переборщить. Рекомендуется поиграться с диапазоном значений t, чтобы определить откуда и куда движется кривая. Данный пример берёт начало в точке [-1, 0] и стремится к [0, 0]. [nticks,1000] - этот параметр задает число точек для интерполяции графика. Чем их больше - тем более гладким будет выглядеть график и больше времени потребуется на его построение.
Графики в полярных координатах - применяется функция draw2d со следующими аргументами:
user_preamble = "set grid polar", // построение в полярных координатах;
nticks = n, // n - число точек;
xrange = [dx1, dx2], // диапазон изменения x;
yrange = [dy1, dy2], // диапазон изменения y;
color = red, // цвет;
line_width = k, // ширина линии, которой строится график;
title = "общее название графика",
polar(функция, переменная, нижняя_граница _переменной, верхняя_граница_переменной) // функция построения графика;
Обязательными являются первый и последний аргументы функции. Первый инициирует построение графика в полярных координатах, последний (polar) - это функция, по которой строится график.
plot3d(((x - 10)/5)*((y - 10)/5),[x, 0,20],[y, 0,20]) - трехмерная (3D) графика;
Редактирование трехмерного графика осуществляется так же, как и двумерного.
Трехмерная поверхность может быть заменена градиентным переходом цветов. Для этого следует применить опцию "set view map".

<h4>Программирование (подробнее в документации)</h4>
for, while, until и т.д.
Примеры:
for i in s do
for k:1 thru b:3 do
for переменная:начало step шаг thru конец do выражение
for переменная:начало step шаг while условие do выражение
for переменная:начало step шаг unless условие do выражение
Задание функции:
f1(x,y):=x+y;



_-=============================-_
##########   ДРУГОЕ   #############
.================================.

Русское обозначение - в Maxima:
arccos - acos
arcsin - asin
arctg - atan
ch - cosh
sh - sinh
ctg - cot
ln - log
tg - tan

Символы греческого алфавита:
Gamma; Theta; Psi и т.д.

Обработка данных:
1)
 load (descriptive)$  /*загрузить расширение*/
 a:[1,2,3,4];
 mean(a);             /*=5/2 среднее*/
 var(a);              /*=5/4 дисперсия*/
 std(a);              /*=?5/2 среднеквадратичное отклонение*/
mean (средняя арифметическая);
median (медиана);
variance (дисперсия);
deviation (среднее квадратичное отклонение);
2)
a:[1.0,2.0,3.0,4.0];
for i in a do ldisp( sin(i)/i );

Вычисление производных по всем переменным, входящим в выражение:
eq: x*l/k; /*исходное выражение*/
res: 0$ for i in listofvars(eq) do res: res + (diff(eq,i) * concat("d",(i)))^2$

Для большей точности существует специальная функция bfloat() (big float, большой float), а также переменная ffprec — за число знаков после запятой. То есть для повышения/понижения точности нужно присвоить переменной fpprec другое числовое значение и воспользоваться функцией bfloat() вместо float(). Нужно, чтобы переменная numer равнялась false.

По умолчанию Maxima работает в системе МКС: метр-килограмм-секунда:
2*m;
2*cm;
setunits([centigram,inch,minute]) - аргументами которой являются три базовых единицы измерения: веса, длины и времени;
setunits([kg, m, s]);
convert(inch,[sm]); - перевод единиц измерения;

stringout("/Users/myusername/file1maxima.mc",INPUT);
To save all your work as a "tape" that can be replayed later, all your input can be saved to a file.    

batch("/Users/myusername/file1maxima.mc");   
Loading the saved file: the saved file can also be loaded directly, although the exact numbering of lines will change from the original calculation.

SIMPSUM:TRUE;
sum(k, k, 1, n), simpsum;
=> \displaystyle {{n^2+n}\over{2}}
product(1/(n^2),n,1,10); Products work in much the same way.

niceindices(powerseries(%e^x, x, 0));
=> \displaystyle \sum_{i=0}^{\infty }{{{x^{i}}\over{i!}}}

taylor(%e^x, x, 0, 5);
=> \displaystyle 1+x+{{x^2}\over{2}}+{{x^3}\over{6}}+{{x^4}\over{24}}+{{x^5}\over{120 }}+\cdots
trunc(%); Since the output of taylor has special properties, we need to convert it into a polynomial.

load("newton");
=>/sw/share/maxima/5.9.0rc3/share/numeric/newton.mac
newton(x^7-5*x^6+4*x^4-5*x^2+x+2,1);
=>8.194213634964119B-1

tex(%)- преобразовать выражение к виду TeX;
$$\left(x+1\right)^2$$

Преобразовать TeX в PDF:
1. Paste the following five lines verbatim into the text editor:
\documentclass{article}
\pagestyle{empty}
\begin{document}
\huge
\end{document}
2. Copy the tex() output line, and paste it between the \huge and \end{document} lines.
3. Save the result in text format as: myoutput.txt
4. In the terminal window, navigate to the directory where you saved myoutput.txt
5. type:
pdflatex myoutput.txt
6. Hit return - a PDF file called myoutput.pdf containing your typeset equation will now be created in this directory.

load(to_poly_solve); - дополнительные процедуры для решения систем алгебраических уравнений;
to_poly_solve([3*z1+z2+2=0,sqrt(z1)=z2],[z1,z2]);

sol:rk([rk1, rk2, gamma, w], [gamma, w, fi, tetta], [0, %pi/8, %pi/2, 0], [t, 0, Tmax with_stdout ("gamma.txt", for k:1 thru points do print (sol[k][1], sol[k][2])) - пример ввода данных из файла.




А теперь рассмотрим типовой пример использования Maxima в студенческой жизни. Красиво и интересно данный процесс был показан в <a href="http://habrahabr.ru/post/193272/">статье на Хабре </a>ранее. Я в свою очередь только поверну координатные оси в одном уравнении:
<source lang="lisp">

F:uxx+2*uxy+cos(x)^2*uyy-ctg(x)*(ux+uy); /*искомое уравнение*/
A:F,uxx=uxx,uxy=0,uyy=0,ux=0,uy=0$ A:A/uxx$
B:F,uxx=0,uxy=uxy,uyy=0,ux=0,uy=0$ B:B/(2*uxy)$
C:F,uxx=0,uxy=0,uyy=uyy,ux=0,uy=0$ C:C/(uyy)$
D:F,uxx=0,uxy=0,uyy=0,ux=ux,uy=0$ D:D/(ux)$
E:F,uxx=0,uxy=0,uyy=0,ux=0,uy=uy$ E:E/(uy)$
print("A = ",A)$ print("B = ",B)$ print("C = ",C)$ print("D = ",D)$ print("E = ",E)$
delta:B^2-A*C$
print("Delta = ", delta)$
/*так как я знаю, что дельта > 0, перехожу сражу к решению гиперболического уравнения */
A*'diff(y,x,1)^2-2*B*'diff(y,x,1)+C=0;
'diff(y,x,1)=(2*B+sqrt((2*B)^2-4*A*C))/(2*A);
ode2(%,y,x);
solve(%,%c)$
w1:rhs(%[1])$ print("w1 = ",w1)$
'diff(y,x,1)=(2*B-sqrt((2*B)^2-4*A*C))/(2*A);
ode2(%,y,x);
solve(%,%c)$
w2:rhs(%[1])$ print("w2 = ",w2)$
ux:un*diff(w2,x)+ue*diff(w1,x);
uy:un*diff(w2,y)+ue*diff(w1,y);
uxx:un*diff(diff(w2,x),x)+unn*diff(w2,x)^2+2*uen*diff(w1,x)*diff(w2,x)+ue*diff(diff(w1,x),x)+uee*diff(w1,x)^2;
uxy:un*diff(diff(w2,x),y)+uen*(diff(w1,x)*diff(w2,y)+diff(w1,y)*diff(w2,x))+unn*diff(w2,x)*diff(w2,y)+ue*diff(diff(w1,x),y)+uee*
diff(w1,x)*diff(w1,y);
uyy:un*diff(diff(w2,y),y)+unn*diff(w2,y)^2+2*uen*diff(w1,y)*diff(w2,y)+ue*diff(diff(w1,y),y)+uee*diff(w1,y)^2;
uy*E+ux*D+uyy*C+2*uxy*B+uxx*A;
%,ctg(x)=cos(x)/sin(x); trigrat(%);
</source>
Результат:
2*uen*cos(2*x)-2*uen

Комментариев нет:

Отправить комментарий

Резюме - бэкап от 6 ноября 2023 г.

Прочнист, инженер-прочнист, инженер-исследователь, инженер-математик Специализации: Учитель, преподаватель, педагог Инженер-конструктор, инж...