A introdução de um produto escalar $\langle \cdot, \cdot \rangle$ em um espaço vetorial $V$ de dimensão finita $n$, além de determinar uma distância entre os vetores, também define o ângulo. Lembremos que: $$ \| x-y \| = \sqrt{\langle x-y,x-y \rangle}.$$ Para o conceito de ângulo, vamos começar só com ortoganalidade. Dizemos que dois vetores $x$ e $y$ são ortogonais quando o produto interno entre eles for zero, $\langle x, y\rangle = 0$.
# Usamos o numpy para a o produto escalar usual
import numpy as np
x=np.array([1,2,0,4,0])
y=np.array([2,-1,4,0,2])
# np.dot() é a função de produto escalar para vetores ver help(np.dot)para o caso geral
np.dot(x,y)
0
A partir de uma base qualquer $\{\mathbf{e}_1,\dots,\mathbf{e}_n\}$, podemos construir uma base ortogonal (os elementos são, dois a dois, ortogonais) $\{\mathbf{f}_1,\dots,\mathbf{f}_n\}$, num processo iterativo chamado método de Gram-Schmidt: $$ \begin{eqnarray} \mathbf{f}_1 &= &\mathbf{e}_1\\ \mathbf{f}_k & = & \mathbf{e}_k - \sum_{i=1}^{k-1}\frac{\langle \mathbf{e}_k,\mathbf{f}_i\rangle}{\langle \mathbf{f}_i,\mathbf{f}_i\rangle}\mathbf{f}_i \end{eqnarray} $$
def GramSchimdt(E):
'''Aplica o processo de Gram-Schmidt para uma array de vetores '''
n,k = np.shape(E)
F = E.copy()
for i in range(1,k):
F[:,i]=F[:,i]-sum(np.dot(E[:,i],F[:,j])/np.dot(F[:,j],F[:,j])*F[:,j] for j in range(i))
return F
# Teste da função:
# Exemplo 1
E = np.array([[2,1],[1,0],[0,2]], dtype=float)
print(E)
[[ 2. 1.] [ 1. 0.] [ 0. 2.]]
F=GramSchimdt(E)
print(F)
[[ 2. 0.2] [ 1. -0.4] [ 0. 2. ]]
# Exemplo 2
E1 = np.array([[2,1,0],[1,-1,3],[0,2,1]], dtype=float)
print(E1)
[[ 2. 1. 0.] [ 1. -1. 3.] [ 0. 2. 1.]]
F1=GramSchimdt(E1)
print(F1)
[[ 2. 0.6 -1.03448276] [ 1. -1.2 2.06896552] [ 0. 2. 1.55172414]]
Se $W \subset V$ é um subspaço vetorial de dimensão $k$ então o conjunto $W^\bot =\{ y \in V: \langle x, y \rangle =0 \forall x\in W\}$ é o complemento ortogonal de $W$. É um subespaço de dimensão $n-k$ e $V=W\oplus W^\bot$.
Seja $W$ um subespaço de $V$, de dimensão $k$. Para cada $v\in V$, denotamos por $\hat{v}$ a projeção ortogonal de $v$ em $W$. Vimos no parágrafo anterior que $(v-\hat{v})\in W^\bot$. Para um outro $w$ qualquer de $W$, podemos escrever $w=\hat{v} + w_1$. Daí: $$ \|v-w\|^2 = \|v-\hat{v} -w_1\|^2 = \langle v-\hat{v} -w_1,v-\hat{v} -w_1\rangle = \|v-\hat{v}\|^2 + \|w_1\|^2 $$ Então a projeção ortogonal $\hat{v}$ é o vetor de $W$ mais próximo de $v$ pela norma euclidiana.