| | | |

Minicurso de Python para Matemática

Material disponível para compra: e-book livro. Consulte outras formas de colaboração aqui!

4.2 Elementos da álgebra linear

O numpy conta com um módulo de álgebra linear, usualmente importado com

1import numpy.linalg as npla

4.2.1 Vetores

Um vetor podem ser alocado usando um numpy.array de um eixo (dimensão). Por exemplo,

x=(2,1), (4.12)
y=(3,1,π) (4.13)

podem ser alocados com

1x = np.array([2,-1])
2print(x)
[ 2 -1]

e

1y = np.array([3, 1, np.pi])
2print(y)
[3. 1. 3.14159265]
E. 4.2.1.

Aloque cada um dos seguintes vetores como um numpy.array:

  1. a)

    x=(1.2,3.1,4)

  2. c)

    z=(π,2,e2)


1import numpy as np
2# a)
3x = np.array([1.2, -3.1, 4])
4print('x = ', x)
5# b)
6z = np.array([np.pi, np.sqrt(2.), np.exp(-2)])
7print('z = ', z)

4.2.2 Produto escalar e norma

Dados dois vetores

x=(x0,x1,,xn1), (4.14)
y=(y0,y1,,yn1), (4.15)

define-se o produto escalar por

xy=x0y0+x1y1++xn1yn1. (4.16)

Com o NumPy, podemos computá-lo com a função hlnumpy.dot. Por exemplo,

1x = np.array([-1, 0, 2])
2y = np.array([0, 1, 1])
3d = np.dot(x,y)
4print(d)
2

A norma l2 de um vetor é definida por

x2=i=0n1xi2. (4.17)

O NumPy conta com o método numpy.linalg.norm para computá-la. Por exemplo,

1nrm = npla.norm(y)
2print(nrm)
4.457533443631058
E. 4.2.2.

Faça um código para computar o produto escalar xy sendo

x=(1.2,ln(2),4), (4.18)
y=(π2,3,e) (4.19)

1import numpy as np
2x = np.array([1.2, np.log(2), 4])
3y = np.array([np.pi**2, np.sqrt(3), np.e])
4d = np.dot(x,y)

4.2.3 Matrizes

Uma matriz pode ser alocada como um numpy.array de dois eixos (dimensões). Por exemplo, as matrizes

A=[217310], (4.20)
B=[402186] (4.21)

podem ser alocadas como segue

1A = np.array([[2,-1,7],
2 [3,1,0]])
3print(A)
[[ 2 -1 7]
[ 3 1 0]]

e

1B = np.array([[4,0],
2 [2,1],
3 [-8,6]])
4print(B)
[[ 4 0]
[ 2 1]
[-8 6]]

Como já vimos, o NumPy conta com operadores elemento-a-elemento que podem ser utilizados na álgebra envolvendo arrays, logo também aplicáveis a matrizes (consulte a Subseção 4.1.3). Na sequência, vamos introduzir outras operações próprias deste tipo de objeto.

E. 4.2.3.

Aloque cada uma das seguintes matrizes como um numpy.array:

  1. a)

    A=[122460] (4.22)
  2. b)

    B=AT


1import numpy as np
2# a)
3A = np.array([[-1, 2],
4 [2, -4],
5 [6, 0]])
6# b)
7B = A.transpose()
E. 4.2.4.

Seja

1A = np.array([[2,1],[1,1],[-3,-2]])

Determine o formato (shape) dos seguintes arrays:

  1. a)

    A[:,0]

  2. b)

    A[:,0:1]

  3. c)

    A[1:3,0]

  4. d)

    A[1:3,0:1]

  5. e)

    A[1:3,0:2]


1import numpy as np
2# a)
3A = np.array([[2, 1],
4 [1, 1],
5 [-3, -2]])
6print('a)', A[:,0].shape)
7print('b)', A[:,0:1].shape)
8print('c)', A[1:3,0].shape)
9print('d)', A[1:3,0:1].shape)
10print('e)', A[1:3,0:2].shape)

4.2.4 Inicialização de matrizes

Além das inicializações de arrays já estudadas na Subseção 4.1.1, temos mais algumas que são particularmente úteis no caso de matrizes.

  • numpy.eye(n): retorna a matriz identidade n×n.

    1I = np.eye(3)
    2print(I)
    [[1. 0. 0.],
    [0. 1. 0.],
    [0. 0. 1.]]
  • numpy.diag: extrai a diagonal ou constrói um numpy.array diagonal.

    1D = np.diag([1,2,3])
    2print(D)
    [[1, 0, 0],
    [0, 2, 0],
    [0, 0, 3]]
E. 4.2.5.

Aloque a matriz dos coeficientes e o vetor dos termos constantes do seguinte sistema de equações

x1=0 (4.23)
xi1+2xixi+1=h2fi (4.24)
xn=0 (4.25)

onde fi=π2sin(πxi), xi=(i1)h, h=1/(n1), n=5.


1import numpy as np
2n = 5
3h = 1./(n-1)
4x = np.linspace(0., 1., n)
5b = np.pi**2*np.sin(np.pi*x)
6A = np.diag(2*np.ones(n)) + \
7 np.diag(-np.ones(n-1), k=-1) + \
8 np.diag(-np.ones(n-1), k=1)
9A[0,0] = 1.
10A[0,1] = 0.
11A[n-1,n-2] = 0.
12A[n-1,n-1] = 1.
13print('A = \n', A)
14print('b = \n', b)

4.2.5 Multiplicação de matrizes

A multiplicação da matriz A=[aij]i,j=0n1,l1 pela matriz B=[bij]i,j=0l1,m1 é a matriz C=AB=[cij]i,j=0n1,m1 tal que

cij=k=0l1aikbk,j (4.26)

O numpy tem a função numpy.matmul para computar a multiplicação de matrizes. Por exemplo, a multiplicação das matrizes dadas em (4.20) e (4.21), computamos

1C = np.matmul(A,B)
2print(C)
[[-50 41],
[ 14 1]]
Observação 4.2.1.(matmul, *, @)

É importante notar que numpy.matmul(A,B) é a multiplicação de matrizes, enquanto que * consiste na multiplicação elemento a elemento. Alternativamente a numpy.matmul(A,B) pode-se usar A @ B.

E. 4.2.6.

Aloque as matrizes

C=[121321023] (4.27)
D=[231164] (4.28)
E=[121013] (4.29)

Então, se existirem, compute e forneça as dimensões das seguintes matrizes

  1. a)

    CD

  2. b)

    DTE

  3. c)

    DTC

  4. d)

    DE


1import numpy as np
2C = np.array([[1, 2, -1],
3 [3, 2, 1],
4 [0, -2, -3]])
5D = np.array([[2, 3],
6 [1, -1],
7 [6, 4]])
8E = np.array([[1, 2, 1],
9 [0, -1, 3]])
10print('a) CD = \n', C@D)
11print("b) não existe D'E")
12print("c) D'C = \n", C.T@C)
13print("d) DE = \n", D@E)

4.2.6 Traço e determinante de uma matriz

O numpy tem a função numpy.ndarray.trace para computar o traço de uma matriz (soma dos elementos de sua diagonal). Por exemplo,

1A = np.array([[-1,2,0],[2,3,1],[1,2,-3]])
2print('tr(A) = ', A.trace())
tr(A) = -1

Já, o determinante é fornecido no módulo numpy.linalg. Por exemplo,

1A = np.array([[-1,2,0],[2,3,1],[1,2,-3]])
2print('det(A) = ', npla.det(A))
det(A) = 25.000000000000007
E. 4.2.7.

Compute a solução do seguinte sistema de equações

x1x2+x3=2 (4.30)
2x1+2x2+x3=5 (4.31)
x1x2+2x3=5 (4.32)

pelo método de Cramer555Gabriel Cramer, 1704 - 1752, matemático suíço. Fonte: Wikipédia: Gabriel Cramer..


1import numpy as np
2import numpy.linalg as npla
3# matriz dos coefs
4A = np.array([[1, -1, 1],
5 [2, 2, 1],
6 [-1, -1, 2]])
7# vetor dos termos consts
8b = np.array([-2, 5, -5])
9# mat aux A1
10A1 = A.copy()
11A1[:,0] = b
12# sol x1
13x1 = npla.det(A1)/npla.det(A)
14print('x1 = ', x1)
15# mat aux A2
16A2 = A.copy()
17A2[:,1] = b
18# sol x2
19x2 = npla.det(A2)/npla.det(A)
20print('x2 = ', x2)
21# mat aux A3
22A3 = A.copy()
23A3[:,2] = b
24# sol x3
25x3 = npla.det(A3)/npla.det(A)
26print('x3 = ', x3)

4.2.7 Posto e inversa de uma matriz

O posto (rank) de uma matriz é o número de linhas ou colunas linearmente independentes. O numpy conta com a função numpy.linalg.matrix_rank para computá-lo. Por exemplo,

1npla.matrix_rank(np.eye(3))
3
1A = np.array([[1,2,3],[-1,1,-1],[0,3,2]])
2npla.matrix_rank(A)
2

O método numpy.linalg.inv pode ser usado para computar a inversa de uma matriz full rank. Por exemplo,

1A = np.array([[1, 2, 3],
2 [-1, 1, -1],
3 [1, 3, 2]])
4Ainv = np.linalg.inv(A)
5print('Ainv @ A = \n', Ainv @ A)
Ainv @ A =
[[ 1.00000000e+00 -2.22044605e-16 -8.88178420e-16]
[ 0.00000000e+00 1.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 -2.22044605e-16 1.00000000e+00]]
E. 4.2.8.

Compute, se possível, a matriz inversa de cada uma das seguintes matrizes

B=[2121] (4.33)
C=[201311210] (4.34)

Verifique suas respostas.


1import numpy as np
2import numpy.linalg as npla
3
4def inv(A):
5 if (npla.matrix_rank(A) == A.shape[1]):
6 return npla.inv(A)
7 else:
8 print('Matriz não invertível.')
9 return None
10
11B = np.array([[2, -1],
12 [-2, 1]])
13print('inv(B) = \n', inv(B))
14
15A = np.array([[-2, 0, 1],
16 [3, 1, -1],
17 [2, 1, 0]])
18print('inv(A) = \n', inv(A))

4.2.8 Autovalores e autovetores de uma Matriz

Um auto-par (λ,v) de uma matriz A, λ um escalar chamado de autovalor e v0 é um vetor chamado de autovetor, é tal que

Aλ=λv. (4.35)

O numpy tem a função numpy.linalg.eig para computar os auto-pares de uma matriz. Por exemplo,

1lmbda, v = npla.eig(np.eye(3))
2print('autovalores = \n', lmbda)
3print('autovetores = \n', v)
autovalores =
[1. 1. 1.]
autovetores =
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]

Observamos que a função retorna um tuple de numpy.arrays, sendo que o primeiro contém os autovalores (repetidos conforme suas multiplicidades) e o segundo item é a matriz dos autovetores (dispostos nas colunas).

E. 4.2.9.

Compute os auto-pares da matriz

A=[132321211]. (4.36)

Então, verifique se, de fato, Av=λv para cada auto-par (λ,v) computado.


1import numpy as np
2import numpy.linalg as npla
3A = np.array([[1, 3, 2],
4 [3, 2, -1],
5 [2, -1, 1]])
6lmbda, v = np.linalg.eig(A)
7# testando os auto-pares
8print(npla.norm(A @ v[:, 0] - lmbda[0] * v[:, 0]) < 1e-10)
9print(npla.norm(A @ v[:, 1] - lmbda[1] * v[:, 1]) < 1e-10)
10print(npla.norm(A @ v[:, 2] - lmbda[2] * v[:, 2]) < 1e-10)

Envie seu comentário

Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!

Opcional. Preencha seu nome para que eu possa lhe contatar.
Opcional. Preencha seu e-mail para que eu possa lhe contatar.
As informações preenchidas são enviadas por e-mail para o desenvolvedor do site e tratadas de forma privada. Consulte a política de uso de dados para mais informações.

Licença Creative Commons
Este texto é disponibilizado nos termos da Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional. Ícones e elementos gráficos podem estar sujeitos a condições adicionais.

Pedro H A Konzen
| | | |