A Linha de Comando Interativa¶
Na maior parte deste tutorial, assumimos que você iniciou o
interpretador Sage usando o comando sage
. Isso inicia uma versão
personalizada da linha de comando IPython, e importa diversas funções
e classes de modo que elas fiquem prontas para serem usadas a partir
da linha de comando. Configuração adicional é possível editando o
arquivo $SAGE_ROOT/ipythonrc
. Assim que você inicia o Sage, você
obtém o seguinte:
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 9.7, Release Date: 2022-01-10 │
│ Using Python 3.10.4. Type "help()" for help. │
└────────────────────────────────────────────────────────────────────┘
sage:
Para sair do Sage pressione Ctrl-D ou digite quit
ou exit
.
sage: quit
Exiting Sage (CPU time 0m0.00s, Wall time 0m0.89s)
>>> from sage.all import *
>>> quit
Exiting Sage (CPU time 0m0.00s, Wall time 0m0.89s)
quit
O wall time é o tempo que passou no relógio “pendurado na sua parede”. Isso é relevante, pois o tempo CPU não conta o tempo usado por subprocessos como GAP ou Singular.
(Evite terminar um processo do Sage usando kill -9
a partir de um
terminal, pois o Sage pode não terminal seus subprocessos, por
exemplo, subprocessos do Maple, ou limpeza de arquivos temporários em
$HOME/.sage/tmp
.)
A Sua Sessão no Sage¶
A sessão é a sequência de entradas e saídas de dados desde o momento em
que você inicia até o momento em que você termina o Sage. O Sage grava
todas as entradas de dados, através do IPython. De fato, se você está
usando a linha de comando (não o Notebook), então a qualquer momento
você pode digitar %history
(ou %hist
) para obter uma lista de
todas as linhas digitadas até então. Você pode digitar ?
no prompt
do Sage para aprender mais sobre o IPython, por exemplo, “IPython
offers numbered prompts … with input and output caching. All input
is saved and can be retrieved as variables (besides the usual arrow
key recall). The following GLOBAL variables always exist (so don’t
overwrite them!)”:
_: previous input (interactive shell and notebook)
__: next previous input (interactive shell only)
_oh : list of all inputs (interactive shell only)
Aqui vai um exemplo:
sage: factor(100)
_1 = 2^2 * 5^2
sage: kronecker_symbol(3,5)
_2 = -1
sage: %hist #This only works from the interactive shell, not the notebook.
1: factor(100)
2: kronecker_symbol(3,5)
3: %hist
sage: _oh
_4 = {1: 2^2 * 5^2, 2: -1}
sage: _i1
_5 = 'factor(ZZ(100))\n'
sage: eval(_i1)
_6 = 2^2 * 5^2
sage: %hist
1: factor(100)
2: kronecker_symbol(3,5)
3: %hist
4: _oh
5: _i1
6: eval(_i1)
7: %hist
>>> from sage.all import *
>>> factor(Integer(100))
_1 = 2^2 * 5^2
>>> kronecker_symbol(Integer(3),Integer(5))
_2 = -1
>>> %hist #This only works from the interactive shell, not the notebook.
1: factor(100)
2: kronecker_symbol(3,5)
3: %hist
>>> _oh
_4 = {1: 2^2 * 5^2, 2: -1}
>>> _i1
_5 = 'factor(ZZ(100))\n'
>>> eval(_i1)
_6 = 2^2 * 5^2
>>> %hist
1: factor(100)
2: kronecker_symbol(3,5)
3: %hist
4: _oh
5: _i1
6: eval(_i1)
7: %hist
factor(100) kronecker_symbol(3,5) %hist #This only works from the interactive shell, not the notebook. _oh _i1 eval(_i1) %hist
Vamos omitir a numeração das linhas no restante deste tutorial e em outras documentações do Sage.
Você também pode salvar uma lista de comandos em uma macro.
sage: E = EllipticCurve([1,2,3,4,5])
sage: M = ModularSymbols(37)
sage: %hist
1: E = EllipticCurve([1,2,3,4,5])
2: M = ModularSymbols(37)
3: %hist
sage: %macro em 1-2
Macro `em` created. To execute, type its name (without quotes).
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> M = ModularSymbols(Integer(37))
>>> %hist
1: E = EllipticCurve([1,2,3,4,5])
2: M = ModularSymbols(37)
3: %hist
>>> %macro em Integer(1)-Integer(2)
Macro `em` created. To execute, type its name (without quotes).
E = EllipticCurve([1,2,3,4,5]) M = ModularSymbols(37) %hist %macro em 1-2
sage: E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over
Rational Field
sage: E = 5
sage: M = None
sage: em
Executing Macro...
sage: E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over
Rational Field
>>> from sage.all import *
>>> E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over
Rational Field
>>> E = Integer(5)
>>> M = None
>>> em
Executing Macro...
>>> E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over
Rational Field
E E = 5 M = None em E
Quando se usa a linha de comando, qualquer comando UNIX pode ser
executado a partir do Sage inserindo um ponto de exclamação !
como
prefixo. Por exemplo,
sage: !ls
auto example.sage glossary.tex t tmp tut.log tut.tex
>>> from sage.all import *
>>> !ls
auto example.sage glossary.tex t tmp tut.log tut.tex
!ls
fornece a lista de arquivos do atual diretório.
O PATH
possui o diretório bin do Sage em primeiro, portanto se
você digitar p
, gap
, singular
, maxima
, etc., você
executa a versão incluída no Sage.
sage: !gp
Reading GPRC: /etc/gprc ...Done.
GP/PARI CALCULATOR Version 2.2.11 (alpha)
i686 running linux (ix86/GMP-4.1.4 kernel) 32-bit version
...
sage: !singular
SINGULAR / Development
A Computer Algebra System for Polynomial Computations / version 3-0-1
0<
by: G.-M. Greuel, G. Pfister, H. Schoenemann \ October 2005
FB Mathematik der Universitaet, D-67653 Kaiserslautern \
>>> from sage.all import *
>>> !gp
Reading GPRC: /etc/gprc ...Done.
GP/PARI CALCULATOR Version 2.2.11 (alpha)
i686 running linux (ix86/GMP-4.1.4 kernel) 32-bit version
...
>>> !singular
SINGULAR / Development
A Computer Algebra System for Polynomial Computations / version 3-0-1
0<
by: G.-M. Greuel, G. Pfister, H. Schoenemann \ October 2005
FB Mathematik der Universitaet, D-67653 Kaiserslautern \
!gp !singular
Gravando Entradas e Saídas de dados¶
Gravar a sua sessão no Sage não é o mesmo que salvá-la (veja
Salvando e Abrindo Sessões Completas). Para gravar a entrada de dados (e opcionalmente
a saída) use o comando logstart
. Digite logstart?
para mais
detalhes. Você pode usar esse comando para gravar tudo o que você
digita, toda a saída de dados, e até mesmo usar essa entrada de dados
que você guardou em uma sessão futura (simplesmente importando o
arquivo log).
was@form:~$ sage
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 9.7, Release Date: 2022-01-10 │
│ Using Python 3.10.4. Type "help()" for help. │
└────────────────────────────────────────────────────────────────────┘
sage: logstart setup
Activating auto-logging. Current session state plus future input saved.
Filename : setup
Mode : backup
Output logging : False
Timestamping : False
State : active
sage: E = EllipticCurve([1,2,3,4,5]).minimal_model()
sage: F = QQ^3
sage: x,y = QQ['x,y'].gens()
sage: G = E.gens()
sage:
Exiting Sage (CPU time 0m0.61s, Wall time 0m50.39s).
was@form:~$ sage
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 9.7, Release Date: 2022-01-10 │
│ Using Python 3.10.4. Type "help()" for help. │
└────────────────────────────────────────────────────────────────────┘
sage: load "setup"
Loading log file <setup> one line at a time...
Finished replaying log file <setup>
sage: E
Elliptic Curve defined by y^2 + x*y = x^3 - x^2 + 4*x + 3 over Rational
Field
sage: x*y
x*y
sage: G
[(2 : 3 : 1)]
Se você usa o Sage no terminal konsole
do Linux KDE, então você
pode gravar a sessão da seguinte forma: após iniciar o Sage no
konsole
, selecione “settings”, então “history…”, então “set
unlimited”. Quando você estiver pronto para guardar a sua sessão,
selecione “edit” e então “save history as…” e digite um nome para
salvar o texto de sua sessão em seu computador. Após salvar esse
arquivo, você poderia abri-lô em um editor, tal como o xemacs, e
imprimi-lo.
Colar Texto Ignora Prompts¶
Suponha que você está lendo uma sequência de comandos em Sage ou
Python e quer copiá-los no Sage. Mas eles têm os irritantes prompts
>>>
ou sage:
para te aborrecer. De fato, você pode copiar e
colar um exemplo, incluindo os prompts se você quiser, no Sage. Em
outras palavras, automaticamente o Sage remove os caracteres >>>
ou sage:
antes de colar o conteúdo no Python. Por exemplo,
sage: 2^10
1024
sage: sage: sage: 2^10
1024
sage: >>> 2^10
1024
>>> from sage.all import *
>>> Integer(2)**Integer(10)
1024
>>> sage: sage: Integer(2)**Integer(10)
1024
>>> >>> Integer(2)**Integer(10)
1024
2^10 sage: sage: 2^10 >>> 2^10
Comandos de Tempo¶
Se você colocar o comando %time
no começo de uma linha de comando,
o tempo que o comando leva para ser executado vai aparecer após a
saída de dados. Por exemplo, nós podemos comparar o tempo de execução
para certas operações de exponenciação de várias formas. Os tempos
abaixo vão ser provavelmente muito diferentes para o seu computador,
ou até mesmo para versões diferentes do Sage. Primeiro, usando o
Python
sage: %time a = int(1938)^int(99484)
CPU times: user 0.66 s, sys: 0.00 s, total: 0.66 s
Wall time: 0.66
>>> from sage.all import *
>>> %time a = int(Integer(1938))**int(Integer(99484))
CPU times: user 0.66 s, sys: 0.00 s, total: 0.66 s
Wall time: 0.66
%time a = int(1938)^int(99484)
Isso significa que levou 0.66 segundos no total, e o wall time, isto é, a quantidade de tempo que passou no seu relógio de parede, é também 0.66 segundos. Se o seu computador está executado outros programas o wall time pode ser muito maior do que o tempo de CPU.
A seguir verificamos o tempo de exponenciação usando o tipo Integer do Sage, o qual é implementado (em Cython) usando a biblioteca GMP:
sage: %time a = 1938^99484
CPU times: user 0.04 s, sys: 0.00 s, total: 0.04 s
Wall time: 0.04
>>> from sage.all import *
>>> %time a = Integer(1938)**Integer(99484)
CPU times: user 0.04 s, sys: 0.00 s, total: 0.04 s
Wall time: 0.04
%time a = 1938^99484
Usando a biblioteca C do PARI:
sage: %time a = pari(1938)^pari(99484)
CPU times: user 0.05 s, sys: 0.00 s, total: 0.05 s
Wall time: 0.05
>>> from sage.all import *
>>> %time a = pari(Integer(1938))**pari(Integer(99484))
CPU times: user 0.05 s, sys: 0.00 s, total: 0.05 s
Wall time: 0.05
%time a = pari(1938)^pari(99484)
A GMP é melhor, mas por pouco (como esperado, pois a versão do PARI contida no Sage usa a GMP para aritmética de inteiros).
Você pode também contar o tempo de um bloco de comandos usado o
comando cputime
, como ilustrado abaixo:
sage: t = cputime()
sage: a = int(1938)^int(99484)
sage: b = 1938^99484
sage: c = pari(1938)^pari(99484)
sage: cputime(t) # somewhat random output
0.64
>>> from sage.all import *
>>> t = cputime()
>>> a = int(Integer(1938))**int(Integer(99484))
>>> b = Integer(1938)**Integer(99484)
>>> c = pari(Integer(1938))**pari(Integer(99484))
>>> cputime(t) # somewhat random output
0.64
t = cputime() a = int(1938)^int(99484) b = 1938^99484 c = pari(1938)^pari(99484) cputime(t) # somewhat random output
sage: cputime?
...
Return the time in CPU second since Sage started, or with optional
argument t, return the time since time t.
INPUT:
t -- (optional) float, time in CPU seconds
OUTPUT:
float -- time in CPU seconds
>>> from sage.all import *
>>> cputime?
...
Return the time in CPU second since Sage started, or with optional
argument t, return the time since time t.
INPUT:
t -- (optional) float, time in CPU seconds
OUTPUT:
float -- time in CPU seconds
cputime?
O comando walltime
se comporta como o comando cputime
, exceto
que ele conta o tempo do relógio.
Nós podemos também calcular a potência acima em alguns softwares de álgebra incluídos no Sage. Em cada caso executamos um comando trivial no sistema de modo a inicializar o servidor para aquele programa. O tempo mais relevante é o tempo do relógio. Todavia, se houver uma diferença significativa entre o wall time e o CPU time então isso pode indicar algum problema de performance que vale a pena investigar.
sage: time 1938^99484;
CPU times: user 0.01 s, sys: 0.00 s, total: 0.01 s
Wall time: 0.01
sage: gp(0)
0
sage: time g = gp('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.04
sage: maxima(0)
0
sage: time g = maxima('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.30
sage: kash(0)
0
sage: time g = kash('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.04
sage: mathematica(0)
0
sage: time g = mathematica('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.03
sage: maple(0)
0
sage: time g = maple('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.11
sage: libgap(0)
0
sage: time g = libgap.eval('1938^99484;')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 1.02
>>> from sage.all import *
>>> time Integer(1938)**Integer(99484);
CPU times: user 0.01 s, sys: 0.00 s, total: 0.01 s
Wall time: 0.01
>>> gp(Integer(0))
0
>>> time g = gp('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.04
>>> maxima(Integer(0))
0
>>> time g = maxima('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.30
>>> kash(Integer(0))
0
>>> time g = kash('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.04
>>> mathematica(Integer(0))
0
>>> time g = mathematica('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.03
>>> maple(Integer(0))
0
>>> time g = maple('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.11
>>> libgap(Integer(0))
0
>>> time g = libgap.eval('1938^99484;')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 1.02
time 1938^99484; gp(0) time g = gp('1938^99484') maxima(0) time g = maxima('1938^99484') kash(0) time g = kash('1938^99484') mathematica(0) time g = mathematica('1938^99484') maple(0) time g = maple('1938^99484') libgap(0) time g = libgap.eval('1938^99484;')
Note que o GAP e o Maxima são os mais lentos neste teste (isso foi
executado no computador sage.math.washington.edu
). Devido ao
processamento extra (overhead) da interface pexpect, talvez não seja
apropriado comparar esses resultados com o Sage, que é o mais rápido.
Outras Dicas para o IPython¶
Como observado acima, o Sage usa o IPython como interface, logo você pode usar quaisquer comandos e recursos do IPython. Você pode ler a Documentação completa do IPython (em inglês).
Você pode usar
%edit
(ou%ed
oued
) para abrir um editor, se você desejar digitar algum código mais complexo. Antes de iniciar o Sage, certifique-se de que a variável de ambienteEDITOR
está definida com o seu editor favorito (colocandoexport EDITOR=/usr/bin/emacs
ouexport EDITOR=/usr/bin/vim
or algo similar no lugar apropriado, como um arquivo.profile
). A partir do prompt do Sage, o comando%edit
irá abrir o editor escolhido. Então usando o editor você pode definir uma função:def some_function(n): return n**2 + 3*n + 2
Salve e feche o editor. No restante da sua sessão do Sage, você pode usar então a função
some_function
. Se você quiser modificá-la, digite%edit some_function
no prompt do Sage.Se você for calcular algo e quiser modificar o resultado para outro uso, execute o cálculo e então digite
%rep
: isso irá colocar o resultado do comando anterior no prompt do Sage, pronto para ser editado.:sage: f(x) = cos(x) sage: f(x).derivative(x) -sin(x)
>>> from sage.all import * >>> __tmp__=var("x"); f = symbolic_expression(cos(x)).function(x) >>> f(x).derivative(x) -sin(x)
f(x) = cos(x) f(x).derivative(x)
A esta altura, se você digitar
%rep
no prompt do Sage, você irá obter um novo prompt, seguido de-sin(x)
, com o cursor no final da linha.
Para mais informações, digite %quickref
para ver um guia rápido de
referência do IPython. Quando este tutorial foi escrito (Fevereiro 2015),
o Sage usa a versão 2.3.0 do IPython, e a documentation for its magic commands está disponível na internet.
Erros e Exceções¶
Quando algo errado ocorre, você usualmente verá uma “exceção” do
Python. O Python até mesmo tenta sugerir o que ocasionou a exceção,
por exemplo, NameError
ou ValueError
(veja o Referência da
Biblioteca Python [PyLR] para uma lista completa de exceções). Por
exemplo,
sage: 3_2
------------------------------------------------------------
File "<console>", line 1
ZZ(3)_2
^
SyntaxError: invalid ...
sage: EllipticCurve([0,infinity])
------------------------------------------------------------
Traceback (most recent call last):
...
TypeError: Unable to coerce Infinity (<class 'sage...Infinity'>) to Rational
>>> from sage.all import *
>>> Integer(3_2)
------------------------------------------------------------
File "<console>", line 1
ZZ(3)_2
^
SyntaxError: invalid ...
>>> EllipticCurve([Integer(0),infinity])
------------------------------------------------------------
Traceback (most recent call last):
...
TypeError: Unable to coerce Infinity (<class 'sage...Infinity'>) to Rational
3_2 EllipticCurve([0,infinity])
O debugador interativo é as vezes útil para entender o que houve de
errado. Você pode ativá-lo e desativá-lo usando %pdb
(o padrão é
desativado). O prompt ipdb>
aparece se uma exceção é levantada e o
debugador está ativado. A partir do debugador, você pode imprimir o
estado de qualquer variável local, e mover a pilha de execução para
cima e para baixo. Por exemplo,
sage: %pdb
Automatic pdb calling has been turned ON
sage: EllipticCurve([1,infinity])
---------------------------------------------------------------------------
<class 'exceptions.TypeError'> Traceback (most recent call last)
...
ipdb>
>>> from sage.all import *
>>> %pdb
Automatic pdb calling has been turned ON
>>> EllipticCurve([Integer(1),infinity])
---------------------------------------------------------------------------
<class 'exceptions.TypeError'> Traceback (most recent call last)
...
ipdb>
%pdb EllipticCurve([1,infinity])
Para uma lista de comandos do debugador, digite ?
no prompt
ipbd>
:
ipdb> ?
Documented commands (type help <topic>):
========================================
EOF break commands debug h l pdef quit tbreak
a bt condition disable help list pdoc r u
alias c cont down ignore n pinfo return unalias
args cl continue enable j next pp s up
b clear d exit jump p q step w
whatis where
Miscellaneous help topics:
==========================
exec pdb
Undocumented commands:
======================
retval rv
Digite Ctrl-D ou quit
para retornar ao Sage.
Busca Reversa e Completamento Tab¶
Busca reversa: Digite o começo de um comando, e então Ctrl-p
(ou
tecle a seta para cima) para voltar para cada linha que você digitou
que começa daquela forma. Isso funciona mesmo se você encerrou o Sage
e iniciou novamente mais tarde. Você também pode fazer uma busca
reversa ao longo da história usando Ctrl-r
. Todos esses recursos
usam o pacote readline
, que está disponível no Linux.
Para ilustrar a busca reversa, primeiro crie o e espaço vetorial tri-dimensional \(V=\QQ^3\) da seguinte forma:
sage: V = VectorSpace(QQ,3)
sage: V
Vector space of dimension 3 over Rational Field
>>> from sage.all import *
>>> V = VectorSpace(QQ,Integer(3))
>>> V
Vector space of dimension 3 over Rational Field
V = VectorSpace(QQ,3) V
Você pode usar a seguinte notação mais compacta:
sage: V = QQ^3
>>> from sage.all import *
>>> V = QQ**Integer(3)
V = QQ^3
Então é fácil listar todas as funções para \(V\) usando
completamento. Digite V
, e então pressione a tecla [tab]
no
seu teclado:
sage: V.[tab key]
V._VectorSpace_generic__base_field
...
V.ambient_space
V.base_field
V.base_ring
V.basis
V.coordinates
...
V.zero_vector
>>> from sage.all import *
>>> V.[tab key]
V._VectorSpace_generic__base_field
...
V.ambient_space
V.base_field
V.base_ring
V.basis
V.coordinates
...
V.zero_vector
V.[tab key]
Se você digitar as primeiras letras de uma função, e então a tecla
[tab]
, você obtém apenas funções que começam conforme indicado.
sage: V.i[tab key]
V.is_ambient V.is_dense V.is_full V.is_sparse
>>> from sage.all import *
>>> V.i[tab key]
V.is_ambient V.is_dense V.is_full V.is_sparse
V.i[tab key]
Se você gostaria de saber o que uma função faz, por exemplo, a função
coordinates, digite V.coordinates?
para ajuda ou
V.coordinates??
para ver o código fonte, como explicado na próxima
sessão.
Sistema de Ajuda Integrado¶
O Sage possui um sistema de ajuda integrado. Digite o nome da função seguido de ? para ver informações sobre a função.
sage: V = QQ^3
sage: V.coordinates?
Type: instancemethod
Base Class: <class 'instancemethod'>
String Form: <bound method FreeModule_ambient_field.coordinates of Vector
space of dimension 3 over Rational Field>
Namespace: Interactive
File: /home/was/s/local/lib/python2.4/site-packages/sage/modules/f
ree_module.py
Definition: V.coordinates(self, v)
Docstring:
Write v in terms of the basis for self.
Returns a list c such that if B is the basis for self, then
sum c_i B_i = v.
If v is not in self, raises an ArithmeticError exception.
EXAMPLES:
sage: M = FreeModule(IntegerRing(), 2); M0,M1=M.gens()
sage: W = M.submodule([M0 + M1, M0 - 2*M1])
sage: W.coordinates(2*M0-M1)
[2, -1]
>>> from sage.all import *
>>> V = QQ**Integer(3)
>>> V.coordinates?
Type: instancemethod
Base Class: <class 'instancemethod'>
String Form: <bound method FreeModule_ambient_field.coordinates of Vector
space of dimension 3 over Rational Field>
Namespace: Interactive
File: /home/was/s/local/lib/python2.4/site-packages/sage/modules/f
ree_module.py
Definition: V.coordinates(self, v)
Docstring:
Write v in terms of the basis for self.
Returns a list c such that if B is the basis for self, then
sum c_i B_i = v.
If v is not in self, raises an ArithmeticError exception.
EXAMPLES:
>>> M = FreeModule(IntegerRing(), Integer(2)); M0,M1=M.gens()
>>> W = M.submodule([M0 + M1, M0 - Integer(2)*M1])
>>> W.coordinates(Integer(2)*M0-M1)
[2, -1]
V = QQ^3 V.coordinates? M = FreeModule(IntegerRing(), 2); M0,M1=M.gens() W = M.submodule([M0 + M1, M0 - 2*M1]) W.coordinates(2*M0-M1)
Como mostrado acima, o comando de ajuda mostra o tipo do objeto, o arquivo no qual ele é definido, e uma descrição útil da função com exemplos que você pode colar na sua sessão atual. Quase todos esses exemplos são regularmente testados automaticamente para certificar que eles se comportam exatamente como esperado.
Outro recurso que vai muito na direção do espírito de código aberto do
Sage é que se f
é uma função do Python, então o comando f??
mostra o código fonte que define f
. Por exemplo,
sage: V = QQ^3
sage: V.coordinates??
Type: instancemethod
...
Source:
def coordinates(self, v):
"""
Write $v$ in terms of the basis for self.
...
"""
return self.coordinate_vector(v).list()
>>> from sage.all import *
>>> V = QQ**Integer(3)
>>> V.coordinates??
Type: instancemethod
...
Source:
def coordinates(self, v):
"""
Write $v$ in terms of the basis for self.
...
"""
return self.coordinate_vector(v).list()
V = QQ^3 V.coordinates??
Isso nos diz que tudo que a função coordinates
faz é chamar a
função coordinate_vector
e converter o resultado para uma lista. O
que a função coordinate_vector
faz?
sage: V = QQ^3
sage: V.coordinate_vector??
...
def coordinate_vector(self, v):
...
return self.ambient_vector_space()(v)
>>> from sage.all import *
>>> V = QQ**Integer(3)
>>> V.coordinate_vector??
...
def coordinate_vector(self, v):
...
return self.ambient_vector_space()(v)
V = QQ^3 V.coordinate_vector??
A função coordinate_vector
coage a sua entrada em um espaço
ambiente, o que tem o efeito de calcular o vetor de coeficientes de
\(v\) em termos de \(V\). O espaço \(V\) já é o espaço
ambiente pois é simplesmente \(\QQ^3\). Existe também uma função
coordinate_vector
para subespaços, que é diferente. Vamos criar um
subespaço e ver:
sage: V = QQ^3; W = V.span_of_basis([V.0, V.1])
sage: W.coordinate_vector??
...
def coordinate_vector(self, v):
"""
...
"""
# First find the coordinates of v wrt echelon basis.
w = self.echelon_coordinate_vector(v)
# Next use transformation matrix from echelon basis to
# user basis.
T = self.echelon_to_user_matrix()
return T.linear_combination_of_rows(w)
>>> from sage.all import *
>>> V = QQ**Integer(3); W = V.span_of_basis([V.gen(0), V.gen(1)])
>>> W.coordinate_vector??
...
def coordinate_vector(self, v):
"""
...
"""
# First find the coordinates of v wrt echelon basis.
w = self.echelon_coordinate_vector(v)
# Next use transformation matrix from echelon basis to
# user basis.
T = self.echelon_to_user_matrix()
return T.linear_combination_of_rows(w)
V = QQ^3; W = V.span_of_basis([V.0, V.1]) W.coordinate_vector??
(Se você acha que a implementação é ineficiente, por favor junte-se a nós para ajudar a optimizar as funções de álgebra linear.)
Você também pode digitar help(command_name)
ou help(class)
para ler um arquivo de ajuda sobre determinada classe.
sage: help(VectorSpace)
Help on function VectorSpace in module sage.modules.free_module:
VectorSpace(K, dimension_or_basis_keys=None, sparse=False, inner_product_matrix=None, *,
with_basis='standard', dimension=None, basis_keys=None, **args)
EXAMPLES:
The base can be complicated, as long as it is a field.
::
sage: V = VectorSpace(FractionField(PolynomialRing(ZZ,'x')),3)
sage: V
Vector space of dimension 3 over Fraction Field of Univariate Polynomial Ring in x
over Integer Ring
sage: V.basis()
[
(1, 0, 0),
(0, 1, 0),
--More--
>>> from sage.all import *
>>> help(VectorSpace)
Help on function VectorSpace in module sage.modules.free_module:
VectorSpace(K, dimension_or_basis_keys=None, sparse=False, inner_product_matrix=None, *,
with_basis='standard', dimension=None, basis_keys=None, **args)
EXAMPLES:
The base can be complicated, as long as it is a field.
::
>>> V = VectorSpace(FractionField(PolynomialRing(ZZ,'x')),Integer(3))
>>> V
Vector space of dimension 3 over Fraction Field of Univariate Polynomial Ring in x
over Integer Ring
>>> V.basis()
[
(1, 0, 0),
(0, 1, 0),
--More--
help(VectorSpace) V = VectorSpace(FractionField(PolynomialRing(ZZ,'x')),3) V V.basis()
Quando você digita q
para sair do sistema de ajuda, a sua sessão
aparece na tela da mesma forma que anteriormente. O texto de ajuda não
fica permanentemente em sua tela, ao contrário da saída de
function_name?
que as vezes fica. É partircularmente útil digitar
help(module_name)
. Por exemplo, espaços vetoriais são definidos em
sage.modules.free_module
, então digite
help(sage.modules.free_module)
para obter documentação sobre esse
módulo. Quando visualizando documentação usando a ajuda, você pode
procurar no texto digitando /
e na ordem reversa digitando ?
.
Salvando e Carregando Objetos Individuais¶
Suponha que você calcule uma matriz, ou pior ainda, um espaço complicado de símbolos, e gostaria de salvá-los para uso posterior. O que você pode fazer? Existem várias estratégias que os sistemas computacionais de álgebra adotam para salvar objetos individuais.
Salve seus cálculos: Suportam apenas salvar e carregar uma sessão completa (por exemplo, GAP, Magma).
Entrada e Saída Unificadas: Faz com que cada objeto seja impresso de uma forma que possa ser lido novamente (GP/PARI).
Eval: Torna fácil processar um código arbitrário no interpretador (por exemplo, Singular, PARI).
Como o Sage usa o Python, ele adota uma estratégia diferente, que se baseia no fato de que qualquer objeto pode ser “serializado”, isto é, transformado em uma string a partir da qual o objeto pode ser recuperado. Isso segue o espírito da estratégia unificada de entrada e saída do PARI, exceto que não possue a desvantagem que os objetos são impressos na tela em uma forma muito complicada. Além disso, o suporte para salvar e recuperar é (na maior parte dos casos) completamente automática, não requerendo nenhuma programação extra; é simplesmente um recurso do Python que foi implementado na linguagem desde o início de seu desenvolvimento.
Quase todos os objetos x
podem ser armazenados em disco de forma
comprimida usando save(x, filename)
(ou em muitos casos
x.save(filename)
). Para carregar o objeto de volta no Sage use
load(filename)
.
sage: A = MatrixSpace(QQ,3)(range(9))^2
sage: A
[ 15 18 21]
[ 42 54 66]
[ 69 90 111]
sage: save(A, 'A')
>>> from sage.all import *
>>> A = MatrixSpace(QQ,Integer(3))(range(Integer(9)))**Integer(2)
>>> A
[ 15 18 21]
[ 42 54 66]
[ 69 90 111]
>>> save(A, 'A')
A = MatrixSpace(QQ,3)(range(9))^2 A save(A, 'A')
Você deve agora sair do Sage e reiniciá-lo. Então você pode obter
A
de volta:
sage: A = load('A')
sage: A
[ 15 18 21]
[ 42 54 66]
[ 69 90 111]
>>> from sage.all import *
>>> A = load('A')
>>> A
[ 15 18 21]
[ 42 54 66]
[ 69 90 111]
A = load('A') A
Você pode fazer o mesmo com objetos mais complicados, por exemplo, curvas elípticas. Todos os dados sobre o objeto são guardados e restaurados com o objeto. Por exemplo,
sage: E = EllipticCurve('11a')
sage: v = E.anlist(100000) # takes a while
sage: save(E, 'E')
sage: quit
>>> from sage.all import *
>>> E = EllipticCurve('11a')
>>> v = E.anlist(Integer(100000)) # takes a while
>>> save(E, 'E')
>>> quit
E = EllipticCurve('11a') v = E.anlist(100000) # takes a while save(E, 'E') quit
A versão em disco de E
ocupa 153 kilobytes, pois ela guarda os
primeiros 1000000 \(a_n\) com ela.
~/tmp$ ls -l E.sobj
-rw-r--r-- 1 was was 153500 2006-01-28 19:23 E.sobj
~/tmp$ sage [...]
sage: E = load('E')
sage: v = E.anlist(100000) # instant!
(Em Python, salvar e restaurar é feito usando o módulo cPickle
. Em
particular, um objeto x
do Sage pode ser salvo usando
cPickle.dumps(x, 2)
. Note o 2
!)
O sage não pode salvar e carregar objetos criados em algum outro sistema computacional de álgebra, por exemplo, GAP, Singular, Maxima, etc. Eles são carregados em um estado “inválido”. Em GAP, embora muitos objetos podem ser impressos de uma forma que eles podem ser reconstruídos, muitos não, logo reconstrução a partir de suas representações impressas não é permitido.
sage: a = libgap(2)
sage: a.save('a')
sage: load('a')
Traceback (most recent call last):
...
ValueError: The session in which this object was defined is no longer
running.
>>> from sage.all import *
>>> a = libgap(Integer(2))
>>> a.save('a')
>>> load('a')
Traceback (most recent call last):
...
ValueError: The session in which this object was defined is no longer
running.
a = libgap(2) a.save('a') load('a')
Objetos do GP/PARI também podem ser salvos e carregados pois suas representações em forma impressa são suficientes para reconstruí-los.
sage: a = gp(2)
sage: a.save('a')
sage: load('a')
2
>>> from sage.all import *
>>> a = gp(Integer(2))
>>> a.save('a')
>>> load('a')
2
a = gp(2) a.save('a') load('a')
Objetos que foram salvos podem ser abertos posteriormente em
computadores com arquiteturas e sistemas operacionais diferentes, por
exemplo, você poderia salvar uma matriz muito grande em um OS X de
32-bits e abri-lo em um Linux de 64-bits, encontrar a forma reduzida,
e movê-lo de volta. Além disso, em muitos casos você pode até mesmo
abrir objetos em versões do Sage diferentes daquela no qual o objeto
foi salvo, desde que o código para aquele objeto não seja muito
diferente. Todos os atributos do objetos são armazendos, assim como a
classe (mas não o código fonte) que define o objeto. Se aquela classe
não existir mais em uma nova versão do Sage, então o objeto não pode
ser reaberto nessa versão. Mas você poderia abri-lo em uma versão mais
antiga, obter o dicionário do objeto (com x.__dict__
), salvar o
dicionário, e abri-lo em uma versão mais nova.
Salvando como Texto¶
Você também pode salvar a representação em texto (ASCII) de objetos em um arquivo, simplesmente abrindo um arquivo em modo de escrita, e escrevendo a string que representa o objeto no arquivo (você pode salvar mais de um objeto dessa forma). Quando você terminar de escrever os objetos, feche o arquivo.
sage: R.<x,y> = PolynomialRing(QQ,2)
sage: f = (x+y)^7
sage: o = open('file.txt','w')
sage: o.write(str(f))
sage: o.close()
>>> from sage.all import *
>>> R = PolynomialRing(QQ,Integer(2), names=('x', 'y',)); (x, y,) = R._first_ngens(2)
>>> f = (x+y)**Integer(7)
>>> o = open('file.txt','w')
>>> o.write(str(f))
>>> o.close()
R.<x,y> = PolynomialRing(QQ,2) f = (x+y)^7 o = open('file.txt','w') o.write(str(f)) o.close()
Salvando e Abrindo Sessões Completas¶
O Sage é flexível para salvar e abrir sessões completas.
O comando save_session(sessionname)
salva todas as variáveis que
você definiu na sessão atual como um dicionário com o nome
sessionname
. (No caso raro de uma variável não poder ser salva,
ela simplesmente não aparece no dicionário.) O resultado é um arquivo
.sobj
que pode ser aberto como qualquer outro objeto que foi
salvo. Quando você abre os objetos que foram salvos em uma sessão,
você obtém um dicionário cujas chaves (keys) são os nomes das
variáveis e os valores são os objetos.
Você pode usar o comando load_session(sessionname)
para carregar
na presente sessão as variáveis definidas em sessioname
. Note que
isso não remove as variáveis já definidas na presente sessão; em vez
disso, as duas sessões são combinadas.
Primeiro iniciamos o Sage e definimos algumas variáveis.
sage: E = EllipticCurve('11a')
sage: M = ModularSymbols(37)
sage: a = 389
sage: t = M.T(2003).matrix(); t.charpoly().factor()
_4 = (x - 2004) * (x - 12)^2 * (x + 54)^2
>>> from sage.all import *
>>> E = EllipticCurve('11a')
>>> M = ModularSymbols(Integer(37))
>>> a = Integer(389)
>>> t = M.T(Integer(2003)).matrix(); t.charpoly().factor()
_4 = (x - 2004) * (x - 12)^2 * (x + 54)^2
E = EllipticCurve('11a') M = ModularSymbols(37) a = 389 t = M.T(2003).matrix(); t.charpoly().factor()
A seguir nós salvamos a nossa sessão, o que armazena cada uma das variáveis acima em um arquivo. Então visualizamos o arquivo, que tem por volta de 3K bytes.
sage: save_session('misc')
Saving a
Saving M
Saving t
Saving E
sage: quit
was@form:~/tmp$ ls -l misc.sobj
-rw-r--r-- 1 was was 2979 2006-01-28 19:47 misc.sobj
>>> from sage.all import *
>>> save_session('misc')
Saving a
Saving M
Saving t
Saving E
>>> quit
was@form:~/tmp$ ls -l misc.sobj
-rw-r--r-- 1 was was 2979 2006-01-28 19:47 misc.sobj
save_session('misc') quit
Por fim reiniciamos o Sage, definimos algumas variáveis extra, e carregamos a sessão que foi salva anteriormente.
sage: b = 19
sage: load_session('misc')
Loading a
Loading M
Loading E
Loading t
>>> from sage.all import *
>>> b = Integer(19)
>>> load_session('misc')
Loading a
Loading M
Loading E
Loading t
b = 19 load_session('misc')
Cada variável que foi salva está de novo disponível. Além disso, a
variável b
não foi redefinida.
sage: M
Full Modular Symbols space for Gamma_0(37) of weight 2 with sign 0
and dimension 5 over Rational Field
sage: E
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational
Field
sage: b
19
sage: a
389
>>> from sage.all import *
>>> M
Full Modular Symbols space for Gamma_0(37) of weight 2 with sign 0
and dimension 5 over Rational Field
>>> E
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational
Field
>>> b
19
>>> a
389
M E b a