Álgebra Linear Computacional básica
Contents
9. Álgebra Linear Computacional básica#
9.1. Objetivos#
Associar conceitos abstratos de Álgebra Linear a estruturas computacionais;
Realizar operações básicas com vetores e matrizes;
Saber como resolver sistemas lineares de pequeno porte;
Calcular autovalores e autovetores em matrizes reais;
9.2. Introdução#
Neste capítulo, mostraremos como realizar operações básicas entre matrizes e vetores usando o computador. A manipulação de matrizes e vetores é essencial em muitas ciências, principalmente para resolver sistemas lineares.
As matrizes são utilizadas na computação para armazenar informações bidimensionais. Em particular, podem representar translação, rotação, escalonamento e sistemas de equações. O estudo da relação entre algoritmos e métodos computacionais para trabalhar eficientemente com matrizes e vetores é realizado no âmbito da Álgebra Linear Computacional.
9.3. Matrizes e vetores#
Uma matriz
As colunas de uma matriz com
é uma representação equivalente para a matriz anterior.
Em Python, usamos o módulo numpy para trabalhar com matrizes e vetores. Vetores são arrays 1D, ao passo que matrizes são arrays 2D, ou seja, um “array de arrays”.
Exemplo. Represente computacionalmente os vetores do
Note
O NumPy possui uma classe especial para se trabalhar com matrizes e vetores em uma ou duas dimensões, a saber o tipo matrix
, ou mat
. Com objetos matrix
, as operações particulares de multiplicação matriz-matriz ou matriz-vetor comportam-se diferentemente daquelas na classe ndarray
. Neste texto, abordaremos apenas os tipos ndarray
porque são aplicáveis também a matrizes multidimensionais.
import numpy as np
u = np.array([3,-2,9])
v = np.array([-2,4,0])
w = np.array([1,0,0])
print(u), print(v), print(w);
[ 3 -2 9]
[-2 4 0]
[1 0 0]
Exemplo. Represente computacionalmente a matriz 3 x 3 dada por
Observe que os vetores devem ser escritos como “coluna”.
A = np.array([[3,-2,1],[-2,4,0],[9,0,0]])
print(A)
[[ 3 -2 1]
[-2 4 0]
[ 9 0 0]]
Exemplo. Represente computacionalmente a matriz
Vamos escrever linha por linha.
L1 = np.array([2,-2]) # linha 1
L2 = np.array([4,1]) # linha 2
L3 = np.array([2,1]) # linha 3
A2 = np.array([L1,L2,L3]) # lista de listas
print(A2)
[[ 2 -2]
[ 4 1]
[ 2 1]]
Diretamente, poderíamos também definir:
A3 = np.array([[2,-2],[4,1],[2,1]])
print(A3)
[[ 2 -2]
[ 4 1]
[ 2 1]]
Note que cada lista representa uma linha.
9.3.1. Transposição#
Matrizes e vetores podem ser transpostos com .T
:
A2T = A2.T
print(A2T)
[[ 2 4 2]
[-2 1 1]]
Assim, com as variáveis antes definidas, poderíamos, equivalentemente, fazer para
# modo 2: matriz transposta
At = np.array([u,v,w]).T
print(At)
[[ 3 -2 1]
[-2 4 0]
[ 9 0 0]]
9.3.2. Teste de igualdade#
Podemos verificar a igualdade entre matrizes como
A == At
array([[ True, True, True],
[ True, True, True],
[ True, True, True]])
No caso de vetores:
# vetor "linha" não difere
# do vetor "coluna"
u == u.T
array([ True, True, True])
9.4. Operações fundamentais#
9.4.1. Adição e subtração#
A adição (subtração) de matrizes e vetores pode ser realizada de modo usual com computação vetorizada.
Exemplo:
# adição
ad = u + v
print(ad)
# subtração
sub = u - v
print(sub)
[1 2 9]
[ 5 -6 9]
Exemplo:
# adição
B = np.array([u,2*u,3*v]).T
ad2 = A + B
print(ad2)
sub2 = A - B
print(sub2)
[[ 6 4 -5]
[-4 0 12]
[18 18 0]]
[[ 0 -8 7]
[ 0 8 -12]
[ 0 -18 0]]
9.4.2. Produto interno#
O produto interno .dot
:
pi = np.dot(u,v)
print(pi)
pi2 = np.dot(np.array([3,1]),np.array([-1,-1]))
print(pi2)
-14
-4
Uma segunda forma, mais imediata, emprega o operador infixo @
:
pii = u @ v
print(pii)
pii2 = np.array([3,1]) @ np.array([-1,-1])
print(pii2)
-14
-4
9.4.3. Norma de vetor#
A norma
np.sqrt(np.dot(u,u))
9.695359714832659
9.4.4. Produto de matrizes#
O produto np.dot
, mas recomenda-se usar np.matmul
.
# não tem o mesmo efeito para
# matrizes A e B de tamanhos arbitrários
np.dot(A,B)
array([[ 22, 44, -42],
[-14, -28, 60],
[ 27, 54, -54]])
# uso recomendado para a operação tradicional
np.matmul(A,B)
array([[ 22, 44, -42],
[-14, -28, 60],
[ 27, 54, -54]])
9.4.5. Produto entre matriz e vetor#
Neste caso, sendo
b = np.array([3,4,1])
np.dot(A,b)
array([ 2, 10, 27])
9.5. Demais operações com numpy.linalg
#
Para outras operações, devemos utilizar o submódulo numpy.linalg
. Para importá-lo com o alias lin
, fazemos:
import numpy.linalg as lin
9.5.1. Determinante#
O determinante de det
.
# calculando o determinante da matriz
det = lin.det(A)
print(det)
-36.0
9.5.2. Inversa de uma matriz#
A inversa de uma matriz é dada por
B2 = np.array([[1,2,3],
[2,3,4],
[1,2,0]])
B3 = lin.inv(B2)
print(np.matmul(B3,B2))
[[1.00000000e+00 2.22044605e-16 0.00000000e+00]
[1.11022302e-16 1.00000000e+00 0.00000000e+00]
[0.00000000e+00 0.00000000e+00 1.00000000e+00]]
9.5.3. Soluções de sistemas lineares#
Para resolver sistemas lineares, devemos escrever as equações em forma de matriz, ou seja, solve
.
Exemplo: Resolva o sistema linear abaixo:
para
A = np.array([[-4,1],[3, 5]])
b = np.array([1/2,10])
# solução
x = lin.solve(A, b)
print(x)
[0.32608696 1.80434783]
9.5.4. Inversa de matriz#
A inversa de uma matriz (faça esta operação apenas para matrizes quadradas de pequena dimensão) pode ser encontrada como:
Ainv = lin.inv(A)
print(Ainv)
[[-0.2173913 0.04347826]
[ 0.13043478 0.17391304]]
Para realizar uma “prova real” da solução do sistema anterior, poderíamos fazer:
x2 = np.dot(lin.inv(A), b)
print(x2)
[0.32608696 1.80434783]
Note, entretanto que:
x == x2
array([ True, True])
Isto ocorre devido a erros numéricos. Um teste mais adequado deve computar a norma do vetor “erro”, dado por
e = b - np.dot(A,x)
lin.norm(e)
0.0
Isto é, esperamos que
Warning
Nunca compare dois números reais (float
) usando igualdade. Ou seja, x == y
, não é, em geral, um bom teste lógico para verificar se x
e y
possuem o mesmo valor numérico.
9.6. Algumas matrizes especiais#
9.6.1. Nula#
Para criar uma matriz nula de ordem m x n, usamos zeros
.
m,n = 3,4
np.zeros((m,n))
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
9.6.2. Identidade#
Uma matriz identidade (quadrada) de ordem p é criada com eye
.
p = 4
np.eye(p)
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
9.6.3. Matriz de “uns”#
Uma matriz composta apenas de valores 1 de ordem m x n pode ser criada com ones
:
np.ones((3,5))
array([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
9.6.4. Triangular inferior#
A matriz triangular inferior de uma dada matriz pode ser criada com tril
. Note que podemos também defini-la explicitamente, linha a linha.
# os valores correspondentes
# são zerados
np.tril(B)
array([[ 3, 0, 0],
[-2, -4, 0],
[ 9, 18, 0]])
9.6.5. Triangular superior#
A matriz triangular superior de uma dada matriz pode ser criada com triu
. Note que podemos também defini-la explicitamente, linha a linha.
np.triu(B)
array([[ 3, 6, -6],
[ 0, -4, 12],
[ 0, 0, 0]])
Exercício. Por que há dois valores False
no teste a seguir?
B == np.tril(B) + np.triu(B)
array([[False, True, True],
[ True, False, True],
[ True, True, True]])
9.7. Autovalores e autovetores#
Um vetor
O número real
A = np.array([[2,1],
[1,-5]])
w, v = lin.eig(A)
a,b = w
# autovalores
print(a,b)
# autovetor 1
print(v[:,0])
# autovetor 2
print(v[:,1])
2.1400549446402586 -5.1400549446402595
[0.99033427 0.13870121]
[-0.13870121 0.99033427]
9.8. Somas e valores extremos#
Podemos calcular somas de elementos de matrizes e vetores de maneiras diferentes. Para matrizes, em particular, há soma total, por linha, ou por coluna.
a = np.array([1,-2,-3,10])
# soma de todos os elementos
np.sum(a)
6
# modo alternativo
a.sum()
6
# soma total de matriz
O = np.ones((5,3))
np.sum(O)
15.0
# modo alternativo
O.sum()
15.0
# soma por linha
M = np.array( [ [ [ [-1,0],[1,0] ], [ [-1,0],[1,0] ]] ])
np.sum(M,axis=2)
array([[[0, 0],
[0, 0]]])
# soma por coluna
np.sum(O,axis=1)
array([3., 3., 3., 3., 3.])
Valores máximos e mínimos, absolutos ou não, também podem ser computados com funções simples.
# min
np.min(a)
-3
# max
np.max(a)
10
# modo alternativo
a.min()
-3
a.max()
10
# mínimo absoluto
np.abs(a).min()
1
# máximo absoluto
np.abs(a).max()
10
O2 = np.array([[-4,5],[2,7]])
# min
np.min(O2)
-4
# max
np.max(O2)
7
O2.min()
-4
O2.max()
7
np.abs(O2).min()
2
np.abs(O2).max()
7