# -*- coding: utf-8 -*-
"""Algebra_Linear_no_Python-Colab.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/18WA6PXajjsR3ipWb-9c5dfxojLcI6QMv

# **Álgebra Linear**
"""

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

v1 = [2,5]
v2 = [1,6,8]
v1 ,v2

type(v1)

v3 = np.array([8,3,9])
type(v3)

v3.shape[0]

v3.shape

v4=np.array([1.+2.j, 3.+4.j, 5, 6.j], dtype=complex)
v4

type(v4)

"""# **Lendo elementos de um array**"""

a = np.array([7,5,3,9,0,2])
a

a[0]

a[1:]

a[1:4]

a[-1]

a[-3]

a[-6]

a[-3:-1]

"""#**Plotando um vetor**"""

v = [3,5]
u = [1,2,3]

plt.plot(v)

plt.plot([0,v[0]] , [0,v[1]])

"""# **Plota um vetor 2D**"""

plt.plot([0,v[0]] , [0,v[1]])
plt.plot([8,-8] , [0,0] , 'k--')
plt.plot([0,0] , [8,-8] , 'k--')
plt.grid()
plt.axis((-8, 8, -8, 8))
plt.show()

"""# **Plota um vetor 3D**"""

fig = plt.figure()
ax = Axes3D(fig)
ax.plot([0,u[0]],[0,u[1]],[0,u[2]])
#plt.axis('equal')
ax.plot([0, 0],[0, 0],[-5, 5],'k--')
ax.plot([0, 0],[-5, 5],[0, 0],'k--')
ax.plot([-5, 5],[0, 0],[0, 0],'k--')
plt.show()

"""# **Soma de vetores**"""

v1 = np.array([2,-4])
v2 = np.array([4,6])
v3 = v1+v2
v3 = np.add(v1,v2)
print('V3 =' ,v3)
plt.plot([0,v1[0]] , [0,v1[1]] , 'r' , label = 'v1')
plt.plot([0,v2[0]] , [0,v2[1]], 'b' , label = 'v2')
plt.plot([0,v3[0]] , [0,v3[1]] , 'g' , label = 'v3')
plt.plot([8,-8] , [0,0] , 'k--')
plt.plot([0,0] , [8,-8] , 'k--')
plt.grid()
plt.axis((-8, 8, -8, 8))
plt.legend()
plt.show()

plt.plot([0,v1[0]] , [0,v1[1]] , 'r' , label = 'vetor v1')
plt.plot([0,v2[0]]+v1[0] , [0,v2[1]]+v1[1], 'b' , label = 'vetor v2')
plt.plot([0,v3[0]] , [0,v3[1]] , 'g' , label = 'vetor v3')
plt.plot([8,-8] , [0,0] , 'k--')
plt.plot([0,0] , [8,-8] , 'k--')
plt.grid()
plt.axis((-8, 8, -8, 8))
plt.legend()
plt.show()

"""# **Multiplicação de vetor por um escalar**"""

u1 = np.array([4,4])
a = .5
u2 = u1*a
plt.plot([0,u1[0]] , [0,u1[1]] , 'r' , label = 'v1')
plt.plot([0,u2[0]] , [0,u2[1]], 'b--' , label = 'v2')
plt.plot([8,-8] , [0,0] , 'k--')
plt.plot([0,0] , [8,-8] , 'k--')
plt.grid()
plt.axis((-8, 8, -8, 8))
plt.legend()
plt.show()

u1 = np.array([4,4])
a = -.3
u2 = u1*a
plt.plot([0,u1[0]] , [0,u1[1]] , 'r' , label = 'v1')
plt.plot([0,u2[0]] , [0,u2[1]], 'b' , label = 'v2')
plt.plot([8,-8] , [0,0] , 'k--')
plt.plot([0,0] , [8,-8] , 'k--')
plt.grid()
plt.axis((-8, 8, -8, 8))
plt.legend()
plt.show()

"""# **Multiplicação de vetores**"""

a1 = [2,4,6]
a2 = [3,5,1]
print(np.multiply(a1,a2))

"""# **Produto interno**"""

a1 = np.array([2,4,6])
a2 = np.array([3,5,1])

dotp = a1@a2
print(" Dot product - ",dotp)

dotp = np.dot(a1,a2)
print(" Dot product usign np.dot",dotp)

dotp = np.inner(a1,a2)
print(" Dot product usign np.inner", dotp)

dotp = sum(np.multiply(a1,a2))
print(" Dot product usign np.multiply & sum",dotp)

dotp = np.matmul(a1,a2)
print(" Dot product usign np.matmul",dotp)

dotp = 0
for i in range(len(a1)):
    dotp = dotp + a1[i]*a2[i]
print(" Dot product usign for loop" , dotp)

"""# **Tamanho de um vetor**"""

v3 = np.array([1,2,3,4,5,6,7])
length = np.sqrt(np.dot(v3,v3))
length

v3 = np.array([1,2,3,4,5,6,7])
length = np.sqrt(sum(np.multiply(v3,v3)))
length

v3 = np.array([1,2,3,4,5,6,7])
length = np.sqrt(np.matmul(v3,v3))
length

"""# **Vetor normalizado**"""

v1 = [1,1]
length_v1 = np.sqrt(np.dot(v1,v1))
norm_v1 = v1/length_v1
length_v1 , norm_v1

v1 = [1,1]
norm_v1 = v1/np.linalg.norm(v1)
norm_v1

"""# **Ângulo entre vetores**"""

#First Method
v1 = np.array([5,5])
v2 = np.array([-5,5])
ang = np.rad2deg(np.arccos( np.dot(v1,v2) / (np.linalg.norm(v1)*np.linalg.norm(v2))))
plt.plot([0,v1[0]] , [0,v1[1]] , 'r' , label = 'v1')
plt.plot([0,v2[0]]+v1[0] , [0,v2[1]]+v1[1], 'b' , label = 'v2')
plt.plot([15,-15] , [0,0] , 'k--')
plt.plot([0,0] , [15,-15] , 'k--')
plt.grid()
plt.axis((-15, 15, -15, 15))
plt.legend()
plt.title('Angulo entre vetores - %s'  %ang)
plt.show()

#Second Method
v1 = np.array([5,5])
v2 = np.array([-5,5])
lengthV1 = np.sqrt(np.dot(v1,v1)) 
lengthV2  = np.sqrt(np.dot(v2,v2))
ang = np.rad2deg(np.arccos( np.dot(v1,v2) / (lengthV1 * lengthV2)))
print('Angulo entre vetores - %s' %ang)

v1 = np.array([5,2,-3])
v2 = np.array([7,-1,2])
fig = plt.figure()
ax = Axes3D(fig)
ax.plot([0, v1[0]],[0, v1[1]],[0, v1[2]],'b')
ax.plot([0, v2[0]],[0, v2[1]],[0, v2[2]],'r')
ang = np.rad2deg(np.arccos( np.dot(v1,v2) / (np.linalg.norm(v1)*np.linalg.norm(v2)) ))
plt.title('Angulo entre vetores: %s degrees.' %ang)

"""# **Produtos interno e externo**"""

v1 = np.array([1,2,1])
v2 = np.array([2,1,2])
np.inner(v1,v2)

print("\n Inner Product ==>  \n", np.inner(v1,v2))
print("\n Outer Product ==>  \n", np.outer(v1,v2))

"""# **Produto vetorial**"""

v1 = np.array([7,0,0])
v2 = np.array([0,7,0])
print("\nVector Cross Product ==>  \n", np.cross(v1,v2))

"""# **Operações com matrizes**

# **Criação de matriz**
"""

A = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
A

type(A)

A.dtype

B = np.array([[2.7,6.03,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
B

type(B)

B.dtype

A.shape

A[0,]

A[:,0]

A[0,0]

A[0][0]

A[1:3 , 1:3]

"""# **Matriz de zeros**"""

np.zeros(36).reshape(6,6)

np.zeros((6,6))

"""# **Matriz de 1's**"""

np.ones(25).reshape(5,5)

np.ones((5,5))

"""# **Matriz de números aleatórios**"""

X = np.random.random((3,4))
X

"""# **Matriz identidade**"""

I = np.eye(7)
I

"""# **Matriz diagonal**"""

D = np.diag([1,2,3,4,5,6,7])
D

"""# **Matrizes triangulares (superior e inferior)**"""

M = np.random.randn(5,5)
U = np.triu(M)
L = np.tril(M)
print("matriz aleatória \n" , M)
print("\n")


print("matriz triangular inferior \n" , L)
print("\n")

print("matriz triangular superior \n" , U)

"""# **Concatenação de matrizes**"""

A = np.array([[1,2] , [3,4] ,[5,6]])
B = np.array([[9,2] , [3,-3]])
C = np.concatenate((A,B))
C , C.shape , type(C) , C.dtype

np.full((7,7) , 4)

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

M.flatten()

"""# **Soma de matrizes**"""

M = np.array([[1,2,3],[4,-3,6],[7,8,0]])
N = np.array([[5,5,5],[6,6,6],[7,7,7]])

print("\n Primeira matriz (M)  ==>  \n", M)
print("\n Segunda matriz (N)  ==>  \n", N)

C = M+N
print("\n soma (M+N)  ==>  \n", C)

# ou

C = np.add(M,N,dtype = np.float64)
print("\n soma usando np.add  ==>  \n", C)

"""# **Subtração de matrizes**"""

M = np.array([[1,2,3],[4,-3,6],[7,8,0]])
N = np.array([[5,5,5],[6,6,6],[7,7,7]])

print("\n Primeira matriz (M)  ==>  \n", M)
print("\n Segunda matriz (N)  ==>  \n", N)

C = M-N
print("\n Subtração (M-N)  ==>  \n", C)

# ou

C = np.subtract(M,N,dtype = np.float64)
print("\n Subtração usando np.subtract  ==>  \n", C)

"""# **Multiplicação de matriz por escalar**"""

M = np.array([[1,9,3],[2,-7,6],[8,7,0]])

C = 20

print("\n Matriz (M)  ==>  \n", M)

print("\n Multiplicação por escalar ==>  \n", C*M)

# ou

print("\n Multiplicação por escalar usando np.multiply ==>  \n", np.multiply(C,M))

"""# **Transposta de uma matriz**"""

M = np.array([[1,9,3],[2,-7,6],[8,7,0]])

print("\n Matriz (M)  ==>  \n", M)

print("\n Transposta de M ==>  \n", np.transpose(M))

# ou

print("\nTransposta de M ==>  \n", M.T)

"""# **Determinante de uma matriz**"""

M = np.array([[1,9,3],[2,-7,6],[8,7,0]])

print("\n Matriz (M)  ==>  \n", M)

print("\n Determinante de M ==>  ", np.linalg.det(M))

"""# **Posto de uma matriz**"""

M = np.array([[1,9,3],[2,-7,6],[8,7,0]])

print("\n Matriz (M)  ==>  \n", M)

print("\n Posto de M ==> ", np.linalg.matrix_rank(M))

"""# **Traço de uma matriz**"""

M = np.array([[1,9,3],[2,-7,6],[8,7,0]])

print("\n Matriz (M)  ==>  \n", M)

print("\n Traço de M ==> ", np.trace(M))

"""# **Inversa de uma matriz**"""

M = np.array([[1,9,3],[2,-7,6],[8,7,0]])

print("\n Matriz (M)  ==>  \n", M)

print("\n Inversa de M ==> \n", np.linalg.inv(M))

"""# **Multiplicação de matrizes (pontual)**"""

M = np.array([[1,9,3],[2,-7,6],[8,7,0]])
N = np.array([[5,5,5],[6,6,6],[7,7,7]])

print("\n Primeira matriz (M)  ==>  \n", M)
print("\n Segunda matriz (N)  ==>  \n", N)

print("\n Multiplication pontual de M e N  ==> \n", M*N)

# ou

print("\n Multiplication pontual de M e N  ==> \n", np.multiply(M,N))

"""# **Produto escalar matricial**"""

M = np.array([[1,9,3],[2,-7,6],[8,7,0]])
N = np.array([[5,5,5],[6,6,6],[7,7,7]])

print("\n Primeira matriz (M) \n", M)
print("\n Segunda matriz (N) \n", N)

print("\n Produto escalar \n", M@N)

# ou

print("\n Produto escala usando np.matmul \n", np.matmul(M,N))

# ou

print("\n Produto escala usando np.dot \n", np.dot(M,N))

"""# **"Divisão" de Matrizes**"""

M = np.array([[1,9,3],[2,-7,6],[8,7,0]])
N = np.array([[5,5,5],[6,6,6],[7,7,7]])

print("\n Primeira matriz (M) \n", M)
print("\n Segunda matriz (N) \n", N)


print("\n Divisão (M/N) \n", M/N)

# ou

print("\n Divisão (M/N) \n", np.divide(M,N))

"""# **Soma de todos elementos da matriz**"""

N = np.array([[5,5,5],[6,6,6],[7,7,7]])

print("Matriz (N) \n", N)

print ("Soma de todos elementos da matriz")
print (np.sum(N))

"""# **Adição com base na coluna**"""

N = np.array([[5,5,5],[6,6,6],[7,7,7]])

print("Matriz (N)  ==>  \n", N)

print ("Adição com base na coluna")
print (np.sum(N,axis=0))

"""# **Adição com base na linha**"""

N = np.array([[5,5,5],[6,6,6],[7,7,7]])

print("Matriz (N)  ==>  \n", N)

print ("Adição com base na linha")
print (np.sum(N,axis=1))

"""# **Produto de Kronecker de matrizes**"""

M1 = np.array([[1,2,3] , [4,5,6]]) 
M1

M2 = np.array([[10,10,10],[10,10,10]])
M2

np.kron(M1,M2)

"""# **Multiplicação matriz-vetor**"""

A = np.array([[1,2,3] ,[4,5,6]])
v = np.array([10,20,30])
print ("Multiplicação matriz-vetor \n", A*v)

"""# **Produto escalar matriz-vetor**"""

A = np.array([[1,2,3] ,[4,5,6]])
v = np.array([10,20,30])

print ("Produto escalar matriz-vetor \n" , A@v)

"""# **Potências de matriz**"""

M1 = np.array([[1,2],[5,6]])
M1

# Matriz na potencia 3

M1@M1@M1

# Matriz na potencia 3 usando np.linalg.matrix_power

np.linalg.matrix_power(M1,3)

"""# **Tensores**"""

# Criando um Tensor

T1 = np.array([
  [[1,2,3],    [4,5,6],    [7,8,9]],
  [[10,11,12], [13,14,15], [16,17,18]],
  [[19,20,21], [22,23,24], [25,26,27]],
  ])

T1

T2 = np.array([
  [[0,0,0] , [0,0,0] , [0,0,0]],
  [[2,2,2] , [2,2,2] , [2,2,2]],
  [[4,4,4] , [4,4,4] , [4,4,4]]
    
])

T2

"""# **Soma de tensores**"""

A = T1+T2
A

"""# **Subtração de tensores**"""

S = T1-T2
S

np.subtract(T1,T2)

"""# **Produto de tensores (baseado em elementos)**"""

P = T1*T2
P

np.multiply(T1,T2)

"""# **"Divisão" de tensores (baseado em elementos)**"""

D = T1/T2
D

np.divide(T1,T2)

"""# **Produto escalar de tensores**"""

T1

T2

np.tensordot(T1,T2)

"""# **Solução de sistemas lineares (AX=B)**"""

A = np.array([[4,-2,3] , [1,-5,6] , [-7,8,9]])
A

B = np.random.random((3,1))
B

# Primeiro metodo
X = np.dot(np.linalg.inv(A) , B)
X

# Segundo Metodo
X = np.matmul(np.linalg.inv(A) , B)
X

# Terceiro metodo
X = np.linalg.inv(A)@B
X

# Quarto metodo
X = np.linalg.solve(A,B)
X