| | | | |

4 Elementos da Computação Matricial

Compre o e-book deste material aqui!

Nesta seção, vamos explorar a NumPy (Numerical Python), biblioteca para tratamento numérico de dados. Ela é extensivamente utilizada nos mais diversos campos da ciência e da engenharia. Aqui, vamos nos restringir a introduzir algumas de suas ferramentas para a computação matricial.

Usualmente, a biblioteca é importada como segue

1import numpy as np

4.1 NumPy array

Um numpy.array é uma tabela de valores (vetor, matriz ou multidimensional) e contém informação sobre os dados brutos, indexação e como interpretá-los. Os elementos são todos do mesmo tipo (diferente de uma lista Python), referenciados pela propriedade dtype. A indexação dos elementos pode ser feita por um tuple de inteiros não negativos, por booleanos, por outro numpy.array ou por números inteiros. O ndim de um numpy.array é seu número de dimensões (chamadas de axes77endnote: 7axes, do inglês, plural de axis, eixo.). O numpy.ndarray.shape é um tuple de inteiros que fornece seu tamanho (número de elementos) em cada dimensão. Sua inicialização pode ser feita usando-se listas simples ou encadeadas. Por exemplo,

1a = np.array([1, 3, -1, 2])
2print(a)
[ 1  3 -1  2]
1a.dtype
dtype(’int64’)
1a.shape
(4,)
1a[2]
-1
1a[1:3]
array([ 3, -1])

temos um numpy.array de números inteiros com quatro elementos dispostos em um único axis (eixo). Podemos interpretá-lo como uma representação de um vetor linha ou coluna, i.e.

a=(1,3,1,2) (28)

vetor coluna ou aT vetor linha.

Outro exemplo,

1a = np.array([[1.0,2,3],
2              [-3,-2,-1]])
3a.dtype
dtype(’float64’)
1a.shape
(2, 3)
1a[1,1]
-2.0

temos um numpy.array de números decimais (float) dispostos em um arranjo com dois axes (eixos). O primeiro axis tem tamanho 2 e o segundo tem tamanho 3. Ou seja, podemos interpretá-lo como uma matriz de duas linhas e três colunas. Podemos fazer sua representação algébrica como

a=[123321] (29)
Exercício 4.1.1.

Use numpy.array para alocar:

  1. a)

    o vetor

    v=(5,π,sen(π/3)) (30)
  2. b)

    a matriz

    A=[11322e13] (31)
Resposta.
1import numpy as np
2# a)
3v = np.array([-5., np.pi, np.sin(np.pi/3)])
4print('v = ', v)
5# b)
6A = np.array([[-1., 1./3],
7              [2., np.sqrt(2)],
8              [np.exp(-1.), -3.]])
9print('A = \n', A)

4.1.1 Inicialização de um array

O NumPy conta com úteis funções de inicialização de numpy.array. Vejam algumas das mais frequentes:

  • numpy.zeros: inicializa um numpy.array com todos seus elementos iguais a zero.

    1np.zeros(2)
    array([0., 0.])
    
  • numpy.ones: inicializa um numpy.array com todos seus elementos iguais a 1.

    1np.ones((3,2), dtype='int')
    array([[1, 1],
          [1, 1],
          [1, 1]])
    
  • numpy.empty: inicializa um numpy.array sem alocar valores para seus elementos88endnote: 8Atenção! No momento da alocação, os valores dos elementos serão dinâmicos conforme “lixo” da memória..

    1np.empty(3)
    array([4.9e-324, 1.5e-323, 2.5e-323])
    
  • numpy.arange: inicializa um numpy.array com uma sequência de elementos99endnote: 9Similar à função Python range..

    1np.arange(1,6,2)
    array([1, 3, 5])
    
  • numpy.linspace(a, b[, num=n]): inicializa um numpy.array como uma sequência de elementos que começa em a, termina em b (incluídos) e contém n elementos igualmente espaçados.

    1np.linspace(0, 1, num=5)
    array([0.  , 0.25, 0.5 , 0.75, 1.  ])
    
Exercício 4.1.2.

Aloque a matriz escalar

A=[200020002] (32)

como um numpy.array.

Resposta.
1import numpy as np
2A = -2*np.ones((3,3))
3print('A = \n', A)
Exercício 4.1.3.

Construa um numpy.array para alocar uma partição uniforme com 11 pontos do intervalo [0,1]. Ou seja, um arranjo 𝒙=(x1,x2,,xn), de elementos xi=(i1)h, com passo h=1/(n1).

Resposta.
1import numpy as np
2x = np.linspace(0., 1., 11)
3print('x = ', x)

4.1.2 Manipulação de arrays

Outras duas funções importantes no tratamento de arrays são:

  • numpy.reshape: permite a alteração da forma de um numpy.array.

    1a = np.array([-2,-1])
    2print(a)
    [-2 -1]
    
    1b = a.reshape(2,1)
    2print(b)
    [[-2]
     [-1]]
    

    O numpy.reshape também permite a utilização de um coringa -1 que será dinamicamente determinado de forma obter-se uma estrutura adequada. Por exemplo,

    1a = np.array([[1,2],[3,4]])
    2print(a)
    [[1 2]
     [3 4]]
    
    1b = a.reshape((-1,1))
    2print(b)
    [[1]
     [2]
     [3]
     [4]]
    
  • numpy.transpose: computa a transposta de uma matriz.

    1a = np.array([[1,2],[3,4]])
    2print(a)
    [[1 2]
     [3 4]]
    
    1b = a.transpose()
    2print(b)
    [[1 3]
     [2 4]]
    
  • numpy.concatenate: concatena arrays.

    1a = np.array([1,2])
    2b = np.array([2,3])
    3c = np.concatenate((a,b))
    4print(c)
    [1 2 2 3]
    
    1a = a.reshape((1,-1))
    2b = b.reshape((1,-1))
    3d = np.concatenate((a,b), axis=0)
    4print(d)
    [[1 2]
     [2 3]]
    
Exercício 4.1.4.

Aloque o seguinte vetor como um numpy.array

𝒂=(2,3,1,1,4,5). (33)

Então, use o método numpy.reshape para, a partir de b, alocar a matriz

A=[1145] (34)

como um numpy.array.

Resposta.
1import numpy as np
2a = np.array([2, 3, -1, 1, 4, 5])
3A = a.reshape((3,-1))
Exercício 4.1.5.

Tendo em vista que

A=[32121232] (35)

é uma matriz ortogonal1010endnote: 10A é dita matriz ortogonal, quando A1=AT., compute A1.

Resposta.
1import numpy as np
2A = np.array([[np.sqrt(3)/2, -1./2],
3              [1./2, np.sqrt(3)/2]])
4Ainv = A.transpose()
Exercício 4.1.6.

Considere o seguinte sistema de equações

2x1x2 =3 (36)
x1+3x2 =2

Use numpy.array para alocar:

  1. 1.

    a matriz de coeficientes deste sistema.

  2. 2.

    o vetor dos termos constantes deste sistema.

  3. 3.

    a matriz estendida deste sistema.

Resposta.
1import numpy as np
2# a)
3A = np.array([[2, -1],
4              [1, 3]])
5# b)
6b = np.array([3, -2])
7# c)
8E = np.concatenate((A, b.reshape(-1,1)), axis=1)

4.1.3 Operadores Elemento-a-Elemento

Os operadores aritméticos disponível no Python atuam elemento-a-elemento nos numpy.arrays. Por exemplo,

1a = np.array([1,2])
2b = np.array([2,3])
3a+b
array([3, 5])
1a-b
array([-1, -1])
1b*a
array([2, 6])
1a**b
array([1, 8])
12*b
array([4, 6])

O NumPy também conta com várias funções matemáticas elementares que operam elemento-a-elemento em arrays. Por exemplo,

1a = np.array([np.pi, np.sqrt(2)])
2a
array([3.14159265, 1.41421356])
1np.sin(a)
array([1.22464680e-16, 9.87765946e-01])
1np.exp(a)
array([23.14069263,  4.11325038])
Exercício 4.1.7.

Compute os valores da função cosseno para os elementos do vetor

𝜽=(0.,30,45,60,90). (37)
Resposta.
1import numpy as np
2thta = np.array([0., np.pi/6, np.pi/4,
3                 np.pi/3, np.pi/2])
4y = np.cos(thta)

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), (38)
y=(3,1,π) (39)

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]
Exercício 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)

Resposta.
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), (40)
y=(y0,y1,,yn1), (41)

define-se o produto escalar por

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

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. (43)

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

1nrm = npla.norm(y)
2print(nrm)
4.457533443631058
Exercício 4.2.2.

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

x=(1.2,ln(2),4), (44)
y=(π2,3,e) (45)
Resposta.
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], (48)
B=[402186] (52)

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.

Exercício 4.2.3.

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

  1. a)
    A=[122460] (53)
  2. b)

    B=AT

Resposta.
1import numpy as np
2# a)
3A = np.array([[-1, 2],
4              [2, -4],
5              [6, 0]])
6# b)
7B = A.transpose()
Exercício 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]

Resposta.
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]]
    
Exercício 4.2.5.

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

x1=0 (54)
xi1+2xixi+1=h2fi
xn=0

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

Resposta.
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 (55)

O numpy tem a função numpy.matmul para computar a multiplicação de matrizes. Por exemplo, a multiplicação das matrizes dadas em (48) e (52), 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.

Exercício 4.2.6.

Aloque as matrizes

C=[121321023] (59)
D=[231164] (63)
E=[121013] (66)

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

Resposta.
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
Exercício 4.2.7.

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

x1x2+x3 =2 (67)
2x1+2x2+x3 =5
x1x2+2x3 =5

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

Resposta.
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 Rank e Inversa de uma Matriz

O 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]]
Exercício 4.2.8.

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

B=[2121] (70)
C=[201311210] (74)

Verifique suas respostas.

Resposta.
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. (75)

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).

Exercício 4.2.9.

Compute os auto-pares da matriz

A=[132321211]. (76)

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

Resposta.
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

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. Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!