# ÁLGEBRA LINEAR COMPUTACIONAL

## SEGUNDA AVALIAÇÃO - 2020.2 - PROFESSOR ERITO MARQUES   

---
### GRUPO:
**Ícaro Santos Barcelos Pereira - _2017780187_**\
**Leandro Bataglia Pereira - _2018780199_**\
**Pedro Henrique Farolfi Camelo - _2018780326_**

---

Repositório dos algoritmos solicitados na segunda prova da disciplina de Álgebra Linear Computacional.
##### Instruções:
As respostas devem ser enviadas no formato jupyter notebook.\
Os trabalhos devem ser feitos em grupo. Não é permitida troca de informações entre os grupos.\
Fixada a data de entrega, não serão aceitos trabalhos entregues fora dessa data.


```python
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning) 
warnings.filterwarnings("ignore",category=UserWarning)
```


```python
import numpy as np
import pandas as pd
import math
from normas import *
from criterios import *
from cholesky import *
from iterativos import *
from benford import *
from fatoracaoLU import fatoracaoLU
from substituicao import resolve_substituicao
from sympy import Matrix, init_printing
init_printing()
#BIBLIOTECA QUE NÃO ESTOU USANDO MAS PODE SER ÚTIL PARA EXIBIR AS MATRIZES/VETORES = display(Matrix(*variavel que representa o dado*)
```


```python
# Coverti isso aqui em um procedimento, a parada é que vc pode mandar isso
# ocorrer no início de qualquer célula e pode alterar o excel em tempo de execução :)

# CONVERSÃO DOS DADOS EM ARRAYS DA NUMPY COM TYPE 'float64'
def ler_matriz_A_vetor_b(file_excel, sheet_matriz, sheet_vetor):
    df_matriz = pd.read_excel(r"dados/"+file_excel+".xlsx", header=None, sheet_name=sheet_matriz) # Le o arquivo do excel que contém a matriz A sem cabeçalho
    df_vetor = pd.read_excel(r"dados/"+file_excel+".xlsx", header=None, sheet_name=sheet_vetor) # Le o arquivo do excel que contém o vetor b sem cabeçalho
    matriz = np.array(df_matriz, dtype='f8') # Converte a matriz A em um array da numpy
    vetor = np.ravel(np.array(df_vetor, dtype='f8')) # Converte o vetor b em um array da numpy
    return matriz, vetor
```

### 1) Implemente um algoritmo que leia uma matriz A e um vetor b (de uma planilha excel) e avalie:


```python
matriz, vetor = ler_matriz_A_vetor_b("prova_ALC_testes", "matriz_A(1)", "vetor_b(1)")
```

**a)** se A é tridiagonal;


```python
def verifica_tridiagonal(matriz_A, debug=False):
    linhas, colunas = np.shape(matriz_A)
    
    try:
        assert linhas == colunas
    except:
        if debug:
            print("A matriz não é quadrada -> não é tridiagonal")
        return False

    for i in range(linhas):
        for j in range(colunas):
            if np.abs(i-j) <= 1 and matriz_A[i,j] == 0:
                return False
            if np.abs(i-j) >= 2 and matriz_A[i,j] != 0:
                return False
    return True
```


```python
verifica_tridiagonal(matriz, debug=True)
```




    False




```python
#declarando vetor na mão:
A = np.array([[1,1,0],
              [1,1,1],
              [0,1,1]])
verifica_tridiagonal(A)
```




    True



**b)** se A é triangular superior;


```python
def verifica_tri_superior(matriz_A, debug=False):
    linhas, colunas = np.shape(matriz_A)
    
    try:
        assert linhas == colunas
    except:
        if debug:
            print("A matriz não é quadrada -> não é triangular superior")
        return False

    for i in range(linhas):
        for j in range(i):
            if matriz_A[i,j] != 0:
                return False
    return True
```


```python
verifica_tri_superior(matriz, debug=True)
```




    False



**c)** se A é triangular inferior;


```python
def verifica_tri_inferior(matriz_A):
    linhas, colunas = np.shape(matriz_A)
    
    try:
        assert linhas == colunas
    except:
        print("A matriz não é quadrada -> não é triangular inferior")
        return False

    for j in range(colunas):
        for i in range(j):
            if matriz_A[i,j] != 0:
                return False
    return True
```


```python
verifica_tri_inferior(matriz)
```




    False



**d)** se Traço de A é maior que 4.


```python
def traco(matriz_A, debug=False):
    linhas, colunas = np.shape(matriz_A)
    
    try:
        assert linhas == colunas
    except:
        if debug:
            print("A matriz não é quadrada -> traço não está definido.")
        return False
    
    n, traco = min((linhas, colunas)), 0
    for i in range(n):
        traco += matriz_A[i,i]
    if traco > 4:
        print("O traço da matriz é " + str(traco) + ", portanto é maior que 4")
        return True
    print("O traço da matriz é " + str(traco) + ", portanto não é maior que 4")
    return False
```


```python
A = np.array([[1,2,3],[1,2,3]])
traco(A, debug=True)
```

    A matriz não é quadrada -> traço não está definido.





    False




```python
traco(matriz, debug=True)
```

    O traço da matriz é 1179.0, portanto é maior que 4





    True



---
### 2) Implemente um algoritmo que leia uma matriz A (triangular) e um vetor b (de uma planilha excel) e resolva o sistema Ax = b por substituição para frente ou para trás conforme o caso.


```python
def resolve_substituicao(matriz_A, vetor_b):
    
    if checa_tamanho_matriz_vetor(matriz_A, vetor_b) == False:
        return False
        
    if(verifica_tri_inferior(matriz_A)):
        return resolve_subs_frente(matriz_A, vetor_b)

    elif(verifica_tri_superior(matriz_A)):
        return resolve_subs_tras(matriz_A,vetor_b)
        
    else:
        print("A matriz não é triangular")
        return False
        
        
def checa_tamanho_matriz_vetor(matriz_A, vetor_b):
    lin_A, col_A = np.shape(matriz_A)
    col_b = np.shape(vetor_b)
    
    try:
        assert lin_A == col_b[0]
    except:
        print("A quantidade de linhas em A e de colunas em b são distintas")
        return False
    return True
    
    
def resolve_subs_frente(matriz_A, vetor_b): # Resolve um sistema com matriz triangular inferior
    n = len(matriz_A)
    vetor_resultado = np.array(np.copy(vetor_b), dtype='f8')

    for i in range(n):
        for j in range(i):
            vetor_resultado[i] = vetor_resultado[i] - matriz_A[i,j] * vetor_resultado[j]
        vetor_resultado[i] = vetor_resultado[i]/matriz_A[i,i]
    return vetor_resultado

def resolve_subs_tras(matriz_A,vetor_b): # Resolve um sistema com matriz triangular superior
    n = len(matriz_A)
    vetor_resultado = np.array(np.copy(vetor_b), dtype='f8')

    for i in range(n-1,-1,-1):
        for j in range(n-1,i,-1):
            vetor_resultado[i] = vetor_resultado[i] - matriz_A[i,j] * vetor_resultado[j]
        vetor_resultado[i] = vetor_resultado[i]/matriz_A[i,i]
    return vetor_resultado
```


```python
matriz, vetor = ler_matriz_A_vetor_b("prova_ALC_testes", "matriz_A(1)", "vetor_b(1)")

delta_x = resolve_substituicao(matriz, vetor)

if delta_x != False:
    print("Vetor x resultado da substituição:\n",delta_x,"\n")
```

    A matriz não é triangular


---
### 3) Implemente um algoritmo que leia uma matriz A e um vetor b (de uma planilha excel) e:




```python
matriz, vetor = ler_matriz_A_vetor_b("prova_ALC_testes", "matriz_A(1)", "vetor_b(1)")
```

**a)** Avalie se é possível obter o fator de Cholesky;


```python
def checa_positiva_definida(matriz_A, debug=False):
        
    n = len(matriz_A) # n é a ordem da matriz a
    matriz_R = np.copy(np.triu(matriz_A)) # matriz_r é uma cópia triangular superior da matriz A
    for i in range(n):
            for k in range(i): # Não é executado quando i = 0
                matriz_R[i,i] = matriz_R[i,i] - math.pow(matriz_R[k,i],2) # Define os termos da diagonal principal
            if matriz_R[i,i] <= 0: # Se algum elemento da diagonal principal for menor ou igual a zero, por definição, a matriz não é positiva definida
                if debug:
                    print("Erro: A matriz não é positiva definida.")
                return False
            matriz_R[i,i] = math.sqrt(matriz_R[i,i]) 
            for j in range(i+1,n): # Não é executado quando i = n
                for k in range(i): # Não é executado quando i = 0
                    matriz_R[i,j] = matriz_R[i,j] - (matriz_R[k,i] * matriz_R[k,j])
                matriz_R[i,j] = matriz_R[i,j]/matriz_R[i,i]
    return True         
```


```python
A = np.array([[2.,1.,0.],
              [1.,2.,-1.],
              [0.,-1.,2.]])
```


```python
A = np.array([[2.,1.,0.],
              [1.,2.,-1.],
              [0.,-1.,2.]])
```


```python
b = np.array([[3.],[0.],[1.]])
```


```python
checa_positiva_definida(A, debug=True)
```




    True



**b)** Resolva o sistema Ax = b usando a fatoração de Cholesky.


```python
def decomposicao_cholesky(matriz_A, vetor_b):
    n = len(matriz_A) # n é a ordem da matriz a
    matriz_R = np.copy(np.triu(matriz_A)) # matriz_r é uma cópia triangular superior da matriz A

    for i in range(n):
        for k in range(i): # Não é executado quando i = 0
            matriz_R[i,i] = matriz_R[i,i] - math.pow(matriz_R[k,i],2) # Define os termos da diagonal principal
        if matriz_R[i,i] <= 0: # Se algum elemento da diagonal principal for menor ou igual a zero, por definição, a matriz não é positiva definida
            print("Erro: A matriz não é positiva definida.")
            return
        matriz_R[i,i] = math.sqrt(matriz_R[i,i]) 
        for j in range(i+1,n): # Não é executado quando i = n
            for k in range(i): # Não é executado quando i = 0
                matriz_R[i,j] = matriz_R[i,j] - (matriz_R[k,i] * matriz_R[k,j])
            matriz_R[i,j] = matriz_R[i,j]/matriz_R[i,i]

    return resolve_cholesky(matriz_R, vetor_b)

def resolve_cholesky(matriz_R, vetor_b):
    matriz_Rt = np.copy(np.transpose(matriz_R)) # matriz_rt é a matriz R transposta
    
    vetor_y = subs.resolve_substituicao(matriz_Rt, vetor_b) # Faz o cálculo de Rt * y = b para obter o vetor y
    vetor_x = subs.resolve_substituicao(matriz_R, vetor_y) # Faz o cálculo de R * x = y para obter o vetor x (resultado)

    return vetor_x # Retorna o vetor x (resultado)
```


```python
# TESTE DO ALGORITMO DE DECOMPOSIÇÃO DE CHOLESKY E NORMA RESIDUAL (cholesky.py, normas.py)
delta_x = decomposicao_cholesky(matriz, vetor)
print("Vetor x resultado da Decomposição de Cholesky:\n",delta_x,"\n")
#residual(matriz, vetor, delta_x)
```

    Erro: A matriz não é positiva definida.
    Vetor x resultado da Decomposição de Cholesky:
     None 
    


---
### 4) Implemente um algoritmo que leia uma matriz A e um vetor b (de uma planilha excel) e:


```python
matriz, vetor = ler_matriz_A_vetor_b("prova_ALC_testes", "matriz_A(1)", "vetor_b(1)")
```

**a)** Avalie se algum critério é satisfeito para aplicação dos métodos de Gauss-Seidel, Jacobi e SOR;


```python
def criterio_linhas(matriz_A): # Verificar o critério das linhas para o método de Jacobi
    n, m = len(matriz_A), len(matriz_A[0]) # n e m são as dimensões da matriz
    soma = 0

    for i in range(n): # Percorre toda a matriz
        for j in range(m):
            if i != j: # Desconsidera os termos da diagonal principal
                soma += np.abs(matriz_A[i,j])

        if soma >= np.abs(matriz_A[i,i]): # Verifica se a soma de todos os termos (sem contar o termo da diagonal principal) de cada linha é menor ou maior que o termo da diagonal principal (Critério das linhas)
            return False

        soma = 0
    return True
```


```python
def criterio_sassenfeld(matriz_A):
    n, m = len(matriz_A), len(matriz_A[0]) # n e m são as dimensões da matriz
    aux = 0 # Variável que auxilia nos somatórios dos termos tanto de Aij*Beta, quanto de Aij
    vetor_betao = np.zeros(m) # Vetor de Betas iniciado com termos iguais a zero

    for i in range(n):
        for j in range(i): # j vai até i-1 (desconsidera a primeira iteração)
            aux += np.abs(matriz_A[i,j]) * vetor_betao[j] # A partir da segunda iteração, inclui a multiplicação de Aij pelos Betas anteriores no somatório (já que na primeira iteração não há Betas anteriores, obviamente)
        for j in range(i,n):
            aux += np.abs(matriz_A[i,j]) # Somatório dos módulos dos termos de Aij
        vetor_betao[i] = aux/np.abs(matriz_A[i,i]) #Divide o valor da soma pelo termo da diagonal principal
        aux = 0 # Zera a variável auxiliar pra próxima iteração
    
    print("Maior betão:", np.max(vetor_betao))
    if np.max(vetor_betao) < 1: # Verifica se a condição do critério de Sassenfeld (max(B) < 1) é satisfeita
        return True
    return False
```


```python
criterio_linhas(matriz)
```




    False




```python
criterio_sassenfeld(matriz)
```

    Maior betão: 10602274533433.357





    False



**b)** Resolva o sistema Ax = b usando os métodos iterativos de Gauss-Seidel, Jacobi e SOR.

## Jacobi


```python
def jacobi(matriz_A, vetor_b, vetor_x=0, N=10000, p=1e-15): # Função que executa o algoritmo de Jacobi
    n, m = len(matriz_A), len(matriz_A[0]) # n e m são as dimensões da matriz
    aux = 0 # Variável que vai auxiliar a armazenar as subtrações dos valores Aij*xj

    if isinstance(vetor_x, int): # Se não é fornecido um vetor de aproximação inicial para x, ele é iniciado aqui com todos os elementos iguais a zero
        vetor_x = np.zeros(m)
    
    vetor_aux = np.copy(vetor_x) # Vetor auxiliar igual ao vetor x que representa a iteração k+1

    if criterio_linhas(matriz_A): # Verifica se o critério das linhas é satisfeito
        print("O critério das linhas foi satisfeito: O sistema converge.")
    else:
        print("ATENÇÃO: O critério das linhas não foi satisfeito.")

    for k in range(N): # Executa todas as iterações especificadas na chamada da função (N) se a condição de parada não for satisfeita
        for i in range(n):
            for j in range(n):
                if i != j: # Pula os elementos da diagonal principal pois eles não são utilizados
                    aux += matriz_A[i,j] * vetor_x[j] # Acumula as subtrações dos valores de Aij*xj
            
            vetor_aux[i] = (vetor_b[i] - aux)/matriz_A[i,i] # Executa a iteração do método com (bi-Aij*xj)/Aii
            aux = 0 # Zera a contagem do somatório dos valores novamente

        termos_encontrados = 0
        for i in range(n): #Verifica elemento por elemento de vetor_x e do vetor_aux
            if vetor_x[i] != 0:
                if np.abs(vetor_aux[i] - vetor_x[i])/np.abs(vetor_x[i]) <= p: # Condição de parada caso a variação relativa de uma iteração para outra seja menor que a tolerância p 
                    termos_encontrados += 1
            else:
                if np.abs(vetor_aux[i] - vetor_x[i]) <= p*np.abs(vetor_x[i]):
                    termos_encontrados += 1
                    
        if(termos_encontrados == n):
            print("(Jacobi) Resultado encontrado com o critério de parada, na iteração:", k)
            return vetor_x

        vetor_x = np.copy(vetor_aux) # Atualiza o vetor_x (k) com os valores do vetor_aux (k+1)

    print("(Jacobi) Resultado encontrado com o número máximo de iterações.")
    return vetor_x # Retorna o vetor solução
```


```python
print(jacobi(matriz, vetor, N=100))
```

    ATENÇÃO: O critério das linhas não foi satisfeito.
    (Jacobi) Resultado encontrado com o número máximo de iterações.
    [-2.21507407e+191 -7.85062201e+191 -4.02063148e+191 -3.00124088e+191
     -2.34581480e+192 -2.32464880e+191 -4.58103429e+192 -4.79832453e+191
     -5.85375866e+191 -4.90112952e+191 -2.01091315e+191 -2.59706719e+191
     -6.26779852e+191 -1.21273532e+192 -8.04504337e+192 -2.42684232e+192
     -4.65327284e+191 -2.98587023e+191 -3.29553950e+191 -4.17899256e+191
     -4.88807065e+191 -4.20548399e+191 -3.16760574e+192 -1.26588784e+192
     -1.08434271e+193]


## Gauss-Seidel


```python
def seidel(matriz_A, vetor_b, vetor_x=0, N=1000, p=1e-15): # Função que executa o algoritmo de Gauss-Seidel
    n, m = len(matriz_A), len(matriz_A[0]) # n e m são as dimensões da matriz
    aux = 0 # Variável que vai auxiliar a armazenar as subtrações dos valores Aij*xj

    if isinstance(vetor_x, int): # Se não é fornecido um vetor de aproximação inicial para x, ele é iniciado aqui com todos os elementos iguais a zero
        vetor_x = np.zeros(m)

    vetor_aux = np.copy(vetor_x) # Vetor auxiliar igual ao vetor x que representa a iteração k+1
    	
    if criterio_linhas(matriz_A): # Verifica se o critério das linhas é satisfeito
        print("O critério das linhas foi satisfeito: O sistema converge.")
    else:
        print("ATENÇÃO: O critério das linhas não foi satisfeito.")

    if criterio_sassenfeld(matriz_A): # Verifica se o critério de Sassenfeld é satisfeito
        print("O critério de Sassenfeld foi satisfeito.")
    else:
        print("ATENÇÃO: O critério de Sassenfeld não foi satisfeito.")

    for k in range(N): # Executa todas as iterações especificadas na chamada da função
        for i in range(n):
            for j in range(m):
                if i != j: # Pula os elementos da diagonal principal pois eles não são utilizados
                    if i > j:
                        aux += matriz_A[i,j] * vetor_aux[j] # Acumula as subtrações dos valores de Aij*xj utilizando os valores que já foram atualizados (de 0 a i) que ficam no vetor auxiliar
                    else:
                        aux += matriz_A[i,j] * vetor_x[j] # Acumula as subtrações dos valores de Aij*xj utilizando os valores ainda não foram atualizados (de i+1 a n) que ficam no vetor x

            vetor_aux[i] = (vetor_b[i] - aux)/matriz_A[i,i] # Executa a iteração do método com (bi-Aij*xj)/Aii
            aux = 0 # Zera a contagem do somatório dos valores novamente

        termos_encontrados = 0
        for i in range(n): #Verifica elemento por elemento de vetor_x e do vetor_aux
            if vetor_x[i] != 0:
                if np.abs(vetor_aux[i] - vetor_x[i])/np.abs(vetor_x[i]) <= p: # Condição de parada caso a variação relativa de uma iteração para outra seja menor que a tolerância p 
                    termos_encontrados += 1
            else:
                if np.abs(vetor_aux[i] - vetor_x[i]) <= p*np.abs(vetor_x[i]):
                    termos_encontrados += 1
                    
        if(termos_encontrados == n):
                print("(Seidel) Resultado encontrado com o critério de parada, na iteração:", k)
                return vetor_x

        vetor_x = np.copy(vetor_aux) # Atualiza o vetor_x (k) com os valores do vetor_aux (k+1)

    print("(Seidel) Resultado encontrado com o número máximo de iterações.")
    return vetor_x # Retorna o vetor solução
```


```python
print(seidel(matriz, vetor))
```

    ATENÇÃO: O critério das linhas não foi satisfeito.
    Maior betão: 10602274533433.357
    ATENÇÃO: O critério de Sassenfeld não foi satisfeito.
    (Seidel) Resultado encontrado com o número máximo de iterações.
    [nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
     nan nan nan nan nan nan nan]


    <ipython-input-32-caf3047c1391>:25: RuntimeWarning: overflow encountered in double_scalars
      aux += matriz_A[i,j] * vetor_aux[j] # Acumula as subtrações dos valores de Aij*xj utilizando os valores que já foram atualizados (de 0 a i) que ficam no vetor auxiliar
    <ipython-input-32-caf3047c1391>:25: RuntimeWarning: invalid value encountered in double_scalars
      aux += matriz_A[i,j] * vetor_aux[j] # Acumula as subtrações dos valores de Aij*xj utilizando os valores que já foram atualizados (de 0 a i) que ficam no vetor auxiliar
    <ipython-input-32-caf3047c1391>:27: RuntimeWarning: invalid value encountered in double_scalars
      aux += matriz_A[i,j] * vetor_x[j] # Acumula as subtrações dos valores de Aij*xj utilizando os valores ainda não foram atualizados (de i+1 a n) que ficam no vetor x
    <ipython-input-32-caf3047c1391>:27: RuntimeWarning: overflow encountered in double_scalars
      aux += matriz_A[i,j] * vetor_x[j] # Acumula as subtrações dos valores de Aij*xj utilizando os valores ainda não foram atualizados (de i+1 a n) que ficam no vetor x


## SOR


```python
def calcular_omega_otimo(matriz_A):
    
    if checa_positiva_definida(matriz_A, debug=True) == False or verifica_tridiagonal(matriz_A, debug=True) == False:
        print("Não há como encontrar w ótimo.")
        return None        
    
    D = np.copy(matriz_A)
    for i in range(3):
        for j in range(3):
            if i != j:
                D[i,j] = 0.
    D = np.linalg.inv(D)
    
    L = np.tril(A)
    U = np.triu(A)

    for i in range(3):
        for j in range(3):
            if i == j:
                L[i,j] = 0.
                U[i,j] = 0.

    LU = L + U
    T = np.matmul(D, LU)
    P = np.linalg.eig(T)
    p = np.amax(P[0])
    
    print("omega: {}".format(2/(1 + math.sqrt(1 - pow(p, 2)))))
    return 2/(1 + math.sqrt(1 - pow(p, 2)))
    
```


```python
def sor(matriz_A, vetor_b, vetor_x=0, N=10000, p=1e-15, w=1.7): # Quando w = 1 é igual ao Seidel
    n, m = len(matriz_A), len(matriz_A[0]) # n e m são as dimensões da matriz
    aux = 0 # Variável que vai auxiliar a armazenar as subtrações dos valores Aij*xj
    
    omega = calcular_omega_otimo(matriz_A)
    
    if omega != None:
        w = omega

    if isinstance(vetor_x, int): # Se não é fornecido um vetor de aproximação inicial para x, ele é iniciado aqui com todos os elementos iguais a zero
        vetor_x = np.zeros(m)

    vetor_aux = np.copy(vetor_x) # Vetor auxiliar igual ao vetor x que representa a iteração k+1

    if criterio_linhas(matriz_A): # Verifica se o critério das linhas é satisfeito
        print("O critério das linhas foi satisfeito: O sistema converge.")
    else:
        print("ATENÇÃO: O critério das linhas não foi satisfeito.")

    if criterio_sassenfeld(matriz_A): # Verifica se o critério das linhas é satisfeito
        print("O critério de Sassenfeld foi satisfeito.")
    else:
        print("ATENÇÃO: O critério de Sassenfeld não foi satisfeito.")

    for k in range(N): # Executa todas as iterações especificadas na chamada da função
        for i in range(n):
            for j in range(m):
                if i != j: # Pula os elementos da diagonal principal pois eles não são utilizados
                    if i > j:
                        aux += matriz_A[i,j] * vetor_aux[j] # Acumula as subtrações dos valores de Aij*xj utilizando os valores que já foram atualizados (de 0 a i) que ficam no vetor auxiliar
                    else:
                        aux += matriz_A[i,j] * vetor_x[j] # Acumula as subtrações dos valores de Aij*xj utilizando os valores ainda não foram atualizados (de i+1 a n) que ficam no vetor x

            vetor_aux[i] = (1-w)*vetor_x[i] + (w*(vetor_b[i] - aux))/matriz_A[i,i] # Executa a iteração do método com (1-w)*xi(bi-Aij*xj)/Aii
            aux = 0 # Zera a contagem do somatório dos valores novamente

        termos_encontrados = 0
        for i in range(n): #Verifica elemento por elemento de vetor_x e do vetor_aux
            if vetor_x[i] != 0:
                if np.abs(vetor_aux[i] - vetor_x[i])/np.abs(vetor_x[i]) <= p: # Condição de parada caso a variação relativa de uma iteração para outra seja menor que a tolerância p 
                    termos_encontrados += 1
            else:
                if np.abs(vetor_aux[i] - vetor_x[i]) <= p*np.abs(vetor_x[i]):
                    termos_encontrados += 1
                    
        if(termos_encontrados == n):
                print("(SOR) Resultado encontrado com o critério de parada, na iteração:", k)
                return vetor_x

        vetor_x = np.copy(vetor_aux) # Atualiza o vetor_x (k) com os valores do vetor_aux (k+1)

    print("(SOR) Resultado encontrado com o número máximo de iterações.")
    return vetor_x # Retorna o vetor solução
```


```python
a = np.array([[2.,1.,0.],[1.,2.,-1.],[0.,-1.,2.]])
```


```python
b = np.array([[3.],[0.],[1.]])
```


```python
x = np.array([[0.],[0.],[0.]])
```


```python
print(jacobi(a, b, x))
print(seidel(a, b, x))
print(sor(a, b, x))
```

    ATENÇÃO: O critério das linhas não foi satisfeito.
    (Jacobi) Resultado encontrado com o critério de parada, na iteração: 99
    [[ 2.0000000e+00]
     [-1.0000000e+00]
     [ 8.8817842e-16]]
    ATENÇÃO: O critério das linhas não foi satisfeito.
    Maior betão: 2.25
    ATENÇÃO: O critério de Sassenfeld não foi satisfeito.
    (Seidel) Resultado encontrado com o critério de parada, na iteração: 52
    [[ 2.]
     [-1.]
     [ 0.]]
    omega: 1.17157287525381
    ATENÇÃO: O critério das linhas não foi satisfeito.
    Maior betão: 2.25
    ATENÇÃO: O critério de Sassenfeld não foi satisfeito.
    (SOR) Resultado encontrado com o critério de parada, na iteração: 424
    [[ 2.]
     [-1.]
     [ 0.]]


---
### 5) Implemente um algoritmo que leia uma matriz A (de uma planilha excel) e:


```python
def ler_matriz_A(file_matrix, sheet_matriz):
    df_matriz = pd.read_excel(r"dados/"+file_matrix+".xlsx", header=None, sheet_name=sheet_matriz) # Le o arquivo do excel que contém a matriz A sem cabeçalho
    matriz = np.array(df_matriz, dtype='f8') # Converte a matriz A em um array da numpy
    return matriz
```


```python
matriz = ler_matriz_A("prova_ALC_testes", "matriz_A(2)")
```

**a)** Calcule a transposta de A;


```python
def calcula_transposta(matriz_A):
    if not verifica_quadrada(matriz_A):
        print("A matriz não é quadrada.")
        return None

    n = len(matriz_A)
    matriz_At = np.zeros((n,n), dtype='f8')

    for i in range(n):
        for j in range(n):
            if i == j:
                matriz_At[i,j] = matriz_A[i,j]
            else:
                matriz_At[i,j] = matriz_A[j,i]
    
    return matriz_At
    
```


```python
Matrix(calcula_transposta(matriz))
```




$\displaystyle \left[\begin{array}{ccccccccccccccccccccccccc}91452.0 & 55679.0 & 74196.0 & 50369.0 & 65933.0 & 58983.0 & 57282.0 & 86619.0 & 77605.0 & 58674.0 & 59851.0 & 64857.0 & 69439.0 & 55411.0 & 53319.0 & 66426.0 & 58593.0 & 64599.0 & 76799.0 & 73032.0 & 64518.0 & 48233.0 & 66645.0 & 60829.0 & 66596.0\\55679.0 & 65707.0 & 74216.0 & 37748.0 & 57071.0 & 53220.0 & 58214.0 & 72412.0 & 57615.0 & 47372.0 & 45828.0 & 51951.0 & 57106.0 & 52960.0 & 49850.0 & 52216.0 & 59587.0 & 62269.0 & 69177.0 & 70313.0 & 58249.0 & 50165.0 & 52239.0 & 53685.0 & 50243.0\\74196.0 & 74216.0 & 106855.0 & 53876.0 & 66014.0 & 75409.0 & 71392.0 & 100305.0 & 77671.0 & 61476.0 & 67259.0 & 69436.0 & 74697.0 & 67445.0 & 60738.0 & 74261.0 & 75472.0 & 80328.0 & 86587.0 & 88406.0 & 76591.0 & 70006.0 & 64575.0 & 66976.0 & 70245.0\\50369.0 & 37748.0 & 53876.0 & 48748.0 & 41012.0 & 44969.0 & 38317.0 & 58496.0 & 47805.0 & 41115.0 & 42991.0 & 51213.0 & 52266.0 & 45265.0 & 37281.0 & 46016.0 & 46906.0 & 45027.0 & 47163.0 & 46086.0 & 51440.0 & 37987.0 & 45395.0 & 38554.0 & 50585.0\\65933.0 & 57071.0 & 66014.0 & 41012.0 & 79341.0 & 54990.0 & 48071.0 & 73169.0 & 68617.0 & 48358.0 & 52529.0 & 59419.0 & 60988.0 & 49604.0 & 45862.0 & 47887.0 & 60380.0 & 61638.0 & 70678.0 & 67484.0 & 64183.0 & 40100.0 & 66726.0 & 61053.0 & 63560.0\\58983.0 & 53220.0 & 75409.0 & 44969.0 & 54990.0 & 81033.0 & 55404.0 & 71312.0 & 69545.0 & 39659.0 & 56638.0 & 54765.0 & 62119.0 & 48354.0 & 51622.0 & 53278.0 & 55752.0 & 58712.0 & 72928.0 & 68654.0 & 62901.0 & 54749.0 & 59374.0 & 48251.0 & 57492.0\\57282.0 & 58214.0 & 71392.0 & 38317.0 & 48071.0 & 55404.0 & 70860.0 & 66195.0 & 58152.0 & 40066.0 & 44798.0 & 44856.0 & 62974.0 & 56700.0 & 47595.0 & 56390.0 & 56159.0 & 62644.0 & 68640.0 & 62619.0 & 60449.0 & 54762.0 & 46380.0 & 45245.0 & 46442.0\\86619.0 & 72412.0 & 100305.0 & 58496.0 & 73169.0 & 71312.0 & 66195.0 & 119662.0 & 78127.0 & 73439.0 & 65880.0 & 71849.0 & 76429.0 & 72657.0 & 66130.0 & 81352.0 & 70572.0 & 85049.0 & 91567.0 & 92798.0 & 77968.0 & 65462.0 & 72862.0 & 71505.0 & 78249.0\\77605.0 & 57615.0 & 77671.0 & 47805.0 & 68617.0 & 69545.0 & 58152.0 & 78127.0 & 95010.0 & 47967.0 & 63304.0 & 70526.0 & 70080.0 & 49868.0 & 55068.0 & 65282.0 & 62660.0 & 63675.0 & 80032.0 & 80175.0 & 70347.0 & 53446.0 & 69325.0 & 64456.0 & 68950.0\\58674.0 & 47372.0 & 61476.0 & 41115.0 & 48358.0 & 39659.0 & 40066.0 & 73439.0 & 47967.0 & 62381.0 & 48742.0 & 46488.0 & 55011.0 & 55790.0 & 41509.0 & 57698.0 & 43944.0 & 51390.0 & 56613.0 & 59549.0 & 58542.0 & 38889.0 & 49767.0 & 48121.0 & 57648.0\\59851.0 & 45828.0 & 67259.0 & 42991.0 & 52529.0 & 56638.0 & 44798.0 & 65880.0 & 63304.0 & 48742.0 & 61735.0 & 54519.0 & 62740.0 & 45391.0 & 42671.0 & 55453.0 & 48817.0 & 52109.0 & 58966.0 & 62451.0 & 59620.0 & 44416.0 & 54339.0 & 47345.0 & 60586.0\\64857.0 & 51951.0 & 69436.0 & 51213.0 & 59419.0 & 54765.0 & 44856.0 & 71849.0 & 70526.0 & 46488.0 & 54519.0 & 86233.0 & 69696.0 & 46373.0 & 53911.0 & 56829.0 & 62156.0 & 61194.0 & 64494.0 & 72696.0 & 64713.0 & 41217.0 & 62938.0 & 64332.0 & 63511.0\\69439.0 & 57106.0 & 74697.0 & 52266.0 & 60988.0 & 62119.0 & 62974.0 & 76429.0 & 70080.0 & 55011.0 & 62740.0 & 69696.0 & 88343.0 & 63047.0 & 58429.0 & 70516.0 & 57778.0 & 72127.0 & 71249.0 & 73181.0 & 68927.0 & 54201.0 & 61029.0 & 56029.0 & 63691.0\\55411.0 & 52960.0 & 67445.0 & 45265.0 & 49604.0 & 48354.0 & 56700.0 & 72657.0 & 49868.0 & 55790.0 & 45391.0 & 46373.0 & 63047.0 & 72923.0 & 41999.0 & 58256.0 & 51047.0 & 65167.0 & 62432.0 & 56009.0 & 60077.0 & 52371.0 & 51691.0 & 49725.0 & 51968.0\\53319.0 & 49850.0 & 60738.0 & 37281.0 & 45862.0 & 51622.0 & 47595.0 & 66130.0 & 55068.0 & 41509.0 & 42671.0 & 53911.0 & 58429.0 & 41999.0 & 59338.0 & 50999.0 & 44441.0 & 59090.0 & 56983.0 & 62862.0 & 52121.0 & 38740.0 & 50123.0 & 46163.0 & 44724.0\\66426.0 & 52216.0 & 74261.0 & 46016.0 & 47887.0 & 53278.0 & 56390.0 & 81352.0 & 65282.0 & 57698.0 & 55453.0 & 56829.0 & 70516.0 & 58256.0 & 50999.0 & 80679.0 & 50279.0 & 64435.0 & 68755.0 & 68819.0 & 65497.0 & 57893.0 & 47295.0 & 48008.0 & 62149.0\\58593.0 & 59587.0 & 75472.0 & 46906.0 & 60380.0 & 55752.0 & 56159.0 & 70572.0 & 62660.0 & 43944.0 & 48817.0 & 62156.0 & 57778.0 & 51047.0 & 44441.0 & 50279.0 & 79370.0 & 64060.0 & 67823.0 & 72858.0 & 67075.0 & 53125.0 & 64238.0 & 54453.0 & 53791.0\\64599.0 & 62269.0 & 80328.0 & 45027.0 & 61638.0 & 58712.0 & 62644.0 & 85049.0 & 63675.0 & 51390.0 & 52109.0 & 61194.0 & 72127.0 & 65167.0 & 59090.0 & 64435.0 & 64060.0 & 89614.0 & 69058.0 & 75253.0 & 60567.0 & 60826.0 & 65264.0 & 56169.0 & 48050.0\\76799.0 & 69177.0 & 86587.0 & 47163.0 & 70678.0 & 72928.0 & 68640.0 & 91567.0 & 80032.0 & 56613.0 & 58966.0 & 64494.0 & 71249.0 & 62432.0 & 56983.0 & 68755.0 & 67823.0 & 69058.0 & 95485.0 & 87216.0 & 73030.0 & 57886.0 & 67621.0 & 63402.0 & 68153.0\\73032.0 & 70313.0 & 88406.0 & 46086.0 & 67484.0 & 68654.0 & 62619.0 & 92798.0 & 80175.0 & 59549.0 & 62451.0 & 72696.0 & 73181.0 & 56009.0 & 62862.0 & 68819.0 & 72858.0 & 75253.0 & 87216.0 & 104616.0 & 75308.0 & 57730.0 & 72067.0 & 66660.0 & 64582.0\\64518.0 & 58249.0 & 76591.0 & 51440.0 & 64183.0 & 62901.0 & 60449.0 & 77968.0 & 70347.0 & 58542.0 & 59620.0 & 64713.0 & 68927.0 & 60077.0 & 52121.0 & 65497.0 & 67075.0 & 60567.0 & 73030.0 & 75308.0 & 87788.0 & 51382.0 & 64059.0 & 61285.0 & 75877.0\\48233.0 & 50165.0 & 70006.0 & 37987.0 & 40100.0 & 54749.0 & 54762.0 & 65462.0 & 53446.0 & 38889.0 & 44416.0 & 41217.0 & 54201.0 & 52371.0 & 38740.0 & 57893.0 & 53125.0 & 60826.0 & 57886.0 & 57730.0 & 51382.0 & 63215.0 & 41599.0 & 39606.0 & 42276.0\\66645.0 & 52239.0 & 64575.0 & 45395.0 & 66726.0 & 59374.0 & 46380.0 & 72862.0 & 69325.0 & 49767.0 & 54339.0 & 62938.0 & 61029.0 & 51691.0 & 50123.0 & 47295.0 & 64238.0 & 65264.0 & 67621.0 & 72067.0 & 64059.0 & 41599.0 & 81339.0 & 59117.0 & 58287.0\\60829.0 & 53685.0 & 66976.0 & 38554.0 & 61053.0 & 48251.0 & 45245.0 & 71505.0 & 64456.0 & 48121.0 & 47345.0 & 64332.0 & 56029.0 & 49725.0 & 46163.0 & 48008.0 & 54453.0 & 56169.0 & 63402.0 & 66660.0 & 61285.0 & 39606.0 & 59117.0 & 70832.0 & 60604.0\\66596.0 & 50243.0 & 70245.0 & 50585.0 & 63560.0 & 57492.0 & 46442.0 & 78249.0 & 68950.0 & 57648.0 & 60586.0 & 63511.0 & 63691.0 & 51968.0 & 44724.0 & 62149.0 & 53791.0 & 48050.0 & 68153.0 & 64582.0 & 75877.0 & 42276.0 & 58287.0 & 60604.0 & 82109.0\end{array}\right]$



**b)** Calcule o determinante de A;


```python
def eliminacao_gauss(matriz_A):
    n = len(matriz_A)
    Am = np.array(matriz_A).astype("float64")

    for i in range(n):
        for j in range(i+1, n):
            if Am[i,i] == 0:
                Am[i,i] = 1e-18

            x = Am[j,i]/Am[i,i] # x é o multiplicador necessário para executar a eliminação
            for k in range(n):
               Am[j,k] -= Am[i,k] * x # aplica o multiplicador x para zerar os elementos abaixo da diagonal principal

    return calcula_determinante(Am, n) # retorna o vetor resultado

def calcula_determinante(matriz_A, n):
    det = 1
    for i in range(n):
        det *= matriz_A[i,i]
    return det

```


```python
eliminacao_gauss(matriz)
```

**c)** Calcule a matriz adjunta de A;


```python
def calcula_adjunta(matriz_A):
    if verifica_inversa(matriz_A):
        matriz_Adj = np.linalg.inv(matriz_A) * eliminacao_gauss(matriz_A)
        return matriz_Adj
```


```python
print(calcula_adjunta(matriz))
```

    A matriz é quadrada
    O determinante da matriz é: 1.809225640752816e+97
    [[ 2.18976648e+96  3.29994217e+96  5.58389985e+95  2.92783527e+95
      -2.03534984e+96 -2.36899618e+96 -5.50695114e+96  5.56505936e+95
      -3.82070029e+95 -5.35550547e+96  1.49829376e+96 -1.61176699e+96
       1.73225255e+96  1.54159730e+96  3.86518043e+95 -1.03851399e+96
      -1.03318594e+96  3.84136131e+95  2.15896487e+96 -5.31253148e+95
       3.99371498e+96  4.93413144e+95  6.98444992e+94 -3.03110404e+95
      -8.49040544e+95]
     [ 3.29994217e+96  4.98290950e+96  8.39954897e+95  4.43369933e+95
      -3.07182723e+96 -3.57137721e+96 -8.30586076e+96  8.42264733e+95
      -5.74222763e+95 -8.07654383e+96  2.26034329e+96 -2.43160828e+96
       2.61440020e+96  2.32211712e+96  5.78620430e+95 -1.56446934e+96
      -1.55871781e+96  5.80478295e+95  3.25585364e+96 -8.03621022e+95
       6.02497461e+96  7.40936689e+95  1.06077010e+95 -4.55738134e+95
      -1.28356107e+96]
     [ 5.58389985e+95  8.39954897e+95  1.46970788e+95  7.58187475e+94
      -5.17157626e+95 -6.05386182e+95 -1.40396100e+96  1.40097624e+95
      -9.81748804e+94 -1.36586070e+96  3.79552354e+95 -4.10949870e+95
       4.42039654e+95  3.92767708e+95  9.88910370e+94 -2.64190017e+95
      -2.65942854e+95  9.62952834e+94  5.50215187e+95 -1.34673858e+95
       1.01850705e+96  1.26762941e+95  2.01771484e+94 -7.79358071e+94
      -2.16839447e+95]
     [ 2.92783527e+95  4.43369933e+95  7.58187475e+94  4.58038632e+94
      -2.72962739e+95 -3.18733566e+95 -7.38671835e+95  7.30265511e+94
      -5.19362070e+94 -7.18343220e+95  2.00610517e+95 -2.18400931e+95
       2.32342773e+95  2.03108995e+95  4.99338622e+94 -1.38252449e+95
      -1.41493347e+95  5.34384453e+94  2.91933196e+95 -7.08999975e+94
       5.36874118e+95  6.57232328e+94  1.01775014e+94 -3.80500413e+94
      -1.15866344e+95]
     [-2.03534984e+96 -3.07182723e+96 -5.17157626e+95 -2.72962739e+95
       1.89906155e+96  2.20360327e+96  5.12389714e+96 -5.18181279e+95
       3.52662809e+95  4.97753565e+96 -1.39306724e+96  1.50054559e+96
      -1.61415227e+96 -1.42927771e+96 -3.56935914e+95  9.70109445e+95
       9.60132651e+95 -3.63289134e+95 -2.01245774e+96  4.97014091e+95
      -3.71606201e+96 -4.58408829e+95 -6.35382105e+94  2.81091830e+95
       7.87742552e+95]
     [-2.36899618e+96 -3.57137721e+96 -6.05386182e+95 -3.18733566e+95
       2.20360327e+96  2.56877123e+96  5.96220571e+96 -6.02374768e+95
       4.13359707e+95  5.79776975e+96 -1.62316672e+96  1.74499465e+96
      -1.87575009e+96 -1.66723623e+96 -4.19759224e+95  1.12666826e+96
       1.12046173e+96 -4.16113562e+95 -2.34105351e+96  5.76036517e+95
      -4.32489238e+96 -5.37173151e+95 -7.66356006e+94  3.28352177e+95
       9.19512046e+95]
     [-5.50695114e+96 -8.30586076e+96 -1.40396100e+96 -7.38671835e+95
       5.12389714e+96  5.96220571e+96  1.38606328e+97 -1.40225121e+96
       9.59233926e+95  1.34757179e+97 -3.77152498e+96  4.05771520e+96
      -4.36161389e+96 -3.87669505e+96 -9.71450649e+95  2.61399557e+96
       2.59937961e+96 -9.68520755e+95 -5.43653637e+96  1.33958148e+96
      -1.00518673e+97 -1.24079812e+96 -1.75262967e+95  7.61076386e+95
       2.13885366e+96]
     [ 5.56505936e+95  8.42264733e+95  1.40097624e+95  7.30265511e+94
      -5.18181279e+95 -6.02374768e+95 -1.40225121e+96  1.46862125e+95
      -9.61482337e+94 -1.36546482e+96  3.83751885e+95 -4.09833815e+95
       4.42167044e+95  3.93669270e+95  9.73064165e+94 -2.63232484e+95
      -2.61968508e+95  9.49822761e+94  5.47755925e+95 -1.36770882e+95
       1.01862060e+96  1.24009257e+95  1.78160539e+94 -7.69947548e+94
      -2.20177355e+95]
     [-3.82070029e+95 -5.74222763e+95 -9.81748804e+94 -5.19362070e+94
       3.52662809e+95  4.13359707e+95  9.59233926e+95 -9.61482337e+94
       6.96344917e+94  9.36325182e+95 -2.62509625e+95  2.80864668e+95
      -3.00281027e+95 -2.70041549e+95 -6.85582152e+94  1.78321131e+95
       1.80928039e+95 -6.48320641e+94 -3.75837012e+95  9.12374774e+94
      -6.95509182e+95 -8.62722678e+94 -1.35268798e+94  5.20035093e+94
       1.48651533e+95]
     [-5.35550547e+96 -8.07654383e+96 -1.36586070e+96 -7.18343220e+95
       4.97753565e+96  5.79776975e+96  1.34757179e+97 -1.36546482e+96
       9.36325182e+95  1.31143223e+97 -3.67205086e+96  3.94544911e+96
      -4.23699391e+96 -3.77732453e+96 -9.46905416e+95  2.53360631e+96
       2.52776567e+96 -9.34173064e+95 -5.28058717e+96  1.29899888e+96
      -9.77272504e+96 -1.20339271e+96 -1.73143840e+95  7.39381272e+95
       2.08258457e+96]
     [ 1.49829376e+96  2.26034329e+96  3.79552354e+95  2.00610517e+95
      -1.39306724e+96 -1.62316672e+96 -3.77152498e+96  3.83751885e+95
      -2.62509625e+95 -3.67205086e+96  1.03361014e+96 -1.10401978e+96
       1.18382626e+96  1.05884785e+96  2.66396770e+95 -7.08444645e+95
      -7.05810588e+95  2.60866895e+95  1.47891033e+96 -3.64363760e+95
       2.73542029e+96  3.36018409e+95  4.69179118e+94 -2.05925727e+95
      -5.85062505e+95]
     [-1.61176699e+96 -2.43160828e+96 -4.10949870e+95 -2.18400931e+95
       1.50054559e+96  1.74499465e+96  4.05771520e+96 -4.09833815e+95
       2.80864668e+95  3.94544911e+96 -1.10401978e+96  1.19074119e+96
      -1.27740554e+96 -1.13387221e+96 -2.83955391e+95  7.63869018e+95
       7.60174718e+95 -2.84647832e+95 -1.59168968e+96  3.91675735e+95
      -2.94191110e+96 -3.61433068e+95 -5.11361911e+94  2.20704557e+95
       6.25813808e+95]
     [ 1.73225255e+96  2.61440020e+96  4.42039654e+95  2.32342773e+95
      -1.61415227e+96 -1.87575009e+96 -4.36161389e+96  4.42167044e+95
      -3.00281027e+95 -4.23699391e+96  1.18382626e+96 -1.27740554e+96
       1.37656189e+96  1.21620210e+96  3.03350950e+95 -8.25095112e+95
      -8.18215039e+95  3.06125922e+95  1.71147882e+96 -4.23059166e+95
       3.16398041e+96  3.90968073e+95  5.53596469e+94 -2.39388194e+95
      -6.73022398e+95]
     [ 1.54159730e+96  2.32211712e+96  3.92767708e+95  2.03108995e+95
      -1.42927771e+96 -1.66723623e+96 -3.87669505e+96  3.93669270e+95
      -2.70041549e+95 -3.77732453e+96  1.05884785e+96 -1.13387221e+96
       1.21620210e+96  1.09458670e+96  2.75889646e+95 -7.26002522e+95
      -7.24598497e+95  2.63952103e+95  1.51507581e+96 -3.71443625e+95
       2.80908667e+96  3.44723419e+95  4.93165241e+94 -2.14264460e+95
      -5.98868959e+95]
     [ 3.86518043e+95  5.78620430e+95  9.88910370e+94  4.99338622e+94
      -3.56935914e+95 -4.19759224e+95 -9.71450649e+95  9.73064165e+94
      -6.85582152e+94 -9.46905416e+95  2.66396770e+95 -2.83955391e+95
       3.03350950e+95  2.75889646e+95  7.38470855e+94 -1.83198880e+95
      -1.80664877e+95  6.48794879e+94  3.80851595e+95 -9.25830388e+94
       7.02495718e+95  8.90345709e+94  1.19213708e+94 -5.43834646e+94
      -1.48245092e+95]
     [-1.03851399e+96 -1.56446934e+96 -2.64190017e+95 -1.38252449e+95
       9.70109445e+95  1.12666826e+96  2.61399557e+96 -2.63232484e+95
       1.78321131e+95  2.53360631e+96 -7.08444645e+95  7.63869018e+95
      -8.25095112e+95 -7.26002522e+95 -1.83198880e+95  5.03534133e+95
       4.91306361e+95 -1.88515645e+95 -1.03056884e+96  2.54574947e+95
      -1.89671883e+96 -2.39559015e+95 -3.08459546e+94  1.46026549e+95
       3.98655190e+95]
     [-1.03318594e+96 -1.55871781e+96 -2.65942854e+95 -1.41493347e+95
       9.60132651e+95  1.12046173e+96  2.59937961e+96 -2.61968508e+95
       1.80928039e+95  2.52776567e+96 -7.05810588e+95  7.60174718e+95
      -8.18215039e+95 -7.24598497e+95 -1.80664877e+95  4.91306361e+95
       4.93455295e+95 -1.81544956e+95 -1.02097468e+96  2.50906429e+95
      -1.88813846e+96 -2.35510963e+95 -3.56352360e+94  1.43272953e+95
       4.02770602e+95]
     [ 3.84136131e+95  5.80478295e+95  9.62952834e+94  5.34384453e+94
      -3.63289134e+95 -4.16113562e+95 -9.68520755e+95  9.49822761e+94
      -6.48320641e+94 -9.34173064e+95  2.60866895e+95 -2.84647832e+95
       3.06125922e+95  2.63952103e+95  6.48794879e+94 -1.88515645e+95
      -1.81544956e+95  7.81124055e+94  3.85188292e+95 -9.53781591e+94
       7.02128451e+95  8.69369491e+94  9.26093837e+93 -5.27277257e+94
      -1.44088462e+95]
     [ 2.15896487e+96  3.25585364e+96  5.50215187e+95  2.91933196e+95
      -2.01245774e+96 -2.34105351e+96 -5.43653637e+96  5.47755925e+95
      -3.75837012e+95 -5.28058717e+96  1.47891033e+96 -1.59168968e+96
       1.71147882e+96  1.51507581e+96  3.80851595e+95 -1.03056884e+96
      -1.02097468e+96  3.85188292e+95  2.13972703e+96 -5.27547030e+95
       3.94355611e+96  4.89901818e+95  6.76881886e+94 -2.98059398e+95
      -8.37026029e+95]
     [-5.31253148e+95 -8.03621022e+95 -1.34673858e+95 -7.08999975e+94
       4.97014091e+95  5.76036517e+95  1.33958148e+96 -1.36770882e+95
       9.12374774e+94  1.29899888e+96 -3.64363760e+95  3.91675735e+95
      -4.23059166e+95 -3.71443625e+95 -9.25830388e+94  2.54574947e+95
       2.50906429e+95 -9.53781591e+94 -5.27547030e+95  1.32868446e+95
      -9.72927167e+95 -1.20332439e+95 -1.65666869e+94  7.32709579e+94
       2.07893147e+95]
     [ 3.99371498e+96  6.02497461e+96  1.01850705e+96  5.36874118e+95
      -3.71606201e+96 -4.32489238e+96 -1.00518673e+97  1.01862060e+96
      -6.95509182e+95 -9.77272504e+96  2.73542029e+96 -2.94191110e+96
       3.16398041e+96  2.80908667e+96  7.02495718e+95 -1.89671883e+96
      -1.88813846e+96  7.02128451e+95  3.94355611e+96 -9.72927167e+95
       7.29439403e+96  9.00799205e+95  1.28130517e+95 -5.51918135e+95
      -1.55514582e+96]
     [ 4.93413144e+95  7.40936689e+95  1.26762941e+95  6.57232328e+94
      -4.58408829e+95 -5.37173151e+95 -1.24079812e+96  1.24009257e+95
      -8.62722678e+94 -1.20339271e+96  3.36018409e+95 -3.61433068e+95
       3.90968073e+95  3.44723419e+95  8.90345709e+94 -2.39559015e+95
      -2.35510963e+95  8.69369491e+94  4.89901818e+95 -1.20332439e+95
       9.00799205e+95  1.18476485e+95  1.64554514e+94 -7.00550870e+94
      -1.89540275e+95]
     [ 6.98444992e+94  1.06077010e+95  2.01771484e+94  1.01775014e+94
      -6.35382105e+94 -7.66356006e+94 -1.75262967e+95  1.78160539e+94
      -1.35268798e+94 -1.73143840e+95  4.69179118e+94 -5.11361911e+94
       5.53596469e+94  4.93165241e+94  1.19213708e+94 -3.08459546e+94
      -3.56352360e+94  9.26093837e+93  6.76881886e+94 -1.65666869e+94
       1.28130517e+95  1.64554514e+94  6.19513022e+93 -9.91850230e+93
      -2.87199985e+94]
     [-3.03110404e+95 -4.55738134e+95 -7.79358071e+94 -3.80500413e+94
       2.81091830e+95  3.28352177e+95  7.61076386e+95 -7.69947548e+94
       5.20035093e+94  7.39381272e+95 -2.05925727e+95  2.20704557e+95
      -2.39388194e+95 -2.14264460e+95 -5.43834646e+94  1.46026549e+95
       1.43272953e+95 -5.27277257e+94 -2.98059398e+95  7.32709579e+94
      -5.51918135e+95 -7.00550870e+94 -9.91850230e+93  4.56501078e+94
       1.15281685e+95]
     [-8.49040544e+95 -1.28356107e+96 -2.16839447e+95 -1.15866344e+95
       7.87742552e+95  9.19512046e+95  2.13885366e+96 -2.20177355e+95
       1.48651533e+95  2.08258457e+96 -5.85062505e+95  6.25813808e+95
      -6.73022398e+95 -5.98868959e+95 -1.48245092e+95  3.98655190e+95
       4.02770602e+95 -1.44088462e+95 -8.37026029e+95  2.07893147e+95
      -1.55514582e+96 -1.89540275e+95 -2.87199985e+94  1.15281685e+95
       3.40035651e+95]]


**d)** Calcule o traço de A;


```python
def traco(matriz_A):
    linhas, colunas = np.shape(matriz_A)
    n, traco = min((linhas, colunas)), 0

    for i in range(n):
        traco += matriz_A[i,i]
    return traco

```


```python
print("Traço de A:", traco(matriz))
```

    Traço de A: 2024668.0


**e)** Avalie se A é simétrica;


```python
def verifica_simetria(matriz_A):
    if verifica_quadrada(matriz_A):
        n = len(matriz_A)
        for i in range(n):
            for j in range(n):
                if (i != j) and (matriz_A[i,j] != matriz_A[j,i]):
                    print("A matriz não é simétrica")
                    return False
        print("A matriz é simétrica")
        return True
    print("A matriz não é quadrada")
    return False
```


```python
verifica_simetria(matriz)
```

    A matriz é simétrica





    True



**f)** Avalie se A é ortogonal;


```python
def verifica_ortogonal(matriz_A):
    if not verifica_quadrada:
        print("A matriz não é quadrada.")
        return False
    
    if not verifica_inversa:
        print("A matriz é singular.")
        return False
    
    n = len(matriz_A)
    matriz_At = calcula_transposta(matriz_A)
    matriz_Id = np.identity(n)

    matriz_Resultado = np.matmul(matriz_A, matriz_At)

    if (matriz_Resultado-matriz_Id).all() <= 1e-10:
        print("A matriz é ortogonal.")
        return True
    else:
        print("A matriz não é ortogonal.")
        return False
```


```python
verifica_ortogonal(matriz)
```

    A matriz não é ortogonal.





    False



**g)** Calcule a norma de linha, norma de Frobenius e norma coluna de A.


```python
def soma_linha(matriz_A): # norma-infinita matricial
    n, max, x = len(matriz_A), 0, 0

    for i in range(n):
        for j in range(n):
            x += math.fabs(matriz_A[i,j])
        
        if x > max:
            max = x

    return max
```


```python
soma_linha(matriz)
```


```python
def frobenius(matriz_A): # norma-2 matricial
    n, x = len(matriz_A), 0

    for i in range(n):
        for j in range(n):
            x += math.pow(math.fabs(matriz_A[i,j]), 2)

    return x ** (1/2)
```


```python
frobenius(matriz)
```


```python
def soma_coluna(matriz_A): # norma-1 matricial
    n, max, x = len(matriz_A), 0, 0

    for j in range(n):
        for i in range(n):
            x += math.fabs(matriz_A[i,j])
        
        if x > max:
            max = x
    
    return max
```


```python
soma_coluna(matriz)
```

**h)** Avalie se A é positiva definida.


```python
def checa_positiva_definida(matriz_A, debug=False):
    if not verifica_inversa or not verifica_quadrada or not verifica_simetria:
        return False

    n = len(matriz_A) # n é a ordem da matriz a
    matriz_R = np.copy(np.triu(matriz_A)) # matriz_r é uma cópia triangular superior da matriz A

    for i in range(n):
            for k in range(i): # Não é executado quando i = 0
                matriz_R[i,i] = matriz_R[i,i] - math.pow(matriz_R[k,i],2) # Define os termos da diagonal principal
            if matriz_R[i,i] <= 0: # Se algum elemento da diagonal principal for menor ou igual a zero, por definição, a matriz não é positiva definida
                if debug:
                    print("Erro: A matriz não é positiva definida.")
                return False
            matriz_R[i,i] = math.sqrt(matriz_R[i,i]) 
            for j in range(i+1,n): # Não é executado quando i = n
                for k in range(i): # Não é executado quando i = 0
                    matriz_R[i,j] = matriz_R[i,j] - (matriz_R[k,i] * matriz_R[k,j])
                matriz_R[i,j] = matriz_R[i,j]/matriz_R[i,i]
    return True
```


```python
checa_positiva_definida(matriz)
```




    True



---
### 6) Construa um algoritmo que receba dois vetores x e y e uma matriz A positiva definida (de uma planilha excel). Calcule:


```python
def ler_matriz_A_vetor_x_vetor_y(file_name, file_matrix, file_array_x, file_array_y):
    df_matriz = pd.read_excel(r"dados/"+file_name+".xlsx", header=None, sheet_name=file_matrix) # Le o arquivo do excel que contém a matriz A sem cabeçalho
    df_vetor_x = pd.read_excel(r"dados/"+file_name+".xlsx", header=None, sheet_name=file_array_x) # Le o arquivo do excel que contém o vetor x sem cabeçalho
    df_vetor_y = pd.read_excel(r"dados/"+file_name+".xlsx", header=None, sheet_name=file_array_y) # Le o arquivo do excel que contém o vetor y sem cabeçalho
    matriz = np.array(df_matriz, dtype='f8') # Converte a matriz A em um array da numpy
    vetor_x = np.ravel(np.array(df_vetor_x, dtype='f8')) # Converte o vetor b em um array da numpy
    vetor_y = np.ravel(np.array(df_vetor_y, dtype='f8')) # Converte o vetor b em um array da numpy
    return matriz, vetor_x, vetor_y

```


```python
matriz, vetor_x, vetor_y = ler_matriz_A_vetor_x_vetor_y("prova_ALC_testes", "matriz_A(2)", "vetor_b(1)", "vetor_b(1)")
```

**a)** Norma 1, norma 2 e norma infinito de x e y.


```python
def manhattan(vetor): # norma-1 vetorial
    n, x = len(vetor), 0

    for i in range(n):
        x += np.fabs(vetor[i])
    return x
```


```python
print(manhattan(vetor_x))
print(manhattan(vetor_y))
```

    26072.0
    26072.0



```python
def euclidiana(vetor): # norma-2 vetorial
    n, x = len(vetor), 0

    for i in range(n):
        x += np.fabs(vetor[i]) ** 2

    return x ** (1/2)
```


```python
print(euclidiana(vetor_x))
print(euclidiana(vetor_y))
```

    5264.014627639251
    5264.014627639251



```python
def infinita(vetor): # norma-infinita vetorial
    n, max = len(vetor), vetor[0]
    
    for i in range(1, n):
        if np.fabs(vetor[i]) > max:
            max = np.fabs(vetor[i])

    return max
```


```python
print(infinita(vetor_x))
print(infinita(vetor_y))
```

    1291.0
    1291.0


**b)** Ângulo entre x e y;


```python
def produto_interno(vetor_x, vetor_y):
    n, p_interno = len(vetor_x), 0

    for i in range(n):
        p_interno += vetor_x[i] * vetor_y[i]
    
    return p_interno

def angulo_vetores(vetor_x, vetor_y):
    n = len(vetor_x)

    p_interno = produto_interno(vetor_x, vetor_y)
    norma_x = euclidiana(vetor_x)
    norma_y = euclidiana(vetor_y)
    p_normas = norma_x * norma_y

    div = p_interno/p_normas

    return np.arccos(div)
```


```python
angulo_vetores(vetor_x, vetor_y)
```

**c)** Norma de x e y induzida por A;


```python
def matricial_induzida(matriz_A, vetor_b, norma=manhattan):
    
    if norma == manhattan:
        mat = np.matmul(matriz_A, vetor_b)
        return manhattan(mat)/manhattan(b)
    
    elif norma == euclidiana:
        mat = np.matmul(matriz_A, vetor_b)
        return euclidiana(mat)/euclidiana(mat)
    
    elif norma == infinita:
        mat = np.matmul(matriz_A, vetor_b)
        return infinita(mat)/infinita(mat)
```


```python
matricial_induzida(matriz, vetor_x)
```




    array([9.86160695e+09])




```python
a = np.array([[3,2,1],[1,4,2],[2,1,3]])
```

**d)** Produto interno de x e y.


```python
def produto_interno(vetor_x, vetor_y):
    n, p_interno = len(vetor_x), 0

    for i in range(n):
        p_interno += vetor_x[i] * vetor_y[i]
    
    return p_interno
```


```python
produto_interno(vetor_x, vetor_y)
```

---
### 7) Implemente um algoritmo que leia uma matriz A e um vetor b (de uma planilha excel). Encontre a fatoração LU de A.


```python
matriz, vetor = ler_matriz_A_vetor_b("prova_ALC_testes", "matriz_A(1)", "vetor_b(1)")
```


```python
fatoracaoLU(matriz,vetor)
```




    array([ 218.15690039, -134.91978861, -228.57366314,  196.17807308,
            -23.10822144,  120.75613378,   76.57658357,   32.56339464,
            112.28655838, -311.76230605,    9.73618607,  179.86106078,
             37.55533057,   -5.28610392,   20.3176418 ,  120.6584339 ,
            184.2906244 ,   34.16170845, -178.63243142,  -42.98537213,
           -108.87178633,  -70.23227857,  168.6609164 , -259.13412099,
           -164.019284  ])



---
### 8) Construa um algoritmo que receba uma matriz A positiva (de uma planilha excel). Calcule:


```python
matriz = ler_matriz_A("prova_ALC_testes", "matriz_A(2)")
```

**a)** O número condição;


```python
def condition_number(matriz):
    inv = np.linalg.inv(matriz)
    kond = frobenius(matriz) * frobenius(inv)
    print("Número condição de {} significa que, para um sistema linear esta matriz, o erro esperado causado por uma perturbação em b vai será de aproximadamente {}".format(kond, kond))
    return kond
```

**b)** Retorne uma mensagem ao usuário sobre sua interpretação.


```python
condition_number(matriz)
```

    Número condição de 1543177713.9375234 significa que, para um sistema linear esta matriz, o erro esperado causado por uma perturbação em b vai será de aproximadamente 1543177713.9375234


---
### 9) Construa um algoritmo que receba três matrizes: U, sigma e V (de uma planilha excel) e:


```python
def ler_matrizes_USV(file_excel):
    df_matriz_U = pd.read_excel(r"dados/"+file_excel+".xlsx", header=None, sheet_name='matriz_U') # Le o arquivo do excel que contém a matriz A sem cabeçalho
    df_matriz_S = pd.read_excel(r"dados/"+file_excel+".xlsx", header=None, sheet_name='matriz_S') # Le o arquivo do excel que contém o vetor x sem cabeçalho
    df_matriz_V = pd.read_excel(r"dados/"+file_excel+".xlsx", header=None, sheet_name='matriz_V') # Le o arquivo do excel que contém o vetor y sem cabeçalho
    matriz_U = np.array(df_matriz_U, dtype='f8') # Converte a matriz A em um array da numpy
    matriz_S = np.array(df_matriz_S, dtype='f8') # Converte a matriz A em um array da numpy
    matriz_Vt = np.array(df_matriz_V, dtype='f8') # Converte a matriz A em um array da numpy
    return matriz_U, matriz_S, matriz_Vt

matriz_U, matriz_S, matriz_Vt = ler_matrizes_USV("prova_ALC_testes")
```

**a)** Avalie se o produto das três matrizes representa uma decomposição SVD de alguma matriz X;

**b)** Caso a resposta à pergunta anterior seja negativa, retorne ao usuário uma explicação justificando esse fato.


```python
# U e V ortogonais e S não-quadrada e diagonal
def verifica_diagonal(matriz):
    n, m = np.shape(matriz)

    for i in range(n):
        for j in range(m):
            if i != j and matriz[i,j] != 0:
                print("A matriz não é diagonal.")
                return False
    print("A matriz é diagonal.")
    return True

def verifica_SVD(matriz_U, matriz_S, matriz_Vt):
    print("Para as matrizes USVt serem a decomposição SVD de uma matriz X:\n-> U e Vt devem ser ortogonais.\n-> S deve ser diagonal não-quadrada.\n")
    print("Verificando se U é ortogonal...")
    if verifica_ortogonal(matriz_U):
        print("\nVerificando se Vt é ortogonal...")
        if verifica_ortogonal(matriz_Vt):
            print("\nVerificando se S é diagonal e não-quadrada...")
            if verifica_diagonal(matriz_S):
                nS, mS = np.shape(matriz_S)
                if nS != mS:
                    print("A matriz é não-quadrada.")
                    print("")
                    mU = len(matriz_U)
                    nVt = len(matriz_Vt)

                    if mU == nS and mS == nVt:
                        print("As matrizes são a decomposição SVD da matriz X abaixo:")
                        matriz_X = np.matmul(np.matmul(matriz_U, matriz_S), matriz_Vt)
                        print(matriz_X)

                        return True
                    else:
                        print("As matrizes não têm dimensões compatíveis para executar um produto de matrizes.")
                        return False
                else:
                    print("A matriz S é quadrada.")
                    return False
            else:
                print("A matriz S não é diagonal.")
                return False
        else:
            print("A matriz Vt não é ortogonal.")
            return False
    else:
        print("A matriz U não é ortogonal.")
        return False
```


```python
verifica_SVD(matriz_U, matriz_S, matriz_Vt)
```

    Para as matrizes USVt serem a decomposição SVD de uma matriz X:
    -> U e Vt devem ser ortogonais.
    -> S deve ser diagonal não-quadrada.
    
    Verificando se U é ortogonal...
    A matriz é ortogonal.
    
    Verificando se Vt é ortogonal...
    A matriz não é ortogonal.
    A matriz Vt não é ortogonal.





    False



---
### 10) Construa um algoritmo que leia uma planilha em Excel com 4 colunas e calcule a estatística de Benford (para 1 dígito) para cada uma das colunas.


```python
benford(ler_dados_benford("dados_benford"))
```

    Porcentagem de ocorrência de "1" em cada coluna: 10.6692% | 11.1430% | 11.8036% | 10.9420% | 
    Porcentagem de ocorrência de "2" em cada coluna: 11.1574% | 11.0281% | 10.8271% | 11.3297% | 
    Porcentagem de ocorrência de "3" em cada coluna: 11.3297% | 10.8415% | 11.3441% | 11.2005% | 
    Porcentagem de ocorrência de "4" em cada coluna: 11.3584% | 10.5112% | 10.3676% | 10.7553% | 
    Porcentagem de ocorrência de "5" em cada coluna: 10.6117% | 11.1430% | 11.2866% | 11.0999% | 
    Porcentagem de ocorrência de "6" em cada coluna: 11.2435% | 11.3584% | 10.8845% | 11.0425% | 
    Porcentagem de ocorrência de "7" em cada coluna: 11.8323% | 11.1861% | 11.4733% | 10.7266% | 
    Porcentagem de ocorrência de "8" em cada coluna: 11.0999% | 11.1717% | 11.4159% | 11.6743% | 
    Porcentagem de ocorrência de "9" em cada coluna: 10.6979% | 11.6169% | 10.5974% | 11.2005% | 


713aec1182f586981b116360098f4f007e0642d7
ipynb
Jupyter Notebook
run.ipynb
eRRe-i/algebra-linear-computacional
f2caffdb33aed0fad9d811b20f6505ad6513d824
MIT
run.ipynb
eRRe-i/algebra-linear-computacional
f2caffdb33aed0fad9d811b20f6505ad6513d824
MIT
run.ipynb
eRRe-i/algebra-linear-computacional
f2caffdb33aed0fad9d811b20f6505ad6513d824
MIT
Qwen/Qwen-72B
1. YES
2. YES