Previous: Введение в программирование на Maxima, Up: Программы Maxima [Contents][Index]
Печатает стек вызовов, т.е. список функций, которые вызывают текущую активную функцию.
Вызов backtrace()
печатает весь стек вызовов.
Вызов backtrace (n)
печатает n последних
функций, включая текущую.
Функция backtrace
может вызываться внутри программы, функции или из интерактивного
приглашение а не только из контекста отладки.
Примеры:
backtrace()
печатает весь стек вызовов.
(%i1) h(x) := g(x/7)$ (%i2) g(x) := f(x-11)$ (%i3) f(x) := e(x^2)$ (%i4) e(x) := (backtrace(), 2*x + 13)$ (%i5) h(10); #0: e(x=4489/49) #1: f(x=-67/7) #2: g(x=10/7) #3: h(x=10) 9615 (%o5) ---- 49
backtrace (n)
печатает n последних
функций, включая текущую.
(%i1) h(x) := (backtrace(1), g(x/7))$ (%i2) g(x) := (backtrace(1), f(x-11))$ (%i3) f(x) := (backtrace(1), e(x^2))$ (%i4) e(x) := (backtrace(1), 2*x + 13)$ (%i5) h(10); #0: h(x=10) #0: g(x=10/7) #0: f(x=-67/7) #0: e(x=4489/49) 9615 (%o5) ---- 49
Команда do
используется для выполнения итераций. Т.к. команда do
довольно обща, то она будет описана в двух частях.
Сначала будет описана обычная форма, аналогична используемым
в нескольких других языках программирования (Fortran, Algol, PL/I и т.д.).
Далее будут описаны другие возможности.
Существует три формы команды, отличающиеся только условием завершения. А именно:
for variable: initial_value step increment
thru limit do body
for variable: initial_value step increment
while condition do body
for variable: initial_value step increment
unless condition do body
(Как альтернатива, команда step
может быть задана после условия завершения или
границы.)
Параметры initial_value, increment, limit и body
могут быть произвольными выражениями. Если приращение равно 1, то команда
"step 1
" может быть опущена.
Перед выполнение команды do
, переменной variable
(далее называемой управляющей переменной) присваивается начальное значение initial_value.
Далее: (1) если значение управляющей переменной превышает верхнюю границу,
задаваемую thru
, или если условие unless
равно true
,
или условие while
равно false
, то do
завершается.
(2) Вычисляется body. (3) Приращение добавляется к управляющей переменой.
Шаги (1) – (3) повторяются до выполнения условия завершения.
Можно задавать несколько условий завершения. В этом случае команда do
завершается при удовлетворении любого из них.
Обычно тест thru
выполняется, когда управляющая переменная становится больше
limit, когда приращение increment неотрицательно, или, если переменная становится меньше
limit, когда приращение increment отрицательно.
Параметры increment и limit могут быть нечисловыми выражениями, если
может быть определено их неравенство. Однако, если increment не является
синтаксически отрицательным (например, отрицательным числом) в момент начала выполнения команды do
,
то Maxima предполагает положительность increment во время выполнения do
.
Если на самом деле increment окажется неположительным, то do
может не завершиться надлежащим образом.
Отметим, что limit, increment и условие завершения вычисляются
заново для каждой итерации. Таким образом, если какое-либо из этих выражений требует
длительного вычисления, но не меняется от итерации к итерации при вычислении
body, то будет более эффективным присвоить их
значение переменной до выполнения do
и использовать эту переменную.
Значение, обычно возвращаемое командой do
, есть атом done
.
Однако, функция return
может быть использована внутри body
для завершения do
и задания возвращаемого значения.
Отметим, что вызов return
внутри цикла do
, расположенного в блоке
block
, завершает do
а не блок block
.
Функция go
не может быть использована для выхода из команды do
в объемлющий блок block
.
Управляющая переменная всегда локальна в рамках do
, т.е.
эту переменную можно использовать внутри цикла и это не
окажет влияния на переменную с тем же именем вне do
.
После завершения do
, управляющая переменная остается несвязанной.
(%i1) for a:-3 thru 26 step 7 do display(a)$ a = - 3 a = 4 a = 11 a = 18 a = 25
(%i1) s: 0$ (%i2) for i: 1 while i <= 10 do s: s+i; (%o2) done (%i3) s; (%o3) 55
Отметим, что условие while i <= 10
эквивалентно условию
unless i > 10
или условию thru 10
.
(%i1) series: 1$ (%i2) term: exp (sin (x))$ (%i3) for p: 1 unless p > 7 do (term: diff (term, x)/p, series: series + subst (x=0, term)*x^p)$ (%i4) series; 7 6 5 4 2 x x x x x (%o4) -- - --- - -- - -- + -- + x + 1 90 240 15 8 2
что дает 8 членов ряда Тейлора для e^sin(x)
.
(%i1) poly: 0$ (%i2) for i: 1 thru 5 do for j: i step -1 thru 1 do poly: poly + i*x^j$ (%i3) poly; 5 4 3 2 (%o3) 5 x + 9 x + 12 x + 14 x + 15 x (%i4) guess: -3.0$ (%i5) for i: 1 thru 10 do (guess: subst (guess, x, 0.5*(x + 10/x)), if abs (guess^2 - 10) < 0.00005 then return (guess)); (%o5) - 3.162280701754386
В этом примере вычисляется отрицательный квадратный корень числа 10
с использованием метода Ньютона-Рафсона с максимальным числом итераций 10.
Если условие сходимости не будет выполнено, то возвращается значение
done
.
Вместо добавления значения к управляющей переменной возможен
другой способ ее изменения на каждом цикле итерации.
В этом случае можно использовать next expression
вместо step increment
.
Что вызывает присваивание управляющей переменной значения expression
при каждой итерации.
(%i6) for count: 2 next 3*count thru 20 do display (count)$ count = 2 count = 6 count = 18
Синтаксис for variable from value ...do...
может
быть использован как альтернатива for variable: value ...do...
.
Что позволяет располагать from value
после значений step
или next
,
или после условия завершения. Если from value
опущено, то в качестве начального
значения предполагается 1.
Иногда требуется выполнить итерации без использования управляющей переменной. В этом случае можно задать только условие завершения без команд инициализации и изменения управляющей переменной, как сделано в следующем примере, вычисляющем квадратный корень числа 5 при неточном затравочном значении.
(%i1) x: 1000$ (%i2) thru 20 do x: 0.5*(x + 5.0/x)$ (%i3) x; (%o3) 2.23606797749979 (%i4) sqrt(5), numer; (%o4) 2.23606797749979
Если необходимо, то можно полностью опустить условия завершения
и использовать только do body
, что вызывает бесконечное
вычисление body. В этом случае для завершения do
следует
использовать return
.
(%i1) newton (f, x):= ([y, df, dfx], df: diff (f ('x), 'x), do (y: ev(df), x: x - f(x)/y, if abs (f (x)) < 5e-6 then return (x)))$ (%i2) sqr (x) := x^2 - 5.0$ (%i3) newton (sqr, 1000); (%o3) 2.236068027062195
(Заметим, что return
вызывает возвращение текущего значения x
в качестве значения do
. Блок block
завершается, и значение do
возвращается в качестве значения блока, т.к. do
является последней командой block
.)
В Maxima доступна еще одна форма команды do
. Ее синтаксис:
for variable in list end_tests do body
Элементы списка list (произвольные выражения)
последовательно присваиваются переменной variable
Для каждой итерации вычисления body.
Необязательное условие end_tests может использоваться для завершения do
,
иначе цикл завершится при исчерпании list или при выполнении return
внутри body. (На самом деле, list может быть любым
неатомарным выражением, последовательные части которого будут использованы в итерации.)
(%i1) for f in [log, rho, atan] do ldisp(f(1))$ (%t1) 0 (%t2) rho(1) %pi (%t3) --- 4 (%i4) ev(%t3,numer); (%o4) 0.78539816
Вычисляет одно за другим выражения expr_1, ..., expr_n
и, если не возникает ошибок, возвращает [expr_n]
(список).
Если при вычислении одного из аргументов возникает ошибка, то
errcatch
предотвращает дальнейшее распространение ошибки и возвращает
пустой список []
без дальнейшего вычисления аргументов.
Функция errcatch
полезна в пакетных batch
файлах,
если ожидается возможное возникновение ошибки, что без
перехвата ошибки приводит к завершению batch
.
Вычисляет и печатает expr_1, ..., expr_n, и
затем вызывает ошибку, что возвращает управление на верхний
уровень Maxima или ближайшему объемлющему errcatch
.
Значением переменной error
является список, описывающий ошибку.
Первый элемент error
– строка форматирования,
которая объединяет все строки из параметров expr_1, ..., expr_n,
остальные элементы – есть значения нестроковых аргументов.
Функция errormsg()
форматирует и печатает error
,
что повторяет печать самой последней ошибки.
Повторяет печать самой последней ошибки.
Информация об ошибке содержится в переменной error
, и errormsg
форматирует и печатает ее.
Используется в циклах. См. do
для описания средств Maxima для
организации итераций.
Используется внутри блока block
для передачи управления на команду,
помеченную параметром go
. Для пометки команды в блоке, перед ней помещают
другую команду в виде атома (метки). Например:
block ([x], x:1, loop, x+1, ..., go(loop), ...)
Аргументом go
должна быть метка, определенная в том же блоке block
.
Нельзя использовать go
для передачи управления на метку в блоке отличном от
того, где находится сама команда go
.
Условное вычисление. Существуют различные формы условного выражения if
.
if cond_1 then expr_1 else expr_0
вычисляет и возвращает значение expr_1, если значение cond_1 равно true
,
иначе вычисляет и возвращает значение expr_0
.
if cond_1 then expr_1 elseif cond_2 then expr_2 elseif ... else expr_0
вычисляет и возвращает значение expr_k, если cond_k равно true
а все предыдущие условия равны false
.
Если не одно из условий не равно true
, то вычисляется и возвращается значение expr_0.
Если завершающее else
отсутствует, то в конце подразумевается else false
.
Т.е. if cond_1 then expr_1
эквивалентно
if cond_1 then expr_1 else false
,
а if cond_1 then expr_1 elseif ... elseif cond_n then expr_n
эквивалентно
if cond_1 then expr_1 elseif ... elseif cond_n then expr_n else false
.
Альтернативы expr_0, ..., expr_n могут быть произвольными выражениями Maxima,
включая вложенные if
выражения.
Альтернативы не упрощаются и не вычисляются до тех пор пока соответствующее условие
не равно true
.
Условия cond_1, ..., cond_n являются выражениями, которые потенциально или фактически
вычисляются в true
или false
.
Если значение условия не равно ни true
, ни false
, то
поведение if
управляется глобальной переменной prederror
.
Если prederror
равна true
, то любое значение условия, отличное от true
или false
,
считается ошибкой. Иначе, условия, которые не вычисляются в true
или false
,
считаются допустимыми и результатом вычисления является условное выражение.
Вместе с другими элементами, условия могут включать следующие логические операторы и операторы отношения.
Операция Символ Тип меньше < отношение, инфиксный меньше или равно <= отношение, инфиксный равенство (синтаксическое) = отношение, инфиксный отрицание = # отношение, инфиксный равенство (значение) equal отношение, функция отрицане equal notequal отношение, функция больше или равно >= отношение, инфиксный больше > отношение, инфиксный и and логический, инфиксный или or логический, инфиксный нет not логический, префиксный
Возвращает выражение, с оператором верхнего уровня таким же как у выражений
expr_1, ..., expr_n но аргументы которого являются результатами
применения f к соответствующим аргументам выражений expr_i.
Здесь, f – либо функция n аргументов, либо lambda
выражение с n аргументами.
Если переменная maperror
равна false
, то map
:
(1) остановится на самом коротком выражении expr_i, если не все expr_i
имеют одинаковую длину; (2) применит f к [expr_1, expr_2,...],
если не все expr_i имеют одинаковый тип. Если maperror
равна true
,
то в оба вышеуказанных случая считаются ошибкой.
Одним из применений функции map
является применение какой-либо функции
(например, partfrac
) к каждому члену большого выражения вместо применения
ее к выражению целиком, что может привести к слишком сложным вычислениям и,
как следствие, к нехватке памяти.
(%i1) map(f,x+a*y+b*z); (%o1) f(b z) + f(a y) + f(x) (%i2) map(lambda([u],partfrac(u,x)),x+1/(x^3+4*x^2+5*x+2)); 1 1 1 (%o2) ----- - ----- + -------- + x x + 2 x + 1 2 (x + 1) (%i3) map(ratsimp, x/(x^2+x)+(y^2+y)/y); 1 (%o3) y + ----- + 1 x + 1 (%i4) map("=",[a,b],[-0.5,3]); (%o4) [a = - 0.5, b = 3]
Возвращает true
тогда и только тогда, когда выражение expr рассматривается map-процедурами
как атомарное выражение. К таким "mapatoms" относятся атомы, числа (включая рациональные) и
переменные с индексом.
Значение по умолчанию: true
Если переменная maperror
равна false
, то все map
функции, например:
map (f, expr_1, expr_2, ...)
(1) остановится на самом коротком выражении expr_i, если не все expr_i имеют одинаковую длину; (2) применит f к [expr_1, expr_2,...], если не все expr_i имеют одинаковый тип.
Если maperror
равна true
,
то в оба вышеуказанных случая считаются ошибками.
Значение по умолчанию: true
Если переменная mapprint
равна true
, то функции
map
, mapl
и fullmap
в определенных ситуациях
выдают различные сообщения. Включая ситуации, когда map
использует
apply
или map
обрезает до самого короткого списка.
Если mapprint
равна false
, то данные сообщения подавляются.
Возвращает список с f, примененной к частям выражений expr_1, ..., expr_n. f – есть имя функции или лямбда-выражение.
Функция maplist
отличается от map (f, expr_1, ..., expr_n)
,
которая возвращает выражение с главным оператором, одним для всех выражений expr_i
(за исключеним упрощений и случая, когда map
выполняет apply
).
Значение по умолчанию: false
Если prederror
равна true
, то ошибка случается всякий раз, как только
вычисленное значение предиката команды if
или функции is
отлично от
true
или false
.
Если false
, то в этом случае возвращается unknown
.
Работа с prederror: false
не поддерживается транслированном коде.
Однако, maybe
поддерживается в транслированном коде.
См. также is
и maybe
.
Используется для явного выхода из блока, делая value значением этого блока.
См. block
для более детального описания.
Применяет функцию f к expr рекурсивно начиная с верхнего уровня и глубже. Это может быть полезно, если, например, требуется полная факторизация:
(%i1) exp:(a^2+2*a+1)*y + x^2$ (%i2) scanmap(factor,exp); 2 2 (%o2) (a + 1) y + x
Отметим, что то, как scanmap
применяет данную функцию factor
к подвыражениям
expr, зависит от формы этого выражения. И если дана другая форма expr,
то результат scanmap
может быть другим. Так, %o2
не получится,
если scanmap
применить к раскрытому варианту exp
:
(%i3) scanmap(factor,expand(exp)); 2 2 (%o3) a y + 2 a y + y + x
Еще один пример рекурсивного применения scanmap
ко всем подвыражениям,
включая экспоненты:
(%i4) expr : u*v^(a*x+b) + c$ (%i5) scanmap('f, expr); f(f(f(a) f(x)) + f(b)) (%o5) f(f(f(u) f(f(v) )) + f(c))
scanmap (f, expr, bottomup)
применяет f к expr с
самого глубокого уровня вверх. Например, для неопределенной функции f
,
scanmap(f,a*x+b) -> f(a*x+b) -> f(f(a*x)+f(b)) -> f(f(f(a)*f(x))+f(b)) scanmap(f,a*x+b,bottomup) -> f(a)*f(x)+f(b) -> f(f(a)*f(x))+f(b) -> f(f(f(a)*f(x))+f(b))
В данном случае результат одинаков для обоих вариантов вызова.
Вычисляет выражение expr и "бросает" его значение вверх до ближайшего catch
.
Функции throw
и catch
реализуют механизм нелокального возврата.
См. do
.
Применяет функцию f к каждому элементу внешнего произведения a_1 x a_2 ... x a_n.
f – есть имя функции с n аргументами или лямбда-выражение с n аргументами. Каждый элемент a_k может быть списком, списком списков, матрицей или любым другим выражением.
Значение outermap
является вложенной структурой.
Пусть x является возвращаемым значением.
Тогда x имеет ту же структуру, как первый аргумент (список, список списков или матрица),
x[i_1]...[i_m]
имеет ту же структуру, как второй аргумент (список, список списков или матрица),
x[i_1]...[i_m][j_1]...[j_n]
имеет ту же структуру, как третий аргумент (список, список списков или матрица),
и т.д., где m, n, ... – есть число индексов, необходимых для для доступа к элементам
каждого из аргументов (один для списка, два для матрицы, еще один для вложенного списка).
Аргументы, не являющиеся списками и матрицами, не оказывают влияния на возвращаемое значение.
Отметим, что результат outermap
отличается от применения f ко всем
элементам внешнего произведения, возвращаемого cartesian_product
.
Функция outermap
сохраняет структуру аргументов в возвращаемом значении, а cartesian_product
нет.
Функция outermap
вычисляет свои аргументы.
См. также map
, maplist
и apply
.
Примеры:
Простые примеры outermap
.
Для прояснения комбинации аргументов, F
оставлена неопределенной.
(%i1) outermap (F, [a, b, c], [1, 2, 3]); (%o1) [[F(a, 1), F(a, 2), F(a, 3)], [F(b, 1), F(b, 2), F(b, 3)], [F(c, 1), F(c, 2), F(c, 3)]] (%i2) outermap (F, matrix ([a, b], [c, d]), matrix ([1, 2], [3, 4])); [ [ F(a, 1) F(a, 2) ] [ F(b, 1) F(b, 2) ] ] [ [ ] [ ] ] [ [ F(a, 3) F(a, 4) ] [ F(b, 3) F(b, 4) ] ] (%o2) [ ] [ [ F(c, 1) F(c, 2) ] [ F(d, 1) F(d, 2) ] ] [ [ ] [ ] ] [ [ F(c, 3) F(c, 4) ] [ F(d, 3) F(d, 4) ] ] (%i3) outermap (F, [a, b], x, matrix ([1, 2], [3, 4])); [ F(a, x, 1) F(a, x, 2) ] [ F(b, x, 1) F(b, x, 2) ] (%o3) [[ ], [ ]] [ F(a, x, 3) F(a, x, 4) ] [ F(b, x, 3) F(b, x, 4) ] (%i4) outermap (F, [a, b], matrix ([1, 2]), matrix ([x], [y])); [ [ F(a, 1, x) ] [ F(a, 2, x) ] ] (%o4) [[ [ ] [ ] ], [ [ F(a, 1, y) ] [ F(a, 2, y) ] ] [ [ F(b, 1, x) ] [ F(b, 2, x) ] ] [ [ ] [ ] ]] [ [ F(b, 1, y) ] [ F(b, 2, y) ] ] (%i5) outermap ("+", [a, b, c], [1, 2, 3]); (%o5) [[a + 1, a + 2, a + 3], [b + 1, b + 2, b + 3], [c + 1, c + 2, c + 3]]
Более детальное исследование работы outermap
.
Первый, второй и третий аргументы являются матрицей, списком и матрицей соответственно.
Возвращаемое значение является матрицей.
Каждый элемент этой матрицы есть список, и каждый элемент данного списка – матрица.
(%i1) arg_1 : matrix ([a, b], [c, d]); [ a b ] (%o1) [ ] [ c d ] (%i2) arg_2 : [11, 22]; (%o2) [11, 22] (%i3) arg_3 : matrix ([xx, yy]); (%o3) [ xx yy ] (%i4) xx_0 : outermap (lambda ([x, y, z], x / y + z), arg_1, arg_2, arg_3); [ [ a a ] [ a a ] ] [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] [ [ 11 11 ] [ 22 22 ] ] (%o4) Col 1 = [ ] [ [ c c ] [ c c ] ] [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] [ [ 11 11 ] [ 22 22 ] ] [ [ b b ] [ b b ] ] [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] [ [ 11 11 ] [ 22 22 ] ] Col 2 = [ ] [ [ d d ] [ d d ] ] [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] [ [ 11 11 ] [ 22 22 ] ] (%i5) xx_1 : xx_0 [1][1]; [ a a ] [ a a ] (%o5) [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] [ 11 11 ] [ 22 22 ] (%i6) xx_2 : xx_0 [1][1] [1]; [ a a ] (%o6) [ xx + -- yy + -- ] [ 11 11 ] (%i7) xx_3 : xx_0 [1][1] [1] [1][1]; a (%o7) xx + -- 11 (%i8) [op (arg_1), op (arg_2), op (arg_3)]; (%o8) [matrix, [, matrix] (%i9) [op (xx_0), op (xx_1), op (xx_2)]; (%o9) [matrix, [, matrix]
Функция outermap
сохраняет структуру аргументов в возвращаемом значении, а cartesian_product
нет.
(%i1) outermap (F, [a, b, c], [1, 2, 3]); (%o1) [[F(a, 1), F(a, 2), F(a, 3)], [F(b, 1), F(b, 2), F(b, 3)], [F(c, 1), F(c, 2), F(c, 3)]] (%i2) setify (flatten (%)); (%o2) {F(a, 1), F(a, 2), F(a, 3), F(b, 1), F(b, 2), F(b, 3), F(c, 1), F(c, 2), F(c, 3)} (%i3) map (lambda ([L], apply (F, L)), (%o3) {F(a, 1), F(a, 2), F(a, 3), F(b, 1), F(b, 2), F(b, 3), F(c, 1), F(c, 2), F(c, 3)} (%i4) is (equal (%, %th (2))); (%o4) true
Previous: Введение в программирование на Maxima, Up: Программы Maxima [Contents][Index]