This is maxima.info, produced by makeinfo version 6.5 from maxima.texi.

This is a Texinfo Maxima Manual

   Copyright 1994,2001 William F. Schelter

START-INFO-DIR-ENTRY
* Maxima: (maxima).     A computer algebra system.
END-INFO-DIR-ENTRY


File: maxima.info,  Node: Списки,  Next: Множества,  Prev: Правила преобразования и шаблоны,  Up: Top

35 Списки
*********

* Menu:

* Ведение в работу со списками::
* Функции и переменные для работы со списками::


File: maxima.info,  Node: Ведение в работу со списками,  Next: Функции и переменные для работы со списками,  Prev: Списки,  Up: Списки

35.1 Ведение в работу со списками
=================================

Списки являются основными строительными блоками в Maxima и Lisp.  Все
типы данных, за исключением массивов, хеш-таблиц и чисел, представлены,
как Lisp списки.  Эти списки имеют вид

     ((MPLUS) $A 2)

для обозначения ‘a+2’.  На уровне Maxima мы увидим в инфиксной нотации
‘a+2’.  Maxima тоже имеет свои собственные списки, которые печатаются
как

     [1, 2, 7, x+y]

для списка из 4 элементов.  Внутренне, это выражение соответствует Lisp
списку

     ((MLIST) 1  2  7  ((MPLUS)  $X $Y ))

Флаг, который обозначает тип выражения Maxima, сам является списком, и
после упрощения, данный список приобретет вид

     ((MLIST SIMP) 1 2 7 ((MPLUS SIMP) $X $Y))


File: maxima.info,  Node: Функции и переменные для работы со списками,  Prev: Ведение в работу со списками,  Up: Списки

35.2 Функции и переменные для работы со списками
================================================

 -- Функция: append (<list_1>, ..., <list_n>)
     Возвращает новый список элементов <list_1> с последующими
     элементами <list_2> и т.д.  ‘append’ работает и с выражениями
     общего вида, например, ‘append (f(a,b), f(c,d,e));’ дает
     ‘f(a,b,c,d,e)’.

     См.  ‘example(append);’ для примера.

 -- Функция: assoc (<key>, <list>, <default>)
 -- Функция: assoc (<key>, <list>)
     Эта функция ищет ключ <key> в правых частях списка <list>, имеющего
     форму ‘[x,y,z,...]’, где каждый элемент <list> есть выражение с
     бинарным оператором и двумя операндами.  Например, ‘x=1’, ‘2^3’,
     ‘[a,b]’ и т.д.  Ключ <key> сравнивается с первым операндом.  Если
     ключ ‘key’ найден, то ‘assoc’ возвращает второй операнд.  В
     противном случае возвращается значение <default>.  Параметр
     <default> не обязателен и по умолчанию равен ‘false’.

 -- Функция: atom (<expr>)
     Возвращает ‘true’ если <expr> является атомарным (т.е.  число, имя
     или строка) и ‘false’ в противном случае.  Т.е.  ‘atom(5)’ равно
     ‘true’, тогда как ‘atom(a[1])’ и ‘atom(sin(x))’ равны ‘false’
     (предполагая, что ‘a[1]’ и ‘x’ не имеют значения).

 -- Функция: cons (<expr>, <list>)
     Возвращает новый список, составленный из первого элемента равного
     <expr> с последующими элементами <list>.  Функция ‘cons’ работает и
     с произвольными выражениями, например, ‘cons(x, f(a,b,c));’ ->
     ‘f(x,a,b,c)’.

 -- Функция: copylist (<list>)
     Возвращает копию списка <list>.

 -- Функция: create_list (<form>, <x_1>, <list_1>, ..., <x_n>, <list_n>)

     Создает список, вычисляя выражение <form> с <x_1> последовательно
     равным элементам <list_1>, <x_2> последовательно равным элементам
     <list_2> и т.д.  Общее число элементов в результирующем списке
     равно произведению числа элементов во всех списках.  Каждая
     переменная <x_i> должна быть символом.  Переменные не вычисляются.
     Списки вычисляются однажды в начале итерации.

          (%i1) create_list(x^i,i,[1,3,7]);
                           3   7
          (%o1)       [x, x , x ]

     Двойная итерация:

          (%i1) create_list([i,j],i,[a,b],j,[e,f,h]);
          (%o1) [[a, e], [a, f], [a, h], [b, e], [b, f], [b, h]]

     Вместо списка <list_i> можно использовать два параметра, которые
     должны иметь числовые значения.  Они будут рассматриваться как
     нижняя и верхняя границы итерации (включительно).

          (%i1) create_list([i,j],i,[1,2,3],j,1,i);
          (%o1) [[1, 1], [2, 1], [2, 2], [3, 1], [3, 2], [3, 3]]

     Отметим, что пределы для переменной ‘j’ могут зависеть от ‘i’.

 -- Функция: delete (<expr_1>, <expr_2>)
 -- Функция: delete (<expr_1>, <expr_2>, <n>)
     Удаляет все элементы, равные <expr_1>, из <expr_2>.  При этом
     <expr_1> может быть слагаемым <expr_2> (если это сумма) или
     множителем <expr_2> (если это произведение).

          (%i1) delete(sin(x), x+sin(x)+y);
          (%o1)                         y + x


     Вызов ‘delete(<expr_1>, <expr_2>, <n>)’ удаляет первые <n> случаев
     <expr_1> из <expr_2>.  Если число включений <expr_1> в <expr_2>
     меньше <n>, то будут удалены все.

          (%i1) delete(a, f(a,b,c,d,a));
          (%o1)                      f(b, c, d)
          (%i2) delete(a, f(a,b,a,c,d,a), 2);
          (%o2)                     f(b, c, d, a)


 -- Функция: eighth (<expr>)
     Возвращает восьмой элемент выражения или списка <expr>.  См.
     ‘first’ по поводу подробностей.

 -- Функция: endcons (<expr>, <list>)
     Возвращает новый список, состоящий из элементов ‘list’ с
     последующим <expr>.  Функция ‘endcons’ работает и с общими
     выражениями, например, ‘endcons(x, f(a,b,c));’ -> ‘f(a,b,c,x)’.

 -- Функция: fifth (<expr>)
     Возвращает пятый элемент выражения или списка <expr>.  См.  ‘first’
     по поводу подробностей.

 -- Функция: first (<expr>)
     Возвращает первый элемент <expr>, что может быть первым элементом
     списка, первой строкой в матрице, первым слагаемым суммы и т.д.
     Заметим, что ‘first’ и другие подобные функции, такие как ‘rest’ и
     ‘last’, работают с внешней (печатной) формой выражения <expr>, а не
     с тем, как это выражение было введено.  Если значение ‘inflag’
     равно ‘true’, то эти функции будут работать с внутренним
     представлением выражения <expr>.  Отметим, что упрощатель изменяет
     порядок членов в выражениях.  Так, ‘first(x+y)’ будет равно ‘x’,
     если ‘inflag’ равна ‘true’, и ‘y’, если ‘inflag’ равна ‘false’
     (‘first(y+x)’ даст одинаковый результат в обоих случаях).  Функции
     ‘second’ ..  ‘tenth’ дают со второго по десятый элемент выражения.

 -- Функция: fourth (<expr>)
     Возвращает четвертый элемент выражения или списка <expr>.  См.
     ‘first’ по поводу подробностей.

 -- Функция: get (<a>, <i>)
     Возвращает определенное пользователем свойство атома <a>,
     обозначенное <i>, или ‘false’, если атом не имеет свойства <i>.

     Функция ‘get’ вычисляет свои аргументы.

          (%i1) put (%e, 'transcendental, 'type);
          (%o1)                    transcendental
          (%i2) put (%pi, 'transcendental, 'type)$
          (%i3) put (%i, 'algebraic, 'type)$
          (%i4) typeof (expr) := block ([q],
                  if numberp (expr)
                  then return ('algebraic),
                  if not atom (expr)
                  then return (maplist ('typeof, expr)),
                  q: get (expr, 'type),
                  if q=false
                  then errcatch (error(expr,"is not numeric.")) else q)$
          (%i5) typeof (2*%e + x*%pi);
          x is not numeric.
          (%o5)  [[transcendental, []], [algebraic, transcendental]]
          (%i6) typeof (2*%e + %pi);
          (%o6)     [transcendental, [algebraic, transcendental]]


 -- Функция: join (<l>, <m>)
     Возвращает новый список, состоящий из чередующихся элементов
     списков <l> и <m>.  Результат будет иметь вид ‘[<l>[1], <m>[1],
     <l>[2], <m>[2], ...]’.  Списки <l> и <m> могут иметь элементы
     любого типа.

     Если списки имеют разную длину, то ‘join’ отбросит последние
     элементы более длинного списка.

     Ситуация, когда либо <l>, либо <m> не является списком, считается
     ошибкой.

     Примеры:

          (%i1) L1: [a, sin(b), c!, d - 1];
          (%o1)                [a, sin(b), c!, d - 1]
          (%i2) join (L1, [1, 2, 3, 4]);
          (%o2)          [a, 1, sin(b), 2, c!, 3, d - 1, 4]
          (%i3) join (L1, [aa, bb, cc, dd, ee, ff]);
          (%o3)        [a, aa, sin(b), bb, c!, cc, d - 1, dd]

 -- Функция: last (<expr>)
     Возвращает последний элемент <expr> (элемент, слагаемое, множитель,
     строку и т.п.).

 -- Функция: length (<expr>)
     По умолчанию возвращает число частей внешней (печатной) формы
     выражения <expr>.  Для списка – это число элементов, для матрицы –
     число строк, для суммы – число слагаемых (см.  ‘dispform’).

     Результат ‘length’ зависит от переключателя ‘inflag’.  Например,
     ‘length(a/(b*c));’ дает 2, если ‘inflag’ равен ‘false’
     (предполагается, что ‘exptdispflag’ равна ‘true’), и дает 3, если
     ‘inflag’ равен ‘true’, т.к.  внутренние представление есть
     ‘a*b^-1*c^-1’.

 -- Управляющая переменная: listarith
     Значение по умолчанию: ‘true’ Если равна ‘false’, то все
     арифметические операции со списками не работают.  Если равна
     ‘true’, то все операции список-матрица вызывают преобразование
     списков в матрицы и дают результат матричного типа.  Однако,
     операции список-список продолжают давать списки.

 -- Функция: listp (<expr>)
     Возвращает ‘true’, если <expr> является списком и ‘false’ в
     противном случае.

 -- Функция: makelist (<expr>, <i>, <i_0>, <i_1>)
 -- Функция: makelist (<expr>, <x>, <list>)
     Создает и возвращает список, каждый элемент которого построен из
     выражения <expr>.

     Вызов ‘makelist (<expr>, <i>, <i_0>, <i_1>)’ возвращает список, с
     ‘j’-м элементом равным ‘ev (<expr>, <i>=j)’ для ‘j’, пробегающего
     значения от <i_0> до <i_1>.

     Вызов ‘makelist (<expr>, <x>, <list>)’ возвращает список, с ‘j’-м
     элементом равным ‘ev (<expr>, <x>=<list>[j])’ для ‘j’, пробегающего
     значения от 1 до ‘length (<list>)’.

     Примеры:

          (%i1) makelist(concat(x,i),i,1,6);
          (%o1)               [x1, x2, x3, x4, x5, x6]
          (%i2) makelist(x=y,y,[a,b,c]);
          (%o2)                 [x = a, x = b, x = c]


 -- Функция: member (<expr_1>, <expr_2>)

     Возвращает ‘true’ если ‘is(<expr_1> = <a>)’, для некоторого
     элемента <a> из ‘args(<expr_2>)’, и ‘false’ в противном случае.

     Обычно, ‘expr_2’ является списком.  В этом случае ‘args(<expr_2>) =
     <expr_2>’ и ‘is(<expr_1> = <a>)’ для некоторого элемента <a> из
     ‘expr_2’.

     Функция ‘member’ не анализирует составные части аргументов
     ‘expr_2’, и может возвратить ‘false’ даже если ‘expr_1’ является
     частью какого-либо из аргументов ‘expr_2’.

     См.  также ‘elementp’.

     Примеры:

          (%i1) member (8, [8, 8.0, 8b0]);
          (%o1)                         true
          (%i2) member (8, [8.0, 8b0]);
          (%o2)                         false
          (%i3) member (b, [a, b, c]);
          (%o3)                         true
          (%i4) member (b, [[a, b], [b, c]]);
          (%o4)                         false
          (%i5) member ([b, c], [[a, b], [b, c]]);
          (%o5)                         true
          (%i6) F (1, 1/2, 1/4, 1/8);
                                         1  1  1
          (%o6)                     F(1, -, -, -)
                                         2  4  8
          (%i7) member (1/8, %);
          (%o7)                         true
          (%i8) member ("ab", ["aa", "ab", sin(1), a + b]);
          (%o8)                         true

 -- Функция: ninth (<expr>)
     Возвращает девятый элемент выражения или списка <expr>.  См.
     ‘first’ по поводу подробностей.

 -- Функция: unique (<L>)

     Возвращает уникальные элементы списка <L>.

     Если все элементы списка <L> уникальны, то ‘unique’ возвращает
     копию верхнего уровня списка <L>, а не сам список <L>.

     Если <L> не является списком, то ‘unique’ возвращает <L>.

     Пример:

          (%i1) unique ([1, %pi, a + b, 2, 1, %e, %pi, a + b, [1]]);
          (%o1)              [1, 2, %e, %pi, [1], b + a]

 -- Функция: rest (<expr>, <n>)
 -- Функция: rest (<expr>)
     Возвращает <expr> без первых <n> элементов, если <n> положительно,
     или без последних ‘- <n>’ элементов, если <n> отрицательно.  Если
     <n> равен 1, то он может быть опущен.  Выражение <expr> может быть
     списком, матрицей или выражением.

 -- Функция: reverse (<list>)
     Изменяет порядок членов <list> (но не сами члены) на обратный.
     Функция ‘reverse’ также работает с выражениями общего вида,
     например, ‘reverse(a=b);’ дает ‘b=a’.

 -- Функция: second (<expr>)
     Возвращает второй элемент выражения или списка <expr>.  См.
     ‘first’ по поводу подробностей.

 -- Функция: seventh (<expr>)
     Возвращает седьмой элемент выражения или списка <expr>.  См.
     ‘first’ по поводу подробностей.

 -- Функция: sixth (<expr>)
     Возвращает шестой элемент выражения или списка <expr>.  См.
     ‘first’ по поводу подробностей.

 -- Функция: sublist_indices (<L>, <P>)

     Возвращает список индексов элементов ‘x’ списка <L>, для которых
     предикат ‘maybe(<P>(x))’ возвращает ‘true’, за исключением
     элементов ‘unknown’ и ‘false’.  Параметр <P> может быть именем
     функции или лямбда-выражением.  Параметр <L> должен быть списком.

     Примеры:

          (%i1) sublist_indices ('[a, b, b, c, 1, 2, b, 3, b],
                                 lambda ([x], x='b));
          (%o1)                     [2, 3, 7, 9]
          (%i2) sublist_indices ('[a, b, b, c, 1, 2, b, 3, b], symbolp);
          (%o2)                  [1, 2, 3, 4, 7, 9]
          (%i3) sublist_indices ([1 > 0, 1 < 0, 2 < 1, 2 > 1, 2 > 0],
                                 identity);
          (%o3)                       [1, 4, 5]
          (%i4) assume (x < -1);
          (%o4)                       [x < - 1]
          (%i5) map (maybe, [x > 0, x < 0, x < -2]);
          (%o5)                [false, true, unknown]
          (%i6) sublist_indices ([x > 0, x < 0, x < -2], identity);
          (%o6)                          [2]

 -- Функция: tenth (<expr>)
     Возвращает десятый элемент выражения или списка <expr>.  См.
     ‘first’ по поводу подробностей.

 -- Функция: third (<expr>)
     Возвращает третий элемент выражения или списка <expr>.  См.
     ‘first’ по поводу подробностей.


File: maxima.info,  Node: Множества,  Next: Определение функций,  Prev: Списки,  Up: Top

36 Множества
************

* Menu:

* Введение в работу с множествами::
* Функции и переменные для работы с множествами::


File: maxima.info,  Node: Введение в работу с множествами,  Next: Функции и переменные для работы с множествами,  Prev: Множества,  Up: Множества

36.1 Введение в работу с множествами
====================================

Maxima предоставляет функции, такие как пересечение или объединение, для
работы с конечными множествами, определяемыми перечислением элементов.
Maxima трактует списки и множества как различные объекты.  Это позволяет
работать с множествами, элементами которых сами могут быть списками или
множествами.

   В дополнение к функциям для работы конечными множествами Maxima
определяет некоторые функции, относящиеся к комбинаторике, что включает:
числа Стирлинга первого и второго рода, числа Белла, мультиномиальные
коэффициенты, разбиения неотрицательных целых чисел и некоторые другие.
Maxima также определяет дельта-функцию Кронекера.

36.1.1 Использование
--------------------

Для того, чтобы задать множество с элементами ‘a_1, ..., a_n’, следует
написать ‘set(a_1, ..., a_n)’ или ‘{a_1, ..., a_n}’; для пустого
множества надо написать ‘set()’ или ‘{}’.  При вводе формы ‘set(...)’ и
‘{ ... }’ эквивалентны.  При выводе множества всегда печатаются с
фигурными скобками.

   Если элемент множества присутствует более одного раза, то упрощение
удалит повторяющиеся элементы.

     (%i1) set();
     (%o1)                          {}
     (%i2) set(a, b, a);
     (%o2)                        {a, b}
     (%i3) set(a, set(b));
     (%o3)                       {a, {b}}
     (%i4) set(a, [b]);
     (%o4)                       {a, [b]}
     (%i5) {};
     (%o5)                          {}
     (%i6) {a, b, a};
     (%o6)                        {a, b}
     (%i7) {a, {b}};
     (%o7)                       {a, {b}}
     (%i8) {a, [b]};
     (%o8)                       {a, [b]}

   Два элемента <x> и <y> являются повторяющимися (т.е.  рассматриваются
совпадающими с точки зрения включения в множество), тогда и только
тогда, когда ‘is(<x> = <y>)’ дает ‘true’.  Заметим, что ‘is(equal(<x>,
<y>))’ может давать ‘true’, тогда как ‘is(<x> = <y>)’ дает ‘false’.  В
этом случае элементы <x> и <y> считаются различными.

     (%i1) x: a/c + b/c;
                                   b   a
     (%o1)                         - + -
                                   c   c
     (%i2) y: a/c + b/c;
                                   b   a
     (%o2)                         - + -
                                   c   c
     (%i3) z: (a + b)/c;
                                   b + a
     (%o3)                         -----
                                     c
     (%i4) is (x = y);
     (%o4)                         true
     (%i5) is (y = z);
     (%o5)                         false
     (%i6) is (equal (y, z));
     (%o6)                         true
     (%i7) y - z;
                                b + a   b   a
     (%o7)                    - ----- + - + -
                                  c     c   c
     (%i8) ratsimp (%);
     (%o8)                           0
     (%i9) {x, y, z};
                               b + a  b   a
     (%o9)                    {-----, - + -}
                                 c    c   c

   Для того, чтобы создать множество из элементов списка, используется
‘setify’.

     (%i1) setify ([b, a]);
     (%o1)                        {a, b}

   Элементы множества ‘x’ и ‘y’ равны если ‘is(x = y)’ вычисляется в
‘true’.  Тогда ‘rat(x)’ и ‘x’ являются равными элементами множества, и,
следовательно

     (%i1) {x, rat(x)};
     (%o1)                          {x}

   Далее, поскольку ‘is((x - 1)*(x + 1) = x^2 - 1)’ вычисляется в
‘false’, то ‘(x - 1)*(x + 1)’ и ‘x^2 - 1’ есть различные элементы, и

     (%i1) {(x - 1)*(x + 1), x^2 - 1};
                                            2
     (%o1)               {(x - 1) (x + 1), x  - 1}

   Для приведения этого множества к одноэлементному следует применить
‘rat’ к каждому элементу:

     (%i1) {(x - 1)*(x + 1), x^2 - 1};
                                            2
     (%o1)               {(x - 1) (x + 1), x  - 1}
     (%i2) map (rat, %);
                                   2
     (%o2)/R/                    {x  - 1}

   Для удаления повторов из множеств другого вида может потребоваться
применение других упрощающих функций.  Вот пример, использующий
‘trigsimp’:

     (%i1) {1, cos(x)^2 + sin(x)^2};
                                 2         2
     (%o1)                {1, sin (x) + cos (x)}
     (%i2) map (trigsimp, %);
     (%o2)                          {1}

   Множество является упрощенным, если его элементы не повторяются и
упорядочены.  Текущая реализация Maxima функций для работы с множествами
использует функцию ‘orderlessp’ для упорядочения, однако будущие версии
могут использовать другую упорядочивающую функцию.

   Некоторые операции над множествами, такие как подстановки, вызывают
автоматическое упрощение.  Например,

     (%i1) s: {a, b, c}$
     (%i2) subst (c=a, s);
     (%o2)                        {a, b}
     (%i3) subst ([a=x, b=x, c=x], s);
     (%o3)                          {x}
     (%i4) map (lambda ([x], x^2), set (-1, 0, 1));
     (%o4)                        {0, 1}

   Maxima рассматривает списки и множества как различные объекты;
функции, подобные ‘union’ и ‘intersection’, сигнализируют об ошибке если
их аргументы не являются множествами.  Если необходимо применить функцию
для работы с множествами к списку, то надо сначала использовать ‘setify’
для преобразования списка в множество.  Таким образом

     (%i1) union ([1, 2], {a, b});
     Function union expects a set, instead found [1,2]
      -- an error.  Quitting.  To debug this try debugmode(true);
     (%i2) union (setify ([1, 2]), {a, b});
     (%o2)                     {1, 2, a, b}

   Для того, чтобы получить все элементы множества ‘s’, удовлетворяющие
предикату ‘f’, используйте ‘subset(s, f)’ (предикат – функция, дающая
логическое значение).  Например, чтобы найти в заданном множестве
уравнения, которые не зависят от переменной ‘z’, используйте

     (%i1) subset ({x + y + z, x - y + 4, x + y - 5},
                                         lambda ([e], freeof (z, e)));
     (%o1)               {- y + x + 4, y + x - 5}

   Раздел *note Функции и переменные для работы с множествами:: содержит
полный список функций Maxima, предназначенных для работы с множествами.

36.1.2 Итерация по элементам множества
--------------------------------------

Существует два способа организации цикла по элементам множества.  Один
способ – использовать ‘map’, например:

     (%i1) map (f, {a, b, c});
     (%o1)                  {f(a), f(b), f(c)}

   Другой способ – использовать ‘for <x> in <s> do’

     (%i1) s: {a, b, c};
     (%o1)                       {a, b, c}
     (%i2) for si in s do print (concat (si, 1));
     a1
     b1
     c1
     (%o2)                         done

   Maxima функции ‘first’ и ‘rest’ правильно работают с множествами.
Примененная к множеству, ‘first’ возвращает первый элемент множества,
какой именно – может зависеть от реализации.  Если ‘s’ является
множеством, то ‘rest(s)’ эквивалентно ‘disjoin(first(s), s)’.  В
настоящий момент есть другие функции Maxima, корректно работающие с
множествами.  В будущих версиях функции ‘first’ и ‘rest’ могут работать
на множествах иначе или не работать вовсе.

36.1.3 Ошибки
-------------

Функции для работы с множествами используют Maxima функцию ‘orderlessp’
для сортировки элементов множества и Lisp функцию ‘like’ для проверки
равенства элементов.  Обе эти функции имеют известные ошибки, которые
проявляются при попытке использовать множества, элементы которых
являются списками или матрицами, включающими выражения в канонической
рациональной форме (КРВ). Например

     (%i1) {[x], [rat (x)]};
     Maxima encountered a Lisp error:

       The value #:X1440 is not of type LIST.

     Automatically continuing.
     To reenable the Lisp debugger set *debugger-hook* to nil.

   Это выражение вызывает ошибку (сообщение об ошибке зависит от версии
Lisp и Maxima).  Другой пример

     (%i1) setify ([[rat(a)], [rat(b)]]);
     Maxima encountered a Lisp error:

       The value #:A1440 is not of type LIST.

     Automatically continuing.
     To reenable the Lisp debugger set *debugger-hook* to nil.

   Эти ошибки вызваны ошибками в ‘orderlessp’ и ‘like’, а не ошибками в
реализации функций работы с множествами.  Для иллюстрации попробуем
следующие выражения

     (%i1) orderlessp ([rat(a)], [rat(b)]);
     Maxima encountered a Lisp error:

       The value #:B1441 is not of type LIST.

     Automatically continuing.
     To reenable the Lisp debugger set *debugger-hook* to nil.
     (%i2) is ([rat(a)] = [rat(a)]);
     (%o2)                         false

   До тех пор, пока эти ошибки не исправлены, не следует использовать
множества с элементами в виде списков и матриц, содержащих выражения в
формате КРВ. Множества, просто содержащие выражения КРВ в качестве
элементов, не создают проблем.

     (%i1) {x, rat (x)};
     (%o1)                          {x}

   Maxima функция ‘orderlessp’ имеет еще одну ошибку, которая может
создать проблемы при работе с множествами.  А именно, упорядочивающий
предикат ‘orderlessp’ не является транзитивным.  Простейший известный
пример, демонстрирующий это

     (%i1) q: x^2$
     (%i2) r: (x + 1)^2$
     (%i3) s: x*(x + 2)$
     (%i4) orderlessp (q, r);
     (%o4)                         true
     (%i5) orderlessp (r, s);
     (%o5)                         true
     (%i6) orderlessp (q, s);
     (%o6)                         false

   Эта ошибка вызывает проблемы со всеми функциями для работы с
множествами и даже с другими функциями Maxima.  Возможно, но точно не
известно, что эту ошибку можно обойти, если все элементы множества или
являются КРВ, или упрощены с помощью ‘ratsimp’.

   Механизмы Maxima ‘orderless’ и ‘ordergreat’ не совместимы с функциями
для работы с множествами.  Если требуется использовать либо ‘orderless’,
либо ‘ordergreat’, то следует вызывать эти функции до формирования
множеств, и не следует использовать ‘unorder’.

   Если вы встретите что-то, что может быть ошибкой в функциях работы с
множествами, пожалуйста, сообщите об этом в базу данных ошибок Maxima.
См.  ‘bug_report’.

36.1.4 Авторы
-------------

Функции для работы с множествами Maxima и документация к ним написаны
Ставросом Макракисом (Stavros Macrakis of Cambridge, Massachusetts) и
Бартоном Уиллисом (Barton Willis of the University of Nebraska at
Kearney (UNK)).


File: maxima.info,  Node: Функции и переменные для работы с множествами,  Prev: Введение в работу с множествами,  Up: Множества

36.2 Функции и переменные для работы с множествами
==================================================

 -- Функция: adjoin (<x>, <a>)

     Возвращает объединение множества <a> с ‘{<x>}’.

     Функция ‘adjoin’ вызывает ошибку, если <a> не является множеством.

     Вызовы ‘adjoin(<x>, <a>)’ и ‘union(set(<x>), <a>)’ эквивалентны,
     однако ‘adjoin’ может быть несколько быстрее, чем ‘union’.

     См.  также ‘disjoin’.

     Примеры:

          (%i1) adjoin (c, {a, b});
          (%o1)                       {a, b, c}
          (%i2) adjoin (a, {a, b});
          (%o2)                        {a, b}

 -- Функция: belln (<n>)

     Представляет n-ое число Белла.  ‘belln(n)’ есть число разбиений
     множества с <n> элементами.

     Для неотрицательного целого <n>, ‘belln(<n>)’ упрощается в n-ое
     число Белла.  Для других значений аргумента ‘belln’ не упрощается.

     Функция ‘belln’ дистрибутивна по отношению к уравнениям, спискам,
     матрицам и множествам.

     Примеры:

     Функция ‘belln’, примененная к неотрицательным целым числам.

          (%i1) makelist (belln (i), i, 0, 6);
          (%o1)               [1, 1, 2, 5, 15, 52, 203]
          (%i2) is (cardinality (set_partitions ({})) = belln (0));
          (%o2)                         true
          (%i3) is (cardinality (set_partitions ({1, 2, 3, 4, 5, 6})) =
                                 belln (6));
          (%o3)                         true

     Функция ‘belln’, примененная к аргументам, не являющимися
     неотрицательными целыми числами.

          (%i1) [belln (x), belln (sqrt(3)), belln (-9)];
          (%o1)        [belln(x), belln(sqrt(3)), belln(- 9)]

 -- Функция: cardinality (<a>)

     Возвращает число различных элементов множества <a>.

     Функция ‘cardinality’ игнорирует повторяющиеся элементы даже если
     упрощение отключено.

     Примеры:

          (%i1) cardinality ({});
          (%o1)                           0
          (%i2) cardinality ({a, a, b, c});
          (%o2)                           3
          (%i3) simp : false;
          (%o3)                         false
          (%i4) cardinality ({a, a, b, c});
          (%o4)                           3

 -- Функция: cartesian_product (<b_1>, ... , <b_n>)
     Возвращает множество списков формы ‘[<x_1>, ..., <x_n>]’, где
     <x_1>, ..., <x_n> есть элементы множеств <b_1>, ...  , <b_n>
     соответственно.

     Функция ‘cartesian_product’ вызывает ошибку, если хотя бы один из
     ее аргументов не является множеством.

     Примеры:

          (%i1) cartesian_product ({0, 1});
          (%o1)                      {[0], [1]}
          (%i2) cartesian_product ({0, 1}, {0, 1});
          (%o2)           {[0, 0], [0, 1], [1, 0], [1, 1]}
          (%i3) cartesian_product ({x}, {y}, {z});
          (%o3)                      {[x, y, z]}
          (%i4) cartesian_product ({x}, {-1, 0, 1});
          (%o4)              {[x, - 1], [x, 0], [x, 1]}

 -- Функция: disjoin (<x>, <a>)
     Возвращает множество <a> без элемента <x>.  Если <x> не является
     элементом <a>, то <a> возвращается неизменным.

     Функция ‘disjoin’ вызывает ошибку, если <a> не является множеством.

     ‘disjoin(<x>, <a>)’, ‘delete(<x>, <a>)’ и ‘setdifference(<a>,
     set(<x>))’ эквивалентны.  Из этих вариантов ‘disjoin’ обычно
     быстрее других.

     Примеры:

          (%i1) disjoin (a, {a, b, c, d});
          (%o1)                       {b, c, d}
          (%i2) disjoin (a + b, {5, z, a + b, %pi});
          (%o2)                      {5, %pi, z}
          (%i3) disjoin (a - b, {5, z, a + b, %pi});
          (%o3)                  {5, %pi, b + a, z}

 -- Функция: disjointp (<a>, <b>)
     Возвращает ‘true’ тогда и только тогда, когда множества <a> и <b>
     не пересекаются.

     Функция ‘disjointp’ вызывает ошибку, если <a> или <b> не являются
     множествами.

     Примеры:

          (%i1) disjointp ({a, b, c}, {1, 2, 3});
          (%o1)                         true
          (%i2) disjointp ({a, b, 3}, {1, 2, 3});
          (%o2)                         false

 -- Функция: divisors (<n>)

     Представляет множество делителей <n>.

     Функция ‘divisors(<n>)’ упрощается до множества целых чисел, при
     этом <n> является ненулевым целым числом.  Множество делителей
     включает 1 и <n>.  Делители отрицательного числа совпадают с
     таковыми для его абсолютного значения.

     Функция ‘divisors’ дистрибутивна по отношению к уравнениям,
     спискам, матрицам и множествам.

     Примеры:

     Мы можем проверить, что число 28 является совершенным, т.е.  сумма
     делителей, за исключением самого числа, равна 28.

          (%i1) s: divisors(28);
          (%o1)                 {1, 2, 4, 7, 14, 28}
          (%i2) lreduce ("+", args(s)) - 28;
          (%o2)                          28

     Функция ‘divisors’ является упрощающей.  Подстановка 8 для ‘a’ в
     ‘divisors(a)’ дает делители без перевычисления ‘divisors(8)’.

          (%i1) divisors (a);
          (%o1)                      divisors(a)
          (%i2) subst (8, a, %);
          (%o2)                     {1, 2, 4, 8}

     Функция ‘divisors’ дистрибутивна по отношению к уравнениям,
     спискам, матрицам и множествам.

          (%i1) divisors (a = b);
          (%o1)               divisors(a) = divisors(b)
          (%i2) divisors ([a, b, c]);
          (%o2)        [divisors(a), divisors(b), divisors(c)]
          (%i3) divisors (matrix ([a, b], [c, d]));
                            [ divisors(a)  divisors(b) ]
          (%o3)             [                          ]
                            [ divisors(c)  divisors(d) ]
          (%i4) divisors ({a, b, c});
          (%o4)        {divisors(a), divisors(b), divisors(c)}

 -- Функция: elementp (<x>, <a>)
     Возвращает ‘true’ тогда и только тогда, когда <x> является
     элементом множества <a>.

     Функция ‘elementp’ вызывает ошибку, если <a> не является
     множеством.

     Примеры:

          (%i1) elementp (sin(1), {sin(1), sin(2), sin(3)});
          (%o1)                         true
          (%i2) elementp (sin(1), {cos(1), cos(2), cos(3)});
          (%o2)                         false

 -- Функция: emptyp (<a>)
     Возвращает ‘true’ тогда и только тогда, когда <a> есть пустое
     множество или список.

     Примеры:

          (%i1) map (emptyp, [{}, []]);
          (%o1)                     [true, true]
          (%i2) map (emptyp, [a + b, {{}}, %pi]);
          (%o2)                 [false, false, false]

 -- Функция: equiv_classes (<s>, <F>)
     Возвращает множество классов эквивалентности множества <s> по
     отношению эквивалентности <F>.

     <F> – есть функция двух переменных, определенная на Декартовом
     произведении <s> на <s>.  Возвращаемое <F> значение есть ‘true’ или
     ‘false’, либо выражение <expr> такое, что ‘is(<expr>)’ дает ‘true’
     или ‘false’.

     Если <F> не является отношением эквивалентности, то ‘equiv_classes’
     применит его без возражения, но результат будет скорее всего
     неправильным.

     Примеры:

     Отношение эквивалентности является лямбда-выражением, возвращающим
     ‘true’ или ‘false’.

          (%i1) equiv_classes ({1, 1.0, 2, 2.0, 3, 3.0},
                                  lambda ([x, y], is (equal (x, y))));
          (%o1)            {{1, 1.0}, {2, 2.0}, {3, 3.0}}

     Отношение эквивалентности есть имя реляционной функции ‘is’, дающей
     ‘true’ или ‘false’.

          (%i1) equiv_classes ({1, 1.0, 2, 2.0, 3, 3.0}, equal);
          (%o1)            {{1, 1.0}, {2, 2.0}, {3, 3.0}}

     Классы эквивалентности – числа отличающиеся на несколько чисел 3.

          (%i1) equiv_classes ({1, 2, 3, 4, 5, 6, 7},
                               lambda ([x, y], remainder (x - y, 3) = 0));
          (%o1)              {{1, 4, 7}, {2, 5}, {3, 6}}

 -- Функция: every (<f>, <s>)
 -- Функция: every (<f>, <L_1>, ..., <L_n>)

     Возвращает ‘true’, если предикат <f> дает ‘true’ для всех
     аргументов.

     Если второй аргумент является множеством, то ‘every(<f>, <s>)’
     возвращает ‘true’, если ‘is(<f>(<a_i>))’ возвращает ‘true’ для всех
     <a_i> в <s>.  ‘every’ может вычислять <f> для всех <a_i> в <s>, а
     может и не для всех.  Т.к.  множества не упорядочены, то ‘every’
     может вычислять ‘<f>(<a_i>)’ в произвольном порядке.

     Примененная к одному или нескольким спискам, ‘every(<f>, <L_1>,
     ..., <L_n>)’ возвращает ‘true’, если ‘is(<f>(<x_1>, ..., <x_n>))’
     возвращает ‘true’ для всех <x_1>, ..., <x_n> в <L_1>, ..., <L_n>
     соответственно.  ‘every’ может вычислять <f> для всех комбинаций
     <x_1>, ..., <x_n>, а может и не для всех.  ‘every’ вычисляет списки
     в порядке возрастания индекса.

     Для пустого множества ‘{}’ и пустого списка ‘[]’ ‘every’ возвращает
     ‘false’.

     Если глобальный флаг ‘maperror’ равен ‘true’, то все списки <L_1>,
     ..., <L_n> должны иметь одинаковую длину.  Если ‘maperror’ равен
     ‘false’, то списки обрезаются до длины самого короткого.

     Значение предиката <f>, который вычисляется посредством ‘is’ в
     значение, отличное от ‘true’ или ‘false’, управляется глобальным
     флагом ‘prederror’.  Если ‘prederror’ равен ‘true’, то данные
     значения рассматриваются как ‘false’, и возвращаемое ‘every’
     значение есть ‘false’.  Если ‘prederror’ равен ‘false’, то такие
     значения рассматриваются как ‘unknown’, и возвращаемое ‘every’
     значение равно ‘unknown’.

     Примеры:

     ‘every’, примененная к одному списку.  Предикат является функцией
     одного аргумента.

          (%i1) every (integerp, {1, 2, 3, 4, 5, 6});
          (%o1)                         true
          (%i2) every (atom, {1, 2, sin(3), 4, 5 + y, 6});
          (%o2)                         false

     ‘every’, примененная к двум спискам.  Предикат – функция двух
     аргументов.

          (%i1) every ("=", [a, b, c], [a, b, c]);
          (%o1)                         true
          (%i2) every ("#", [a, b, c], [a, b, c]);
          (%o2)                         false

     Значение предиката <f>, вычисляемого в значение, отличное от ‘true’
     или ‘false’, управляется глобальным флагом ‘prederror’.

          (%i1) prederror : false;
          (%o1)                         false
          (%i2) map (lambda ([a, b], is (a < b)), [x, y, z],
                             [x^2, y^2, z^2]);
          (%o2)              [unknown, unknown, unknown]
          (%i3) every ("<", [x, y, z], [x^2, y^2, z^2]);
          (%o3)                        unknown
          (%i4) prederror : true;
          (%o4)                         true
          (%i5) every ("<", [x, y, z], [x^2, y^2, z^2]);
          (%o5)                         false

 -- Функция: extremal_subset (<s>, <f>, max)
 -- Функция: extremal_subset (<s>, <f>, min)

     Возвращает подмножество <s>, на котором функция <f> принимает
     минимальное или максимальное значение.

     ‘extremal_subset(<s>, <f>, max)’ возвращает подмножество множества
     или списка <s>, для которого вещественнозначная функция <f>
     принимает максимальное значение.

     ‘extremal_subset(<s>, <f>, min)’ возвращает подмножество множества
     или списка <s>, для которого вещественнозначная функция <f>
     принимает минимальное значение.

     Примеры:

          (%i1) extremal_subset ({-2, -1, 0, 1, 2}, abs, max);
          (%o1)                       {- 2, 2}
          (%i2) extremal_subset ({sqrt(2), 1.57, %pi/2}, sin, min);
          (%o2)                       {sqrt(2)}

 -- Функция: flatten (<expr>)

     Собирает аргументы подвыражений, имеющих оператор верхнего уровня
     такой же как у <expr>, и строит выражение из этих собранных
     аргументов.

     Аргументы, имеющие оператор верхнего уровня отличный от главного
     оператора ‘expr’, копируются без модификации даже если они, в свою
     очередь, имеют некоторые подвыражения с главным оператором ‘expr’.

     Возможно, что ‘flatten’ построит выражение с числом аргументов
     недопустимым для данного типа оператора, что может привести к
     ошибке упрощателя или вычислителя.  Функция ‘flatten’ не пытается
     определить подобные ситуации.

     Выражения, имеющие специальные представления, например,
     канонические рациональные выражения (КРВ), не обрабатываются
     ‘flatten’.  В этом случае ‘flatten’ возвращает аргумент без
     изменения.

     Примеры:

     Примененная к списку, ‘flatten’ собирает все элементы, являющиеся
     списками.

          (%i1) flatten ([a, b, [c, [d, e], f], [[g, h]], i, j]);
          (%o1)            [a, b, c, d, e, f, g, h, i, j]

     Примененная к множеству, ‘flatten’ собирает все элементы,
     являющиеся множествами.

          (%i1) flatten ({a, {b}, {{c}}});
          (%o1)                       {a, b, c}
          (%i2) flatten ({a, {[a], {a}}});
          (%o2)                       {a, [a]}

     Функция ‘flatten’ похожа на объявление оператора n-арным.  Однако
     ‘flatten’ не влияет на подвыражения, имеющие оператор, отличный от
     главного оператора выражения, тогда как декларация оператора
     n-арным действует на них.

          (%i1) expr: flatten (f (g (f (f (x)))));
          (%o1)                     f(g(f(f(x))))
          (%i2) declare (f, nary);
          (%o2)                         done
          (%i3) ev (expr);
          (%o3)                      f(g(f(x)))

     ‘flatten’ трактует функции с индексом также как любые другие
     операторы.

          (%i1) flatten (f[5] (f[5] (x, y), z));
          (%o1)                      f (x, y, z)
                                      5

     Функция ‘flatten’ может составить выражение, в котором число
     аргументов отличается от объявленного числа аргументов оператора.

          (%i1) 'mod (5, 'mod (7, 4));
          (%o1)                   mod(5, mod(7, 4))
          (%i2) flatten (%);
          (%o2)                     mod(5, 7, 4)
          (%i3) ''%, nouns;
          Wrong number of arguments to mod
           -- an error.  Quitting.  To debug this try debugmode(true);

 -- Функция: full_listify (<a>)
     Заменяет в <a> все множества на списки и возвращает результат.
     ‘full_listify’ заменяет операторы множества на операторы списка во
     вложенных подвыражениях, даже если главный оператор не есть ‘set’.

     Функция ‘listify’ заменяет только главный оператор.

     Примеры:

          (%i1) full_listify ({a, b, {c, {d, e, f}, g}});
          (%o1)               [a, b, [c, [d, e, f], g]]
          (%i2) full_listify (F (G ({a, b, H({c, d, e})})));
          (%o2)              F(G([a, b, H([c, d, e])]))

 -- Функция: fullsetify (<a>)
     Если <a> является списком, то ‘fullsetify’ заменяет оператор списка
     на оператор множества и применяет ‘fullsetify’ ко всем членам этого
     множества.  Если аргумент <a> не является списком, то он
     возвращается неизменным.

     Функция ‘setify’ заменяет только главный оператор.

     Примеры:

     В строке ‘(%o2)’ аргумент ‘f’ не преобразован в множество, т.к.
     главный оператор не является списком ‘f([b])’.

          (%i1) fullsetify ([a, [a]]);
          (%o1)                       {a, {a}}
          (%i2) fullsetify ([a, f([b])]);
          (%o2)                      {a, f([b])}

 -- Функция: identity (<x>)

     Возвращает <x> для любого аргумента <x>.

     Примеры:

     Функция ‘identity’ может использоваться как предикат, если
     параметры уже являются логическими значениями.

          (%i1) every (identity, [true, true]);
          (%o1)                         true

 -- Функция: integer_partitions (<n>)
 -- Функция: integer_partitions (<n>, <len>)

     Возвращает целочисленные разбиения <n>, т.е.  списки целых чисел,
     сумма которых равна <n>.

     Функция ‘integer_partitions(<n>)’ возвращает множество всех
     разбиений <n>.  Каждое разбиение есть список, отсортированный от
     большего значения к меньшему.

     Вызов ‘integer_partitions(<n>, <len>)’ возвращает все разбиения
     длины <len> или менее.  В этом случае к разбиениям, имеющим число
     членов меньшее, чем <len>, добавляются нули, чтобы сделать все
     возвращаемые разбиения одинаковой длины <len>.

     Список [a_1, ..., a_m] есть разбиение неотрицательного целого числа
     n, если (1) каждое a_i есть ненулевое положительное число и (2) a_1
     + ... + a_m = n.  Таким образом, 0 не имеет разбиений.

     Примеры:

          (%i1) integer_partitions (3);
          (%o1)               {[1, 1, 1], [2, 1], [3]}
          (%i2) s: integer_partitions (25)$
          (%i3) cardinality (s);
          (%o3)                         1958
          (%i4) map (lambda ([x], apply ("+", x)), s);
          (%o4)                         {25}
          (%i5) integer_partitions (5, 3);
          (%o5) {[2, 2, 1], [3, 1, 1], [3, 2, 0], [4, 1, 0], [5, 0, 0]}
          (%i6) integer_partitions (5, 2);
          (%o6)               {[3, 2], [4, 1], [5, 0]}

     Для того, чтобы найти все разбиения, удовлетворяющие определенному
     условию, можно использовать функцию ‘subset’.  В следующем примере
     находятся все разбиения 10, состоящие из простых чисел.

          (%i1) s: integer_partitions (10)$
          (%i2) cardinality (s);
          (%o2)                          42
          (%i3) xprimep(x) := integerp(x) and (x > 1) and primep(x)$
          (%i4) subset (s, lambda ([x], every (xprimep, x)));
          (%o4) {[2, 2, 2, 2, 2], [3, 3, 2, 2], [5, 3, 2], [5, 5], [7, 3]}

 -- Функция: intersect (<a_1>, ..., <a_n>)

     Функция ‘intersect’ идентична ‘intersection’.

 -- Функция: intersection (<a_1>, ..., <a_n>)
     Возвращает множество, содержащие элементы, общие для всех множеств
     <a_1>, ..., <a_n>.

     Функция ‘intersection’ вызывает ошибку, если хотя бы один из
     аргументов не является множеством.

     Примеры:

          (%i1) S_1 : {a, b, c, d};
          (%o1)                     {a, b, c, d}
          (%i2) S_2 : {d, e, f, g};
          (%o2)                     {d, e, f, g}
          (%i3) S_3 : {c, d, e, f};
          (%o3)                     {c, d, e, f}
          (%i4) S_4 : {u, v, w};
          (%o4)                       {u, v, w}
          (%i5) intersection (S_1, S_2);
          (%o5)                          {d}
          (%i6) intersection (S_2, S_3);
          (%o6)                       {d, e, f}
          (%i7) intersection (S_1, S_2, S_3);
          (%o7)                          {d}
          (%i8) intersection (S_1, S_2, S_3, S_4);
          (%o8)                          {}

 -- Функция: kron_delta (<x>, <y>)

     Дельта-функция Кронекера.

     ‘kron_delta’ упрощается в 1, если <x> и <y> идентичны или очевидно
     эквивалентны, и упрощается в 0, если <x> и <y> очевидно не
     эквивалентны.  Иначе, если эквивалентность или неэквивалентность
     <x> и <y> не ясна, то ‘kron_delta’ упрощается в невычисляемую форму
     (noun).  По отношению к числам с плавающей точкой ‘kron_delta’
     реализует осторожный подход.  Если разница ‘<x> - <y>’ является
     числом с плавающей точкой, то ‘kron_delta’ упрощается в
     невычисляемую форму, даже когда <x> по-видимому эквивалентно <y>.

     Функция ‘kron_delta(<x>, <y>)’ упрощается в 1, если ‘is(x = y)’
     равно ‘true’.  ‘kron_delta’ тоже упрощается в 1, если ‘sign(abs(<x>
     - <y>))’ есть ‘zero’ и ‘<x> - <y>’ не является числом с плавающей
     точкой (ни обычное число с плавающей точкой, ни число с плавающей
     точкой повышенной точности).  ‘kron_delta’ упрощается в 0, если
     ‘sign(abs(<x> - <y>))’ равно ‘pos’.

     Если же ‘sign(abs(<x> - <y>))’ дает что-то отличное от ‘pos’ или
     ‘zero’, или ‘zero’ но ‘<x> - <y>’ есть число с плавающей точкой, то
     ‘kron_delta’ возвращает невычисляемое выражение.

     Функция ‘kron_delta’ объявлена симметричной.  Т.е.
     ‘kron_delta(<x>, <y>)’ равно ‘kron_delta(<y>, <x>)’.

     Примеры:

     Аргументы ‘kron_delta’ идентичны.  ‘kron_delta’ упрощается в 1.

          (%i1) kron_delta (a, a);
          (%o1)                           1
          (%i2) kron_delta (x^2 - y^2, x^2 - y^2);
          (%o2)                           1
          (%i3) float (kron_delta (1/10, 0.1));
          (%o3)                           1

     Аргументы ‘kron_delta’ эквивалентны, и их разница не есть число с
     плавающей точкой.  ‘kron_delta’ упрощается в 1.

          (%i1) assume (equal (x, y));
          (%o1)                     [equal(x, y)]
          (%i2) kron_delta (x, y);
          (%o2)                           1

     Аргументы ‘kron_delta’ не эквивалентны.  ‘kron_delta’ упрощается в
     0.

          (%i1) kron_delta (a + 1, a);
          (%o1)                           0
          (%i2) assume (a > b)$
          (%i3) kron_delta (a, b);
          (%o3)                           0
          (%i4) kron_delta (1/5, 0.7);
          (%o4)                           0

     Аргументы ‘kron_delta’ могут быть, а могут и не быть эквивалентны.
     ‘kron_delta’ упрощается в невычисляемое выражение.

          (%i1) kron_delta (a, b);
          (%o1)                   kron_delta(a, b)
          (%i2) assume(x >= y)$
          (%i3) kron_delta (x, y);
          (%o3)                   kron_delta(x, y)

     Аргументы ‘kron_delta’ эквивалентны, но их разница является числом
     с плавающей точкой.  ‘kron_delta’ упрощается в невычисляемое
     выражение.

          (%i1) 1/4 - 0.25;
          (%o1)                          0.0
          (%i2) 1/10 - 0.1;
          (%o2)                          0.0
          (%i3) 0.25 - 0.25b0;
          Warning:  Float to bigfloat conversion of 0.25
          (%o3)                         0.0b0
          (%i4) kron_delta (1/4, 0.25);
                                            1
          (%o4)                  kron_delta(-, 0.25)
                                            4
          (%i5) kron_delta (1/10, 0.1);
                                            1
          (%o5)                  kron_delta(--, 0.1)
                                            10
          (%i6) kron_delta (0.25, 0.25b0);
          Warning:  Float to bigfloat conversion of 0.25
          (%o6)               kron_delta(0.25, 2.5b-1)

     Функция ‘kron_delta’ симметрична.

          (%i1) kron_delta (x, y);
          (%o1)                   kron_delta(x, y)
          (%i2) kron_delta (y, x);
          (%o2)                   kron_delta(x, y)
          (%i3) kron_delta (x, y) - kron_delta (y, x);
          (%o3)                           0
          (%i4) is (equal (kron_delta (x, y), kron_delta (y, x)));
          (%o4)                         true
          (%i5) is (kron_delta (x, y) = kron_delta (y, x));
          (%o5)                         true

 -- Функция: listify (<a>)

     Возвращает список с элементами <a>, если <a> есть множество.  В
     противном случае ‘listify’ возвращает <a>.

     Функция ‘full_listify’ заменяет все операторы множества в <a> на
     операторы списка.

     Примеры:

          (%i1) listify ({a, b, c, d});
          (%o1)                     [a, b, c, d]
          (%i2) listify (F ({a, b, c, d}));
          (%o2)                    F({a, b, c, d})

 -- Функция: lreduce (<F>, <s>)
 -- Функция: lreduce (<F>, <s>, <s_0>)

     Расширяет бинарную функцию <F> до n-арной методом композиции.
     Аргумент <s> является списком.

     ‘lreduce(<F>, <s>)’ возвращает ‘F(... F(F(s_1, s_2), s_3), ...
     s_n)’.  Если присутствует необязательный аргумент <s_0>, то
     результат эквивалентен ‘lreduce(<F>, cons(<s_0>, <s>))’.

     Функция <F> сначала применяется к левой паре элементов списка,
     откуда происходит название "lreduce" (left reduce).

     См.  также ‘rreduce’, ‘xreduce’ и ‘tree_reduce’.

     Примеры:

     ‘lreduce’ без необязательного аргумента.

          (%i1) lreduce (f, [1, 2, 3]);
          (%o1)                     f(f(1, 2), 3)
          (%i2) lreduce (f, [1, 2, 3, 4]);
          (%o2)                  f(f(f(1, 2), 3), 4)

     ‘lreduce’ с необязательным аргументом.

          (%i1) lreduce (f, [1, 2, 3], 4);
          (%o1)                  f(f(f(4, 1), 2), 3)

     ‘lreduce’ примененная к встроенным бинарным операторам.  ‘/’ – есть
     оператор деления.

          (%i1) lreduce ("^", args ({a, b, c, d}));
                                         b c d
          (%o1)                       ((a ) )
          (%i2) lreduce ("/", args ({a, b, c, d}));
                                          a
          (%o2)                         -----
                                        b c d

 -- Функция: makeset (<expr>, <x>, <s>)

     Возвращает множество с элементами, сгенерированными из выражения
     <expr>, где <x> есть список переменных <expr>, а <s> есть множество
     или список списков.  Для определения элемента результирующего
     списка выражение <expr> вычисляется при переменных <x>, равным
     значениям из <s> (параллельное присваивание).

     Каждый член <s> должен иметь ту же длину, что и <x>.  Список
     переменных <x> должен быть списком символов без индексов.  Даже
     если символ только один, то <x> должен быть одноэлементным списком,
     а каждый член <s> должен быть одноэлементным списком.

     См.  также ‘makelist’.

     Примеры:

          (%i1) makeset (i/j, [i, j], [[1, a], [2, b], [3, c], [4, d]]);
                                     1  2  3  4
          (%o1)                     {-, -, -, -}
                                     a  b  c  d
          (%i2) S : {x, y, z}$
          (%i3) S3 : cartesian_product (S, S, S);
          (%o3) {[x, x, x], [x, x, y], [x, x, z], [x, y, x], [x, y, y],
          [x, y, z], [x, z, x], [x, z, y], [x, z, z], [y, x, x],
          [y, x, y], [y, x, z], [y, y, x], [y, y, y], [y, y, z],
          [y, z, x], [y, z, y], [y, z, z], [z, x, x], [z, x, y],
          [z, x, z], [z, y, x], [z, y, y], [z, y, z], [z, z, x],
          [z, z, y], [z, z, z]}
          (%i4) makeset (i + j + k, [i, j, k], S3);
          (%o4) {3 x, 3 y, y + 2 x, 2 y + x, 3 z, z + 2 x, z + y + x,
                                                 z + 2 y, 2 z + x, 2 z + y}
          (%i5) makeset (sin(x), [x], {[1], [2], [3]});
          (%o5)               {sin(1), sin(2), sin(3)}

 -- Функция: moebius (<n>)

     Представляет функцию Мебиуса.

     Если <n> есть произведение k различных простых чисел, то
     ‘moebius(<n>)’ упрощается до (-1)^k.  Если <n> = 1, то функция
     упрощается в 1.  Для всех остальных положительных целых функция
     упрощается в 0.

     Функция ‘moebius’ дистрибутивна по отношению к уравнениям, спискам,
     матрицам и множествам.

     Примеры:

          (%i1) moebius (1);
          (%o1)                           1
          (%i2) moebius (2 * 3 * 5);
          (%o2)                          - 1
          (%i3) moebius (11 * 17 * 29 * 31);
          (%o3)                           1
          (%i4) moebius (2^32);
          (%o4)                           0
          (%i5) moebius (n);
          (%o5)                      moebius(n)
          (%i6) moebius (n = 12);
          (%o6)                    moebius(n) = 0
          (%i7) moebius ([11, 11 * 13, 11 * 13 * 15]);
          (%o7)                      [- 1, 1, 1]
          (%i8) moebius (matrix ([11, 12], [13, 14]));
                                     [ - 1  0 ]
          (%o8)                      [        ]
                                     [ - 1  1 ]
          (%i9) moebius ({21, 22, 23, 24});
          (%o9)                      {- 1, 0, 1}

 -- Функция: multinomial_coeff (<a_1>, ..., <a_n>)
 -- Функция: multinomial_coeff ()

     Возвращает мультиномиальный коэффициент.

     Если каждое <a_k> есть неотрицательное целое число, то
     мультиномиальный коэффициент дает число способов положить ‘<a_1> +
     ... + <a_n>’ различных объектов в n ящиков с <a_k> элементами в
     k-ом ящике.  В целом, ‘multinomial_coeff (<a_1>, ..., <a_n>)’ равна
     ‘(<a_1> + ... + <a_n>)!/(<a_1>! ... <a_n>!)’.

     ‘multinomial_coeff()’ (без аргументов) дает 1.

     ‘minfactorial’ может упрощать значения, возвращаемые
     ‘multinomial_coeff’.

     Примеры:

          (%i1) multinomial_coeff (1, 2, x);
                                      (x + 3)!
          (%o1)                       --------
                                        2 x!
          (%i2) minfactorial (%);
                               (x + 1) (x + 2) (x + 3)
          (%o2)                -----------------------
                                          2
          (%i3) multinomial_coeff (-6, 2);
                                       (- 4)!
          (%o3)                       --------
                                      2 (- 6)!
          (%i4) minfactorial (%);
          (%o4)                          10

 -- Функция: num_distinct_partitions (<n>)
 -- Функция: num_distinct_partitions (<n>, list)

     Возвращает число целочисленных разбиений с различными частями для
     <n>, если <n> – неотрицательное целое.  Иначе
     ‘num_distinct_partitions’ возвращает невычисляемую форму.

     ‘num_distinct_partitions(<n>, list)’ возвращает список чисел
     целочисленных разбиений с различными частями для 1, 2, 3, ..., <n>
     .

     Разбиение числа <n> с различными частями есть список различных
     положительных целых k_1, ..., k_m, таких что <n> = k_1 + ... + k_m.

     Примеры:

          (%i1) num_distinct_partitions (12);
          (%o1)                          15
          (%i2) num_distinct_partitions (12, list);
          (%o2)      [1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 15]
          (%i3) num_distinct_partitions (n);
          (%o3)              num_distinct_partitions(n)

 -- Функция: num_partitions (<n>)
 -- Функция: num_partitions (<n>, list)

     Возвращает число целочисленных разбиений числа <n>, если <n> –
     неотрицательное целое.  Иначе ‘num_partitions’ возвращает
     невычисляемую форму.

     ‘num_partitions(<n>, list)’ возвращает список чисел целочисленных
     разбиений для 1, 2, 3, ..., <n>.

     Для неотрицательного целого <n>, ‘num_partitions(<n>)’ равна
     ‘cardinality(integer_partitions(<n>))’.  На самом деле
     ‘num_partitions’ не строит полное множество разбиений и поэтому
     работает значительно быстрее.

     Примеры:

          (%i1) num_partitions (5) = cardinality (integer_partitions (5));
          (%o1)                         7 = 7
          (%i2) num_partitions (8, list);
          (%o2)            [1, 1, 2, 3, 5, 7, 11, 15, 22]
          (%i3) num_partitions (n);
          (%o3)                   num_partitions(n)

 -- Функция: partition_set (<a>, <f>)

     Разбивает множество <a> в соответствии с предикатом <f>.

     Функция ‘partition_set’ возвращает список двух множеств.  Первое
     множество состоит из элементов <a>, для которых <f> равен ‘false’,
     а второе включает все остальные элементы <a>.  Функция
     ‘partition_set’ не применяет ‘is’ к возвращаемым <f> значениям.

     ‘partition_set’ вызывает ошибку, если <a> не является множеством.

     См.  также ‘subset’.

     Примеры:

          (%i1) partition_set ({2, 7, 1, 8, 2, 8}, evenp);
          (%o1)                   [{1, 7}, {2, 8}]
          (%i2) partition_set ({x, rat(y), rat(y) + z, 1},
                               lambda ([x], ratp(x)));
          (%o2)/R/              [{1, x}, {y, y + z}]

 -- Функция: permutations (<a>)

     Возвращает множество различных перестановок членов списка или
     множества <a>.  Каждая перестановка является списком.

     Если <a> является списком, то повторные члены <a> включаются в
     перестановки.

     ‘permutations’ вызывает ошибку, если <a> не является списком или
     множеством.

     См.  также ‘random_permutation’.

     Примеры:

          (%i1) permutations ([a, a]);
          (%o1)                       {[a, a]}
          (%i2) permutations ([a, a, b]);
          (%o2)           {[a, a, b], [a, b, a], [b, a, a]}

 -- Функция: powerset (<a>)
 -- Функция: powerset (<a>, <n>)

     Возвращает множество всех подмножеств <a> или подмножество этого
     множества подмножеств.

     ‘powerset(<a>)’ возвращает множество всех подмножеств множества
     <a>.  ‘powerset(<a>)’ имеет ‘2^cardinality(<a>)’ членов.

     ‘powerset(<a>, <n>)’ возвращает множество подмножеств <a>, которые
     имеют мощность <n>.

     ‘powerset’ вызывает ошибку, если <a> не является множеством или <n>
     не есть целое число.

     Примеры:

          (%i1) powerset ({a, b, c});
          (%o1) {{}, {a}, {a, b}, {a, b, c}, {a, c}, {b}, {b, c}, {c}}
          (%i2) powerset ({w, x, y, z}, 4);
          (%o2)                    {{w, x, y, z}}
          (%i3) powerset ({w, x, y, z}, 3);
          (%o3)     {{w, x, y}, {w, x, z}, {w, y, z}, {x, y, z}}
          (%i4) powerset ({w, x, y, z}, 2);
          (%o4)   {{w, x}, {w, y}, {w, z}, {x, y}, {x, z}, {y, z}}
          (%i5) powerset ({w, x, y, z}, 1);
          (%o5)                 {{w}, {x}, {y}, {z}}
          (%i6) powerset ({w, x, y, z}, 0);
          (%o6)                         {{}}

 -- Функция: random_permutation (<a>)

     Возвращает случайную перестановку множества или списка <a>,
     построенную при помощи алгоритма тасования Кнута.

     Возвращаемое значение есть новый список, который отличен от
     исходного аргумента даже если все элементы совпадают.  Однако
     элементы списка не копируются.

     Примеры:

          (%i1) random_permutation ([a, b, c, 1, 2, 3]);
          (%o1)                  [c, 1, 2, 3, a, b]
          (%i2) random_permutation ([a, b, c, 1, 2, 3]);
          (%o2)                  [b, 3, 1, c, a, 2]
          (%i3) random_permutation ({x + 1, y + 2, z + 3});
          (%o3)                 [y + 2, z + 3, x + 1]
          (%i4) random_permutation ({x + 1, y + 2, z + 3});
          (%o4)                 [x + 1, y + 2, z + 3]

 -- Функция: rreduce (<F>, <s>)
 -- Функция: rreduce (<F>, <s>, <s_{n + 1}>)

     Расширяет бинарную функцию <F> до n-арной методом композиции.
     Аргумент <s> является списком.

     ‘rreduce(<F>, <s>)’ возвращает ‘F(s_1, ... F(s_{n - 2}, F(s_{n -
     1}, s_n)))’.  Если присутствует необязательный аргумент <s_{n +
     1}>, то результат эквивалентен ‘rreduce(<F>, endcons(<s_{n + 1}>,
     <s>))’.

     Функция <F> сначала применяется к правой паре элементов списка,
     откуда происходит название "rreduce" (right reduce).

     См.  также ‘lreduce’, ‘tree_reduce’ и ‘xreduce’.

     Примеры:

     ‘rreduce’ без необязательного аргумента.

          (%i1) rreduce (f, [1, 2, 3]);
          (%o1)                     f(1, f(2, 3))
          (%i2) rreduce (f, [1, 2, 3, 4]);
          (%o2)                  f(1, f(2, f(3, 4)))

     ‘rreduce’ с необязательным аргументом.

          (%i1) rreduce (f, [1, 2, 3], 4);
          (%o1)                  f(1, f(2, f(3, 4)))

     ‘rreduce’ примененный к встроенным операторам.  ‘/’ – есть оператор
     деления.

          (%i1) rreduce ("^", args ({a, b, c, d}));
                                           d
                                          c
                                         b
          (%o1)                         a
          (%i2) rreduce ("/", args ({a, b, c, d}));
                                         a c
          (%o2)                          ---
                                         b d

 -- Функция: setdifference (<a>, <b>)

     Возвращает множество, содержащее элементы множества <a>, которые
     отсутствуют в множестве <b>.

     ‘setdifference’ вызывает ошибку, если <a> или <b> не являются
     множествами.

     Примеры:

          (%i1) S_1 : {a, b, c, x, y, z};
          (%o1)                  {a, b, c, x, y, z}
          (%i2) S_2 : {aa, bb, c, x, y, zz};
          (%o2)                 {aa, bb, c, x, y, zz}
          (%i3) setdifference (S_1, S_2);
          (%o3)                       {a, b, z}
          (%i4) setdifference (S_2, S_1);
          (%o4)                     {aa, bb, zz}
          (%i5) setdifference (S_1, S_1);
          (%o5)                          {}
          (%i6) setdifference (S_1, {});
          (%o6)                  {a, b, c, x, y, z}
          (%i7) setdifference ({}, S_1);
          (%o7)                          {}

 -- Функция: setequalp (<a>, <b>)

     Возвращает ‘true’ если <a> и <b> имеют одинаковое количество
     элементов, и ‘is(<x> = <y>)’ равно ‘true’ для ‘x’ из <a> и ‘y’ из
     <b>, в порядке, определяемом ‘listify’.  Иначе ‘setequalp’
     возвращает ‘false’.

     Примеры:

          (%i1) setequalp ({1, 2, 3}, {1, 2, 3});
          (%o1)                         true
          (%i2) setequalp ({a, b, c}, {1, 2, 3});
          (%o2)                         false
          (%i3) setequalp ({x^2 - y^2}, {(x + y) * (x - y)});
          (%o3)                         false

 -- Функция: setify (<a>)

     Составляет множество из элементов списка <a>.  Повторяющиеся
     элементы списка <a> удаляются, а элементы результирующего множества
     сортируются в соответствии с предикатом ‘orderlessp’.

     ‘setify’ вызывает ошибку, если <a> не является списком.

     Примеры:

          (%i1) setify ([1, 2, 3, a, b, c]);
          (%o1)                  {1, 2, 3, a, b, c}
          (%i2) setify ([a, b, c, a, b, c]);
          (%o2)                       {a, b, c}
          (%i3) setify ([7, 13, 11, 1, 3, 9, 5]);
          (%o3)                {1, 3, 5, 7, 9, 11, 13}

 -- Функция: setp (<a>)

     Возвращает ‘true’ тогда и только тогда, когда <a> является Maxima
     множеством.

     ‘setp’ возвращает ‘true’ как для неупрощенных множеств (т.е.
     содержащих излишние элементы), так и для упрощенных множеств.

     ‘setp’ is equivalent to the Maxima function ‘setp(a) := not atom(a)
     and op(a) = 'set’.

     Примеры:

          (%i1) simp : false;
          (%o1)                         false
          (%i2) {a, a, a};
          (%o2)                       {a, a, a}
          (%i3) setp (%);
          (%o3)                         true

 -- Функция: set_partitions (<a>)
 -- Функция: set_partitions (<a>, <n>)

     Возвращает множество разбиений <a> или подмножество этого
     множества.

     ‘set_partitions(<a>, <n>)’ возвращает множество всех разбиений <a>
     в <n> непустых непересекающихся подмножеств.

     ‘set_partitions(<a>)’ возвращает множество всех разбиений.

     ‘stirling2’ возвращает мощность множества всех разбиений множества.

     Множество множеств P есть разбиение множества S, если

       1. каждый элемент P есть непустое множество,
       2. различные члены P не пересекаются,
       3. объединение всех членов P равно S.

     Примеры:

     Пустое множество есть разбиение самого себя, т.к.  условия 1 и 2
     очевидно выполняются.

          (%i1) set_partitions ({});
          (%o1)                         {{}}

     Мощность множества разбиений может быть определена при помощи
     ‘stirling2’.

          (%i1) s: {0, 1, 2, 3, 4, 5}$
          (%i2) p: set_partitions (s, 3)$
          (%i3) cardinality(p) = stirling2 (6, 3);
          (%o3)                        90 = 90

     Каждый элемент ‘p’ должен иметь <n> = 3 члена.  Проверим:

          (%i1) s: {0, 1, 2, 3, 4, 5}$
          (%i2) p: set_partitions (s, 3)$
          (%i3) map (cardinality, p);
          (%o3)                          {3}

     Наконец, для каждого члена ‘p’ объединение всех членов должно
     совпадать с ‘s’.  Проверим:

          (%i1) s: {0, 1, 2, 3, 4, 5}$
          (%i2) p: set_partitions (s, 3)$
          (%i3) map (lambda ([x], apply (union, listify (x))), p);
          (%o3)                 {{0, 1, 2, 3, 4, 5}}

 -- Функция: some (<f>, <a>)
 -- Функция: some (<f>, <L_1>, ..., <L_n>)

     Возвращает ‘true’, если предикат <f> дает ‘true’ для одного или
     более аргументов.

     Если второй параметр является множеством, то ‘some(<f>, <s>)’
     возвращает ‘true’, если ‘is(<f>(<a_i>))’ дает ‘true’ для одного или
     более <a_i> из <s>.  ‘some’ может вычислять <f> для всех или не для
     всех <a_i> из <s>.  Т.к.  множества не упорядочены, то ‘some’ может
     вычислять ‘<f>(<a_i>)’ в любом порядке.

     Если аргументы являются одним или несколькими списками, то
     ‘some(<f>, <L_1>, ..., <L_n>)’ возвращает ‘true’, если
     ‘is(<f>(<x_1>, ..., <x_n>))’ дает ‘true’ для одного или более
     <x_1>, ..., <x_n> из <L_1>, ..., <L_n> соответственно.  ‘some’
     может вычислять, а может и не вычислять <f> для некоторых
     комбинаций <x_1>, ..., <x_n>.  ‘some’ вычисляет списки в порядке
     возрастания индекса.

     Для пустого множества ‘{}’ или списка ‘[]’ ‘some’ возвращает
     ‘false’.

     Если глобальный флаг ‘maperror’ равен ‘true’, то все списки <L_1>,
     ..., <L_n> должны иметь одинаковую длину.  Если ‘maperror’ равен
     ‘false’, то списки обрезаются до длины самого короткого.

     Значения предиката <f> (вычисляемое посредством ‘is’) отличное от
     ‘true’ или ‘false’ управляется глобальным флагом ‘prederror’.  Если
     ‘prederror’ равен ‘true’, то такие значения трактуются как ‘false’.
     Если ‘prederror’ равен ‘false’, то такие значения трактуются как
     ‘unknown’.

     Примеры:

     Функция ‘some’, примененная к одному множеству.  Предикат есть
     функция одного аргумента.

          (%i1) some (integerp, {1, 2, 3, 4, 5, 6});
          (%o1)                         true
          (%i2) some (atom, {1, 2, sin(3), 4, 5 + y, 6});
          (%o2)                         true

     Функция ‘some’, примененная к спискам.  Предикат есть функция двух
     аргументов.

          (%i1) some ("=", [a, b, c], [a, b, c]);
          (%o1)                         true
          (%i2) some ("#", [a, b, c], [a, b, c]);
          (%o2)                         false

     Значение предиката <f>, отличное от ‘true’ или ‘false’, управляется
     глобальным флагом ‘prederror’.

          (%i1) prederror : false;
          (%o1)                         false
          (%i2) map (lambda ([a, b], is (a < b)), [x, y, z],
                     [x^2, y^2, z^2]);
          (%o2)              [unknown, unknown, unknown]
          (%i3) some ("<", [x, y, z], [x^2, y^2, z^2]);
          (%o3)                        unknown
          (%i4) some ("<", [x, y, z], [x^2, y^2, z + 1]);
          (%o4)                         true
          (%i5) prederror : true;
          (%o5)                         true
          (%i6) some ("<", [x, y, z], [x^2, y^2, z^2]);
          (%o6)                         false
          (%i7) some ("<", [x, y, z], [x^2, y^2, z + 1]);
          (%o7)                         true

 -- Функция: stirling1 (<n>, <m>)

     Представляет число Стирлинга первого рода.

     Для неотрицательных целых <n> и <m> величина ‘stirling1 (<n>, <m>)’
     есть число перестановок множества из <n> элементов, имеющих <m>
     циклов.  См.  книгу Graham, Knuth и Patashnik Concrete Mathematics
     по поводу деталей.  Для определения ‘stirling1 (<n>, <m>)’ с <m>,
     меньшим нуля, Maxima использует рекуррентное соотношение.  Для <n>
     меньших нуля и нецелых аргументов функция не определена.

     ‘stirling1’ является упрощающей функцией.  Maxima знает следующие
     тождества.

       1. stirling1(0, n) = kron_delta(0, n) (См.  [1])
       2. stirling1(n, n) = 1 (См.  [1])
       3. stirling1(n, n - 1) = binomial(n, 2) (См.  [1])
       4. stirling1(n + 1, 0) = 0 (См.  [1])
       5. stirling1(n + 1, 1) = n! (См.  [1])
       6. stirling1(n + 1, 2) = 2^n - 1 (См.  [1])

     Эти тождества применяются, если аргументы являются целыми или
     символами, которые объявлены целыми, и первый аргумент
     неотрицателен.  Функция ‘stirling1’ не упрощается для нецелых
     аргументов.

     Ссылки:

     [1] Donald Knuth, The Art of Computer Programming, third edition,
     Volume 1, Section 1.2.6, Equations 48, 49, and 50.

     Примеры:

          (%i1) declare (n, integer)$
          (%i2) assume (n >= 0)$
          (%i3) stirling1 (n, n);
          (%o3)                           1

     Функция ‘stirling1’ не упрощается для нецелых аргументов.

          (%i1) stirling1 (sqrt(2), sqrt(2));
          (%o1)              stirling1(sqrt(2), sqrt(2))

     Maxima применяет тождества для ‘stirling1’.

          (%i1) declare (n, integer)$
          (%i2) assume (n >= 0)$
          (%i3) stirling1 (n + 1, n);
                                      n (n + 1)
          (%o3)                       ---------
                                          2
          (%i4) stirling1 (n + 1, 1);
          (%o4)                          n!

 -- Функция: stirling2 (<n>, <m>)

     Представляет число Стирлинга второго рода.

     Для неотрицательных целых <n> и <m> число ‘stirling2 (<n>, <m>)’
     есть число способов, которыми множество мощности <n> может быть
     разбито на <m> непересекающихся подмножеств.  Для определения
     ‘stirling2 (<n>, <m>)’ с <m>, меньшим нуля, Maxima использует
     рекуррентное соотношение.  Для <n> меньших нуля и нецелых
     аргументов функция не определена.

     ‘stirling2’ является упрощающей функцией.  Maxima знает следующие
     тождества.

       1. stirling2(0, n) = kron_delta(0, n) (См.  [1])
       2. stirling2(n, n) = 1 (См.  [1])
       3. stirling2(n, n - 1) = binomial(n, 2) (См.  [1])
       4. stirling2(n + 1, 1) = 1 (См.  [1])
       5. stirling2(n + 1, 2) = 2^n - 1 (См.  [1])
       6. stirling2(n, 0) = kron_delta(n, 0) (См.  [2])
       7. stirling2(n, m) = 0 when m > n (См.  [2])
       8. stirling2(n, m) = sum((-1)^(m - k) binomial(m k) k^n,i,1,m) /
          m! если m и n целые и n неотрицательно.  (См.  [3])

     Эти тождества применяются, если аргументы являются целыми или
     символами, которые объявлены целыми, и первый аргумент
     неотрицателен.  Функция ‘stirling2’ не упрощается для нецелых
     аргументов.

     Ссылки:

     [1] Donald Knuth.  The Art of Computer Programming, third edition,
     Volume 1, Section 1.2.6, Equations 48, 49, and 50.

     [2] Graham, Knuth, and Patashnik.  Concrete Mathematics, Table 264.

     [3] Abramowitz and Stegun.  Handbook of Mathematical Functions,
     Section 24.1.4.

     Примеры:

          (%i1) declare (n, integer)$
          (%i2) assume (n >= 0)$
          (%i3) stirling2 (n, n);
          (%o3)                           1

     Функция ‘stirling2’ не упрощается для нецелых аргументов.

          (%i1) stirling2 (%pi, %pi);
          (%o1)                  stirling2(%pi, %pi)

     Maxima применяет тождества для ‘stirling2’.

          (%i1) declare (n, integer)$
          (%i2) assume (n >= 0)$
          (%i3) stirling2 (n + 9, n + 8);
                                   (n + 8) (n + 9)
          (%o3)                    ---------------
                                          2
          (%i4) stirling2 (n + 1, 2);
                                        n
          (%o4)                        2  - 1

 -- Функция: subset (<a>, <f>)

     Возвращает подмножество множества <a>, которое удовлетворяет
     предикату <f>.

     Функция ‘subset’ возвращает множество, состоящее из элементов <a>,
     для которых <f> возвращает любое значение, отличное от ‘false’.
     Функция ‘subset’ не применяет ‘is’ к значению, возвращаемому <f>.

     Функция ‘subset’ вызывает ошибку, если <a> не является множеством.

     См.  также ‘partition_set’.

     Примеры:

          (%i1) subset ({1, 2, x, x + y, z, x + y + z}, atom);
          (%o1)                     {1, 2, x, z}
          (%i2) subset ({1, 2, 7, 8, 9, 14}, evenp);
          (%o2)                      {2, 8, 14}

 -- Функция: subsetp (<a>, <b>)

     Возвращает ‘true’ тогда и только тогда, когда <a> есть подмножество
     <b>.

     Функция ‘subsetp’ вызывает ошибку, если <a> или <b> не являются
     множествами.

     Примеры:

          (%i1) subsetp ({1, 2, 3}, {a, 1, b, 2, c, 3});
          (%o1)                         true
          (%i2) subsetp ({a, 1, b, 2, c, 3}, {1, 2, 3});
          (%o2)                         false

 -- Функция: symmdifference (<a_1>, ..., <a_n>)

     Возвращает симметричную разницу, т.е.  множество, элементы которого
     присутствуют только в одном множестве <a_k>.

     При задании двух аргументов, ‘symmdifference(<a>, <b>)’
     эквивалентно ‘union ( setdifference (<a>, <b> ), setdifference
     (<b>, <a>))’.

     Функция ‘symmdifference’ вызывает ошибку, если любой из ее
     аргументов не является множеством.

     Примеры:

          (%i1) S_1 : {a, b, c};
          (%o1)                       {a, b, c}
          (%i2) S_2 : {1, b, c};
          (%o2)                       {1, b, c}
          (%i3) S_3 : {a, b, z};
          (%o3)                       {a, b, z}
          (%i4) symmdifference ();
          (%o4)                          {}
          (%i5) symmdifference (S_1);
          (%o5)                       {a, b, c}
          (%i6) symmdifference (S_1, S_2);
          (%o6)                        {1, a}
          (%i7) symmdifference (S_1, S_2, S_3);
          (%o7)                        {1, z}
          (%i8) symmdifference ({}, S_1, S_2, S_3);
          (%o8)                        {1, z}

 -- Функция: tree_reduce (<F>, <s>)
 -- Функция: tree_reduce (<F>, <s>, <s_0>)

     Расширяет бинарную функцию <F> до n-арной методом композиции.
     Аргумент <s> является множеством или списком.

     Функция ‘tree_reduce’ действует следующим образом: <F> применяется
     к последовательным парам элементов, чтобы сформировать новый список
     ‘[<F>(<s_1>, <s_2>), <F>(<s_3>, <s_4>), ...]’.  При этом если число
     элементов нечетно, то последний элемент остается неизменным.  Затем
     процесс повторяется до тех пор, пока не останется только один
     элемент списка, который и возвращается в качестве значения.

     Если присутствует необязательный элемент <s_0>, то результат
     эквивалентен ‘tree_reduce(<F>, cons(<s_0>, <s>)’.

     Для сложения чисел с плавающей точкой ‘tree_reduce’ может
     возвращать сумму с меньшей ошибкой округления, чем ‘rreduce’ или
     ‘lreduce’.

     Элементы <s> и частичные результаты могут быть представлены в виде
     бинарного дерева минимальной глубины, откуда происходит название
     "tree_reduce".

     Примеры:

     Функция ‘tree_reduce’, примененная к списку с четным числом
     элементов.

          (%i1) tree_reduce (f, [a, b, c, d]);
          (%o1)                  f(f(a, b), f(c, d))

     Функция ‘tree_reduce’, примененная к списку с нечетным числом
     элементов.

          (%i1) tree_reduce (f, [a, b, c, d, e]);
          (%o1)               f(f(f(a, b), f(c, d)), e)

 -- Функция: union (<a_1>, ..., <a_n>)
     Возвращает объединение множеств от <a_1> до <a_n>.

     Вызов ‘union()’ (без аргументов) возвращает пустое множество.

     Функция ‘union’ возвращает ошибку, если любой из ее аргументов не
     является множеством.

     Примеры:

          (%i1) S_1 : {a, b, c + d, %e};
          (%o1)                   {%e, a, b, d + c}
          (%i2) S_2 : {%pi, %i, %e, c + d};
          (%o2)                 {%e, %i, %pi, d + c}
          (%i3) S_3 : {17, 29, 1729, %pi, %i};
          (%o3)                {17, 29, 1729, %i, %pi}
          (%i4) union ();
          (%o4)                          {}
          (%i5) union (S_1);
          (%o5)                   {%e, a, b, d + c}
          (%i6) union (S_1, S_2);
          (%o6)              {%e, %i, %pi, a, b, d + c}
          (%i7) union (S_1, S_2, S_3);
          (%o7)       {17, 29, 1729, %e, %i, %pi, a, b, d + c}
          (%i8) union ({}, S_1, S_2, S_3);
          (%o8)       {17, 29, 1729, %e, %i, %pi, a, b, d + c}

 -- Функция: xreduce (<F>, <s>)
 -- Функция: xreduce (<F>, <s>, <s_0>)

     Расширяет функцию <F> до n-арной методом композиции или, если <F>
     уже n-арная, применяет <F> к <s>.  Если <F> не является n-арной, то
     ‘xreduce’ работает также, как ‘lreduce’.  Аргумент <s> является
     списком.

     Известны следующие n-арные функции: сложение ‘+’, умножение ‘*’,
     ‘and’, ‘or’, ‘max’, ‘min’ и ‘append’.  Функции могут быть объявлены
     n-арными при помощи ‘declare(<F>, nary)’.  Для таких функций,
     ‘xreduce’ работает быстрее, чем ‘rreduce’ или ‘lreduce’.

     Если задан необязательный аргумент <s_0>, то результат эквивалентен
     ‘xreduce(<s>, cons(<s_0>, <s>))’.

     Сложение чисел с плавающей точкой, строго говоря, не является
     ассоциативным.  Функция ‘xreduce’ применяет n-арное сложение, если
     <s> содержит числа с плавающей точкой.

     Примеры:

     Функция ‘xreduce’, примененная к n-арной функции.  ‘F’ вызывается
     однажды со всеми аргументами.

          (%i1) declare (F, nary);
          (%o1)                         done
          (%i2) F ([L]) := L;
          (%o2)                      F([L]) := L
          (%i3) xreduce (F, [a, b, c, d, e]);
          (%o3)         [[[[[("[", simp), a], b], c], d], e]

     Функция ‘xreduce’, примененная к не n-арной функции.  ‘G’
     вызывается несколько раз с двумя аргументами каждый раз.

          (%i1) G ([L]) := L;
          (%o1)                      G([L]) := L
          (%i2) xreduce (G, [a, b, c, d, e]);
          (%o2)         [[[[[("[", simp), a], b], c], d], e]
          (%i3) lreduce (G, [a, b, c, d, e]);
          (%o3)                 [[[[a, b], c], d], e]


File: maxima.info,  Node: Определение функций,  Next: Программы Maxima,  Prev: Множества,  Up: Top

37 Определение функций
**********************

* Menu:

* Введение в определение функций::
* Функции::
* Макросы::
* Функции и переменные для определения функций::


File: maxima.info,  Node: Введение в определение функций,  Next: Функции,  Prev: Определение функций,  Up: Определение функций

37.1 Введение в определение функций
===================================


File: maxima.info,  Node: Функции,  Next: Макросы,  Prev: Введение в определение функций,  Up: Определение функций

37.2 Функции
============

37.2.1 Обычные функции
----------------------

Для определения функций в Maxima используется оператор ‘:=’.  Например

     f(x) := sin(x)

определяет функцию ‘f’.  Функции без имени могут быть созданы при помощи
‘lambda’.  Например

     lambda ([i, j], ...)

может быть использовано вместо ‘f’, и

     f(i,j) := block ([], ...);
     map (lambda ([i], i+1), l)

возвращает список с каждым элементом увеличенным на 1.

   Можно определить функцию с переменным числом аргументов, присваивая
последнему аргументу список дополнительных параметров:

     (%i1) f ([u]) := u;
     (%o1)                      f([u]) := u
     (%i2) f (1, 2, 3, 4);
     (%o2)                     [1, 2, 3, 4]
     (%i3) f (a, b, [u]) := [a, b, u];
     (%o3)               f(a, b, [u]) := [a, b, u]
     (%i4) f (1, 2, 3, 4, 5, 6);
     (%o4)                 [1, 2, [3, 4, 5, 6]]

   Правая часть определения функции является выражением.  Поэтому, если
требуется последовательность выражений, то можно определить правую часть
следующим образом

     f(x) := (expr1, expr2, ...., exprn);

   В этом случае, значение, возвращаемое функцией, будет равно значению
<exprn>.

   Использование команды возврата ‘return’ возможно тоько внутри
программного блока ‘block’.  Блок

     block ([], expr1, ..., if (a > 10) then return(a), ..., exprn)

   сам по себе является выражением и может использоваться в правой части
определения функции.  При этом, команда возврата может быть выполнена
раньше достижения последнего выражения.

   Первый элемент блока ‘[]’ может содержать список переменных и
присваиваемых им значений, например, такой как ‘[a: 3, b, c: []]’.  В
результате, три переменные ‘a’,‘b’ и ‘c’ не будут ссылаться на свои
глобальные значения, а будут иметь локальные значения внутри блока или
внутри функций, вызываемых из этого блока.  Это называется термином
динамическое связывание, поскольку локальные переменные сохраняются от
начала выполнения блока до его завершения.  Как только выполнение
возвращается из блока, или его выполнение прерывается, то старое
значения переменных (если существуют) восстанавливаются.  Это хороший
метод защиты значения переменных.  Отметим, что присваивание начальных
значений переменных в блоке выполняется параллельно.  Это означает, что
если сделать ‘c: a’, в вышеизложенном примере, то значение ‘c’ будет
равно значению ‘a’ до входа в блок и до присваивания ‘a’ локального
значения.  Поэтому, выполнение кода

     block ([a: a], expr1, ... a: a+3, ..., exprn)

   защитит внешнее значение переменной ‘a’ от изменения внутри блока, и,
с другой стороны, обеспечит доступ к этому значению.  Иными словами,
правая часть присваивания вычисляется до выполнения каких-либо
присваиваний.  Простое использование ‘block ([x], ...’ приводит к тому,
что ‘x’ внутри блока равна сама себе, как при запуске новой сессии
Maxima.

   Фактические параметры функции трактуются точно так же, как локальные
переменные в блоке.  Таким образом, при определении

     f(x) := (expr1, ..., exprn);

   и вызове

     f(1);

   создается контекст, аналогичный

     block ([x: 1], expr1, ..., exprn)

   Внутри функций, если правая часть определения функции может
вычисляться во время выполнения, полезно использовать ‘define’ и,
возможно, ‘buildq’.

37.2.2 Функции-массивы
----------------------

Функции-массивы сохраняют значение функции при первом вызове с
определенными значениями параметров, и возвращают сохраненное значение
без перевычисления при последующих вызовах с теми же параметрами.  Такие
функции часто называются “функции с памятью”.

   Имена функций-массивов добавляются к глобальной переменной ‘arrays’
(не к глобальной переменной ‘functions’).  Функция ‘arrayinfo’
возвращает для таких функций список сохраненных элементов, а функция
‘listarray’ возвращает сохраненные значения.  Функции ‘dispfun’ и
‘fundef’ возвращают определения функций-массива.

   Функция ‘arraymake’ создает вызов функции-массива, аналогично тому
как ‘funmake’ делает для обычных функций.  Функция ‘arrayapply’
применяет функцию-массив к аргументам, аналогично тому как ‘apply’
делает для обычных функций.  Не существует полного аналога функции ‘map’
для функций-массивов, но ‘map(lambda([<x>], <a>[<x>]), <L>)’ или
‘makelist(<a>[<x>], <x>, <L>)’, где <L> – список, действует очень
похоже.

   Функция ‘remarray’ удаляет определение функции-массива (включая
сохраненные значения), аналогично тому как ‘remfunction’ делает для
обычных функций.

   Вызов ‘kill(<a>[<x>])’ удаляет сохраненное значение функции-массива
<a> для аргумента <x>.  При следующем вызове <a> с аргументом <x>,
функция будет перевычислена.  Не существует способа сразу удалить все
сохраненные значения функции-массива кроме как вызов ‘kill(<a>)’ или
‘remarray(<a>)’, что также удаляет определение функции.


File: maxima.info,  Node: Макросы,  Next: Функции и переменные для определения функций,  Prev: Функции,  Up: Определение функций

37.3 Макросы
============

 -- Функция: buildq (<L>, <expr>)
     Подставляет значения переменных, определяемых списком <L>, в
     выражение <expr> параллельно без перевычисления <expr>.
     Результирующее выражение упрощается, но не вычисляется после
     выполнения ‘buildq’.

     Элементы списка <L> являются символами или операторами присваивания
     ‘<symbol>: <value>’, вычисляемые параллельно.  Т.е.  значение
     переменных в правой части присваиваний вычисляются в контексте, в
     котором вызван ‘buildq’, но не в контексте списка присваиваний <L>.
     Если для некоторых переменных в списке <L> не задано значений, то
     для них сохраняются значения из контекста вызова ‘buildq’.

     Переменные из списка <L> подставляются в <expr> параллельно.  Т.е.
     значение каждой подстановки определяется до подстановки, и одна
     переменная не оказывает никакого влияния на другую.

     Если переменная <x> присутствует в <expr> в виде ‘splice (<x>)’, то
     <x> должна иметь значение в форме списка, и этот список будет
     вместо подстановки интерполирован в <expr>.

     Любые другие переменные в <expr>, не присутствующие в <L>,
     переносятся в результат буквально без изменения, даже в том случае,
     когда имеют значение в контексте вызова ‘buildq’.

     Примеры:

     Переменной ‘a’ явно присвоено значение ‘x’, тогда как ‘b’ имеет
     значение (а именно 29) из контекста вызова, а ‘c’ сохраняется
     неизменным.  Результат остается невычисленным до явного применения
     ‘''%’.

          (%i1) (a: 17, b: 29, c: 1729)$
          (%i2) buildq ([a: x, b], a + b + c);
          (%o2)                      x + c + 29
          (%i3) ''%;
          (%o3)                       x + 1758

     Переменная ‘e’ равна списку, который подставляется в ‘foo’ и
     интерполируется в ‘bar’.

          (%i1) buildq ([e: [a, b, c]], foo (x, e, y));
          (%o1)                 foo(x, [a, b, c], y)
          (%i2) buildq ([e: [a, b, c]], bar (x, splice (e), y));
          (%o2)                  bar(x, a, b, c, y)

     Результат подстановки упрощается.  Если бы упрощение выполнилось до
     подстановки, то нижеследующие результаты совпали бы.
          (%i1) buildq ([e: [a, b, c]], splice (e) + splice (e));
          (%o1)                    2 c + 2 b + 2 a
          (%i2) buildq ([e: [a, b, c]], 2 * splice (e));
          (%o2)                        2 a b c

     Значения переменных в <L> присваиваются параллельно, при
     последовательном присваивании первый результат был бы равен ‘foo
     (b, b)’.  Подстановки осуществляются параллельно.  Сравните второй
     результат с результатом функции ‘subst’, которая выполняет
     подстановки последовательно.

          (%i1) buildq ([a: b, b: a], foo (a, b));
          (%o1)                       foo(b, a)
          (%i2) buildq ([u: v, v: w, w: x, x: y, y: z, z: u],
                        bar (u, v, w, x, y, z));
          (%o2)                 bar(v, w, x, y, z, u)
          (%i3) subst ([u=v, v=w, w=x, x=y, y=z, z=u],
                       bar (u, v, w, x, y, z));
          (%o3)                 bar(u, u, u, u, u, u)

     Составим список уравнений с переменными в левой части и со
     значениями этих переменных в правой.  Функция ‘macroexpand’ выводит
     выражение, возвращаемое ‘show_values’.

          (%i1) show_values ([L]) ::= buildq ([L], map ("=", 'L, L));
          (%o1)   show_values([L]) ::= buildq([L], map("=", 'L, L))
          (%i2) (a: 17, b: 29, c: 1729)$
          (%i3) show_values (a, b, c - a - b);
          (%o3)          [a = 17, b = 29, c - b - a = 1683]
          (%i4) macroexpand (show_values (a, b, c - a - b));
          (%o4)    map(=, '([a, b, c - b - a]), [a, b, c - b - a])

     Используя функцию нескольких аргументов, создадим другую функцию, у
     которой некоторые аргументы имеют фиксированное значение.

          (%i1) curry (f, [a]) :=
                  buildq ([f, a], lambda ([[x]], apply (f, append (a, x))))$
          (%i2) by3 : curry ("*", 3);
          (%o2)        lambda([[x]], apply(*, append([3], x)))
          (%i3) by3 (a + b);
          (%o3)                       3 (b + a)

 -- Функция: macroexpand (<expr>)
     Если ‘expr’ является вызовом макро-функции, то ‘macroexpand’
     возвращает макро-расширение <expr> без его вычисления.  В противном
     случае, ‘macroexpand’ возвращает <expr>.

     Если макро-расширение <expr> само является макро-вызовом, то оно
     тоже раскрывается.

     Функция ‘macroexpand’ не вычисляет свои аргументы.  Но если
     раскрытие макро-функций приводит к побочным эффектам, то эти
     эффекты выполняются.

     См.  также ‘::=’, ‘macros’ и ‘macroexpand1’.

     Примеры

          (%i1) g (x) ::= x / 99;
                                              x
          (%o1)                      g(x) ::= --
                                              99
          (%i2) h (x) ::= buildq ([x], g (x - a));
          (%o2)            h(x) ::= buildq([x], g(x - a))
          (%i3) a: 1234;
          (%o3)                         1234
          (%i4) macroexpand (h (y));
                                        y - a
          (%o4)                         -----
                                         99
          (%i5) h (y);
                                      y - 1234
          (%o5)                       --------
                                         99

 -- Функция: macroexpand1 (<expr>)
     Если ‘expr’ является вызовом макро-функции, то ‘macroexpand1’
     возвращает макро-расширение <expr> без его вычисления.  В противном
     случае, ‘macroexpand1’ возвращает <expr>.

     Функция ‘macroexpand1’ не вычисляет свои аргументы.  Но если
     раскрытие макро-функций приводит к побочным эффектам, то эти
     эффекты выполняются.

     Если макро-расширение <expr> само является макро-вызовом, то оно не
     раскрывается.

     См.  также ‘::=’, ‘macros’ и ‘macroexpand’.

     Примеры:

          (%i1) g (x) ::= x / 99;
                                              x
          (%o1)                      g(x) ::= --
                                              99
          (%i2) h (x) ::= buildq ([x], g (x - a));
          (%o2)            h(x) ::= buildq([x], g(x - a))
          (%i3) a: 1234;
          (%o3)                         1234
          (%i4) macroexpand1 (h (y));
          (%o4)                       g(y - a)
          (%i5) h (y);
                                      y - 1234
          (%o5)                       --------
                                         99

 -- Глобальная переменная: macros
     Значение по умолчанию: ‘[]’

     ‘macros’ есть список всех определенных пользователем макро-функций.
     Оператор определения макро-функции ‘::=’ добавляет новую
     макро-функцию к этому списку, а ‘kill’, ‘remove’ и ‘remfunction’
     удаляют ее из него.

     См.также ‘infolists’.

 -- Функция: splice (<a>)
     Интерполирует список, обозначенный атомом <a> в выражение, но
     только если ‘splice’ присутствует внутри ‘buildq’.  В противном
     случае ‘splice’ рассматривается как неопределенная функция.  Если
     переменная <a> присутствует внутри ‘buildq’ сама по себе без
     ‘splice’, то вместо <a> подставляется (не интерполируется)
     соответствующий список.  Аргументом ‘splice’ может быть только
     атом, но не явный список или выражение, дающее список в качестве
     значения.

     Обычно, ‘splice’ применяется для задания аргументов функции или
     оператора.  Для функции ‘f’, выражение ‘f (splice (<a>))’ внутри
     ‘buildq’ преобразуется в ‘f (<a>[1], <a>[2], <a>[3], ...)’.  Для
     оператора ‘o’, выражение ‘"o" (splice (<a>)’ внутри ‘buildq’
     преобразуется в ‘"o" (<a>[1], <a>[2], <a>[3], ...)’, где ‘o’ может
     быть оператором любого вида (обычно оператором с многими
     аргументами).  Обратите внимание, что оператор должен быть заключен
     в двойные кавычки ‘"’.

     Примеры:

          (%i1) buildq ([x: [1, %pi, z - y]], foo (splice (x)) / length (x));
                                 foo(1, %pi, z - y)
          (%o1)                -----------------------
                               length([1, %pi, z - y])
          (%i2) buildq ([x: [1, %pi]], "/" (splice (x)));
                                          1
          (%o2)                          ---
                                         %pi
          (%i3) matchfix ("<>", "<>");
          (%o3)                          <>
          (%i4) buildq ([x: [1, %pi, z - y]], "<>" (splice (x)));
          (%o4)                   <>1, %pi, z - y<>


File: maxima.info,  Node: Функции и переменные для определения функций,  Prev: Макросы,  Up: Определение функций

37.4 Функции и переменные для определения функций
=================================================

 -- Функция: apply (<F>, [<x_1>, ..., <x_n>])
     Составляет и вычисляет выражение ‘<F>(<arg_1>, ..., <arg_n>)’.

     Функция ‘apply’ не пытается различить функцию-массив и обычную
     функцию, и если <F> есть имя функции-массива, то ‘apply’ вычисляет
     ‘<F>(...)’ (т.е.  обычный вызов функции с круглыми а не с
     квадратными скобками).  Функция ‘arrayapply’ вычисляет вызов
     функции с квадратными скобками.

     Примеры:

     Функция ‘apply’ вычисляет свои аргументы.  В этом примере, ‘min’
     применяется к значению ‘L’.

          (%i1) L : [1, 5, -10.2, 4, 3];
          (%o1)                 [1, 5, - 10.2, 4, 3]
          (%i2) apply (min, L);
          (%o2)                        - 10.2

     Функция ‘apply’ вычисляет свои аргументы даже если функция <F> не
     вычисляет их.

          (%i1) F (x) := x / 1729;
                                             x
          (%o1)                     F(x) := ----
                                            1729
          (%i2) fname : F;
          (%o2)                           F
          (%i3) dispfun (F);
                                             x
          (%t3)                     F(x) := ----
                                            1729

          (%o3)                         [%t3]
          (%i4) dispfun (fname);
          fname is not the name of a user function.
           -- an error.  Quitting.  To debug this try debugmode(true);
          (%i5) apply (dispfun, [fname]);
                                             x
          (%t5)                     F(x) := ----
                                            1729

          (%o5)                         [%t5]

     Функция ‘apply’ вычисляет имя функции <F>.  Одиночная кавычка ‘'’
     блокирует это вычисление.  ‘demoivre’ является именем глобальной
     переменной и, одновременно, именем функции.

          (%i1) demoivre;
          (%o1)                         false
          (%i2) demoivre (exp (%i * x));
          (%o2)                  %i sin(x) + cos(x)
          (%i3) apply (demoivre, [exp (%i * x)]);
          demoivre evaluates to false
          Improper name or value in functional position.
           -- an error.  Quitting.  To debug this try debugmode(true);
          (%i4) apply ('demoivre, [exp (%i * x)]);
          (%o4)                  %i sin(x) + cos(x)

 -- Функция: block ([<v_1>, ..., <v_m>], <expr_1>, ..., <expr_n>)
 -- Функция: block (<expr_1>, ..., <expr_n>)
     Функция ‘block’ последовательно вычисляет <expr_1>, ..., <expr_n> и
     возвращает значение последнего вычисленного выражения.
     Последовательность вычисления может быть изменена при помощи
     функций ‘go’, ‘throw’ и ‘return’.  Последнее выражение <expr_n>
     вычисляется если не используется ‘return’ или вычисляется
     выражение, содержащие ‘throw’.  Некоторые переменные <v_1>, ...,
     <v_m> могут быть объявлены локальными в блоке, и они отличаются от
     глобальных переменных с теми же именами.  Если не требуется
     определять локальные переменные, то список может быть опущен.
     Внутри блока, все другие переменные, отличные от <v_1>, ..., <v_m>,
     являются глобальными.

     ‘block’ сохраняет текущие значения переменных <v_1>, ..., <v_m>
     (если таковые существуют) при входе в блок, и затем удаляет их
     значения, так чтобы эти переменные вычислялись сами в себя.
     Локальные переменные могут принимать любые значения внутри блока,
     но пр выходе из него сохраненные значения восстанавливаются, а
     локальные в блоке значения теряются.

     Блок может существовать внутри другого блока.  Локальные переменные
     определяются всякий раз как вычисляется новый ‘block’.  Локальные
     переменные объемлющего блока выглядят как глобальные для
     внутреннего блока.  Если переменная не локальна в блоке, то ее
     значение равно последнему, присвоенному в объемлющем блоке, если
     таковое существует, и значению переменной в глобальном окружении в
     противном случае.  Эта политика совпадает с обычным понятием
     "динамической области определения".

     Если необходимо сохранять и восстанавливать другие локальные
     свойства, кроме ‘value’, такие как ‘array’ (кроме полных массивов),
     ‘function’, ‘dependencies’, ‘atvalue’, ‘matchdeclare’, ‘atomgrad’,
     ‘constant’ и ‘nonscalar’, то следует использовать функцию ‘local’
     внутри блока с именем функции в качестве параметра.

     Значением блока является значение последнего выражения или значение
     аргумента функции ‘return’, которая может быть использована для
     явного выхода из блока.  Функция ‘go’ используется для передачи
     управления на команду блока, помеченную аргументом ‘go’.  Для того,
     чтобы пометить команду нужно поместить перед ней метку в виде
     атома.  Например: ‘block ([x], x:1, loop, x: x+1, ..., go(loop),
     ...)’.  Аргументом ‘go’ должна быть метка, определенная в текущем
     блоке.  Невозможно использовать ‘go’ для передачи управления в блок
     отличный от того, в котором находится вызов ‘go’.

     Блоки обычно применяются в правых частях определения функций, но
     могут быть использованы и в других местах.

 -- Функция: break (<expr_1>, ..., <expr_n>)
     Вычисляет и печатает выражения <expr_1>, ..., <expr_n> и затем
     вызывает прерывание Maxima с тем, чтобы пользователь мог
     исследовать и изменить окружение.  Ввод ‘exit;’ возобновляет
     вычисление.

 -- Функция: catch (<expr_1>, ..., <expr_n>)
     Вычисляет <expr_1>, ..., <expr_n> одно за другими и, если одно из
     них приводит к вычислению выражения ‘throw (arg)’, то значением
     ‘catch’ становится значение аргумента ‘throw (arg)’, и дальнейшее
     вычисление не производится.  Такой "нелокальный возврат"
     осуществляется из любого уровня вложенности до первого объемлющего
     ‘catch’.  Если нет объемлющего ‘catch’, то ‘throw’ вызывает ошибку.

     Если вычисление аргументов не приводит к вычислению ‘throw’, то
     значение ‘catch’ равно значению <expr_n>.

          (%i1) lambda ([x], if x < 0 then throw(x) else f(x))$
          (%i2) g(l) := catch (map (''%, l))$
          (%i3) g ([1, 2, 3, 7]);
          (%o3)               [f(1), f(2), f(3), f(7)]
          (%i4) g ([1, 2, -3, 7]);
          (%o4)                          - 3

     Здесь, если список ‘l’ содержит только неотрицательные числа, то
     функция ‘g’ возвращает список функций ‘f’, примененных к элементам
     ‘l’, иначе, ‘g’ "ловит" первое отрицательное число в ‘l’ и
     "бросает" его вверх.

 -- Функция: compfile (<filename>, <f_1>, ..., <f_n>)
 -- Функция: compfile (<filename>, functions)
 -- Функция: compfile (<filename>, all)

     Транслирует функции Maxima в Lisp и записывает полученный код в
     файл <filename>.

     Вызов ‘compfile(<filename>, <f_1>, ..., <f_n>)’ транслирует только
     заданные функции.  Вызов ‘compfile(<filename>, functions)’ или
     вызов ‘compfile(<filename>, all)’ транслирует все определенные
     пользователем функции.

     Код Lisp не вычисляется, а результирующий файл не обрабатывается
     компилятором Lisp.  Функция ‘translate’ создает и вычисляет Lisp
     код.  Функция ‘compile_file’ транслирует код Maxima в Lisp, и затем
     выполняет компилятор Lisp.

     См.  также ‘translate’, ‘translate_file’ и ‘compile_file’.

 -- Функция: compile (<f_1>, ..., <f_n>)
 -- Функция: compile (functions)
 -- Функция: compile (all)
     Транслирует определения Maxima функций <f_1>, ..., <f_n> в Lisp,
     вычисляет Lisp код и вызывает Lisp функцию ‘COMPILE’ на каждую
     транслированную функцию.  Функция ‘compile’ возвращает список
     скомпилированных функций.

     Вызов ‘compile (all)’ или ‘compile (functions)’ компилирует все
     определенные пользователем функции.

     Функция ‘compile’ не вычисляет свои аргументы.  Оператор
     кавычка-кавычка ‘''’ может быть использован для их вычисления.

 -- Функция: define (<f>(<x_1>, ..., <x_n>), <expr>)
 -- Функция: define (<f>[<x_1>, ..., <x_n>], <expr>)
 -- Функция: define (funmake (<f>, [<x_1>, ..., <x_n>]), <expr>)
 -- Функция: define (arraymake (<f>, [<x_1>, ..., <x_n>]), <expr>)
 -- Функция: define (ev (<expr_1>), <expr_2>)

     Определяет функцию с именем <f>, аргументами <x_1>, ..., <x_n> и
     телом функции <expr>.  Функция ‘define’ всегда вычисляет свой
     второй аргумент (если вычисление не экранировано, т.е.  блокировано
     явным образом).  Функция, определенная данным образом, может быть
     обычной функцией Maxima (с аргументами в круглых скобках) или
     функцией-массивом (с аргументам в квадратных скобках).

     Если последний аргумент <x_n> является одноэлементным списком, то
     функция, определенная ‘define’, принимает произвольное число
     аргументов.  Фактические параметры присваиваются по одному
     формальным параметрам <x_1>, ..., <x_(n - 1)>, а все последующие
     фактические параметры, если таковые есть, присваиваются <x_n> одним
     списком.

     Если первый параметр ‘define’ имеет форму ‘<f>(<x_1>, ..., <x_n>)’
     или ‘<f>[<x_1>, ..., <x_n>]’, то аргументы функции вычисляются, а
     <f> нет, даже если уже есть функция или переменная с таким именем.

     Если же первый параметр является выражением с оператором ‘funmake’,
     ‘arraymake’ или ‘ev’, то первый аргумент вычисляется.  Это
     позволяет вычислять как имя функции так и ее тело.

     Все определяемые функции действуют в одном пространстве имен, т.е.
     если функция ‘f’ определена внутри другой функции ‘g’, то действие
     ‘f’ не ограничено функцией ‘g’.

     Если некоторый формальный параметр <x_k> является экранированным
     символом (после вычисления), то функция, определенная ‘define’, не
     будет вычислять соответствующий фактический параметр.  Все
     остальные фактические параметры вычисляются.

     См.  также ‘:=’ и ‘::=’.

     Примеры:

     Функция ‘define’ всегда вычисляет свой второй аргумент (если
     вычисление не блокировано явным образом).

          (%i1) expr : cos(y) - sin(x);
          (%o1)                    cos(y) - sin(x)
          (%i2) define (F1 (x, y), expr);
          (%o2)              F1(x, y) := cos(y) - sin(x)
          (%i3) F1 (a, b);
          (%o3)                    cos(b) - sin(a)
          (%i4) F2 (x, y) := expr;
          (%o4)                   F2(x, y) := expr
          (%i5) F2 (a, b);
          (%o5)                    cos(y) - sin(x)

     Функция, определяемая ‘define’, может быть обычной функцией Maxima
     или функцией-массивом.

          (%i1) define (G1 (x, y), x.y - y.x);
          (%o1)               G1(x, y) := x . y - y . x
          (%i2) define (G2 [x, y], x.y - y.x);
          (%o2)                G2     := x . y - y . x
                                 x, y

     Если последний аргумент <x_n> является одноэлементным списком, то
     определенная ‘define’ функция принимает произвольное число
     аргументов.

          (%i1) define (H ([L]), '(apply ("+", L)));
          (%o1)                H([L]) := apply("+", L)
          (%i2) H (a, b, c);
          (%o2)                       c + b + a

     Если первый параметр является выражением с оператором ‘funmake’,
     ‘arraymake’ или ‘ev’, то первый аргумент вычисляется.

          (%i1) [F : I, u : x];
          (%o1)                        [I, x]
          (%i2) funmake (F, [u]);
          (%o2)                         I(x)
          (%i3) define (funmake (F, [u]), cos(u) + 1);
          (%o3)                  I(x) := cos(x) + 1
          (%i4) define (arraymake (F, [u]), cos(u) + 1);
          (%o4)                   I  := cos(x) + 1
                                   x
          (%i5) define (foo (x, y), bar (y, x));
          (%o5)                foo(x, y) := bar(y, x)
          (%i6) define (ev (foo (x, y)), sin(x) - cos(y));
          (%o6)             bar(y, x) := sin(x) - cos(y)

 -- Функция: define_variable (<name>, <default_value>, <mode>)

     Определяет глобальную переменную.  ‘define_variable’ полезна в
     пользовательских пакетах, которые часто транслируются или
     компилируются.

     Функция ‘define_variable’ выполняет следующие шаги:

       1. ‘mode_declare (<name>, <mode>)’ декларирует тип переменной
          <name> для транслятора.  См.  ‘mode_declare’ для списка
          возможных типов.

       2. Если переменная не имеет значения, то <default_value>
          устанавливается равным <name>.

       3. ‘declare (<name>, special)’ объявляет переменную специальной.

       4. Ассоциирует имя <name> с тестовой функцией, чтобы обеспечить,
          что <name> будут присваиваться значения только объявленного
          типа.

     Свойство ‘value_check’ может быть установлено для любой переменной,
     определенной при помощи ‘define_variable’ с типом отличным от
     ‘any’.  Значение свойства ‘value_check’ является лямбда-выражением
     или именем функции одной переменной.  Эта функция вызывается всякий
     раз, как производится попытка присвоить значение данной переменной.
     Параметром функции ‘value_check’ является предполагаемое новое
     значение переменной.

     Функция ‘define_variable’ вычисляет ‘default_value’ и не вычисляет
     ‘name’ и ‘mode’.  Функция ‘define_variable’ возвращает текущее
     значение ‘name’, что есть ‘default_value’ если ‘name’ не имела
     значения до декларации и значение ‘name’ в противном случае.

     Примеры:

     ‘foo’ – логическая переменная с начальным значением ‘true’.
          (%i1) define_variable (foo, true, boolean);
          (%o1)                         true
          (%i2) foo;
          (%o2)                         true
          (%i3) foo: false;
          (%o3)                         false
          (%i4) foo: %pi;
          Error: foo was declared mode boolean, has value: %pi
           -- an error.  Quitting.  To debug this try debugmode(true);
          (%i5) foo;
          (%o5)                         false

     ‘bar’ – целочисленная переменная, которая должна быть простым
     числом.
          (%i1) define_variable (bar, 2, integer);
          (%o1)                           2
          (%i2) qput (bar, prime_test, value_check);
          (%o2)                      prime_test
          (%i3) prime_test (y) := if not primep(y) then
                                     error (y, "is not prime.");
          (%o3) prime_test(y) := if not primep(y)

                                             then error(y, "is not prime.")
          (%i4) bar: 1439;
          (%o4)                         1439
          (%i5) bar: 1440;
          1440 is not prime.
          #0: prime_test(y=1440)
           -- an error.  Quitting.  To debug this try debugmode(true);
          (%i6) bar;
          (%o6)                         1439

     ‘baz_quux’ – переменная, которой нельзя присвоить значение.  Тип
     ‘any_check’ аналогичен ‘any’, но позволяет применять механизм
     ‘value_check’, в то время как тип ‘any’ этого не позволяет.
          (%i1) define_variable (baz_quux, 'baz_quux, any_check);
          (%o1)                       baz_quux
          (%i2) F: lambda ([y], if y # 'baz_quux then
                           error ("Cannot assign to `baz_quux'."));
          (%o2) lambda([y], if y # 'baz_quux

                                  then error(Cannot assign to `baz_quux'.))
          (%i3) qput (baz_quux, ''F, value_check);
          (%o3) lambda([y], if y # 'baz_quux

                                  then error(Cannot assign to `baz_quux'.))
          (%i4) baz_quux: 'baz_quux;
          (%o4)                       baz_quux
          (%i5) baz_quux: sqrt(2);
          Cannot assign to `baz_quux'.
          #0: lambda([y],if y # 'baz_quux then
                           error("Cannot assign to `baz_quux'."))(y=sqrt(2))
           -- an error.  Quitting.  To debug this try debugmode(true);
          (%i6) baz_quux;
          (%o6)                       baz_quux

 -- Функция: dispfun (<f_1>, ..., <f_n>)
 -- Функция: dispfun (all)
     Выводит определения пользовательских функций <f_1>, ..., <f_n>.
     Каждый аргумент должен быть именем: макроса (определенного при
     помощи ‘::=’), обычной функции (определенной ‘:=’ или ‘define’),
     функции-массива (определенной ‘:=’ или ‘define’, но с аргументами в
     квадратных скобках ‘[ ]’), функцией с индексом (определенной ‘:=’
     или ‘define’, но с частью аргументов в квадратных скобках а с
     другими в круглых ‘( )’), одним из элементов функции с индексом с
     определенным значением индекса, или функцией с постоянным индексом.

     Вызов ‘dispfun (all)’ выводит все пользовательские функции, которые
     определяются списками ‘functions’, ‘arrays’ и ‘macros’, кроме
     функций с постоянным индексом.

     Функция ‘dispfun’ создает метки промежуточных выражений (‘%t1’,
     ‘%t2’ и т.д.)  для каждой выводимой функции и присваивает
     определения функций этим меткам.  В отличии от этого, ‘fundef’
     возвращает определение функции.

     Функция ‘dispfun’ не вычисляет свои аргументы.  Оператор
     кавычка-кавычка ‘''’ может быть использован для их вычисления.
     Функция ‘dispfun’ возвращает список меток промежуточных выражений,
     соответствующих выведенным функциям.

     Примеры:

          (%i1) m(x, y) ::= x^(-y);
                                               - y
          (%o1)                   m(x, y) ::= x
          (%i2) f(x, y) :=  x^(-y);
                                               - y
          (%o2)                    f(x, y) := x
          (%i3) g[x, y] :=  x^(-y);
                                              - y
          (%o3)                     g     := x
                                     x, y
          (%i4) h[x](y) :=  x^(-y);
                                              - y
          (%o4)                     h (y) := x
                                     x
          (%i5) i[8](y) :=  8^(-y);
                                              - y
          (%o5)                     i (y) := 8
                                     8
          (%i6) dispfun (m, f, g, h, h[5], h[10], i[8]);
                                               - y
          (%t6)                   m(x, y) ::= x

                                               - y
          (%t7)                    f(x, y) := x

                                              - y
          (%t8)                     g     := x
                                     x, y

                                              - y
          (%t9)                     h (y) := x
                                     x

                                              1
          (%t10)                     h (y) := --
                                      5        y
                                              5

                                               1
          (%t11)                    h  (y) := ---
                                     10         y
                                              10

                                              - y
          (%t12)                    i (y) := 8
                                     8

          (%o12)       [%t6, %t7, %t8, %t9, %t10, %t11, %t12]
          (%i12) ''%;
                               - y              - y            - y
          (%o12) [m(x, y) ::= x   , f(x, y) := x   , g     := x   ,
                                                      x, y
                            - y           1              1             - y
                  h (y) := x   , h (y) := --, h  (y) := ---, i (y) := 8   ]
                   x              5        y   10         y   8
                                          5             10

 -- Системная переменная: functions
     Значение по умолчанию: ‘[]’

     Переменная ‘functions’ есть список всех обычных функций Maxima в
     текущей сессии.  Обычные функции – это функции, определенные при
     помощи ‘define’ или ‘:=’, и вызываемые с аргументами в круглых
     скобках ‘()’.  Функция может быть определена в командной строке
     Maxima или в файле, загруженном при помощи ‘load’ или ‘batch’.

     Функции-массивы (вызываемые с квадратными скобками, т.е.  ‘F[x]’) и
     функции с индексом (вызываемые с круглыми и квадратными скобками,
     т.е.  ‘F[x](y)’) перечислены в глобальной переменной ‘arrays’, а не
     в ‘functions’.

     Lisp функции не включаются в список.

     Примеры:

          (%i1) F_1 (x) := x - 100;
          (%o1)                   F_1(x) := x - 100
          (%i2) F_2 (x, y) := x / y;
                                                x
          (%o2)                    F_2(x, y) := -
                                                y
          (%i3) define (F_3 (x), sqrt (x));
          (%o3)                   F_3(x) := sqrt(x)
          (%i4) G_1 [x] := x - 100;
          (%o4)                    G_1  := x - 100
                                      x
          (%i5) G_2 [x, y] := x / y;
                                               x
          (%o5)                     G_2     := -
                                       x, y    y
          (%i6) define (G_3 [x], sqrt (x));
          (%o6)                    G_3  := sqrt(x)
                                      x
          (%i7) H_1 [x] (y) := x^y;
                                                y
          (%o7)                     H_1 (y) := x
                                       x
          (%i8) functions;
          (%o8)              [F_1(x), F_2(x, y), F_3(x)]
          (%i9) arrays;
          (%o9)                 [G_1, G_2, G_3, H_1]

 -- Функция: fundef (<f>)
     Возвращает определение функции <f>.

     Аргумент должен быть именем: макроса (определенного при помощи
     ‘::=’), обычной функции (определенной ‘:=’ или ‘define’),
     функции-массива (определенной ‘:=’ или ‘define’, но с аргументами в
     квадратных скобках ‘[ ]’), функцией с индексом (определенной ‘:=’
     или ‘define’, но с частью аргументов в квадратных скобках а с
     другими в круглых ‘( )’), одним из элементов функции с индексом с
     определенным значением индекса, или функцией с постоянным индексом.

     Функция ‘fundef’ не вычисляет свои аргументы.  Оператор
     кавычка-кавычка ‘''’ может быть использован для их вычисления.

     Вызов ‘fundef (<f>)’ возвращает определение функции <f>.  В отличии
     от этого, ‘dispfun (<f>)’ присваивает определения функций меткам
     промежуточных выражений.

 -- Функция: funmake (<F>, [<arg_1>, ..., <arg_n>])
     Возвращает выражение ‘<F>(<arg_1>, ..., <arg_n>)’.  Это выражение
     упрощается но не вычисляется, т.е.  функция <F> не вызывается, даже
     если она определена.

     Функция ‘funmake’ не различает обычные функции и функции-массивы.
     Если <F> есть имя функции-массива, то ‘funmake’ все равно
     возвращает ‘<F>(...)’ (т.е вызов функции с круглыми а не с
     квадратными скобками).  Для функций-массивом следует использовать
     ‘arraymake’.

     Функция ‘funmake’ вычисляет свои аргументы.

     Примеры:

     Функция ‘funmake’, примененная к обычной Maxima функции.

          (%i1) F (x, y) := y^2 - x^2;
                                             2    2
          (%o1)                  F(x, y) := y  - x
          (%i2) funmake (F, [a + 1, b + 1]);
          (%o2)                    F(a + 1, b + 1)
          (%i3) ''%;
                                        2          2
          (%o3)                  (b + 1)  - (a + 1)

     Функция ‘funmake’, примененная к макросу.

          (%i1) G (x) ::= (x - 1)/2;
                                            x - 1
          (%o1)                    G(x) ::= -----
                                              2
          (%i2) funmake (G, [u]);
          (%o2)                         G(u)
          (%i3) ''%;
                                        u - 1
          (%o3)                         -----
                                          2

     Функция ‘funmake’, примененная к функции с индексом.

          (%i1) H [a] (x) := (x - 1)^a;
                                                  a
          (%o1)                   H (x) := (x - 1)
                                   a
          (%i2) funmake (H [n], [%e]);
                                                 n
          (%o2)               lambda([x], (x - 1) )(%e)
          (%i3) ''%;
                                              n
          (%o3)                       (%e - 1)
          (%i4) funmake ('(H [n]), [%e]);
          (%o4)                        H (%e)
                                        n
          (%i5) ''%;
                                              n
          (%o5)                       (%e - 1)

     Функция ‘funmake’, примененная к символу, не являющемуся функцией
     какого-либо типа.

          (%i1) funmake (A, [u]);
          (%o1)                         A(u)
          (%i2) ''%;
          (%o2)                         A(u)

     Функция ‘funmake’ вычисляет аргументы, но не результат.

          (%i1) det(a,b,c) := b^2 -4*a*c;
                                              2
          (%o1)              det(a, b, c) := b  - 4 a c
          (%i2) (x : 8, y : 10, z : 12);
          (%o2)                          12
          (%i3) f : det;
          (%o3)                          det
          (%i4) funmake (f, [x, y, z]);
          (%o4)                    det(8, 10, 12)
          (%i5) ''%;
          (%o5)                         - 284

     Maxima упрощает возвращаемое ‘funmake’ значение.

          (%i1) funmake (sin, [%pi / 2]);
          (%o1)                           1

 -- Функция: lambda ([<x_1>, ..., <x_m>], <expr_1>, ..., <expr_n>)
 -- Функция: lambda ([[<L>]], <expr_1>, ..., <expr_n>)
 -- Функция: lambda ([<x_1>, ..., <x_m>, [<L>]], <expr_1>, ...,
          <expr_n>)
     Определяет и возвращает лямбда-выражение (т.е.  функцию без имени).
     Функция может иметь обязательные параметры <x_1>, ..., <x_m> и/или
     необязательные параметры <L>, представляемые в форме списка.
     Значение, возвращаемое функцией, равно <expr_n>.  Лямбда-выражение
     может быть присвоено переменной и вычислено, как обычная функция.
     Лямбда-выражение может использоваться в тех же контекстах, где
     ожидается имя функции.

     При вычислении функции, создаются неинициализированные локальные
     переменные <x_1>, ..., <x_m>.  ‘lambda’ может использоваться внутри
     ‘block’ или другого ‘lambda’, и локальные переменные создаются
     каждый раз, как вычисляется новый блок ‘block’ или ‘lambda’.
     Локальные переменные выглядят как глобальные для каждого
     внутреннего блока ‘block’ или ‘lambda’.  Если переменная не
     является локальной, то ее значение равно последнему, присвоенному в
     объемлющем блоке ‘block’ или ‘lambda’, если таковое существует, и
     значению переменной в глобальном окружении в противном случае.  Эта
     политика совпадает с обычным понятием "динамической области
     определения".

     После определения локальных переменных, выражения с <expr_1> по
     <expr_n> последовательно вычисляются.  Специальная переменная ‘%%’
     обозначает значение предыдущего выражения.  Среди выражение могут
     применяться ‘throw’ и ‘catch’.

     Команда возврата ‘return’ не может использоваться в
     лямбда-выражении если только она не заключена в блоке ‘block’.  В
     этом случае ‘return’ определяет значение блока а не
     лямбда-выражения в целом, за исключением случая, когда блок
     является последним выражением <expr_n>.  Аналогично, ‘go’ не может
     использоваться в лямбда-выражении без объемлющего блока ‘block’.

     Функция ‘lambda’ не вычисляет свои параметры.  Оператор
     кавычка-кавычка ‘''’ может быть использован для их вычисления.

     Примеры:

        • Лямбда-выражение может быть присвоено переменной и вычислено,
          как обычная функция.
          (%i1) f: lambda ([x], x^2);
                                                2
          (%o1)                    lambda([x], x )
          (%i2) f(a);
                                          2
          (%o2)                          a
        • Лямбда-выражение может использоваться в тех же контекстах, где
          ожидается вычисление функции.
          (%i3) lambda ([x], x^2) (a);
                                          2
          (%o3)                          a
          (%i4) apply (lambda ([x], x^2), [a]);
                                          2
          (%o4)                          a
          (%i5) map (lambda ([x], x^2), [a, b, c, d, e]);
                                  2   2   2   2   2
          (%o5)                 [a , b , c , d , e ]
        • Параметры являются локальными переменными.  Все остальные
          переменные глобальны.  Глобальные переменные вычисляются в
          момент вычисления лямбда-выражения, за исключением случая,
          когда вычисление специально вызвано каким-либо способом,
          например, оператором ‘''’.
          (%i6) a: %pi$
          (%i7) b: %e$
          (%i8) g: lambda ([a], a*b);
          (%o8)                   lambda([a], a b)
          (%i9) b: %gamma$
          (%i10) g(1/2);
                                       %gamma
          (%o10)                       ------
                                         2
          (%i11) g2: lambda ([a], a*''b);
          (%o11)                lambda([a], a %gamma)
          (%i12) b: %e$
          (%i13) g2(1/2);
                                       %gamma
          (%o13)                       ------
                                         2
        • Лямбда-выражения могут быть вложены.  Локальные переменные
          объемлющего лямбда-выражения выглядят глобальными для
          внутреннего, если только во внутреннем лямбда-выражении не
          определены локальные переменные с теми же именами.
          (%i14) h: lambda ([a, b], h2: lambda ([a], a*b), h2(1/2));
                                                             1
          (%o14)    lambda([a, b], h2 : lambda([a], a b), h2(-))
                                                             2
          (%i15) h(%pi, %gamma);
                                       %gamma
          (%o15)                       ------
                                         2
        • Поскольку ‘lambda’ не вычисляет аргументы, нижеприведенное
          лямбда-выражение ‘i’ не определяет функцию "умножить на ‘a’".
          Такая функция может быть определена с помощью ‘buildq’, как
          сделано в лямбда-выражении ‘i2’.
          (%i16) i: lambda ([a], lambda ([x], a*x));
          (%o16)            lambda([a], lambda([x], a x))
          (%i17) i(1/2);
          (%o17)                  lambda([x], a x)
          (%i18) i2: lambda([a], buildq([a: a], lambda([x], a*x)));
          (%o18)    lambda([a], buildq([a : a], lambda([x], a x)))
          (%i19) i2(1/2);
                                               x
          (%o19)                   lambda([x], -)
                                               2
          (%i20) i2(1/2)(%pi);
                                         %pi
          (%o20)                         ---
                                          2
        • Лямбда-выражение может иметь переменное число аргументов, что
          обозначается ‘[<L>]’ в качестве единственного или последнего
          параметра.  Фактические параметры представлены внутри функции
          в виде списка.
          (%i1) f : lambda ([aa, bb, [cc]], aa * cc + bb);
          (%o1)          lambda([aa, bb, [cc]], aa cc + bb)
          (%i2) f (foo, %i, 17, 29, 256);
          (%o2)       [17 foo + %i, 29 foo + %i, 256 foo + %i]
          (%i3) g : lambda ([[aa]], apply ("+", aa));
          (%o3)             lambda([[aa]], apply(+, aa))
          (%i4) g (17, 29, x, y, z, %e);
          (%o4)                  z + y + x + %e + 46

 -- Функция: local (<v_1>, ..., <v_n>)
     Объявляет переменные <v_1>, ..., <v_n> локальными по отношению ко
     всем свойствам в выражении, где используется ‘local’.

     Функция ‘local’ не вычисляет свои аргументы.  Функция ‘local’
     возвращает ‘done’.

     Функция ‘local’ может использоваться только внутри блока ‘block’, в
     теле функции или лямбда-выражении ‘lambda’, в функции ‘ev’, и
     только один раз в каждом случае.

     ‘local’ независима от ‘context’.

 -- Управляющая переменная: macroexpansion
     Значение по умолчанию: ‘false’

     Переменная ‘macroexpansion’ управляет тем, подставляется ли
     макро-расширение (т.е.  возвращаемое значением) вместо вызова
     макро-функции.  Подстановка может ускорить последующие вычисления
     но за счет увеличения памяти для хранения выражений.

     ‘false’
          Макро-расширение не подставляется вместо вызова макро-функции.
     ‘expand’
          При первом вызове макро-функции, макро-расширение сохраняется.
          Для последующих вызовов, макро-расширение не перевычисляется.
          Побочные эффекты (такие как ‘print’ или присваивание
          глобальных переменных) осуществляются только при первом
          вычислении макро-функции.  Макро-расширение в выражении не
          влияет на другие выражения, имеющие такой же вызов
          макро-функции.
     ‘displace’
          При первом вызове макро-функции, макро-расширение
          подставляется вместо вызова, изменяя выражение, из которого
          макро-функция вызывается.  Для последующих вызовов,
          макро-расширение не перевычисляется.  Побочные эффекты
          осуществляются только при первом вычислении макро-функции.
          Макро-расширение в выражении не влияет на другие выражения,
          имеющие такой же вызов макро-функции.

     Примеры:

     Если ‘macroexpansion’ равна ‘false’, то макро-функция вызывается
     всякий раз, как вычисляется вызывающее выражение, и вызывающее
     выражение не изменяется.

          (%i1) f (x) := h (x) / g (x);
                                            h(x)
          (%o1)                     f(x) := ----
                                            g(x)
          (%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                                 return (x + 99));
          (%o2) g(x) ::= block(print("x + 99 is equal to", x),
                                                            return(x + 99))
          (%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                                 return (x - 99));
          (%o3) h(x) ::= block(print("x - 99 is equal to", x),
                                                            return(x - 99))
          (%i4) macroexpansion: false;
          (%o4)                         false
          (%i5) f (a * b);
          x - 99 is equal to x
          x + 99 is equal to x
                                      a b - 99
          (%o5)                       --------
                                      a b + 99
          (%i6) dispfun (f);
                                            h(x)
          (%t6)                     f(x) := ----
                                            g(x)

          (%o6)                         done
          (%i7) f (a * b);
          x - 99 is equal to x
          x + 99 is equal to x
                                      a b - 99
          (%o7)                       --------
                                      a b + 99

     Если ‘macroexpansion’ равна ‘expand’, то макро-функция вызывается
     один раз, и взывающее выражение не изменяется.

          (%i1) f (x) := h (x) / g (x);
                                            h(x)
          (%o1)                     f(x) := ----
                                            g(x)
          (%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                                 return (x + 99));
          (%o2) g(x) ::= block(print("x + 99 is equal to", x),
                                                            return(x + 99))
          (%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                                 return (x - 99));
          (%o3) h(x) ::= block(print("x - 99 is equal to", x),
                                                            return(x - 99))
          (%i4) macroexpansion: expand;
          (%o4)                        expand
          (%i5) f (a * b);
          x - 99 is equal to x
          x + 99 is equal to x
                                      a b - 99
          (%o5)                       --------
                                      a b + 99
          (%i6) dispfun (f);
                                            h(x)
          (%t6)                     f(x) := ----
                                            g(x)

          (%o6)                         done
          (%i7) f (a * b);
                                      a b - 99
          (%o7)                       --------
                                      a b + 99

     Если ‘macroexpansion’ равна ‘expand’, то макро-функция вызывается
     один раз, и взывающее выражение изменяется.

          (%i1) f (x) := h (x) / g (x);
                                            h(x)
          (%o1)                     f(x) := ----
                                            g(x)
          (%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                                 return (x + 99));
          (%o2) g(x) ::= block(print("x + 99 is equal to", x),
                                                            return(x + 99))
          (%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                                 return (x - 99));
          (%o3) h(x) ::= block(print("x - 99 is equal to", x),
                                                            return(x - 99))
          (%i4) macroexpansion: displace;
          (%o4)                       displace
          (%i5) f (a * b);
          x - 99 is equal to x
          x + 99 is equal to x
                                      a b - 99
          (%o5)                       --------
                                      a b + 99
          (%i6) dispfun (f);
                                           x - 99
          (%t6)                    f(x) := ------
                                           x + 99

          (%o6)                         done
          (%i7) f (a * b);
                                      a b - 99
          (%o7)                       --------
                                      a b + 99

 -- Управляющая переменная: mode_checkp
     Значение по умолчанию: ‘true’

     Если ‘mode_checkp’ равна ‘true’, то ‘mode_declare’ проверяет типы
     переменных, имеющих значение до вызова ‘mode_declare’.

 -- Управляющая переменная: mode_check_errorp
     Значение по умолчанию: ‘false’

     Если ‘mode_check_errorp’ равна ‘true’, то ‘mode_declare’ вызывает
     ошибку.

 -- Управляющая переменная: mode_check_warnp
     Значение по умолчанию: ‘true’

     Если ‘mode_check_warnp’ равна ‘true’, то выводятся предупреждения о
     ошибках типизации.

 -- Функция: mode_declare (<y_1>, <mode_1>, ..., <y_n>, <mode_n>)
     Функция ‘mode_declare’ используется для определения типов
     переменных или функций для последующей трансляции и компиляции.
     Вызов ‘mode_declare’ обычно располагается в начале определения
     функции, в начале Maxima-программы или выполняется интерактивно в
     командной строке.

     Параметры ‘mode_declare’ являются парами, состоящими из переменной
     и ее типа, который может быть ‘boolean’, ‘fixnum’, ‘number’,
     ‘rational’ или ‘float’.  Вместо переменной можно использовать
     список переменных, которые все будут объявлены однотипными.

     Если переменная является массивом, и каждый элемент этого массива,
     на который будут ссылаться, имеет значение, то для первой
     декларации границ массива следует использовать ‘array (yi,
     complete, dim1, dim2, ...)’ а не
          array(yi, dim1, dim2, ...)
     Если все элементы массива имеют тип ‘fixnum’ (‘float’), то следует
     использовать ‘fixnum’ (‘float’) вместо ‘complete’.  Кроме того,
     если все элементы массива имеют один тип, скажем ‘m’, то для
     эффективной трансляции следует использовать

          mode_declare (completearray (yi), m))

     Численный код с использованием массивов может работать быстрее при
     объявлении ожидаемого размера массива, как сделано в

          mode_declare (completearray (a [10, 10]), float)

     для массива с плавающей точкой размера 10 x 10.

     Можно определить тип результата функции при помощи ‘function (f_1,
     f_2, ...)’, где ‘f_1’, ‘f_2’, ...  есть имена функций.  Например,
     выражение

          mode_declare ([function (f_1, f_2, ...)], fixnum)

     объявляет значения, возвращаемые функциями ‘f_1’, ‘f_2’, ...,
     целыми числами длиной одно слово.

     Функция ‘modedeclare’ является синонимом ‘mode_declare’.

 -- Функция: mode_identity (<arg_1>, <arg_2>)
     Специальная форма, используемая вместе с ‘mode_declare’ и ‘macros’
     для объявления, например, списка списков чисел с плавающей точкой
     или других подобных составных объектов.  Первый аргумент
     ‘mode_identity’ есть имя типа, как в ‘mode_declare’ (т.е.  одно из
     ‘float’, ‘fixnum’, ‘number’, ‘list’ или ‘any’), а второй аргумент
     есть выражение, которое вычисляется и возвращается как значение
     ‘mode_identity’.  Если возвращаемое значение недопустимо для
     декларации типа, указанного в первом аргументе, то случается ошибка
     или печатается предупреждение.  Важно то, что тип выражения для
     транслятора Maxima в Lisp будет всегда определяться первым
     аргументом, вне зависимости от того, что происходит со вторым.
     Например, ‘x: 3.3; mode_identity (fixnum, x);’ дает ошибку а
     ‘mode_identity (flonum, x)’ возвращает 3.3.  С этим связан ряд
     проблем, например, если известно, что ‘first (l)’ возвращает число,
     то можно написать ‘mode_identity (number, first (l))’.  Но более
     эффективно будет определить новый примитив

          firstnumb (x) ::= buildq ([x], mode_identity (number, first(x)));

     и использовать ‘firstnumb’ всякий раз при обращении к первому
     элементу списка чисел.

 -- Управляющая переменная: transcompile
     Значение по умолчанию: ‘true’

     Если ‘transcompile’ равно ‘true’, то ‘translate’ и ‘translate_file’
     создают декларации, которые делают транслируемый код более удобным
     для компиляции.

     Функция ‘compfile’ устанавливает ‘transcompile: true’ на время
     своей работы.

 -- Функция: translate (<f_1>, ..., <f_n>)
 -- Функция: translate (functions)
 -- Функция: translate (all)
     Транслирует определенные пользователем функции <f_1>, ..., <f_n> из
     языка Maxima в Lisp и вычисляет результат трансляции.  Обычно,
     транслированные функции работают быстрее оригиналов.

     Вызов ‘translate (all)’ или ‘translate (functions)’ транслирует все
     определенные пользователем функции.

     Транслируемые функции должны, где это возможно, содержать в начале
     кода вызовы ‘mode_declare’, для генерации более эффективного кода.

     Например:

          f (x_1, x_2, ...) := block ([v_1, v_2, ...],
              mode_declare (v_1, mode_1, v_2, mode_2, ...), ...)


     где <x_1>, <x_2>, ...  – параметры функции, а <v_1>, <v_2>, ...  –
     локальные переменные.

     Имена транслированных функций удаляются из списка ‘functions’ если
     значение ‘savedef’ равно ‘false’ (см.  ниже) и добавляются к списку
     ‘props’.

     Не следует транслировать недостаточно отлаженные функции.

     При трансляции, выражения предполагаются уже упрощенными.  Если это
     не так, то будет сгенерирован правильный но неоптимальный код.
     Таким образом, не следует устанавливать переключатель ‘simp’ равным
     ‘false’, что подавляет упрощение транслируемых выражений.

     Если переключатель ‘translate’ равен ‘true’, то все определяемые
     пользователем функции автоматически транслируются в Lisp.

     Отметим, что транслируемые функции могут работать не совсем так,
     как до трансляции, т.к.  существуют некоторые несовместимости между
     Lisp и Maxima версиями функции.  Главным образом, функция ‘rat’,
     имеющая более одного параметра, и функция ‘ratvars’ не должны
     использоваться, если некоторые переменные объявлены ‘mode_declare’
     каноническими рациональными выражениями (КРВ). Кроме того,
     ‘prederror: false’ не транслируется.

     Если ‘savedef’ равна ‘true’, то Maxima версия сохраняется при
     трансляции.  Это позволяет выводить определение функции при помощи
     ‘dispfun’ и редактировать его.

     Если ‘transrun’ равна ‘false’, то интерпретируемые варианты будут
     выполняться (если они еще доступны) вместо транслированных для всех
     вызовов функций.

     Функция ‘translate’ возвращает список транслированных функций.

 -- Функция: translate_file (<maxima_filename>)
 -- Функция: translate_file (<maxima_filename>, <lisp_filename>)
     Транслирует файл кода Maxima в файлд кода Lisp.  Функция
     ‘translate_file’ возвращает список трех имен файлов: имя файла
     Maxima, имя файла Lisp и имя файла, содержащего дополнительную
     информацию о трансляции.  Функция ‘translate_file’ вычисляет свои
     аргументы.

     Команды ‘translate_file ("foo.mac"); load("foo.LISP")’ дают тот же
     результат, что и ‘batch ("foo.mac")’ за исключением некоторых
     ограничений, например, на использование ‘''’ и ‘%’.

     Вызов ‘translate_file (<maxima_filename>)’ транслирует файл Maxima
     <maxima_filename> в Lisp файл с аналогичным именем.  Например,
     ‘foo.mac’ транслируется в ‘foo.LISP’.  Имя файла Maxima может
     включать имена директорий, и результирующий Lisp файл будет записан
     в ту же директорию, где располагается исходный файл Maxima.

     Вызов ‘translate_file (<maxima_filename>, <lisp_filename>)’
     транслирует файл Maxima <maxima_filename> в Lisp файл
     <lisp_filename>.  ‘translate_file’ игнорирует расширение имени
     файла для ‘lisp_filename’, если таковое задано.  Расширение Lisp
     файла всегда будет ‘LISP’.  Имя Lisp файла может содержать имена
     директорий, и в этом случае файл будет записан в заданную
     директорию.

     ‘translate_file’ также записывает файл предупреждений транслятора,
     разной степени важности.  Расширение имени этого файла – ‘UNLISP’.
     Этот файл может содержать ценную информацию, возможно туманную, для
     обнаружения ошибок в транслированном коде.  Файл ‘UNLISP’ всегда
     записывается в ту же директорию, где расположен исходный файл
     Maxima.

     ‘translate_file’ генерирует код, в котором некоторые декларации и
     определения вступают в силу сразу в процессе компиляции Lisp кода.
     См.  также ‘compile_file’ по этому поводу.

     См.  также ‘tr_array_as_ref’, ‘tr_bound_function_applyp’,
     ‘tr_exponent’, ‘tr_file_tty_messagesp’,
     ‘tr_float_can_branch_complex’, ‘tr_function_call_default’,
     ‘tr_numer’, ‘tr_optimize_max_loop’, ‘tr_semicompile’,
     ‘tr_state_vars’, ‘tr_warnings_get’, ‘tr_warn_bad_function_calls’,
     ‘tr_warn_fexpr’, ‘tr_warn_meval’, ‘tr_warn_mode’,
     ‘tr_warn_undeclared’, ‘tr_warn_undefined_variable’ и ‘tr_windy’.

 -- Управляющая переменная: transrun
     Значение по умолчанию: ‘true’

     Если ‘transrun’ равна ‘false’, то для всех функций интерпретируемые
     варианты будут выполняться (если они еще доступны) вместо
     транслированных.

 -- Управляющая переменная: tr_array_as_ref
     Значение по умолчанию: ‘true’

     Если ‘translate_fast_arrays’ равна ‘false’, то ссылки на массивы в
     Lisp коде, созданном ‘translate_file’, зависят от
     ‘tr_array_as_ref’.  Если ‘tr_array_as_ref’ равна ‘true’, то имена
     массивов вычисляются, иначе они рассматриваются в транслированном
     коде как буквальные символы.

     ‘tr_array_as_ref’ не действует если ‘translate_fast_arrays’ равна
     ‘true’.

 -- Управляющая переменная: tr_bound_function_applyp
     Значение по умолчанию: ‘true’

     Если ‘tr_bound_function_applyp’ равна ‘true’, то Maxima выдает
     предупреждение, если имеющая значение переменная (такая, как
     аргумент функции) используется как имя функции.

     Например, выражение ‘g (f, x) := f (x+1)’ вызовет предупреждение.

 -- Управляющая переменная: tr_file_tty_messagesp
     Значение по умолчанию: ‘false’

     Если ‘tr_file_tty_messagesp’ равна ‘true’, то сообщения,
     генерируемые ‘translate_file’ в процессе трансляции, отображаются
     на консоли и выводятся в UNLISP файл.  Если ‘false’, то сообщения
     выводятся только в UNLISP файл.

 -- Управляющая переменная: tr_float_can_branch_complex
     Значение по умолчанию: ‘true’

     Сообщает Maxima-Lisp транслятору, что функции ‘acos’, ‘asin’,
     ‘asec’ и ‘acsc’ могут возвращать комплексные значения.

     Эффект ‘tr_float_can_branch_complex’ заключается в следующем.
     Хотя, явного влияния на результат трансляции нет, но если этот флаг
     равен ‘true’, то ‘acos(x)’ имеет тип ‘any’, даже если ‘x’ имеет тип
     ‘float’ (как определено ‘mode_declare’).  Если ли же он равен
     ‘false’, то ‘acos(x)’ имеет тип ‘float’ тогда и тоько тогда, когда
     ‘x’ имеет тип ‘float’.

 -- Управляющая переменная: tr_function_call_default
     Значение по умолчанию: ‘general’

     Если равна ‘false’, то следует вызывать ‘meval’; если ‘expr’, то
     предполагать Lisp функцию с фиксированными аргументами; если
     ‘general’, то генерируется код, подходящий для ‘mexprs’ и ‘mlexprs’
     но не ‘macros’.  ‘general’ обеспечивает правильное связывание
     переменных в компилируемом коде.  В режиме ‘general’, при
     трансляции F(X), если F является связанной переменной, то
     предполагается ‘apply (f, [x])’, и в таком виде транслируется с
     печатью соответствующего предупреждения.  Нет необходимости
     выключать этот механизм.  С установками по умолчанию, отсутствие
     предупреждений не означает полную совместимость транслированного и
     интерпретируемого кода.

 -- Управляющая переменная: tr_numer
     Значение по умолчанию: ‘false’

     Если ‘tr_numer’ равна ‘true’, то для атомов, имеющих свойство
     ‘numer’, например, ‘%pi’, это свойство принимается во внимание
     транслятором.

 -- Управляющая переменная: tr_optimize_max_loop
     Значение по умолчанию: 100

     ‘tr_optimize_max_loop’ есть максимальное число раз, которое цикл
     макро-расширения и оптимизации транслятора будет повторен при
     трансляции формы.  Данный предел установлен для обнаружения ошибок
     макро-расширения и зацикливания оптимизатора.

 -- Управляющая переменная: tr_semicompile
     Значение по умолчанию: ‘false’

     Если ‘tr_semicompile’ равна ‘true’, то ‘translate_file’ и
     ‘compfile’ генерируют формы, которые будут макро-расширены но не
     скомпилированы в машинный код Lisp компилятором.

 -- Системная переменная: tr_state_vars
     Значение по умолчанию:
          [transcompile, tr_semicompile, tr_warn_undeclared, tr_warn_meval,
          tr_warn_fexpr, tr_warn_mode, tr_warn_undefined_variable,
          tr_function_call_default, tr_array_as_ref,tr_numer]

     Список переключателей, которые влияют на форму транслированного
     кода.  Эта информация полезна для отладки транслятора.  Сравнивая
     результат трансляции с ожидаемым для данного состояния результатом,
     можно обнаружить ошибки транслятора.

 -- Функция: tr_warnings_get ()
     Печатает список предупреждений, сгенерированных транслятором в
     процессе текущей трансляции.

 -- Управляющая переменная: tr_warn_bad_function_calls
     Значение по умолчанию: ‘true’

     – выдает предупреждение в случае вызова функции, который может быть
     неверным из-за неправильных деклараций, сделанных во время
     трансляции.

 -- Управляющая переменная: tr_warn_fexpr
     Значение по умолчанию: ‘compfile’

     – выдает предупреждение если встречается FEXPR. Обычно, FEXPR не
     должны присутствовать в транслированном коде.

 -- Управляющая переменная: tr_warn_meval
     Значение по умолчанию: ‘compfile’

     – выдает предупреждение при вызове функции ‘meval’.  Вызов ‘meval’
     означает проблему в транслированном коде.

 -- Управляющая переменная: tr_warn_mode
     Значение по умолчанию: ‘all’

     – выдает предупреждение, когда переменной присваивается значение,
     несовместимое с ее типом.

 -- Управляющая переменная: tr_warn_undeclared
     Значение по умолчанию: ‘compile’

     – управляет тем, когда печатать сообщения о необъявленных
     переменных.

 -- Управляющая переменная: tr_warn_undefined_variable
     Значение по умолчанию: ‘all’

     – печатает предупреждение, когда встречается необъявленная
     переменная.

 -- Управляющая переменная: tr_windy
     Значение по умолчанию: ‘true’

     – вызывает печать полезных комментариев и советов по
     программированию.

 -- Функция: compile_file (<filename>)
 -- Функция: compile_file (<filename>, <compiled_filename>)
 -- Функция: compile_file (<filename>, <compiled_filename>,
          <lisp_filename>)
     Транслирует файл Maxima <filename> в Lisp, выполняет компилятор
     Lisp и, если трансляция и компиляция успешны, то загружает
     скомпилированный код в Maxima.

     ‘compile_file’ возвращает список имен четырех файлов: изначального
     файла кода Maxima, транслированного Lisp файла, файла замечаний по
     трансляции и файла скомпилированного кода.  Если компиляция
     неуспешна, то последний элемент равен ‘false’.

     Некоторые декларации и определения активизируются сразу в процессе
     компиляции Lisp кода (без загрузки скомпилированного кода).  Сюда
     относятся функции, определенные при помощи оператора ‘:=’, макросы,
     определенные при помощи ‘::=’, ‘alias’, ‘declare’,
     ‘define_variable’, ‘mode_declare’ и ‘infix’, ‘matchfix’, ‘nofix’,
     ‘postfix’, ‘prefix’ а также ‘compfile’.

     Присваивания и вызовы функций не вычисляются до загрузки
     скомпилированного файла.  В частности, присваивания флагам
     трансляции (‘tr_numer’ и т.п.)  внутри Maxima файла не оказывают
     влияния на результат трансляции.

     Файл <filename> не может содержать специальные ‘:lisp’ команды.

     Функция ‘compile_file’ вычисляет свои аргументы.

 -- Функция: declare_translated (<f_1>, <f_2>, ...)
     При трансляции кода Maxima в код Lisp, транслятору важно знать,
     какие функции следует вызывать как транслированные или
     компилированные, а какие как обычные Maxima функции или
     неопределенные.  Данная декларация, помещенная в начале
     транслируемого файла, дает транслятору информацию, что хотя <f_n> и
     не имеет свойство Lisp функции во время трансляции, но будет иметь
     таковое в момент вызова.  Если транслятор не знает, что ‘fn’ будет
     Lisp функцией, то генерируется код ‘(MFUNCTION-CALL fn arg1 arg2
     ...)’.


File: maxima.info,  Node: Программы Maxima,  Next: Отладка,  Prev: Определение функций,  Up: Top

38 Программы Maxima
*******************

* Menu:

* Введение в программирование на Maxima::
* Функции и переменные для программирования на Maxima::


File: maxima.info,  Node: Введение в программирование на Maxima,  Next: Функции и переменные для программирования на Maxima,  Prev: Программы Maxima,  Up: Программы Maxima

38.1 Введение в программирование на Maxima
==========================================

Maxima предоставляет цикл ‘do’, для итерации, а также более простые
управляющие конструкции, такие как ‘go’.


File: maxima.info,  Node: Функции и переменные для программирования на Maxima,  Prev: Введение в программирование на Maxima,  Up: Программы Maxima

38.2 Функции и переменные для программирования на Maxima
========================================================

 -- Функция: backtrace ()
 -- Функция: backtrace (<n>)
     Печатает стек вызовов, т.е.  список функций, которые вызывают
     текущую активную функцию.

     Вызов ‘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’ используется для выполнения итераций.  Т.к.  команда
     ‘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

 -- Функция: errcatch (<expr_1>, ..., <expr_n>)
     Вычисляет одно за другим выражения <expr_1>, ..., <expr_n> и, если
     не возникает ошибок, возвращает ‘[<expr_n>]’ (список).  Если при
     вычислении одного из аргументов возникает ошибка, то ‘errcatch’
     предотвращает дальнейшее распространение ошибки и возвращает пустой
     список ‘[]’ без дальнейшего вычисления аргументов.

     Функция ‘errcatch’ полезна в пакетных ‘batch’ файлах, если
     ожидается возможное возникновение ошибки, что без перехвата ошибки
     приводит к завершению ‘batch’.

 -- Функция: error (<expr_1>, ..., <expr_n>)
 -- Системная переменная: error
     Вычисляет и печатает <expr_1>, ..., <expr_n>, и затем вызывает
     ошибку, что возвращает управление на верхний уровень Maxima или
     ближайшему объемлющему ‘errcatch’.

     Значением переменной ‘error’ является список, описывающий ошибку.
     Первый элемент ‘error’ – строка форматирования, которая объединяет
     все строки из параметров <expr_1>, ..., <expr_n>, остальные
     элементы – есть значения нестроковых аргументов.

     Функция ‘errormsg()’ форматирует и печатает ‘error’, что повторяет
     печать самой последней ошибки.

 -- Функция: errormsg ()
     Повторяет печать самой последней ошибки.  Информация об ошибке
     содержится в переменной ‘error’, и ‘errormsg’ форматирует и
     печатает ее.

 -- Специальный оператор: for
     Используется в циклах.  См.  ‘do’ для описания средств Maxima для
     организации итераций.

 -- Функция: go (<tag>)
     Используется внутри блока ‘block’ для передачи управления на
     команду, помеченную параметром ‘go’.  Для пометки команды в блоке,
     перед ней помещают другую команду в виде атома (метки).  Например:

          block ([x], x:1, loop, x+1, ..., go(loop), ...)

     Аргументом ‘go’ должна быть метка, определенная в том же блоке
     ‘block’.  Нельзя использовать ‘go’ для передачи управления на метку
     в блоке отличном от того, где находится сама команда ‘go’.

 -- Специальный оператор: if
     Условное вычисление.  Существуют различные формы условного
     выражения ‘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         логический, префиксный

 -- Функция: map (<f>, <expr_1>, ..., <expr_n>)
     Возвращает выражение, с оператором верхнего уровня таким же как у
     выражений <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]



 -- Функция: mapatom (<expr>)
     Возвращает ‘true’ тогда и только тогда, когда выражение <expr>
     рассматривается map-процедурами как атомарное выражение.  К таким
     "mapatoms" относятся атомы, числа (включая рациональные) и
     переменные с индексом.

 -- Управляющая переменная: maperror
     Значение по умолчанию: ‘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’, то в оба вышеуказанных случая
     считаются ошибками.

 -- Управляющая переменная: mapprint
     Значение по умолчанию: ‘true’

     Если переменная ‘mapprint’ равна ‘true’, то функции ‘map’, ‘mapl’ и
     ‘fullmap’ в определенных ситуациях выдают различные сообщения.
     Включая ситуации, когда ‘map’ использует ‘apply’ или ‘map’ обрезает
     до самого короткого списка.

     Если ‘mapprint’ равна ‘false’, то данные сообщения подавляются.

 -- Функция: maplist (<f>, <expr_1>, ..., <expr_n>)
     Возвращает список с <f>, примененной к частям выражений <expr_1>,
     ..., <expr_n>.  <f> – есть имя функции или лямбда-выражение.

     Функция ‘maplist’ отличается от ‘map (<f>, <expr_1>, ...,
     <expr_n>)’, которая возвращает выражение с главным оператором,
     одним для всех выражений <expr_i> (за исключеним упрощений и
     случая, когда ‘map’ выполняет ‘apply’).

 -- Управляющая переменная: prederror
     Значение по умолчанию: ‘false’

     Если ‘prederror’ равна ‘true’, то ошибка случается всякий раз, как
     только вычисленное значение предиката команды ‘if’ или функции ‘is’
     отлично от ‘true’ или ‘false’.

     Если ‘false’, то в этом случае возвращается ‘unknown’.  Работа с
     ‘prederror: false’ не поддерживается транслированном коде.  Однако,
     ‘maybe’ поддерживается в транслированном коде.

     См.  также ‘is’ и ‘maybe’.

 -- Функция: return (<value>)
     Используется для явного выхода из блока, делая <value> значением
     этого блока.  См.  ‘block’ для более детального описания.

 -- Функция: scanmap (<f>, <expr>)
 -- Функция: scanmap (<f>, <expr>, bottomup)
     Применяет функцию <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))

     В данном случае результат одинаков для обоих вариантов вызова.

 -- Функция: throw (<expr>)
     Вычисляет выражение <expr> и "бросает" его значение вверх до
     ближайшего ‘catch’.  Функции ‘throw’ и ‘catch’ реализуют механизм
     нелокального возврата.

 -- Специальный оператор: while
 -- Специальный оператор: unless
     См.  ‘do’.

 -- Функция: outermap (<f>, <a_1>, ..., <a_n>)
     Применяет функцию <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


File: maxima.info,  Node: Отладка,  Next: Пакет augmented_lagrangian,  Prev: Программы Maxima,  Up: Top

39 Отладка
**********

* Menu:

* Отладка исходного кода::
* Специальные команды::
* Функции и переменные для отладки::


File: maxima.info,  Node: Отладка исходного кода,  Next: Специальные команды,  Up: Отладка

39.1 Отладка на уровне исходного кода
=====================================

Maxima имеет отладчик исходного кода.  Пользователь может определить в
функции точку останова и и продолжить выполнение с этой точки строка за
строкой.  При этом возможно анализировать стек вызовов и переменные,
имеющие значение на данном уровне.

   Команда ‘:help’, или просто ‘:h’, выводит список команд отладчика.
(Команды могут быть сокращены, если сокращение однозначно.  Если оно
неоднозначно, то будет выведен список альтернатив.)  В отладчике
пользователь может также использовать обычные команды Maxima для
исследования, определения и манипулирования переменными и выражениями.

   Точка останова задается командой ‘:br’ в командной строке Maxima.  В
отладчике, пользователь может продвигаться по одной строке за раз с
помощью команды ‘:n’ (“next”).  Команда ‘:bt’ (“backtrace”) выводит
список кадров стека.  Команда ‘:r’ (“resume”) завершает отладчик и
продолжает выполнение программы.  Данные команды проиллюстрированы в
следующем примере.

     (%i1) load ("/tmp/foobar.mac");

     (%o1)                           /tmp/foobar.mac

     (%i2) :br foo
     Turning on debugging debugmode(true)
     Bkpt 0 for foo (in /tmp/foobar.mac line 1)

     (%i2) bar (2,3);
     Bkpt 0:(foobar.mac 1)
     /tmp/foobar.mac:1::

     (dbm:1) :bt                        <-- :bt выводим обратную трассировку вызовов
     #0: foo(y=5)(foobar.mac line 1)
     #1: bar(x=2,y=3)(foobar.mac line 9)

     (dbm:1) :n                         <-- :n продвигаем выполнение на одну строку
     (foobar.mac 2)
     /tmp/foobar.mac:2::

     (dbm:1) :n                         <-- :n продвигаем выполнение на одну строку
     (foobar.mac 3)
     /tmp/foobar.mac:3::

     (dbm:1) u;                         <-- Исследуем знасение переменной u
     28

     (dbm:1) u: 33;                     <-- Устанавливаем значение u равным 33
     33

     (dbm:1) :r                         <-- :r to возобновляем выполнение программы

     (%o2)                                1094

   Содержимое файла ‘/tmp/foobar.mac’:

     foo(y) := block ([u:y^2],
       u: u+3,
       u: u^2,
       u);

     bar(x,y) := (
       x: x+2,
       y: y+2,
       x: foo(y),
       x+y);

   Использование Отладчика в Редакторе Emacs

   Если пользователь выполняет программу в командном окне отладчика
(dbl) редактора GNU emacs или в графической оболочке Xmaxima, то при
достижении точки останова в другой части окна будет показан участок
исходного кода с текущей строкой, выделенной либо красным цветом, либо
маленькой стрелкой.  Пользователь может продолжить выполнение программы
построчно, нажимая M-n (Alt-n).

   Для использования в Emacs отладчика ‘dbl’ требуется файл ‘dbl.el’,
расположенный в директории elisp.  Убедитесь, что файлы elisp
установлены или добавьте директорию elisp программы Maxima к пути:
например, добавте следующие строки к файлу ‘.emacs’ или файлу
‘site-init.el’

     (setq load-path (cons "/usr/share/maxima/5.9.1/emacs" load-path))
     (autoload 'dbl "dbl")

   После этого при вводе

     M-x dbl

   в emacs должно открываться командное окно, в котором можно выполнять
программы, например, Maxima, gcl, gdb и т.д.  Это командное окно “знает”
об отладке исходного кода, который открыт в другом окне редактора.

   Пользователь может установить точку останова в определенной строке
кода, нажав на ‘C-x space’.  При этом производится анализ: в какой
функции находится данная строка и на какой по порядку строке этой
функции стоит курсор.  Если курсор расположен, скажем, на строке 2
функции ‘foo’, тогда в командном окно будет введена команда “‘:br foo
2’”, которая задает точку останова на второй строке функции ‘foo’.  Для
того, чтобы все это работало необходимо, чтобы в окне файла ‘foobar.mac’
был включен режим maxima-mode.el.  Существуют еще дополнительные
команды, доступные в таком окне, такие как вычисление функций Maxima при
нажатии ‘Alt-Control-x’.


File: maxima.info,  Node: Специальные команды,  Next: Функции и переменные для отладки,  Prev: Отладка исходного кода,  Up: Отладка

39.2 Специальные команды
========================

Специальные команды, это ключевые слова, которые не интерпретируются
Maxima как обычные выражения.  Специальные команды вводятся в командной
строке Maxima или отладчика, но не в точке останова.  Все специальные
команды начинаются с двоеточия ’‘:’’.  Например, для вычисления Lisp
формы можно ввести ‘:lisp’ с последующей формой.

     (%i1) :lisp (+ 2 3)
     5

   Число параметров зависит от конкретной команды.  Кроме того, не
обязательно вводить всю команду целиком, достаточно ввести столько,
чтобы сделать команду однозначно определенной среди всех ключевых слов.
Таким образом, для ‘:break’ достаточно ввести ‘:br’.

   Специальные команды перечислены ниже:

‘:break F n’
     Задает точку останова в функции ‘F’ на строке номер ‘n’ от ее
     начала.  Если ‘F’ является строкой, тогда он рассматривается как
     файл и смещение ‘n’ отсчитывается от начала этого файла.  Смещение
     является необязательным.  Если оно не указано, то предполагается
     равным нулю (первая строка функции или файла).
‘:bt’
     Выводит обратную трассировку кадров стека
‘:continue’
     Продолжает вычисление
‘:delete’
     Удаляет заданную точку останова или все, если ни одна не задана
‘:disable’
     Деактивирует заданную точку останова или все, если ни одна не
     задана
‘:enable’
     Активирует заданную точку останова или все, если ни одна не задана
‘:frame n’
     Выводит кадр стека номер ‘n’ или текущий кадр, если номер не указан
‘:help’
     Печатает справку по указанной команде или по всем если ни одна не
     задана
‘:info’
     Печатает информацию об элементе
‘:lisp some-form’
     Вычисляет ‘some-form’ в качестве Lisp формы
‘:lisp-quiet some-form’
     Вычисляет Lisp форму ‘some-form’ без вывода результата
‘:next’
     Как ‘:step’, но ‘:next’ пропускает вызовы функций
‘:quit’
     Выход из текущего уровня отладчика без завершение вычислений
‘:resume’
     Продолжает вычисление
‘:step’
     Продолжает вычисление до достижения новой строки
‘:top’
     Возвращает на уровень командного приглашения Maxima с любого уровня
     отладчика без завершения вычислений


File: maxima.info,  Node: Функции и переменные для отладки,  Prev: Специальные команды,  Up: Отладка

39.3 Функции и переменные для отладки
=====================================

 -- Управляющая переменная: refcheck
     Значение по умолчанию: ‘false’

     Если ‘refcheck’ равна ‘true’, то Maxima печатает сообщение каждый
     раз как имеющая значение переменная используется в вычислении
     первый раз.

 -- Управляющая переменная: setcheck
     Значение по умолчанию: ‘false’

     Если ‘setcheck’ равно списку переменных (возможно с индексом), то
     Maxima печатает сообщение всякий раз как переменным, или переменным
     с индексом, присваивается значение при помощи обычного оператора
     присваивания ‘:’, или оператора присваивания ‘::’, или при
     связывании параметров функций, но не при определении функций ‘:=’
     или макросов ‘::=’.  Сообщение содержит имя переменной и
     присваиваемое значение.

     Переменной ‘setcheck’ может быть присвоено значение ‘all’ или
     ‘true’, что подразумевает все переменные.

     Каждое присваивание ‘setcheck’ устанавливает новый список
     контролируемых переменных и все переменные, которые ранее были в
     списке ‘setcheck’, забываются.

     Переменные, присваиваемые ‘setcheck’ должны быть экранированы,
     иначе они могут быть вычислены.  Например, если переменные ‘x’, ‘y’
     и ‘z’ уже имеют значения, тогда

          setcheck: ['x, 'y, 'z]$

     устанавливает контроль присваивания для этих переменных.

     Сообщение не выводится, если переменной, включенной в список
     ‘setcheck’, присваивается значение равное ей самой, например, ‘X:
     'X’.

 -- Управляющая переменная: setcheckbreak
     Значение по умолчанию: ‘false’

     Если ‘setcheckbreak’ равно ‘true’, то Maxima генерирует прерывание
     всякий раз как переменной из списка ‘setcheck’ присваивается новое
     значение.  Прерывание случается до присваивания нового значения.  В
     этот момент, переменная ‘setval’ содержит новое значение
     переменной.  Таким образом, возможно присвоить переменной другое
     значение путем присваивания его переменной ‘setval’.

     См.  также ‘setcheck’ и ‘setval’.

 -- Системная переменная: setval
     Содержит новое значение, которое будет присвоено переменной, если
     случается прерывание, контролируемое ‘setcheckbreak’.  Таким
     образом, возможно присвоить переменной другое значение путем
     присваивания его переменной ‘setval’.

     См.  также ‘setcheck’ и ‘setcheckbreak’.

 -- Функция: timer (<f_1>, ..., <f_n>)
 -- Функция: timer (all)
 -- Функция: timer ()
     Добавляет функции <f_1>, ..., <f_n> к списку функций, для которых
     собирается статистика тайминга.  Последовательные вызовы ‘timer(f)$
     timer(g)$’ сначала добавляют к списку ‘f’ а затем ‘g’, т.е.  список
     пополняется от одного вызова ‘timer’ к другому.

     ‘timer(all)’ добавляет все пользовательские функции, которые
     определяются глобальной переменной ‘functions’, к списку
     контролируемых функций.

     Без аргументов, ‘timer’ возвращает список контролируемых функций.

     Maxima сохраняет информацию о времени выполнения контролируемых
     функций.  Функция ‘timer_info’ возвращает статистику тайминга,
     включающую: среднее время выполнения, число вызовов и полное время
     выполнения.  Функция ‘untimer’ удаляет функцию из списка
     контролируемых функций.

     ‘timer’ не вычисляет свои аргументы.  Команды ‘f(x) := x^2$ g:f$
     timer(g)$’ не добавят ‘f’ к списку тайминг-контроля.

     Если действует трассировка ‘trace(f)’, то ‘timer(f)’ не работает,
     т.к.  ‘trace’ и ‘timer’ не могут действовать одновременно.

     См.  также ‘timer_devalue’.

 -- Функция: untimer (<f_1>, ..., <f_n>)
 -- Функция: untimer ()
     Удаляет функции <f_1>, ..., <f_n> из списка тайминг-контроля.

     Без аргументов, ‘untimer’ удаляет все функции из списка
     тайминг-контроля.

     После выполнения ‘untimer (f)’, функция ‘timer_info (f)’ продолжает
     содержать ранее собранную статистику, хотя ‘timer_info()’ (без
     аргументов) не возвращает информацию о функциях, которые на данный
     момент не включены в список тайминг-контроля.  Вызов ‘timer (f)’
     обнуляет всю предыдущую статистику и снова добавляет ‘f’ к списку
     тайминг-контроля.

 -- Управляющая переменная: timer_devalue
     Значение по умолчанию: ‘false’

     Если ‘timer_devalue’ равно ‘true’, то Maxima вычитает из статистики
     контролируемой функции время выполнения других контролируемых
     функций.  В противном случае, статистика каждой функции включает
     время, затраченное на выполнение других функций.  Заметим, что
     время, затраченное на выполнение неконтролируемых функций, не
     вычитается из общего времени.

     См.  также ‘timer’ и ‘timer_info’.

 -- Функция: timer_info (<f_1>, ..., <f_n>)
 -- Функция: timer_info ()
     Для функций <f_1>, ..., <f_n>, возвращает матрицу, содержащую
     информацию о тайминге каждой из функций.  Без аргументов,
     ‘timer_info’ возвращает информацию для всех контролируемых функций.

     Матрица, возвращаемая ‘timer_info’, содержит: имя функции, среднее
     время вызова функции, число вызовов, общее время и ‘gctime’, что
     обозначает "время сборки мусора" в Macsyma, но сейчас это время
     всегда равно нулю.

     Данные, сообщаемые ‘timer_info’, могут быть получены другим
     способом при помощи функции ‘get’:

          get(f, 'calls);  get(f, 'runtime);  get(f, 'gctime);

     См.  также ‘timer’.

 -- Функция: trace (<f_1>, ..., <f_n>)
 -- Функция: trace (all)
 -- Функция: trace ()
     Устанавливает трассировку для функций <f_1>, ..., <f_n>, т.е.
     Maxima будет печатать отладочную информацию при каждом вызове любой
     из этих функций.  Последовательные вызовы ‘trace(f)$ trace(g)$’
     сначала включает трассировку ‘f’ а затем трассировку ‘g’, т.е.
     список трассируемых функций пополняется от одного вызова ‘trace’ к
     другому.

     ‘trace(all)’ включает трассировку для всех пользовательских
     функций, которые определяются глобальной переменной ‘functions’.

     Без аргументов, ‘trace’ возвращает список всех трассируемых
     функций.

     Функция ‘untrace’ отменяет трассировку.  См.  также
     ‘trace_options’.

     Функция ‘trace’ не вычисляет свои аргументы.  Команды ‘f(x) := x^2$
     g:f$ trace(g)$’ не добавят ‘f’ к списку трассируемых функций.

     Если функция переопределяется, то она удаляется из списка
     трассируемых функций.  Т.е.  после ‘timer(f)$ f(x) := x^2$’,
     функция ‘f’ трассироваться не будет.

     Если действует ‘timer (f)’, то ‘trace (f)’ не работает; т.к.
     ‘trace’ и ‘timer’ не могут действовать одновременно.

 -- Функция: trace_options (<f>, <option_1>, ..., <option_n>)
 -- Функция: trace_options (<f>)
     Устанавливает опции трассировки для функции <f>.  Любые предыдущие
     опции переопределяются.  ‘trace_options (<f>, ...)’ не действует
     если не включена трассировка ‘trace (<f>)’ (либо до, либо после
     вызова ‘trace_options’).

     ‘trace_options (<f>)’ возвращает все опции в значение "по
     умолчанию".

     Существуют следующие ключевые слова опций трассировки:

        • ‘noprint’ Не печатать сообщения при начале и завершении
          выполнения функции.
        • ‘break’ Установить точки останова до начала выполнения функции
          и после ее завершения.  См.  ‘break’.
        • ‘lisp_print’ Выводить аргументы и возвращаемые значения в виде
          Lisp объектов.
        • ‘info’ Печатать ‘-> true’ при входе и выходе из функции.
        • ‘errorcatch’ Перехватывать ошибки с предоставлением опций:
          сгенерировать ошибку, вычислить функцию повторно, задать
          возвращаемое значение.

     Опции трассировки могут задаваться двумя способами.  Одно ключевое
     слово включает соответствующую опцию безусловно.  Заметим, что для
     включения опции <foo> не следует указывать ‘<foo>: true’, кроме
     того, опции не надо экранировать.  Ключевое слово с предикатом
     включает опцию условно в зависимости от значения предиката.

     Существуют следующие аргументы предиката ‘[level, direction,
     function, item]’, где ‘level’ есть уровень рекурсии; ‘direction’
     есть либо ‘enter’, либо ‘exit’; ‘function’ есть имя функции; и
     ‘item’ есть список аргументов (при входе) или возвращаемое значение
     (при выходе).

     Пример применения безусловных опций трассировки:

          (%i1) ff(n) := if equal(n, 0) then 1 else n * ff(n - 1)$

          (%i2) trace (ff)$

          (%i3) trace_options (ff, lisp_print, break)$

          (%i4) ff(3);

     Ниже, та же функция условной опцией трассировки ‘break’:

          (%i5) trace_options (ff, break(pp))$

          (%i6) pp (level, direction, function, item) := block (print (item),
              return (function = 'ff and level = 3 and direction = exit))$

          (%i7) ff(6);

 -- Функция: untrace (<f_1>, ..., <f_n>)
 -- Функция: untrace ()
     Отменяет трассировку функций <f_1>, ..., <f_n>, установленную ранее
     при помощи ‘trace’.  Без аргументов, ‘untrace’ отменяет трассировку
     всех функций.

     Функция ‘untrace’ возвращает список функций, для которых была
     отменена трассировка.


File: maxima.info,  Node: Пакет augmented_lagrangian,  Next: Пакет bode,  Prev: Отладка,  Up: Top

40 Пакет augmented_lagrangian
*****************************

* Menu:

* Функции и переменные пакета augmented_lagrangian::


File: maxima.info,  Node: Функции и переменные пакета augmented_lagrangian,  Prev: Пакет augmented_lagrangian,  Up: Пакет augmented_lagrangian

40.1 Функции и переменные пакета augmented_lagrangian
=====================================================

 -- Функция: augmented_lagrangian_method (<FOM>, <xx>, <C>, <yy>)
 -- Функция: augmented_lagrangian_method (<FOM>, <xx>, <C>, <yy>,
          optional_args)

     Возвращает приближенный минимум выражения <FOM> по переменным <xx>,
     при связях <C>, равных нулю.  <yy> – список затравочных начальных
     значений <xx>.  Для нахождения минимума используется метод
     расширенного лагранжиана (см.  [1] и [2]).

     ‘optional_args’ – дополнительные аргументы, задаваемые в форме
     ‘<symbol> = <value>’.  Допустимы следующие дополнительные
     аргументы:

     ‘niter’
          Число итераций алгоритма расширенного лагранжиана
     ‘lbfgs_tolerance’
          Допустимое отклонение для LBFGS
     ‘iprint’
          Параметр IPRINT (список двух целых чисел, которые управляют
          уровнем вывода) для LBFGS
     ‘%lambda’
          Начальное значение ‘%lambda’ для вычисления расширенного
          лагранжиана

     Данная реализация минимизирует расширенный лагранжиан методом BFGS
     с ограничением памяти (LBFGS), являющимся квази-нюьтоновым
     алгоритмом.

     Команда ‘load("augmented_lagrangian")’ загружает данную функцию.

     См.  также ‘lbfgs’.

     Ссылки:

     [1]
     <http://www-fp.mcs.anl.gov/otc/Guide/OptWeb/continuous/constrained/nonlinearcon/auglag.html>

     [2] <http://www.cs.ubc.ca/spider/ascher/542/chap10.pdf>

     Пример:

          (%i1) load ("lbfgs");
          (%o1)     /maxima/share/lbfgs/lbfgs.mac
          (%i2) load ("augmented_lagrangian");
          (%o2)
             /maxima/share/contrib/augmented_lagrangian.mac
          (%i3) FOM: x^2 + 2*y^2;
                                         2    2
          (%o3)                       2 y  + x
          (%i4) xx: [x, y];
          (%o4)                        [x, y]
          (%i5) C: [x + y - 1];
          (%o5)                      [y + x - 1]
          (%i6) yy: [1, 1];
          (%o6)                        [1, 1]
          (%i7) augmented_lagrangian_method(FOM, xx, C, yy, iprint=[-1,0]);
          (%o7) [[x = 0.66665984108002, y = 0.33334027245545],
                                           %lambda = [- 1.333337940892525]]


File: maxima.info,  Node: Пакет bode,  Next: Пакет contrib_ode,  Prev: Пакет augmented_lagrangian,  Up: Top

41 Пакет bode
*************

* Menu:

* Функции и переменные пакета bode::


File: maxima.info,  Node: Функции и переменные пакета bode,  Prev: Пакет bode,  Up: Пакет bode

41.1 Функции и переменные пакета bode
=====================================

 -- Функция: bode_gain (<H>, <range>, ...<plot_opts>...)
     Функция для построения амплитудной диаграммы Боде.

     Примеры (c 1 по 7 из
          <http://www.swarthmore.edu/NatSci/echeeve1/Ref/Bode/BodeHow.html>,
     8 от Ron Crummett):
          (%i1) load("bode")$

          (%i2) H1 (s) := 100 * (1 + s) / ((s + 10) * (s + 100))$

          (%i3) bode_gain (H1 (s), [w, 1/1000, 1000])$

          (%i4) H2 (s) := 1 / (1 + s/omega0)$

          (%i5) bode_gain (H2 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i6) H3 (s) := 1 / (1 + s/omega0)^2$

          (%i7) bode_gain (H3 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i8) H4 (s) := 1 + s/omega0$

          (%i9) bode_gain (H4 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i10) H5 (s) := 1/s$

          (%i11) bode_gain (H5 (s), [w, 1/1000, 1000])$

          (%i12) H6 (s) := 1/((s/omega0)^2 + 2 * zeta * (s/omega0) + 1)$

          (%i13) bode_gain (H6 (s), [w, 1/1000, 1000]),
                            omega0 = 10, zeta = 1/10$

          (%i14) H7 (s) := (s/omega0)^2 + 2 * zeta * (s/omega0) + 1$

          (%i15) bode_gain (H7 (s), [w, 1/1000, 1000]),
                            omega0 = 10, zeta = 1/10$

          (%i16) H8 (s) := 0.5 / (0.0001 * s^3 + 0.002 * s^2 + 0.01 * s)$

          (%i17) bode_gain (H8 (s), [w, 1/1000, 1000])$

     Для использования этой функции необходимо сначала выполнить
     ‘load("bode")’.  См.  также ‘bode_phase’

 -- Функция: bode_phase (<H>, <range>, ...<plot_opts>...)
     Функция для построения фазовой диаграммы Боде.

     Примеры (с 1 по 7 из
          <http://www.swarthmore.edu/NatSci/echeeve1/Ref/Bode/BodeHow.html>,
     8 от Ron Crummett):
          (%i1) load("bode")$

          (%i2) H1 (s) := 100 * (1 + s) / ((s + 10) * (s + 100))$

          (%i3) bode_phase (H1 (s), [w, 1/1000, 1000])$

          (%i4) H2 (s) := 1 / (1 + s/omega0)$

          (%i5) bode_phase (H2 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i6) H3 (s) := 1 / (1 + s/omega0)^2$

          (%i7) bode_phase (H3 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i8) H4 (s) := 1 + s/omega0$

          (%i9) bode_phase (H4 (s), [w, 1/1000, 1000]), omega0 = 10$

          (%i10) H5 (s) := 1/s$

          (%i11) bode_phase (H5 (s), [w, 1/1000, 1000])$

          (%i12) H6 (s) := 1/((s/omega0)^2 + 2 * zeta * (s/omega0) + 1)$

          (%i13) bode_phase (H6 (s), [w, 1/1000, 1000]),
                             omega0 = 10, zeta = 1/10$

          (%i14) H7 (s) := (s/omega0)^2 + 2 * zeta * (s/omega0) + 1$

          (%i15) bode_phase (H7 (s), [w, 1/1000, 1000]),
                             omega0 = 10, zeta = 1/10$

          (%i16) H8 (s) := 0.5 / (0.0001 * s^3 + 0.002 * s^2 + 0.01 * s)$

          (%i17) bode_phase (H8 (s), [w, 1/1000, 1000])$

          (%i18) block ([bode_phase_unwrap : false],
                        bode_phase (H8 (s), [w, 1/1000, 1000]));

          (%i19) block ([bode_phase_unwrap : true],
                        bode_phase (H8 (s), [w, 1/1000, 1000]));

     Для использования этой функции необходимо сначала выполнить
     ‘load("bode")’.  См.  также ‘bode_gain’


File: maxima.info,  Node: Пакет contrib_ode,  Next: Пакет descriptive,  Prev: Пакет bode,  Up: Top

42 Пакет contrib_ode
********************

* Menu:

* Введение в пакет contrib_ode::
* Функции и переменные пакета contrib_ode::
* Возможные улучшения пакета contrib_ode::
* Тесты пакета contrib_ode::
* Ссылки для пакета contrib_ode::


File: maxima.info,  Node: Введение в пакет contrib_ode,  Next: Функции и переменные пакета contrib_ode,  Prev: Пакет contrib_ode,  Up: Пакет contrib_ode

42.1 Введение в пакет contrib_ode
=================================

Стандартная процедура Maxima для решения обычных дифференциальных
уравнений (ОДУ) ‘ode2’ решает элементарные линейные ОДУ первого и
второго порядка.  Функция ‘contrib_ode’ расширяет ‘ode2’ дополнительными
методами для линейных и нелинейных ОДУ первого порядка и линейных
однородных ОДУ второго порядка.  Даная программа находится в состоянии
развития и форма вызова функций может измениться в последующих релизах.
После стабилизации код может быть перемещен из директории contrib и
интегрирован в ядро Maxima.

   Для использования пакет должен быть загружен с помощью команды
‘load("contrib_ode")’.

   Функция ‘contrib_ode’ вызывается также, как ‘ode2’.  Она имеет три
аргумента: ОДУ (если правая часть уравнения равна 0, то достаточно
задать только левые части уравнений), зависимая переменная и независимая
переменная.  В случае успеха возвращается список решений.

   Представление решений отличается от такового для ‘ode2’.  Т.к.
нелинейные уравнения могут иметь множественные решения., то
‘contrib_ode’ возвращает список решений.  Решение может иметь несколько
различных форм:
   • явное решение для зависимой переменной,

   • неявное решение для зависимой переменной,

   • параметрическое решение с параметром ‘%t’

   • преобразование в другое ОДУ для зависимой переменной ‘%u’.

   ‘%c’ представляет константу интегрирования для уравнений первого
порядка.  ‘%k1’ и ‘%k2’ – константы интегрирования для уравнений второго
порядка.  Если ‘contrib_ode’ не может получить решение, то возвращается
‘false’, возможно, после печати сообщения об ошибке.

   Необходимо возвращать список решений, т.к.  нелинейные ОДУ первого
порядка могут иметь множественные решения.  Например:

     (%i1) load("contrib_ode")$

     (%i2) eqn:x*'diff(y,x)^2-(1+x*y)*'diff(y,x)+y=0;

                         dy 2             dy
     (%o2)            x (--)  - (x y + 1) -- + y = 0
                         dx               dx
     (%i3) contrib_ode(eqn,y,x);

                                                  x
     (%o3)             [y = log(x) + %c, y = %c %e ]
     (%i4) method;

     (%o4)                        factor

   Нелинейные ОДУ могут иметь особые решения, не имеющие констант
интегрирования, как второе решение в следующем примере:

     (%i1) load("contrib_ode")$

     (%i2) eqn:'diff(y,x)^2+x*'diff(y,x)-y=0;

                            dy 2     dy
     (%o2)                 (--)  + x -- - y = 0
                            dx       dx
     (%i3) contrib_ode(eqn,y,x);

                                                2
                                      2        x
     (%o3)              [y = %c x + %c , y = - --]
                                               4
     (%i4) method;

     (%o4)                       clairault

   Следующее ОДУ имеет два параметрических решение в терминах переменной
‘%t’.  Из этих параметрических решений можно получить явные решения.

     (%i1) load("contrib_ode")$

     (%i2) eqn:'diff(y,x)=(x+y)^2;

                               dy          2
     (%o2)                     -- = (y + x)
                               dx
     (%i3) contrib_ode(eqn,y,x);

     (%o3) [[x = %c - atan(sqrt(%t)), y = - x - sqrt(%t)],
                          [x = atan(sqrt(%t)) + %c, y = sqrt(%t) - x]]
     (%i4) method;

     (%o4)                       lagrange

   Следующий пример (Камке 1.112) демонстрирует неявное решение.

     (%i1) load("contrib_ode")$

     (%i2) assume(x>0,y>0);

     (%o2)                    [x > 0, y > 0]
     (%i3) eqn:x*'diff(y,x)-x*sqrt(y^2+x^2)-y;

                          dy           2    2
     (%o3)              x -- - x sqrt(y  + x ) - y
                          dx
     (%i4) contrib_ode(eqn,y,x);

                                       y
     (%o4)                  [x - asinh(-) = %c]
                                       x
     (%i5) method;

     (%o5)                          lie

   Следующее уравнение Рикатти преобразуется в линейное ОДУ второго
порядка для переменной ‘%u’.  Maxima не может решить новое уравнение, и
оно возвращается нерешенным.
     (%i1) load("contrib_ode")$

     (%i2) eqn:x^2*'diff(y,x)=a+b*x^n+c*x^2*y^2;

                         2 dy      2  2      n
     (%o2)              x  -- = c x  y  + b x  + a
                           dx
     (%i3) contrib_ode(eqn,y,x);

                    d%u
                    ---                            2
                    dx        2     n - 2   a     d %u
     (%o3)  [[y = - ----, %u c  (b x      + --) + ---- c = 0]]
                    %u c                     2      2
                                            x     dx
     (%i4) method;

     (%o4)                        riccati

   Для ОДУ первого порядка ‘contrib_ode’ вызывает ‘ode2’.  Затем
применяются методы: факторизации, Клеро, Лагранжа, Рикатти, Абеля и
метод симметрий Ли.  Метод Ли не применяется к уравнениям Абеля, если
метод Абеля не дает результата, но применяется если метод Рикатти
возвращает нерешенное ОДУ второго порядка.

   Для ОДУ второго порядка ‘contrib_ode’ вызывает ‘ode2’, а затем
‘odelin’.

   Если выполнена команда ‘put('contrib_ode,true,'verbose)’, то
печатается подробная отладочная информация.


File: maxima.info,  Node: Функции и переменные пакета contrib_ode,  Next: Возможные улучшения пакета contrib_ode,  Prev: Введение в пакет contrib_ode,  Up: Пакет contrib_ode

42.2 Функции и переменные пакета contrib_ode
============================================

 -- Функция: contrib_ode (<eqn>, <y>, <x>)

     Возвращает список решение ОДУ <eqn> с независимой переменной <x> и
     зависимой переменной <y>.

 -- Функция: odelin (<eqn>, <y>, <x>)

     Функция ‘odelin’ решает линейные однородные ОДУ первого и второго
     порядка с независимой переменной <x> и зависимой переменной <y>.
     Она возвращает фундаментальный набор решений ОДУ.

     Для ОДУ второго порядка ‘odelin’ использует метод
     Бронштейна-Лафаля, который ищет решение в терминах заданных
     специальных функций.

          (%i1) load("contrib_ode");

          (%i2) odelin(x*(x+1)*'diff(y,x,2)+(x+5)*'diff(y,x,1)+(-4)*y,y,x);
          ...trying factor method
          ...solving 7 equations in 4 variables
          ...trying the Bessel solver
          ...solving 1 equations in 2 variables
          ...trying the F01 solver
          ...solving 1 equations in 3 variables
          ...trying the spherodial wave solver
          ...solving 1 equations in 4 variables
          ...trying the square root Bessel solver
          ...solving 1 equations in 2 variables
          ...trying the 2F1 solver
          ...solving 9 equations in 5 variables
                 gauss_a(- 6, - 2, - 3, - x)  gauss_b(- 6, - 2, - 3, - x)
          (%o2) {---------------------------, ---------------------------}
                              4                            4
                             x                            x


 -- Функция: ode_check (<eqn>, <soln>)

     Возвращает значение ОДУ <eqn> после подстановки в него возможного
     решения <soln>.  Значение эквивалентно нулю, если <soln> является
     решением <eqn>.

          (%i1) load("contrib_ode")$

          (%i2) eqn:'diff(y,x,2)+(a*x+b)*y;

                                   2
                                  d y
          (%o2)                   --- + (a x + b) y
                                    2
                                  dx
          (%i3) ans:[y = bessel_y(1/3,2*(a*x+b)^(3/2)/(3*a))*%k2*sqrt(a*x+b)
                   +bessel_j(1/3,2*(a*x+b)^(3/2)/(3*a))*%k1*sqrt(a*x+b)];

                                            3/2
                              1  2 (a x + b)
          (%o3) [y = bessel_y(-, --------------) %k2 sqrt(a x + b)
                              3       3 a
                                                    3/2
                                      1  2 (a x + b)
                           + bessel_j(-, --------------) %k1 sqrt(a x + b)]
                                      3       3 a
          (%i4) ode_check(eqn,ans[1]);

          (%o4)                           0

 -- Системная переменная: method

     Переменной ‘method’ присваивается название метода успешного решения
     ОДУ.

 -- Переменная: %c

     ‘%c’ – константа интегрирования для ОДУ первого порядка.

 -- Переменная: %k1

     ‘%k1’ – первая константа интегрирования для ОЛУ второго порядка.

 -- Переменная: %k2

     ‘%k2’ – вторая константа интегрирования для ОЛУ второго порядка.

 -- Функция: gauss_a (<a>, <b>, <c>, <x>)

     Функции ‘gauss_a(a,b,c,x)’ и ‘gauss_b(a,b,c,x)’ есть 2F1
     гипергеометрические функции.  Они представляют собой два
     независимых решения гипергеометрического уравнения ‘x(1-x)
     diff(y,x,2) + [c-(a+b+1)x diff(y,x) - aby = 0’ (A&S 15.5.1).

     Эти функции используются только в решениях ОДУ, возвращаемых
     ‘odelin’ и ‘contrib_ode’.  Определение и использование этих функций
     может измениться в последующих релизах Maxima.

     См.  также ‘gauss_b’, ‘dgauss_a’ и ‘gauss_b’.

 -- Функция: gauss_b (<a>, <b>, <c>, <x>)
     См.  ‘gauss_a’.

 -- Функция: dgauss_a (<a>, <b>, <c>, <x>)
     Производная ‘gauss_a(<a>, <b>, <c>, <x>)’ по <x>.

 -- Функция: dgauss_b (<a>, <b>, <c>, <x>)
     Производная ‘gauss_b(<a>, <b>, <c>, <x>)’ по <x>.

 -- Функция: kummer_m (<a>, <b>, <x>)

     M-функция Куммера, как она определена в Abramowitz и Stegun,
     Handbook of Mathematical Functions, Section 13.1.2.

     Эта функция используются только в решениях ОДУ, возвращаемых
     ‘odelin’ и ‘contrib_ode’.  Определение и использование этой функции
     может измениться в последующих релизах Maxima.

     См.  также ‘kummer_u’, ‘dkummer_m’ и ‘dkummer_u’.

 -- Функция: kummer_u (<a>, <b>, <x>)

     U-функция Куммера, как она определена в Abramowitz и Stegun,
     Handbook of Mathematical Functions, Section 13.1.3.

     См.  ‘kummer_m’.

 -- Функция: dkummer_m (<a>, <b>, <x>)
     Производная ‘kummer_m(<a>, <b>, <x>)’ по <x>.

 -- Функция: dkummer_u (<a>, <b>, <x>)
     Производная ‘kummer_u(<a>, <b>, <x>)’ по <x>.


File: maxima.info,  Node: Возможные улучшения пакета contrib_ode,  Next: Тесты пакета contrib_ode,  Prev: Функции и переменные пакета contrib_ode,  Up: Пакет contrib_ode

42.3 Возможные улучшения пакета contrib_ode
===========================================

Данные процедуры находятся в процессе разработки.  Необходимо:

   • Расширить метод факторизации ‘ode1_factor’ для работы с
     множественными корнями.

   • Расширить метод факторизации ‘ode1_factor’ для решения с
     множителями высокого порядка.  В настоящий момент метод пытается
     решить только линейные множители.

   • Исправить процедуру метода Лагранжа ‘ode1_lagrange’ для
     преимущественного использования вещественных корней по отношению с
     комплексными.

   • Добавить дополнительные методы для уравнений Рикатти.

   • Усовершенствовать распознавание уравнений Абеля второго рода.
     Существующее сопоставление с образцом слабо.

   • Работать над процедурой, использующей симметрии групп Ли
     ‘ode1_lie’.  С этой процедурой имеется довольно много проблем:
     некоторые части не реализованы, некоторые тесты зацикливаются,
     некотрые тесты завершаются ошибкой, другие тесты дают слишком
     сложные "решения".  Данная процедура еще не готова для
     практического использования.

   • Добавить больше тестов.


File: maxima.info,  Node: Тесты пакета contrib_ode,  Next: Ссылки для пакета contrib_ode,  Prev: Возможные улучшения пакета contrib_ode,  Up: Пакет contrib_ode

42.4 Тесты пакета contrib_ode
=============================

Процедуры были протестированы на приблизительно одной тысяче примеров из
книг Murphy, Kamke, Zwillinger и других.  Эти тесты включены в
директорию tests.

   • Метод Клеро ‘ode1_clairault’ находит все известные решения, включая
     особые решения уравнения Клеро из книг Murphy и Kamke.

   • Другие процедуры часто возвращают одно решение, в то время как на
     самом деле существуют множественные решения.

   • Некоторые решения, возвращаемые ‘ode1_lie’, излишне сложны и их
     невозможно проверить.

   • В некоторых случаях процедуры завершаются аварийно.


File: maxima.info,  Node: Ссылки для пакета contrib_ode,  Prev: Тесты пакета contrib_ode,  Up: Пакет contrib_ode

42.5 Ссылки для пакета contrib_ode
==================================

  1. E. Kamke, Differentialgleichungen Losungsmethoden und Losungen, Vol
     1, Geest & Portig, Leipzig, 1961

  2. G. M. Murphy, Ordinary Differential Equations and Their Solutions,
     Van Nostrand, New York, 1960

  3. D. Zwillinger, Handbook of Differential Equations, 3rd edition,
     Academic Press, 1998

  4. F. Schwarz, Symmetry Analysis of Abel’s Equation, Studies in
     Applied Mathematics, 100:269-294 (1998)

  5. F. Schwarz, Algorithmic Solution of Abel’s Equation, Computing 61,
     39-49 (1998)

  6. E. S. Cheb-Terrab, A. D. Roche, Symmetries and First Order ODE
     Patterns, Computer Physics Communications 113 (1998), p 239.
     (<http://lie.uwaterloo.ca/papers/ode_vii.pdf>)

  7. E. S. Cheb-Terrab, T. Koloknikov, First Order ODEs, Symmetries and
     Linear Transformations, European Journal of Applied Mathematics,
     Vol.  14, No.  2, pp.  231-246 (2003).
     (<http://arxiv.org/abs/math-ph/0007023>,
     <http://lie.uwaterloo.ca/papers/ode_iv.pdf>)

  8. G. W. Bluman, S. C. Anco, Symmetry and Integration Methods for
     Differential Equations, Springer, (2002)

  9. M. Bronstein, S. Lafaille, Solutions of linear ordinary
     differential equations in terms of special functions, Proceedings
     of ISSAC 2002, Lille, ACM Press, 23-28.
     (<http://www-sop.inria.fr/cafe/Manuel.Bronstein/publications/issac2002.pdf>)


File: maxima.info,  Node: Пакет descriptive,  Next: Пакет diag,  Prev: Пакет contrib_ode,  Up: Top

43 Пакет descriptive
********************

* Menu:

* Введение в пакет descriptive::
* Функции и переменные для манипулирования данными::
* Функции и переменные для описательной статистики::
* Функции и переменные для многомерной описательной статистики::
* Функции и переменные для статистических графиков::


File: maxima.info,  Node: Введение в пакет descriptive,  Next: Функции и переменные для манипулирования данными,  Prev: Пакет descriptive,  Up: Пакет descriptive

43.1 Введение в пакет descriptive
=================================

Пакет ‘descriptive’ содержит набор функций для выполнения вычислений и
визуализации данных в рамках описательной статистики.  Вместе с исходным
кодом пакета Maxima включает также три набора данных: ‘pidigits.data’,
‘wind.data’ и ‘biomed.data’.

   Для справки по функциям пакета ‘descriptive’ можно использовать любое
статистическое руководство.

   Для комментариев, сообщений об ошибках и предложений обращайтесь к
автору пакета по адресу <’mario AT edu DOT xunta DOT es’>.

   Ниже приведен простой пример использования функций пакета
‘descriptive’ в зависимости от природы своих аргументов

     (%i1) load ("descriptive")$
     (%i2) /* univariate sample */   mean ([a, b, c]);
                                 c + b + a
     (%o2)                       ---------
                                     3
     (%i3) matrix ([a, b], [c, d], [e, f]);
                                 [ a  b ]
                                 [      ]
     (%o3)                       [ c  d ]
                                 [      ]
                                 [ e  f ]
     (%i4) /* multivariate sample */ mean (%);
                           e + c + a  f + d + b
     (%o4)                [---------, ---------]
                               3          3

   Отметим, что для многомерной выборки среднее вычисляется для каждой
колонки.

   В случае нескольких выборок, возможно различного размера, для
получения результата для каждой выборки можно использовать функцию ‘map’

     (%i1) load ("descriptive")$
     (%i2) map (mean, [[a, b, c], [d, e]]);
                             c + b + a  e + d
     (%o2)                  [---------, -----]
                                 3        2

   В этом случае в списке находятся две выборки длины 3 и 2.

   Одномерные выборки представляются списками

     (%i1) s1 : [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
     (%o1)           [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]

   а многомерные выборки, матрицами

     (%i1) s2 : matrix ([13.17, 9.29], [14.71, 16.88], [18.50, 16.88],
                  [10.58, 6.63], [13.33, 13.25], [13.21,  8.12]);
                             [ 13.17  9.29  ]
                             [              ]
                             [ 14.71  16.88 ]
                             [              ]
                             [ 18.5   16.88 ]
     (%o1)                   [              ]
                             [ 10.58  6.63  ]
                             [              ]
                             [ 13.33  13.25 ]
                             [              ]
                             [ 13.21  8.12  ]

   В этом случае число колонок равно размерности случайной переменной, а
число строк есть размер выборки.

   Данные могут быть введены в ручную, но большие выборки обычно
хранятся в текстовых файлах.  Например, файл ‘pidigits.data’ содержит
первые 100 цифр числа ‘%pi’:
           3
           1
           4
           1
           5
           9
           2
           6
           5
           3 ...

   Для загрузки этих данных в Maxima следует делать так

     (%i1) load ("numericalio")$
     (%i2) s1 : read_list (file_search ("pidigits.data"))$
     (%i3) length (s1);
     (%o3)                          100

   С другой стороны, файл ‘wind.data’ содержит дневные средние значения
скорости ветра для 5 метеорологических станций в Ирландии (Это часть
данных, взятых с 12 метеорологических станций.  Исходные данные свободно
доступны в StatLib Data Repository и их анализ обсуждается в Haslett,
J., Raftery, A. E. (1989) <Space-time Modelling with Long-memory
Dependence: Assessing Ireland’s Wind Power Resource, with Discussion>.
Applied Statistics 38, 1-50).  Данные загружаются при помощи:

     (%i1) load ("numericalio")$
     (%i2) s2 : read_matrix (file_search ("wind.data"))$
     (%i3) length (s2);
     (%o3)                          100
     (%i4) s2 [%]; /* last record */
     (%o4)            [3.58, 6.0, 4.58, 7.62, 11.25]

   Некоторые выборки содержат нечисловые данные.  Например, файл
‘biomed.data’ (являющийся частью другого большого набора данных из
StatLib Data Repository) содержит четыре измерения крови взятые от двух
групп пациентов разного возраста ‘A’ и ‘B’

     (%i1) load ("numericalio")$
     (%i2) s3 : read_matrix (file_search ("biomed.data"))$
     (%i3) length (s3);
     (%o3)                          100
     (%i4) s3 [1]; /* first record */
     (%o4)            [A, 30, 167.0, 89.0, 25.6, 364]

   Первый пациент принадлежит группе ‘A’, возраст 30 лет, и его/ее
измерения крови есть 167.0, 89.0, 25.6 и 364.

   При работе с категоризированными данными следует соблюдать
осторожность.  В следующем примере символу ‘a’ присвоено значение до
задания катигоризированной выборки

     (%i1) a : 1$
     (%i2) matrix ([a, 3], [b, 5]);
                                 [ 1  3 ]
     (%o2)                       [      ]
                                 [ b  5 ]

