Интерфейсы

Краеугольным камнем Sage является поддержка вычислений с использованием объектов их разных компьютерных алгебраических систем, которые находятся "под одной крышей" и используют общий интерфейс и чистый язык программирования.

Методы console и interact интерфейса делают разные вещи. Например, используя GAP как пример:

  1. gap.console(): Открывает консоль GAP и передает управление GAP'у. Здесь Sage выступает в роли удобной командной строки, вроде Linux Bash Shell.
  2. gap.interact(): Это удобный способ взаимодействия с запущенным интерфейсом GAP, "заполненным" объектами Sage. Вы можете импортировать объекты Sage в сессию GAP (даже из интерактивного интерфейса), и пр.

GP/PARI

PARI это компактная, очень продуманная и хорошо оптимизированная программа на C, которая фокусируется на теории чисел. Существует два раздельных интерфейса которые вы можете использовать в Sage:

  • gp - интерпретатор “G o P ARI” , и
  • pari - С-библиотека PARI.

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

sage: gp('znprimroot(10007)')
Mod(5, 10007)
sage: pari('znprimroot(10007)')
Mod(5, 10007)

В первом случае отдельная копия интерпретатора GP запускается как сервер, и строка 'znprimroot(10007)' отправляется в него, вычисляется с помощью GP, и результат записывается в переменную в GP (которая занимает пространство в памяти процесса GP и не будет освобождена). После этого значение переменной выводится на экран. Во втором случае отдельная программа не запускается, и строка 'znprimroot(10007)' вычисляется конкретной функцией С-библиотеки PARI. Результат сохраняется в heap-памяти Python'а, которая освобождается после того, как переменная перестает использоваться. У объектов разный тип:

sage: type(gp('znprimroot(10007)'))
<class 'sage.interfaces.gp.GpElement'>
sage: type(pari('znprimroot(10007)'))
<type 'sage.libs.pari.gen.gen'>

Так какой же способ использовать? Это зависит от того, что вы делаете. Интерфейс GP может делать все, что может делать программа GP/PARI, запускаемая из командной строки, потому как он запускает эту программу. Вы можете загрузить сложную программу PARI и запустить ее. С другой стороны, интерфейс PARI (через C-библиотеку) имеет намного больше ограничений. Во-первых, не все функции-члены могут быть имплементированы. Во-вторых, много кода, например, численная интеграция, не будет работать через интерфейс PARI. Интерйес PARI может быть намного быстрее и результат его работы может содержать меньше ошибок, по сравнению с GP.

(Если у интерфейса GP закончится память при вычислении данной строки, он автоматически и без предупреждения удовит размер стека и попробует вычисление еще раз. Поэтому ваши вычисления всегда будут произведены корректно, если вы правильно расчитаете размер необходимой памяти. Этот удобный трюк не входит в арсенал простого интерпретатора GP. Относительно интерфейса C-библиотеки PARI: он сразу копирует каждый созданный объект из стека PARI, поэтому стек никогда не растет. Однако, каждый объект не должен превышать размера в 100 мегабайт, или стек будет переполнен при создании объекта. Дополнительное копирование немного влияет на общую производительность.)

Sage использует С-библиотеку PARI, чтобы поддерживать функциональность, схожую с интерпретатором GP/PARI, но включая различные сложные операции по работе с памятью и язык программирования Python.

Сначала, создадим список PARI из списка Python.

sage: v = pari([1,2,3,4,5])
sage: v
[1, 2, 3, 4, 5]
sage: type(v)
<type 'sage.libs.pari.gen.gen'>

Каждый объект PARI является объектом типа py_pari.gen. Тип PARI может быть получен с помощью функции-члена type.

sage: v.type()
't_VEC'

В PARI чтобы создать эллиптическую кривую нужно ввести ellinit([1,2,3,4,5]). В Sage способ схож, только ellinit это метод, который может быть вызван у любого объекта PARI, например наша t\_VEC v.

sage: e = v.ellinit()
sage: e.type()
't_VEC'
sage: pari(e)[:13]
[1, 2, 3, 4, 5, 9, 11, 29, 35, -183, -3429, -10351, 6128487/10351]

Теперь когда у нас есть объект эллиптическая кривая, мы можем вычислить что-нибудь.

sage: e.elltors()
[1, [], []]
sage: e.ellglobalred()
[10351, [1, -1, 0, -1], 1]
sage: f = e.ellchangecurve([1,-1,0,-1])
sage: f[:5]
[1, -1, 0, 4, 3]

GAP

Sage поставляется с GAP 4.4.10 для вычислений в области дискретной математики, в особенности, в теории групп.

Вот пример функции IdGroup из GAP, которая использует базу данных небольших групп, которая должна быть установлена отдельно, как показано ниже.

sage: G = gap('Group((1,2,3)(4,5), (3,4))')
sage: G
Group( [ (1,2,3)(4,5), (3,4) ] )
sage: G.Center()
Group( () )
sage: G.IdGroup()    # requires optional database_gap package
[ 120, 34 ]
sage: G.Order()
120

Мы может провести те же вычисления в Sage без прямого вызова интерфейса GAP следующим образом:

sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
sage: G.center()
Permutation Group with generators [()]
sage: G.group_id()     # requires optional database_gap package
[120, 34]
sage: n = G.order(); n
120

(Для функционала GAP следует установить два дополнительных пакета Sage. Введите sage -optional для списка и выберите пакет вида gap\_packages-x.y.z, потом введите sage -i gap\_packages-x.y.z. Сделайте то же для database\_gap-x.y.z. Некоторые не-GPL пакеты GAP могут быть установлены скачиванием их с сайта GAP [GAPkg], и распаковкой их в директорию $SAGE_ROOT/local/lib/gap-4.4.10/pkg. )

Singular

Singular предоставляет массивную и продуманную библиотеку для базиса Грёбнера, назождения набольшего общего делителя полиномов, базиса пространств плоских кривых Римана-Роха и факторизации, на ряду с другими вещами. Мы покажем пример факторизации полиномов с несколькими переменными используя интерфейс Singular в Sage (не вводите ...):

sage: R1 = singular.ring(0, '(x,y)', 'dp')
sage: R1
//   characteristic : 0
//   number of vars : 2
//        block   1 : ordering dp
//                  : names    x y
//        block   2 : ordering C
sage: f = singular('9*y^8 - 9*x^2*y^7 - 18*x^3*y^6 - 18*x^5*y^6 + \
...   9*x^6*y^4 + 18*x^7*y^5 + 36*x^8*y^4 + 9*x^10*y^4 - 18*x^11*y^2 - \
...   9*x^12*y^3 - 18*x^13*y^2 + 9*x^16')

Теперь когда мы определили f, мы выводим на экран и факторизуем.

sage: f
9*x^16-18*x^13*y^2-9*x^12*y^3+9*x^10*y^4-18*x^11*y^2+36*x^8*y^4+18*x^7*y^5-18*x^5*y^6+9*x^6*y^4-18*x^3*y^6-9*x^2*y^7+9*y^8
sage: f.parent()
Singular
sage: F = f.factorize(); F
[1]:
   _[1]=9
   _[2]=x^6-2*x^3*y^2-x^2*y^3+y^4
   _[3]=-x^5+y^2
[2]:
   1,1,2
sage: F[1][2]
x^6-2*x^3*y^2-x^2*y^3+y^4

Как и на примере GAP в GAP, мы можем совершить данную факторизацию без прямого указания интерфейса Sage (однако за кулисами Sage все равно используется интерфейс Singular). Не вводите ...:

sage: x, y = QQ['x, y'].gens()
sage: f = 9*y^8 - 9*x^2*y^7 - 18*x^3*y^6 - 18*x^5*y^6 + 9*x^6*y^4\
...   + 18*x^7*y^5 + 36*x^8*y^4 + 9*x^10*y^4 - 18*x^11*y^2 - 9*x^12*y^3\
...   - 18*x^13*y^2 + 9*x^16
sage: factor(f)
(9) * (-x^5 + y^2)^2 * (x^6 - 2*x^3*y^2 - x^2*y^3 + y^4)

Maxima

Maxima включена в Sage, так же как имплементация на Лиспе. Пакет gnuplot (который Maxima использует по умолчанию для построения графиков) распространяется как дополнительный пакет Sage. Кроме остальных вещей, Maxima работает с символическими манипуляциями. Maxima может интегрировать и дифференцировать функции символически, решать обыкновенные дифференциальные уравнения 1го порядка, большую часть линейных обыкновенных дифференциальных уравнений 2го порядка, использовать преобразования Лапласа как метод для решения линейных обыкновенных дифференциальных уравнений любого порядка. Maxima также "знает" о большом наборе специальных функций, имеет возможность строить графики используя gnuplot, имеет методы решения и манипуляции матриц (к примеру, метод Гаусса, нахождение собственных значений и векторов), а также умеет решать полиномы.

Мы проиллюстрируем работу Sage/Maxima с помощью матрицы, значения i,j которой являются i/j, для i,j=1,\ldots,4.

sage: f = maxima.eval('ij_entry[i,j] := i/j')
sage: A = maxima('genmatrix(ij_entry,4,4)'); A
matrix([1,1/2,1/3,1/4],[2,1,2/3,1/2],[3,3/2,1,3/4],[4,2,4/3,1])
sage: A.determinant()
0
sage: A.echelon()
matrix([1,1/2,1/3,1/4],[0,0,0,0],[0,0,0,0],[0,0,0,0])
sage: A.eigenvalues()
[[0,4],[3,1]]
sage: A.eigenvectors()
[[[0,4],[3,1]],[[[1,0,0,-4],[0,1,0,-2],[0,0,1,-4/3]],[[1,2,3,4]]]]

Вот другой пример:

sage: A = maxima("matrix ([1, 0, 0], [1, -1, 0], [1, 3, -2])")
sage: eigA = A.eigenvectors()
sage: V = VectorSpace(QQ,3)
sage: eigA
[[[-2,-1,1],[1,1,1]],[[[0,0,1]],[[0,1,3]],[[1,1/2,5/6]]]]
sage: v1 = V(sage_eval(repr(eigA[1][0][0]))); lambda1 = eigA[0][0][0]
sage: v2 = V(sage_eval(repr(eigA[1][1][0]))); lambda2 = eigA[0][0][1]
sage: v3 = V(sage_eval(repr(eigA[1][2][0]))); lambda3 = eigA[0][0][2]

sage: M = MatrixSpace(QQ,3,3)
sage: AA = M([[1,0,0],[1, - 1,0],[1,3, - 2]])
sage: b1 = v1.base_ring()
sage: AA*v1 == b1(lambda1)*v1
True
sage: b2 = v2.base_ring()
sage: AA*v2 == b2(lambda2)*v2
True
sage: b3 = v3.base_ring()
sage: AA*v3 == b3(lambda3)*v3
True

Наконец, мы покажем как строить графики используя openmath. Многие примеры являются модифицированными примерами из руководства к Maxima.

2х-мерныу графики нескольких функций (не вводите ...):

sage: maxima.plot2d('[cos(7*x),cos(23*x)^4,sin(13*x)^3]','[x,0,1]',\
...   '[plot_format,openmath]') # not tested

"Живой" трехмерный график, который вы можете вращать мышкой (не вводите ...):

sage: maxima.plot3d ("2^(-u^2 + v^2)", "[u, -3, 3]", "[v, -2, 2]",\
...   '[plot_format, openmath]') # not tested
sage: maxima.plot3d("atan(-x^2 + y^3/4)", "[x, -4, 4]", "[y, -4, 4]",\
...   "[grid, 50, 50]",'[plot_format, openmath]') # not tested

Следующий график это знаменитая Лента Мёбиуса (не вводите ...):

sage: maxima.plot3d("[cos(x)*(3 + y*cos(x/2)), sin(x)*(3 + y*cos(x/2)),\
...   y*sin(x/2)]", "[x, -4, 4]", "[y, -4, 4]",\
...   '[plot_format, openmath]') # not tested

Следующий график это знаменитая Бутылка Клейна (не вводите ...):

sage: maxima("expr_1: 5*cos(x)*(cos(x/2)*cos(y) + sin(x/2)*sin(2*y)+ 3.0)\
...   - 10.0")
5*cos(x)*(sin(x/2)*sin(2*y)+cos(x/2)*cos(y)+3.0)-10.0
sage: maxima("expr_2: -5*sin(x)*(cos(x/2)*cos(y) + sin(x/2)*sin(2*y)+ 3.0)")
-5*sin(x)*(sin(x/2)*sin(2*y)+cos(x/2)*cos(y)+3.0)
sage: maxima("expr_3: 5*(-sin(x/2)*cos(y) + cos(x/2)*sin(2*y))")
5*(cos(x/2)*sin(2*y)-sin(x/2)*cos(y))
sage: maxima.plot3d ("[expr_1, expr_2, expr_3]", "[x, -%pi, %pi]",\
...   "[y, -%pi, %pi]", "['grid, 40, 40]",\
...   '[plot_format, openmath]') # not tested

Содержание

Предыдущая тема

Интерактивная консоль

Следующая тема

Программирование

Эта страница