Sage é um software matemático livre e de código aberto (open-source), desenvolvido sob a licença GPL por uma comunidade de programadores e matemáticos, que busca ser uma alternativa para os principais sistemas proprietários de software matemático como o Magma, Maple, Mathematica e Matlab.
Ele se utiliza de um grande número de pacotes de código aberto pré-existentes integrando-os em uma interface amigável e de fácil assimilação. Outras informações sobre Sage podem ser lidas na introdução a este artigo.
É possível usar o software de vários modos:
Após a instalação você pode iniciar o programa digitando sage no terminal de sua preferência ou clicando em um atalho criado para este fim. É apresentada uma informação de abertura e o prompt de comando:
Sage Version 4.4.3, Release Date:2010-06-04
Type notebook() for the GUI, and licence() for information
sage:
A nota de abertura faz referência à duas funções internas, notebook() e license(), usadas respectivamente para abrir a GUI (interface gráfica do usuário ou Notebook() e exibir as licenças e programas usados com Sage. Você pode digitar help() para ver algumas sugestões de comandos para obter ajuda. Para encerrar a sessão digite exit ou ctrl-d.
Uma excelente maneira de se aprender o uso de Sage consiste em digitar notebook() para acesssar a interface interativa e depois tutorial(). Isto faz com que se abra uma página de tutorial com linhas interativas que podem ser alteradas pelo usuário. Embora o Notebook seja mais amigável será mais simples examinarmos primeiro alguns comandos de linha. Nesta primeira seção não pretendemos descrever comandos ou sintaxe de Sage de forma completa, mas apenas habilitar o leitor a executar suas próprias experiência como programa.
Convenção: Nestas páginas os quadros exibem a interação do usuário com Sage.
sage: 12345679 * 27 ← esta linha contém o prompt de Sage, onde se digita os comandos
333333333 ← esta é a linha com o output de Sage, onde se exibe a avaliação do comando acima
A maior parte da sintaxe de Sage é diretamente derivada de Python, com algumas poucas exceções. Linhas ou trechos iniciados por # são comentários. O operador de atribuição (=) atribui valores a uma variável. Uma variável e seu tipo são especificados no momento da atribuição:
sage: 3 + 2 * 5 # uso como calculadora
13
sage: x = 17 # x é um inteiro
sage: x # ou print(x)
17
sage: x = 'variavel simples' # x agora é um string (de caracteres)
sage: x
'variavel simples'
sage: x + ' tipo string' # concatenação de strings
'variavel simples tipo string'
sage: reset ('x') # agora a variável x não existe mais
sage: k=.3 # variável de ponto flutuante (float)
sage: k**k
0.696845301935949
sage: a,b = 1,2 # atribuindo muitas variáveis em uma linha
sage: a == b # operador de comparação (igualdade)
False
sage: a < b # operador de comparação
True
As aspas, como delimitadores de strings, podem ser aspas simples ou duplas. Os operadores de comparação, ==, <, >, <=, >= resultam nos valores booleanos, True ou False. A precedência dos operadores é a usual.
sage: d = 3**9 # 39 resulta em 19683
sage: d == 3^9 # comparação, forma alternativa para expoente (não em Python)
True
sage: 3+4*5^6
62503
sage: ((3+4)*5)^6 # para avaliação em outra ordem use parênteses
1838265625
sage: 9 % 5 # resto da divisão inteira de 9 por 5 (mod)
4
sage: 145/25 # a fração é apenas simplificada
29/5
sage: 145./25 # se o operando é de ponto flutuante, o resultado também é
5.80000000000000
sage: 37 // 4 # parte inteira do quociente
9
sage: factor(362880) # decompor em fatores primos
2^7 * 3^4 * 5 * 7
Como visto acima, diversos comandos podem ser acumulados em uma linha, desde que separados por ponto e vírgula (;). Além disto mais de uma variável pode ser atribuída em uma única linha.
sage: a=3/5;b=3/2;c=1/4;a+b+c
47/20
sage: q, w, r, t = 1, 2, 3, 4
sage: q,w,r,t
(1, 2, 3, 4)
No último caso são atribuídos valores a uma lista (uma matriz unidimensional). No entanto, em utilizações que envolvem muitas linhas é importante ter o cuidado de se manter a clareza do que está escrito. Uma linha com muitos comandos pode ser bem mais difícil de ler e entender que linhas com comandos únicos.
O caracter _ (undescore ou sublinhado) se refere ao resultado da última de cálculo como ilustrado no exemplo abaixo.
sage: 3^2*4 + 2%5
38
sage: _ % 5 # resto da divisão de 38 por 5
3
Os seguintes são os tipos básicos de variáveis disponíveis para Sage: inteiros, racionais, reais (ponto flutuante), complexos, listas (lists), tuplas (tuples), dicionários (dictionaries), conjuntos (sets), booleanos e caracteres (strings). Muitos outros tipos existem e outros podem ser construídos pelo usuário com base nos modelos existentes (que são sempre objetos derivados de uma ou outra classe).
sage: a=888888 # inteiro
sage: type(a)
<type 'sage.rings.integer.Integer'>
sage: b=1. # ponto flutuante (o mais próximo que se pode chegar de um real em um computador)
sage: type(b)
<type 'sage.rings.real_mpfr.RealLiteral'>
sage: c=31e12 # Notação científica: 31*10^12
sage: c
3.10000000000000e13
sage: type(c)
<type 'sage.rings.real_mpfr.RealLiteral'>
sage: b=True # booleano
sage: type(b)
<type 'bool'>
sage: q=4/2 # racional
sage: q
2
sage: type(q) # apesar da simplificação a variável ainda é reconhecida como um racional
<type 'sage.rings.rational.Rational'>
sage: z1=1+2j # complexos -> j = sqrt(-1)
sage: z1
1.00000000000000 + 2.00000000000000*I
sage: z2=3-8j
sage: z+z2 # a álgebra dos complexos está implementada
4.00000000000000 - 6.00000000000000*I
sage: z1*z2
19.0000000000000 - 2.00000000000000*I
Uma lista (list) é uma matriz unidimensional indexada a partir do 0.
sage: lvazia=[] # cria uma lista vazia
sage: lvazia
[]
sage: lista=[1,3,5,7,9]
sage: lista[3] # acesso ao quarto elemento da lista
7
sage: lista[0] # acesso ao primeiro elemento da lista
1
sage: # uma lista pode ser acessada do final para o início ( − 1 se refere ao último elemento)
sage: lista[-1]
9
sage: lista[1:3] # acesso a uma fatia (slice) da lista -- segundo até o quarto elemento, exclusive.
[3, 5]
sage: lista[1] = "texto" # um elemento pode ser modificado individualmente
sage: lista[1]
'texto'
sage: lista
[1, 'texto', 5, 7, 9]
sage: lista[1:2] = [] # atribui uma lista vazia à fatia de 2 até 3 (exclusive), i.e. apaga o elemento
sage: lista
[1, 5, 7, 9]
sage: # listas podem ser aninhadas, i.e., um ou mais elementos da lista pode(m) ser outra(s) lista(s)
sage: lista[2]=['a','b','c']
sage: lista # o elemento na terceira posição é uma lista
[1, 5, ['a', 'b', 'c'], 9]
sage: lista[2][1] # acesso a um elemento aninhado (o segundo elemento da lista em lista[2])
'b'
Uma tupla (tuple) é uma matriz unidimensional indexada a partir do 0, praticamente igual às listas mas constituídas de elementos imutáveis.
sage: tupla_1=() # cria uma tupla vazia
sage: tupla_2=(0,1,2,3)
sage: tupla_2[3]
3
As variáveis de string são arrays de caracteres. Como objetos elas possuem métodos que serão explorados mais tarde.
sage: texto_1="É possível usar 'aspas simples' dentro de uma string delimitada por aspas duplas."
sage: print(texto_1) # a função print foi usada aqui para a exibição correta das letras acentuadas.
É possível usar 'aspas simples' dentro de uma string delimitada por aspas duplas.
sage: texto_1='É possível usar "aspas duplas" dentro de uma string delimitada por aspas simples.'
sage: print(texto_1)
É possível usar "aspas duplas" dentro de uma string delimitada por aspas simples.
sage: texto_2="Para usos mais complicados use \"escape caracteres\"..."
sage: # para inserir aspas duplas use 'escape' (\) + caracter
sage: print(texto_2)
Para usos mais complicados use "escape caracteres"...
sage: texto_3="\tTabulações \tpodem \tser \tobtidas \n \tassim \tcomo \tquebras \tde linhas."
sage: print(texto_3) # as tabulações são obtidas com '\t', uma quebra de linha com '\n'.
Tabulações podem ser obtidas
assim como quebras de linhas.
sage: print("strings podem ser" " concatenadas por justaposição" + " ou com uso do operador '+'.")
strings podem ser concatenadas por justaposição ou com uso do operador '+'.
sage: print "strings podem ser" " concatenadas por justaposição" + " ou com uso do operados '+'."
strings podem ser concatenadas por justaposição ou com uso do operados '+'.
sage: # o último comando mostra o uso de print sem os parênteses!
Dicionários (dictionaries) são listas não ordenadas onde cada elemento é formado por uma dupla de dados. O primeiro dado do par é uma "chave" que pode ser usada para a rápida localização do segundo elemento.
sage: MeuDic={1:"um", 2:"dois", 3:"tres"}; MeuDic
{1: 'um', 2: 'dois', 3: 'tres'}
sage: MeuDic[1]
'um'
sage: MeuDic[0] # não existe a chave 0, Sage retorna uma mensagem de erro!
---------------------------------------------------------------------------
KeyError Traceback (most recent call last) (...)
sage: MeuDic['novachave']='novidade' # um novo par é inserido. Chaves podem ser inteiros ou strings
sage: MeuDic[3]='trinta' # o item associado a 3 é alterado
sage: MeuDic
{1: 'um', 2: 'dois', 3: 'trinta', 'novachave': 'novidade'}
Conjuntos (sets) são coleções de objetos não ordenados. Objetos repetidos são ignorados.
sage: C=set([1,2,3,2,1,6,7]); C
set([1, 2, 3, 6, 7])
sage: C2=set(["a","b","c","d","e","f"]); C2
set(['a', 'c', 'b', 'e', 'd', 'f'])
sage: 1 in C # o operador in verifica se o elemento está no conjunto
True
sage: 'z' in C2
False
Variáveis boolenas podem assumir apenas dois valores: True (verdade) ou False (falso). Os operadores lógicos and (e), or (ou), in (pertinência), not (negação), not in (não pertence) podem ser usados em testes lógicos, realizados por meio dos operadores (com resultados booleanos) <, <=, ==, >, >, =, is, is not, in not in.
sage: T = True; F = False
sage: T, F
(True, False)
sage: T and T
True
sage: T and F
False
sage: not T
False
sage: T or F
True
Abaixo mostramos algumas constantes imbutidas e algumas formas de manipulá-las.
sage: a=pi; a
pi
sage: n(a)
3.14159265358979
sage: n(a, 30)
3.1415927
sage: n(a, digits=30)
3.14159265358979323846264338328
sage: sin(a)
0
sage: cos(2*pi)
1
sage: n(e,digits=10)
2.718281828
sage: n(golden_ratio, 50)
1.6180339887499
sage: eg=euler_gamma; eg
euler_gamma
sage: n(eg,90)
0.57721566490153286060651209
sage: n(catalan,90)
0.91596559417721901505460352
sage: log2
log2
sage: exp(log2)
e^log2
sage: n(exp(log2),56)
2.000000000000000
sage: n(exp(log2),digits=1)
2.0
Um grande número de funções elementares estão pré-programadas em Sage. Segue uma lista de algumas delas e alguns exemplos de uso:
sage: sqrt(2) # raiz quadrada, retorna um valor simbólico, sem avaliação
sqrt(2)
sage: sqrt(2.) # arg. ponto flutuante, retorna avaliação com precisão default
1.41421356237310
sage: exp(2) # exponencial, retorna um valor simbólico, sem avaliação
e^2
sage: exp(2.) # arg. ponto flutuante, retorna avaliação com precisão default
7.38905609893065
sage: log(e) # Em sage log = ln (logaritmo natural)
1
sage: log(100000,10) # Logaritmo de base 10
5
sage: log(-1)
# o log funciona com argumentos negativos e complexosI*pi
sage: log(-I)
-1/2*I*pi
Consulte o glossário para saber um pouco mais sobre programação orientada a objetos, propriedades e métodos.
Para forçar uma função a avaliar um valor com precisão definida podemos usar a função n (abreviação de numerical_approx) ou o método n. Ambos podem ser usados com o argumento opcional prec (para precisão em bits), ou digits (para precisão em dígitos). Se omitidos, a precisão default é de 53 bits ou 14 dígitos.
sage: sqrt(pi)
sqrt(pi)
sage: n(sqrt(pi))
1.77245385090552
sage: n(sqrt(pi),56) # prec = 56 bits
1.772453850905516
sage: n(sqrt(pi),digits=56) # raiz de pi com 56 dígitos
1.7724538509055160272981674833411451827975494561223871282
sage:log(10,2) # log 10 na base 2
log(10)/log(2)
sage: n(log(10,2),digits=5) # forçar avaliação com 5 dígitos
3.3219
No exemplo seguinte definimos uma variável em forma octal e exibimos sua representação de string nas bases 2, 8, 10 e 16. O método é obtido por meio da notação de ponto: objeto.metodo.
sage: num = 0203040506
sage: num.str(2)
'10000011000100000101000110'
sage: num.str(8)
'203040506'
sage: num.str(10)
'34357574'
sage: num.str(16)
'20c4146'
sage: sin(1)
sin(1)
sage: sin(1).n() # seno (1) com precisão default: aqui n é um método
0.841470984807897
sage: sin(1).n(digits=45) # seno (1) com 45 dígitos
0.841470984807896506652502321630298999622563061
sage: sin(1).n(prec=45) # seno (1) com precisão de 45 bits
0.8414709848079
sage: n(sin(1)) # seno (1) com precisão default: aqui n é uma função
0.841470984807897
sage: n(sin(1),digits=100)
0.8414709848078965066525023216302989996225630607983710656727517099919104043912396689
486397435430526959
sage: n(pi,digits=100)
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628
034825342117068
sage: numerical_approx(pi,digits=100)
3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862
8034825342117068
Observamos nos exemplos acima o uso de argumentos nomeados de Python. Como veremos em breve, é possível definir funções do usuário com estes argumentos nomeados, por exemplo: seno(x, freq =10, ampl=1) para designar o seno em x, com frequência freq e amplitude amp (sendo que os valores default já estão fornecidos, 10 e 1 respectivamente).
Assim como em Python, é possível investigar que tipo de variável está sendo usada:
sage: a=8
sage: type(a)
<type 'Sage.rings.integer.Integer'>
sage: b=1/3
sage: type(b)
<type 'Sage.rings.rational.Rational'>
sage: c='Uma ou várias palavras!'
sage: type(c)
<type 'str'>
sage: 01010 # um número precedido de 0 é entendido como um octal (de base 8)
520
sage: 8 + 8**3
520
sage: num=01010101
sage: num
266305
sage: num.str(8)
'1010101'
sage: num.str(10)
'266305'
sage: num.str(16)
'41041'
sage: num.str(2)
'1000001000001000001'
A interface de linha de Sage possui o ''completamento de código'' através da tecla tab.
sage: si # pressione (tab)
| sigma | simplicial_complexes | sin | singleton_upper_bound | singular_console | sinh |
| signal | simplify | singleton_bound_asymp | singular | singular_version |
Além disto se pode conseguir ajuda sobre um comando ou função digitando seu nome, seguido de interrogação:
sage: taylor?
Type: function
Functions in more variables are also supported.
...
EXAMPLES:
sage: var('x,k,n')
(x, k, n)
sage: taylor (sqrt (1 - k^^2*sin(x)^2), x, 0, 6)
-1/720*(45*k^6 - 60*k^4 + 16*k^2)*x^6 - 1/24*(3*k^4 - 4*k^2)*x^4 - 1/2*k^2*x^2 + 1
...
Para definir uma função usamos a palavra chave def, seguida do nome da função e seus argumentos.
sage: def Par(n):
....: return n%2 == 0
....:
sage: Par(2)
True
sage: Par(5)
False
A função eprimo abaixo investiga se um número é primo, retornando True ou False. Ela aceita um argumento n, transforma n em uma string e o compara com o string formado pela fatorização de n.
sage: def eprimo(n):
....: return str(n)==str(factor(n))
sage: eprimo(11)
True
sage: eprimo(12)
False
sage: is_prime(97)
True
Tendo definido a função eprimo() podemos chamá-la de dentro de outra função. No exemplo abaixo pediremos a listagem de todos os primos de 1 até n. Se n não for especificado a função usará o valor default n=100.
sage: def listarprimos(n=100):
....: primos=[]
....: for i in range(1,n):
....: if eprimo(i):
....: primos.append(i)
....: print(primos)
....: # tecle <enter> para sair da indentação
sage: listarprimos(9)
[1, 2, 3, 5, 7]
sage: listarprimos()
[1,2,3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Para esta função definimos a variável primos como um array vazio. Depois fizemos uma iteração de i de 1 até n testando se i é um primo, usando a função que definimos anteriormente. Caso afirmativo, i é inserido no array primos através do método append. A função termina imprimindo o array que contém os primos desejados.
No Sage/Python laços ou loops são geralmente obtidos pela iteração de uma variável percorrida dentro de uma lista. A função range(a,b,p) retorna uma lista iniciando em a, terminando em b (sem incluir b) e com passos de p em p.
sage: range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
sage: range(5, 10)
[5, 6, 7, 8, 9]
sage: range(0, 10, 3)
[0, 3, 6, 9]
sage: range(-10, -100, -30)
[-10, -40, -70]
sage: lista1 = range(1,10,2) ; lista1 # lista de 1 até 9, de 2 em 2
[1, 3, 5, 7, 9]
sage: lista2=range(100,0,-5); lista2 # lista de 100 até 0 (exclusive), de 2 em 2
[100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5]
sage: for i in range(5):
....: print '%6s %6s %6s' %(i, i^2, i^3)
0 0 0
1 1 1
2 4 8
3 9 27
4 16 64
sage: frase = ['Eppur', 'si', 'muove']
sage: for i in range(len(frase)):
....: print frase[i], len(frase[i]), ' letras'
Eppur 5 letras
si 2 letras
muove 5 letras
É possível atribuir uma função a uma variável:
sage: f = 5*sin(x); f
(5*sin(x))
sage: f(x = pi/2)
5
sage: f(x = pi/3)
5/2+sqrt(3)
sage: float(f(x = pi/3))
4.3301270189221928
Fica claro nos exemplos acima que usar o modo de comando de linha não é muito prático ou eficiente para operações ou algoritmos que envolvam um número maior de linhas. Qualquer erro de digitação no corpo de uma função exige nova digitação de todo o texto do código. Veremos em uma seção posterior que é possível gravar em arquivos toda uma sessão de trabalho em Sage ou o output de um comando em particular.
Na próxima seção veremos como gravar os comandos em arquivos de scripts que podem ser lidos de dentro de uma sessão interativa ou executados de modo independente.
Leia no site: | Devemos Acreditar na Ciência? | Hipótese, Modelo e Teoria em Física | Cosmologia - Estrutura do Universo | História da Pessoa com Deficiência |