# importando a biblioteca de funções do python
import numpy as np
# iniciando um array em python
M = np.array([10,24,34,45,56])
# mostra o tipo da variável a qual a função type recebe
type(M)
numpy.ndarray
# pode-se imprimir algum tipo de dado dessa forma
type(M)
numpy.ndarray
# digitar a variável no Jupyter Notebook também nos permite ver o seu conteúdo
M
array([10, 24, 34, 45, 56])
# colocar uma variável diretamente também é um formato compilável
print(M)
[10 24 34 45 56]
# atente-se que na progamação, na maioria das linguagens temos um array
# iniciado no elemento [0][0]
print("{}".format(M[0]))
10
# aqui vemos o elemento 4, na terceira possição do array
print("{}".format(M[4]))
56
# mostra todos os elementos do array começando na posição zero até a terceira posição
# atente-se que o último elemento de parada não é considerado no cálculo, e sim o seu antecessor
print("{}".format(M[0:4]))
[10 24 34 45]
# função que mostra a dimensão do array
# (linhas, colunas)
print(M.shape)
(5,)
# criando um array multidimensional
MD = np.array([[1,2,3,4,5],[6,7,8,9,10]])
# imprime o array multidimensional
print("{}".format(MD))
[[ 1 2 3 4 5] [ 6 7 8 9 10]]
# verificando a dimensão do array
MD.shape
(2, 5)
# forma de verificar os elementos da matriz multidimensional
MD[1,1]
7
# outra forma de verificar os elementos da matriz multidimensional
MD[1][1]
7
# o parâmetro de entrada zero permitirá ver a quantidade de linhas do array
MD.shape[0]
2
# o parâmetro de entrada um permitirá ver a quantidade de colunas do array
MD.shape[1]
5
# subMD recebe as linhas localizadas na posição zero e um, e colunas de zero a dois
# atente-se que o último digito de parada é desconsiderado
subMD = MD[0:2, 0:3]
# imprime a matriz subMD
print("{}".format(subMD))
[[1 2 3] [6 7 8]]
# nova entrada para o elemento da matriz localizado na posição MD[1][1]
MD[1,1] = 11
# veja como o elemento da matriz na posição [1][1] foi modificado
print("{}".format(MD))
[[ 1 2 3 4 5] [ 6 11 8 9 10]]
# o fato do primeiro elemento ser um float, número real, indica que todos os outros elementos
# serão também do tipo float
MR = np.array([[1.0,2,3,4,5], [1000,12,4556,788,1], [6,7,8,9,1000]])
# imprime a matriz MR
# Os valores dos elementos da matriz são mostrados no formato de notação científica computacional
print("{}".format(MR))
[[1.000e+00 2.000e+00 3.000e+00 4.000e+00 5.000e+00] [1.000e+03 1.200e+01 4.556e+03 7.880e+02 1.000e+00] [6.000e+00 7.000e+00 8.000e+00 9.000e+00 1.000e+03]]
#observe que a matriz identidade será do tipo float
# o parâmetro de entrada é a ordem da matriz a ser trabalhada
I = np.eye(4)
# imprime a matriz Identidade I
print("{}".format(I))
[[1. 0. 0. 0.] [0. 1. 0. 0.] [0. 0. 1. 0.] [0. 0. 0. 1.]]
# interessante para inicializar uma matriz sem lixo de memória
# são dois parâmetros de entrada, relativos a quantidade de linhas e colunas, respectivamente.
# caso tal matriz seja manipulada por algum procedimento de multiplicação, essa inicialização
# não é uma boa escolha
Z = np.zeros((4,4))
# imprimindo a matriz Z
print("{}".format(Z))
[[0. 0. 0. 0.] [0. 0. 0. 0.] [0. 0. 0. 0.] [0. 0. 0. 0.]]
# mesma ideia da função acima, mas ao invés de zeros, será preenchido com valores 1
# observe que essa matriz é ideal quando trabalha-se com operações de multiplicação
U = np.ones((4,2))
# imprime a matriz U
print("{}".format(U))
[[1. 1.] [1. 1.] [1. 1.] [1. 1.]]
# multiplicando uma matriz com todos os elementos iniciados com 1 por um escalar
print("{}".format(U))
[[1. 1.] [1. 1.] [1. 1.] [1. 1.]]
Ou
# função que cria um array em que todos os seus elementos são iguais a uma constante a ser definida
# np.full((número de linhas, número de colunas), constante a ser definida na matriz)
U = np.full((5,2), 10)
#imprime a matriz U
print("{}".format(U))
[[10 10] [10 10] [10 10] [10 10] [10 10]]
# np.random.random((número de linhas, número de colunas))
# cria uma matriz de números aleatórios
R = np.random.random((4,5))
# imprime a matriz R
print("{}".format(R))
[[0.83670313 0.6563392 0.77275586 0.69965855 0.55071841] [0.51802409 0.62063839 0.35390263 0.80153205 0.32365402] [0.20997078 0.58628487 0.03465468 0.19432512 0.18718823] [0.33339079 0.02659723 0.22485586 0.58804561 0.71405599]]
# criando uma matriz X
X = np.array([[1,2,3],[4,5,6]])
# calcula a média de todos os elementos da matriz X inicializada acima
np.mean(X)
3.5
# criando uma matriz A
A = np.array([[1,2,3],[4,5,6],[7,8,9]])
# criando uma matriz B
B = np.array([[-1,0,1],[0,1,1],[4,4,4]])
# imprime a matriz A
print("{}".format(A))
[[1 2 3] [4 5 6] [7 8 9]]
# imprime a matriz B
print("{}".format(B))
[[-1 0 1] [ 0 1 1] [ 4 4 4]]
# multiplicação simples de uma matriz
# OBS: só é permitido a entrada de matrizes de mesma ordem
A * B
array([[-1, 0, 3], [ 0, 5, 6], [28, 32, 36]])
# soma duas matrizes de mesma ordem
A + B
array([[ 0, 2, 4], [ 4, 6, 7], [11, 12, 13]])
# subtração de duas matrizes de mesma ordem
A - B
array([[2, 2, 2], [4, 4, 5], [3, 4, 5]])
# subtração de duas matrizes de mesma ordem
B - A
array([[-2, -2, -2], [-4, -4, -5], [-3, -4, -5]])
Podemos realizar operações utilizando a biblioteca do numpy. Um motivo para essa escolha é que podemos realizar multiplicações com matrizes de ordens diferentes, mas definidas na operação. Além disso, pode-se mudar o tipo de dados trabalhados na matriz e ainda especificar a quantidade de bytes suportadas para armazenamento de cada elemento da mesma. (Dependência dos requisitos da máquina trabalhada, mas em geral: 16 - 128 bytes).
# multiplicação de matrizes de ordem diferentes, mas com a multiplicação definida
np.multiply(A,B, dtype = float)
array([[-1., 0., 3.], [ 0., 5., 6.], [28., 32., 36.]])
# soma as matrizes de mesma ordem
np.add(A,B, dtype = np.float16)
array([[ 0., 2., 4.], [ 4., 6., 7.], [11., 12., 13.]], dtype=float16)
# subtrai as matrizes de mesma ordem
np.subtract(A,B, dtype = np.int32)
array([[2, 2, 2], [4, 4, 5], [3, 4, 5]])
# subtrai as matrizes de mesma ordem
np.subtract(B,A, dtype = np.int32)
array([[-2, -2, -2], [-4, -4, -5], [-3, -4, -5]])
# criando a matriz A
A = np.array([[1,2,3],[4,5,6]])
# criando a matriz B
B = np.array([[1],[1],[1]])
# outra função que realiza a multiplicação de matrizes de ordens diferentes, mas
# sem especificador de tipo
np.matmul(A,B)
array([[ 6], [15]])
# Matriz com operação não definida, veja que a compilação não ocorrerá
np.matmul(B,A)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-50-7bc42922f4c7> in <module> 1 # Matriz com operação não definida, veja que a compilação não ocorrerá ----> 2 np.matmul(B,A) ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2 is different from 1)
Cuidado, pois mesmo o código estando digitado corretamente, operações matemáticas podem não estar definidas, resultando em erros fatais ou não fatais pelo compilador.
# outra forma de multiplicar duas matrizes
np.dot(A,B)
array([[ 6], [15]])
# criando a matriz a
a = np.array([[1,2,3]])
# criando a matriz b
b = np.array([[4,5,6]])
# Um produto interno é uma generalização do produto escalar. Em um espaço vetorial,
# é uma maneira de multiplicar vetores
# juntos, com o resultado dessa multiplicação sendo um escalar.
np.inner(a,b)
array([[32]])
# criando a matriz A
A = np.array([[1,2,3],[3,4,5]])
# criando a matriz B
B = np.array([[1,5,7],[5,9,9]])
# produto tensorial de dois espaços vetoriais
np.tensordot(A,B)
array(128)
# criando a matriz A
A = np.array([[1,2,7],[3,6,7],[8,9,0]])
# função responsável por calcular a potenciação de matrizes.
# Nesse caso, A está elevada a 5º potência
np.linalg.matrix_power(A,5)
array([[123235, 185759, 175273], [205065, 300027, 255535], [221333, 307524, 210945]])
# criando a matriz A
A = np.array([[1,2],[3,4]])
# criando a matriz B
B = np.array([[0,5],[6,7]])
# calcula o produto kronecker de duas matrizes
np.kron(A,B)
array([[ 0, 5, 0, 10], [ 6, 7, 12, 14], [ 0, 15, 0, 20], [18, 21, 24, 28]])
# criando a matriz A
A = np.array([[4,12,-16],[12,37,-43],[-16,-43,98]])
# função responsável por calcular a fatoração de cholesky
fatorada = np.linalg.cholesky(A)
# imprime a matriz A
fatorada
array([[ 2., 0., 0.], [ 6., 1., 0.], [-8., 5., 3.]])
# provando a validade da Fatoração de Cholesky em python
# multiplica a matriz fatorada por sua transposta, obtendo a matriz A que foi fatorada
np.matmul(fatorada,fatorada.transpose())
array([[ 4., 12., -16.], [ 12., 37., -43.], [-16., -43., 98.]])
# criando uma matriz A
A = np.array([[2,0],[0,1]])
# imprime a matriz A
A
array([[2, 0], [0, 1]])
#determinando autovalores e autovetores
autovalores, autovetores = np.linalg.eig(A)
# matriz diagonal de autovalores
matrizDiagonal = np.diag(autovalores)
# obtendo novamente a matriz A através da decomposição espectral ou valores singulares
# A = PDP^(-1)
A = np.matmul(np.matmul(autovetores,matrizDiagonal),np.linalg.inv(autovetores))
# autovetores da matriz A
autovetores
array([[1., 0.], [0., 1.]])
# matriz diagonal
matrizDiagonal
array([[2., 0.], [0., 1.]])
# matriz de transformação linear
A
array([[2., 0.], [0., 1.]])
# autovalores para a matriz A
autovalores
array([2., 1.])
# outra forma de se obter os autovalores
np.linalg.eigvals(A)
array([2., 1.])
# criando uma matriz A
A = np.array([[2,0],[0,1]])
(U,s,V) = np.linalg.svd(A)
# imprime a matriz U
U
array([[1., 0.], [0., 1.]])
# imprime a matriz s
s
array([2., 1.])
# imprime a matriz V
V
array([[1., 0.], [0., 1.]])
# determinante da matriz
np.linalg.det(A)
2.0
# posto da matriz
np.linalg.matrix_rank(A)
2
# traço da matriz (soma da diagonal)
np.trace(A)
3
# Vamos considerar Ax = B
# criando a matriz A
A = np.array([[3], [4]])
# criando a matriz b
b = np.array([[6], [8]])
# 3x = 6
# 4y = 8
# realiza a multiplicação da matriz inversa de A com a matriz b
X = np.matmul(np.linalg.pinv(A), b)
# imprime a matriz X
X
array([[2.]])
# criando a matriz A
A = np.array([[1,2],[3,4]])
# imprime a matriz inversa
np.linalg.pinv(A)
array([[-2. , 1. ], [ 1.5, -0.5]])