Пусть в сложном выражении надо сгруппировать сомножители при переменных r1, r2, ... . Один из способов сделать это - занести переменные в список рациональных переменных, так, чтобы в дальнейшем выражения? в которых эти переменные встретятся, рассматривались как рациональные выражения от этих переменных. Для этого служит функция RATVARS(var1, var2, ..., varm). После этого функция RATSIMP перегруппирует выражение нужным образом.
ПРИМЕР:
(D3) -d[1][1]*d[1][3]*a[4]+d[3][1]*d[1][2]*a[4]-d[1][1]*d[0][3]*a[3] +d[2][1]*d[1][2]*a[3]+d[0][1]*a[1]*d[1][2] -d[1][1]*d[2][1]*a[1] (C4) ratvars(a[1],a[2],a[3],a[4]); (D4) [a[1],a[2],a[3],a[4]] (C5) ratsimp(d3); (D5) (d[3][1]*d[1][2]-d[1][1]*d[1][3])*a[4] +(d[2][1]*d[1][2]-d[1][1]*d[0][3])*a[3] +a[1]*(d[0][1]*d[1][2]-d[1][1]*d[2][1])
В одном из писем, поступившем в список рассылки, содержался вопрос о преобразовании выражения cos(a+b+c)+cos(a+b-c). Решение основывается на последовательном применении функций TRIGEXPAND, FACTOR и TRIGREDUCE. Однако оказалось, что это упрощение нужно выполнить внури другого выражения, и стандартные средства делали либо слишком много, ибо слишком мало. Именно, требовалось упростить выражение r*sin(a+b+c)-r*sin(a+b-c)+d*cos(a+b+c)-d*cos(a+b-c). Предлагаемое здесь решение основано на функции MAPAT, отсутствующей в библиотеке MAXIMA.
mapat([x]):=block([func:first(x),level:second(x),elist:rest(x,2)], if length(elist)=1 then elist:first(elist), if level>1 then return(mapat(func,level-1,elist)), map(func,elist) );
(C1) load("c:/tmp/.maxima/mapat.mac"); (D1) c:/tmp/.maxima/mapat.mac (C2) r*sin(a+b+c)-r*sin(a+b-c)+d*cos(a+b+c)-d*cos(a+b-c)$ (C3) ratvars(r,d); (D3) [r, d] (C4) trigexpand(c2); (D4) (- SIN(a) SIN(b) SIN(C) + COS(a) COS(b) SIN(C) + COS(a) SIN(b) COS(C) + SIN(a) COS(b) COS(C)) r + (- SIN(a) SIN(b) SIN(C) + COS(a) COS(b) SIN(C) - COS(a) SIN(b) COS(C) - SIN(a) COS(b) COS(C)) r - (COS(a) SIN(b) SIN(C) + SIN(a) COS(b) SIN(C) - SIN(a) SIN(b) COS(C) + COS(a) COS(b) COS(C)) d + (- COS(a) SIN(b) SIN(C) - SIN(a) COS(b) SIN(C) - SIN(a) SIN(b) COS(C) + COS(a) COS(b) COS(C)) d (C6) ratsimp(d4); (D6) (2 COS(a) COS(b) - 2 SIN(a) SIN(b)) SIN(C) r + (- 2 COS(a) SIN(b) - 2 SIN(a) COS(b)) SIN(C) d (C7) mapat(trigreduce,3,d6); (D7) 2 COS(b + a) SIN(C) r - 2 SIN(b + a) SIN(C) dПохожее решение, данное в списке рассылки,
(C1) r*sin(a+b+c)-r*sin(a+b-c)+d*cos(a+b+c)-d*cos(a+b-c)$ (C2) ratsimp(%); (C3) r*(sin(a+b+c)-sin(a+b-c))+d*(cos(a+b+c)-cos(a+b-c))$ (C4) trigexpand(%); (C5) trigsimp(%); (C6) trigreduce(%); (D6) 2 COS(b + a) SIN(c) r - 2 SIN(b + a) SIN(c) dиспользует вызов функции TRIGSIMP, которая, в свою очередь, вызывает RADCAN. именно последняя функция делает работы по вынесению множителей перед r и d и вынесению также за скобки SIN(c).
Ричард Фейтман:
Если вам нужет массив новопорожденных символов, можно сделать так:
block([a],a[1]:?gensym(),a[2]:?gensym() , ..... делаем что-нибудь с ними...);
Бартон Уиллис:
Чтобы установить число знаков для вычислейний с большой точностью,
надо присвоить новое значение переменной fpprec. Например,
(C1) fpprec : 50; (D1) 50 (C2) sqrt(2.0b0); (D2) 1.414213562373095048801688724209698078569671875377B0Числа 2.0 и 2.0d0 оба являются числами с двойной точностью, поэтому значение fpprec не имеет значения для этих чисел
MAXIMA не позволяет писать некторые строки в интерпретаторе, и интерпретатор переписывает их посвоему.Gosei Furuya :
(C2) sump(f):=not(atom(f)) and part(f,0)='SUM$ sump(f) should return true for expr f, sum(,,,). (C3) sump(sum(y^n,n,0,inf)); (D3) FALSE (C4) part('sum(x^n,n,0,inf),0)='SUM; //....(1) (D4) SUM = SUM (C5) is(%); (D5) FALSE (C6) :lisp (print $d4) ((MEQUAL SIMP) %SUM $SUM) Нельзя написать $SUM потому, что MAXIMA перепишет это в виде $%SUM. Остается только написать(C7) sump(f):=not(atom(f))and part(f,0)=part('sum(_x^_n,_n,0,1),0)$ not elegant but (C8) sump(sum(x^n,n,0,inf)); (D9) TRUEСтаврос Макракис:
Возможное решение при обращение с существительными и глаголами:sump(f):=not(atom(f)) and part(f,0)=nounify('sum)$или дажеsump(f):=not(atom(f)) and part(f,0)=''(nounify('sum))$так как nounify будет выполнено только один раз
Как устроены функции с переменным числом аргументов с точки зрения Лиспа?Ричард Фейтман:
Определить в MAXIMA функцию? принимающую переменной число аргументов можно так:
f([x]:=x;Чтобы получить доступ к частям этого x. можно использовать PART, INPART, индексы, FIRST, REST и т.д.
Из Лиспа можно написать(elt $x 0) --> (mlist simp) (elt $x 1) --> $a (для f(a,b,c))Когда MAXIMA была впервые написана, существовали много путей определения функции с различными техниками оценивания аргументов. Это были expr (обычная техника), fexpr, lexpr, и другие. Они все еще могутвстречаться в виде mexpr, mfexpr, и возможно некоторые другие вариации. В сущности все они были включены в Коммон Лисп другими способами? включая аргументы &resr и defmacro.
Как из строки получить список букв? Ричард Фейтман:
(defun $stringtomaximalist(x)(cons '(mlist)(mapcar #'(lambda(z)(concat '$ z))(cdr (explodec x)))))Эта функция еще создает символы вида $G, $A, $T etc.(C9) stringtomaximalist("CGATATATGAGAGAT"); (D9) [C, G, A, T, A, T, A, T, G, A, G, A, G, A, T]
Ваши шаблоны работают неправильно! Рассмотрим пример,matchdeclare(u,freeof(x))$ matchdeclare(y,freeof(t))$ defmatch(pat1, u*v)$ pat1(exp(x+t));Ожидаемое разложение[u=%E^t, v=%E^x]не получается. В чем причина?
Данный шаблон задает впролне определенную конструкцию и Maxima будет только искать совпадения, не пробуя все возможные разбиения. А выражениеexp(x+y)даже не является произведением.
Как собрать все члены выражения, удовлетворяющие моему предикату?
Надо напиcать маленький цикл:selectremove(expr,pred,[ops]):=block([p1:[], p2:[],r], for i:1 thru length(expr) do if (apply(pred,reverse(cons(r:part(expr,i),ops)))) then p1:cons(r,p1) else p2:cons(r,p2), [p1,p2]);
Какие уравнения может решать MAXIMA?
Линейные уравнения: функция linsolve
Системы алгебраических уравнений: algsys
Иррациональные уравнения: функция solve_irrat (не входит в дистрибутив, ее код есть в рассылке)
Рекуррентные уравнения: функция char из пакета recur,
также для разностных уравнений первого и второго порядков функция difference (пакет differ)
Простейшие тригонометрические, логарифмические и трансцендентные: функция solve
Как "поймать" результат команды tex()?
Команда tex() имеет второй необязательный аргумент. Так, вызов tex(...,false) вернет строку, содежращую выключенную формулу (то есть в двойных значках доллара). С помощью функции concat строки можно объединять в математический текст:(C1) concat("Все знают, что $(a+b)^2$ равно ", tex(expand((a+b)^2),false)); (D1) Все знают, что $(a+b)^2$ равно $$b^2+2\,a\,b+a^2$$Руководство говорит, что вторым аргументом команды tex() может быть имя файла. Однако проблема вознимает, когда это имя передается через переменную. Команда tex() автоматически заковычивает второй аргумент, так что, например, команда tex(expr, expr) запишет значение выражения expr в файл с именем "expr". Итак, возможны следующие решения:
filename: "c:\\docs\\maxima\\somefile.tex"$ texf(expr,filename)$
outputfile:"foo404.tex"; tex(%pi,''outputfile);
alias(outputfile,"foo404.tex"); tex(%pi,outputfile); remove(outputfile,alias); /* для переключения на другой выходной файл */
plot_polar(expr,range) := block([theta_var: range[1]], plot2d( ['parametric, cos(theta_var)*expr, sin(theta_var)*expr, range]))$Теперь, чтобы нарисовать полукруг, введем команду
plot_polar(1,[t,0,%pi]);А для кардиоиды достаточно ввести
plot_polar( 1 + 2 * cos(t), [t,0,2*%pi]);
f(x):=diff(sin(x),x);не работает. Работающий вариант
f(x):=subst(t=x,diff(sin(t),t));неудовлетворителен, поскольку он каждый раз наново перевычисляет производную. И, кроме того, если с переменной t связано значение, то будет получено сообщение об ошибке при дифференцировании. Защитой от этого могло бы быть использование оператора block([t,...],...). Но правильным решением будет использование двойного апострофа: expr: diff(sin(t),t); f(t):= ''expr $ Как указывал Ричард Фейтман, это, на самом деле, главное использование оператора '', который в общем случае не должен использоваться как замена команды ev().
sum(cos(j/N), j, 1, N)не вычилсить, даже если установить simpsum:true. Надо воспользоваться командой неопределенного суммирования nusum:
(C1) realpart(nusum(exp(%i*j*x),j,1,N)); SIN(x) SIN(N x + x) + (COS(x) - 1) COS(N x + x) (D2) ----------------------------------------------- 2 2 SIN (x) + (COS(x) - 1) 2 SIN (x) + (COS(x) - 1) COS(x) - ----------------------------- 2 2 SIN (x) + (COS(x) - 1)
A_0 : [ x, y, z ] $ q : [ 1, 2, 3 ] $ map("::", A_0, q);
(%i1) x : 2/(sqrt(5)+7^(1/3))$ (%i2) ratsimp(x), algebraic:true; 3/2 2/3 1/3 5/2 (5 - 7) 7 + (7 sqrt(5) - 25) 7 + 5 - 35 (%o2) --------------------------------------------------- 38