Transformações matriciais;conceitos e teoria, existem recursos livres para aprender praticamente?[encerrado]
-
06-07-2019 - |
Pergunta
Tenho me divertido renderizando tabelas e gráficos de coordenadas ultimamente, e estou fascinado por usar matrizes para transformar espaços de coordenadas.
Consegui escalar e inverter com sucesso os espaços de coordenadas 2 dimensionais, mas agora meu apetite está aguçado.:)
Onde posso ir para obter material educativo claro, informativo, (gratuito) sobre matrizes, matemática matricial, especialmente no que se aplica ao espaço dimensional 2 e 3?
Solução
Resposta Original: Não tenho certeza se você vai gostar de como os cursos de matemática normalmente introduzem matrizes.Como programador, você pode ficar mais feliz em pegar qualquer livro de gráficos 3D decente.Deve certamente ter matrizes 3x3 muito concretas.Descubra também os que lhe ensinarão transformações projetivas (a geometria projetiva é uma área muito bonita de geometria de baixa dimensão e fácil de programar).
Minicurso em matemática matricial com Python 3
Conteúdo:
- Matrizes
[Vector, __add__, reflect_y, rotate, dilate, transform]
- Matrizes:Sobrecarregado
[Matrix, __add__, __str__, __mul__, zero, det, inv, __pow__]
- Bónus:Números complexos
- Matrizes:A (R)evolução.Já está em construção (há um resumo no final)
Prefácio: Com base na minha experiência de ensino, penso que os cursos referenciados por outros são muito bons cursos.Isso significa que, se o seu objetivo é entender matrizes como os matemáticos fazem, você deve, por todos os meios, obter todo o curso.Mas se seus objetivos são mais modestos, aqui está minha tentativa de algo mais adaptado às suas necessidades (mas ainda escrito com o objetivo de transmitir muitos conceitos teóricos, contradizendo meu conselho original.)
Como utilizar:
- Este post é longo.Você pode considerar imprimir isso e ir devagar, como uma parte por dia.
- O código é essencial.Este é um curso para programadores.Os exercícios também são essenciais.
- Você deve dê uma olhada no code companion que contém todo este código e muito mais
- É" 2 pelo preço de 1 " especial:Você também pode aprender Python 3 aqui.E números complexos.
- Eu valorizo muito qualquer tentativa de ler isso (eu me qualifico oficialmente para o post mais longo de todos os tempos?), portanto, sinta-se à vontade para comentar se não entender alguma coisa (e também se entender).
1.Matrizes
Vectores
Antes que as matrizes venham vetores.Você certamente sabe como lidar com os vetores de 2 e 3 dimensões:
class Vector:
"""This will be a simple 2-dimensional vector.
In case you never encountered Python before, this string is a
comment I can put on the definition of the class or any function.
It's just one of many cool features of Python, so learn it here!
"""
def __init__(self, x, y):
self.x = x
self.y = y
agora você pode escrever
v = Vector(5, 3)
w = Vector(7, -1)
mas não é muito divertido por si só.Vamos adicionar métodos mais úteis:
def __str__(self: 'vector') -> 'readable form of vector':
return '({0}, {1})'.format(self.x, self.y)
def __add__(self:'vector', v: 'another vector') -> 'their sum':
return Vector(self.x + v.x, self.y + v.y)
def __mul__(self:'vector', number: 'a real number') -> 'vector':
'''Multiplies the vector by a number'''
return Vector(self.x * number, self.y * number)
Isso torna as coisas mais interessantes como podemos escrever agora:
print(v + w * 2)
e obter a resposta (19, 1)
bem impresso como um vetor (se os exemplos parecerem desconhecidos, pense em como esse código ficaria em C++).
Transformações
Agora é tudo legal poder escrever 1274 * w
mas você precisa de mais operações vetoriais para os gráficos.Aqui estão alguns deles:você pode inverter o vetor (0,0)
ponto, você pode refleti-lo em torno x
ou y
Eixo, você pode girá-lo no sentido horário ou anti-horário (é uma boa ideia desenhar uma imagem aqui).
Vamos fazer algumas operações simples:
...
def flip(self:'vector') -> 'vector flipped around 0':
return Vector(-self.x, -self.y)
def reflect_x(self:'vector') -> 'vector reflected around x axis':
return Vector(self.x, -self.y)
print(v.flip(), v.reflect_x())
- Pergunta: é possível expressar
flip(...)
usando as operações que eu tinha abaixo?Que talreflect_x
?
Agora você pode se perguntar Por Que Eu omiti reflect_y
.Bem, é porque quero que pares por um momento e escrevas a tua própria versão.Ok, aqui está o meu:
def reflect_y(self:'vector') -> 'vector reflected around y axis':
return self.flip().reflect_x()
Veja, se você olhar como esta função calcula, é realmente bastante trivial.Mas de repente uma coisa incrível aconteceu:Consegui escrever uma transformação usando apenas as transformações existentes flip
e reflect_x
.Por tudo o que me interessa, reflect_y
pode ser definido em uma classe derivada sem acesso a x
e y
e ainda funcionaria!
Os matemáticos chamariam essas funções operadores.Eles diriam que reflect_y
é um operador obtido por composição dos operadores flip
e reflect_x
que é
denotado por reflect_y = flip ○ reflect_x
(você deve ver o pequeno círculo, um símbolo Unicode 25CB
).
- Nota: Utilizarei livremente o
=
símbolo a partir de agora para indicar que duas operações produzem o mesmo resultado, como no parágrafo acima.Trata-se de uma " matemática=
", que não pode ser expresso como um programa.
Então, se eu fizer
print(v.reflect_y())
Eu recebo o resultado (-5, 3)
.Vá e imagine!
- Pergunta: Considere uma composição
reflect_y ◦ reflect_y
.Como o nomearia?
Rotações
Essas operações foram boas e úteis, mas provavelmente estão a perguntar-se porque é que demoramos a introduzir rotações.Ok, aqui vou eu:
def rotate(self:'vector', angle:'rotation angle') -> 'vector':
??????
Neste ponto, se souber rodar Vectores, deverá continuar a preencher os pontos de interrogação.Caso contrário, por favor, tenha paciência comigo para mais um caso simples:rotação no sentido anti-horário por 90
graus.Este não é difícil de desenhar num pedaço de papel:
def rotate_90(self:'vector') -> 'rotated vector':
new_x = - self.y
new_y = self.x
return Vector(new_x, new_y)
Tentando
x_axis = Vector(1, 0)
y_axis = Vector(0, 1)
print(x_axis.rotate_90(), y_axis.rotate_90())
agora dá (0, 1) (-1, 0)
.Execute você mesmo!
- Pergunta: Prove que
flip = rotate_90 ◦ rotate_90
.
De qualquer forma, não vou esconder o ingrediente secreto por mais tempo:
import math # we'll need math from now on
...
class Vector:
...
def rotate(self:'vector', angle:'rotation angle') -> 'rotated vector':
cos = math.cos(angle)
sin = math.sin(angle)
new_x = cos * self.x - sin * self.y
new_y = sin * self.x + cos * self.y
return Vector(new_x, new_y)
Agora vamos tentar algo ao longo das linhas:
print(x_axis.rotate(90), y_axis.rotate(90))
Se você espera o mesmo resultado de antes, (0, 1) (-1, 0)
, você está fadado a se decepcionar.Esse código imprime:
(-0.448073616129, 0.893996663601) (-0.893996663601, -0.448073616129)
e rapaz, é feio!
Notação: Direi que aplicámos a operação
rotate(90)
parax
no exemplo acima.O conhecimento que adquirimos é querotate(90) != rotate_90
.Pergunta: O que aconteceu aqui?Como expressar
rotate_90
em termos derotate
?Como expressarflip
em termos derotate
?
Dilatações
Essas rotações são certamente úteis, mas não são tudo o que você precisa fazer, mesmo os gráficos 2D.Considere as seguintes transformações:
def dilate(self:'vector', axe_x:'x dilation', axe_y:'y dilation'):
'''Dilates a vector along the x and y axes'''
new_x = axe_x * self.x
new_y = axe_y * self.y
return Vector(new_x, new_y)
Esta dilate
coisa dilata o x
e y
eixos de uma forma possivelmente diferente.
- Exercício: Preencha os pontos de interrogação em
dilate(?, ?) = flip
,dilate(?, ?) = reflect_x
.
Eu vou usar isso dilate
função para demonstrar uma coisa que os matemáticos chamam comutatividade:isto é, para cada valor de parâmetros a
, b
, c
, d
você pode ter certeza de que
dilate(a, b) ◦ dilate(c, d) = dilate(c, d) ◦ dilate(a, b)
Exercício: Prova-o.Além disso, é verdade que, para todos os valores possíveis de Parâmetros, os valores abaixo se manteriam?
rotate(a) ◦ rotate(b) = rotate(b) ◦ rotate(a)
dilate(a, b) ◦ rotate(c) = rotate(c) ◦ dilate(a, b)
rotate(a) ◦ __mul__(b) = __mul__(b) ◦ rotate(a)
Matrizes
Vamos resumir todas as coisas que tínhamos por aqui, a nossa operadores em vetor x
flip
,reflect_x
,*
,rotate(angle)
,dilate(x, y)
a partir do qual se poderia fazer algumas coisas realmente loucas como
flip ◦ rotate(angle) ◦ dilate(x, y) ◦ rotate(angle_2) ◦ reflect_y + reflect_x = ???
À medida que se criam expressões cada vez mais complicadas, espera-se algum tipo de ordem que reduza subitamente todas as expressões possíveis a uma forma útil.Não temas!Magicamente, cada expressão da forma acima pode ser simplificada para
def ???(self:'vector', parameters):
'''A magical representation of a crazy function'''
new_x = ? * self.x + ? * self.y
new_y = ? * self.x + ? * self.y
return Vector(new_x, new_y)
com alguns números e / ou parâmetros em vez de ?
s.
- Exemplo: Trabalhar para fora o que os valores de'?'são para
__mul__(2) ◦ rotate(pi/4)
- Outro exemplo: Mesma pergunta para
dilate(x, y) ◦ rotate(pi/4)
Isso nos permite escrever uma função universal
def transform(self:'vector', m:'matrix') -> 'new vector':
new_x = m[0] * self.x + m[1] * self.y
new_y = m[2] * self.x + m[3] * self.y
return Vector(new_x, new_y)
que levaria qualquer 4-tupla de números, chamado matriz, e aplicar para vector x
.Aqui está um exemplo:
rotation_90_matrix = (0, -1, 1, 0)
print(v, v.rotate_90(), v.transform(rotation_90_matrix))
que imprime (5, 3) (-3, 5) (-3, 5)
.Observe que, se você se inscrever transform
com
qualquer matriz de origem, você ainda obter origem:
origin = Vector(0, 0)
print(origin.transform(rotation_90_matrix))
- Exercício: quais são as tuplas
m
que descrevemflip
,dilate(x, y)
,rotate(angle)
?
À medida que nos separamos do Vector
aula, aqui está um exercício para aqueles que querem testar seus conhecimentos de matemática vetorial e habilidades Pitônicas:
- A batalha final: Adicionar ao
Vector
Classifique todas as operações vetoriais que você pode criar (quantos operadores padrão você pode sobrecarregar para vetores?Veja a minha resposta).
2.Matrizes:Sobrecarregado
Como descobrimos na seção anterior, uma matriz pode ser pensada como uma abreviação que nos permite codificar uma operação vetorial de maneira simples.Por exemplo, rotation_90_matrix
codifica a rotação em 90 graus.
Objectos matriciais
Agora, à medida que mudamos nossa atenção de vetores para matrizes, devemos, por todos os meios, ter uma classe
para matrix também.Além disso, nessa função Vector.transform(...)
acima do papel da matriz foi um pouco deturpado.É mais comum para m
para ser corrigido enquanto o vetor muda, então, a partir de Agora, nossas transformações serão métodos de classe de matriz:
class Matrix:
def __init__(self:'new matrix', m:'matrix data'):
'''Create a new matrix.
So far a matrix for us is just a 4-tuple, but the action
will get hotter once The (R)evolution happens!
'''
self.m = m
def __call__(self:'matrix', v:'vector'):
new_x = self.m[0] * v.x + self.m[1] * v.y
new_y = self.m[2] * v.x + self.m[3] * v.y
return Vector(new_x, new_y)
Se você não conhece Python, __call__
sobrecarrega o Significado de (...)
para matrizes para que eu possa usar a notação padrão para uma matriz acção em um vetor.Além disso, as matrizes são geralmente escritas usando uma única letra maiúscula:
J = Matrix(rotation_90_matrix)
print(w, 'rotated is', J(w))
- Exercício: repita este exemplo com matrizes do exercício anterior.
Aditamento
Agora, vamos descobrir o que mais podemos fazer com matrizes.Lembre-se que a matriz m
é realmente apenas uma maneira de codificar uma operação em vetores.Observe que para duas funções m1(x)
e m2(x)
Posso criar uma nova função (usando Notação lambda) m = lambda x: m1(x) + m2(x)
.Acontece que se m1
e m2
foram reunidas por matrizes, você também pode codificar isso m
utilização de matrizes!
- Exercício: Pense em quaisquer dificuldades que possa ter com esta afirmação.
Você só precisa adicionar seus dados, como (0, 1, -1, 0) + (0, 1, -1, 0) = (0, 2, -2, 0)
.Veja como adicionar duas tuplas em Python, com algumas técnicas muito úteis e altamente Pitônicas:
def __add__(self:'matrix', snd:'another matrix'):
"""This will add two matrix arguments.
snd is a standard notation for second argument.
(i for i in array) is Python's powerful list comprehension.
zip(a, b) is used to iterate over two sequences together
"""
new_m = tuple(i + j for i, j in zip(self.m, snd.m))
return Matrix(new_m)
Agora podemos escrever expressões como J + J
ou mesmo J + J + J
, mas para ver os resultados, temos que descobrir como imprimir uma matriz.Uma maneira possível seria imprimir uma tupla de 4 números, mas vamos dar uma dica do Matrix.__call__
função que os números devem ser organizados em um 2x2
bloco:
def as_block(self:'matrix') -> '2-line string':
"""Prints the matrix as a 2x2 block.
This function is a simple one without any advanced formatting.
Writing a better one is an exercise.
"""
return ('| {0} {1} |\n' .format(self.m[0], self.m[1]) +
'| {0} {1} |\n' .format(self.m[2], self.m[3]) )
Se você olhar para esta função em ação, notará que há algum espaço para melhorias:
print((J + J + J).as_block())
- Exercício: escreva uma função mais agradável
Matrix.__str__
que irá arredondar o números e imprimi-los nos campos de comprimento fixo.
Agora você deve ser capaz de escrever a matriz para rotação:
def R(a: 'angle') -> 'matrix of rotation by a':
cos = math.cos(a)
sin = math.sin(a)
m = ( ????? )
return Matrix(m)
Exercício: Examinar o código para
Vector.rotate(self, angle)
e preencha os pontos de interrogação.Ensaio comfrom math import pi print(R(pi/4) + R(-pi/4))
Multiplicação
A coisa mais importante que podemos fazer com funções de um parâmetro é compô-las: f = lambda v: f1(f2(v))
.Como espelhar isso com matrizes?Isso exige que examinemos como Matrix(m1) ( Matrix(m2) (v))
funciona.Se você expandi-lo, você notará que
m(v).x = m1[0] * (m2[0]*v.x + m2[1]*v.y) + m1[1] * (m2[2]*v.x + m2[3]*v.y)
e da mesma forma para m(v).y
, que, se você abrir os parênteses, parece suspeitamente semelhante
para Matrix.__call__
usando uma nova tupla m
, tal que m[0] = m1[0] * m2[0] + m1[2] * m2[2]
.Então, vamos tomar isso como uma dica para uma nova definição:
def compose(self:'matrix', snd:'another matrix'):
"""Returns a matrix that corresponds to composition of operators"""
new_m = (self.m[0] * snd.m[0] + self.m[1] * snd.m[2],
self.m[0] * snd.m[1] + self.m[1] * snd.m[3],
???,
???)
return Matrix(new_m)
Exercício: Preencha os pontos de interrogação aqui.Teste-o com
print(R(1).compose(R(2))) print(R(3))
Exercício de matemática: Prove que
R(a).compose(R(b))
é sempre o mesmo queR(a + b)
.
Agora deixe-me dizer a verdade:esta compose
função é, na verdade, como os matemáticos decidiram multiplicar matrizes.Isso faz sentido como uma notação: A * B
é uma matriz que descreve o operador A ○ B
, e como veremos a seguir, há razões mais profundas para chamar isso de 'multiplicação' também.
Para começar a usar a multiplicação em Python, tudo o que precisamos fazer é ordená-la em um Matrix
classe:
class Matrix:
...
__mul__ = compose
- Exercício: Computar
(R(pi/2) + R(pi)) * (R(-pi/2) + R(pi))
.Tente encontrar a resposta primeiro em um pedaço de papel.
Regras para +
e *
Vamos fazer um bom nome para a matriz que corresponde ao dilate(a, b)
operador.Agora não há nada de errado com D(a, b)
, mas eu vou
use uma chance para introduzir uma notação padrão:
def diag(a: 'number', b: 'number') -> 'diagonal 2x2 matrix':
m = (a, 0, 0, b)
return Matrix(m)
Tente print(diag(2, 12345))
para ver por que é chamado a diagonal matrix.
Uma vez que a composição das operações não era sempre comutativa, *
o operador também não será sempre comutativo para matrizes.
- Exercício: volte e refresque o comutatividade coisa, se necessário.Em seguida, dê exemplos de matrizes
A
,B
, feito deR
ediag
, tal queA * B
não é igual aB * A
.
Isso é um tanto estranho, uma vez que a multiplicação por números é sempre comutativa e levanta a questão de saber se compose
realmente merece ser chamado __mul__
.Aqui estão muitas regras que +
e *
fazer satisfazer:
A + B = B + A
A * (B + C) = A * B + A * C
(A + B) * C = A * C + B * C
(A * B) * C = A * (B * C)
Existe uma operação chamada
A - B
e(A - B) + B = A
- Exercício: Prove essas declarações.Como definir
A - B
em termos de+
,*
ediag
?O que fazA - A
igual a?Adicione o método__sub__
para a classeMatrix
.O que acontece se você calcularR(2) - R(1)*R(1)
?A que deveria ser igual?
- Exercício: Prove essas declarações.Como definir
O (A * B) * C = A * (B * C)
igualdade é chamada associatividade e é especialmente bom, pois significa que não precisamos nos preocupar em colocar parênteses em uma expressão
do formulário A * B * C
:
print(R(1) * (diag(2,3) * R(2)))
print((R(1) * diag(2,3)) * R(2))
Vamos encontrar análogos aos números regulares 0
e 1
e subtração:
zero = diag(0, 0)
one = diag(1, 1)
Com as seguintes adições facilmente verificáveis:
A + zero = A
A * zero = zero
A * one = one * A = A
as regras tornam-se completas, no sentido de que há um nome curto para elas: axiomas em anel.Os matemáticos, portanto, diriam que as matrizes formam um anel, e eles de fato sempre usam símbolos +
e *
quando falamos de anéis, e nós também.
Usando as regras, é possível calcular facilmente a expressão da seção anterior:
(R(pi/2) + R(pi)) * (R(-pi/2) + R(pi)) = R(pi/2) * R(-pi/2) + ... = one + ...
- Exercício: Acaba com isto.Prove que
(R(a) + R(b)) * (R(a) - R(b)) = R(2a) - R(2b)
.
Transformações Afins
Tempo para voltar à forma como definimos as matrizes:eles são um atalho para algumas operações que você pode fazer com vetores, então é algo que você pode realmente desenhar.Você pode querer pegar uma caneta ou olhar para os materiais que outros sugeriram para ver exemplos de diferentes transformações planas.
Entre as transformações, procuraremos o afim uns, aqueles que parecem 'iguais' em todos os lugares (sem flexão).Por exemplo, uma rotação em torno de algum ponto (x, y)
qualifica.Ora, esta não pode ser expressa como lambda v: A(v)
, mas em Pode ser escrito na forma lambda v: A(v) + b
para alguma matriz A
e vector b
.
- Exercício: encontre o
A
eb
tal que uma rotação porpi/2
em torno do ponto(1, 0)
tem a forma acima.São únicos?
Note - se que para cada vetor existe uma transformação afim que é um mudança pelo vetor.
Uma transformação afim pode esticar ou dilatar formas, mas deve fazer o mesmo em todos os lugares.Agora, espero que acreditem que a área de qualquer figura muda por um número constante sob a transformação.Para uma transformação dada pela matriz A
este coeficiente é denominado determinante de A
e pode ser calculado aplicando a fórmula para uma área a dois vetores A(x_axis)
e A(y_axis)
:
def det(self: 'matrix') -> 'determinant of a matrix':
return self.m[0]*self.m[3] - self.m[1] * self.m[2]
Como uma verificação de sanidade, diag(a, b).det()
é igual a a * b
.
- Exercício: Verifica isto.O que acontece quando um dos argumentos é 0?Quando é negativo?
Como você pode ver, o determinante da matriz de rotação é sempre o mesmo:
from random import random
r = R(random())
print (r, 'det =', r.det())
Uma coisa interessante sobre det
é que é multiplicativo (meio que segue da definição se você meditar por tempo suficiente):
A = Matrix((1, 2, -3, 0))
B = Matrix((4, 1, 1, 2))
print(A.det(), '*', B.det(), 'should be', (A * B).det())
Inverso
Uma coisa útil que você pode fazer com matrizes é escrever um sistema de duas equações lineares
A.m[0]*v.x + A.m[1]*v.y = b.x
A.m[2]*v.x + A.m[3]*v.y = b.y
de uma forma mais simples: A(v) = b
.Vamos resolver o sistema enquanto ensinam em (algumas) escolas secundárias:multiplique a primeira equação por A.m[3]
, segundo por-A. m1 e adicione (em caso de dúvida, faça isso em um pedaço de papel) para resolver v.x
.
Se você realmente tentou, você deveria ter A.det() * v.x = (A.m[3]) * b.x + (-A.m[1]) * b.y
, o que sugere que você sempre pode obter v
multiplicando b
por alguma outra matriz.Esta matriz é chamada inverso de A
:
def inv(self: 'matrix') -> 'inverse matrix':
'''This function returns an inverse matrix when it exists,
or raises ZeroDivisionError when it doesn't.
'''
new_m = ( self.m[3] / self.det(), -self.m[1] / self.det(),
????? )
return Matrix(new_m)
Como você vê, este método falha alto quando determinante da matriz é zero.Se você realmente quiser, pode pegar essa expectativa com:
try:
print(zero.inv())
except ZeroDivisionError as e: ...
- Exercício: Termine o método.Prove que a matriz inversa não existe quando
self.det() == 0
.Escreva o método para dividir matrizes e testá-lo.Use a matriz inversa para resolver uma equaçãoA(v) = x_axis
(A
foi definido acima).
Poderes
A principal propriedade da matriz inversa é que A * A.inv()
sempre igual a one
- Exercício: verifique você mesmo.Explique por que isso deveria ser assim a partir da definição de matriz inversa.
É por isso que os matemáticos denotam A.inv()
por A
-1.Que tal escrevermos um
boa função para usar A ** n
notação para A
n?Note - se que o ingênuo for i in range(n): answer *= self
o ciclo é O (|n/) que é certamente demasiado lento, porque
isso pode ser feito com uma complexidade de log |n|
:
def __pow__(self: 'matrix', n:'integer') -> 'n-th power':
'''This function returns n-th power of the matrix.
It does it more efficiently than a simple for cycle. A
while loop goes over all bits of n, multiplying answer
by self ** (2 ** k) whenever it encounters a set bit.
...
Exercício: Preencha os detalhes nesta função.Teste-o com
X, Y = A ** 5, A ** -5
print (X, Y, X * Y, sep = '\n')
Esta função só funciona para valores inteiros de n
, embora para algumas matrizes também possamos definir uma potência fracionária, como raiz quadrada (em outras palavras, uma matriz B
tal que B * B = A
).
- Exercício: Encontre uma raiz quadrada de
diag(-1, -1)
.Será esta a única resposta possível?Encontre um exemplo de matriz que não tem uma raiz quadrada.
Bónus:Números complexos
Aqui vou apresentar-vos o assunto exactamente numa secção!Uma vez que é um assunto complexo, é provável que eu falhe, por isso, por favor, perdoe-me antecipadamente.
Primeiro, da mesma forma que temos matrizes zero
e one
, podemos fazer uma matriz de qualquer número real fazendo diag(number, number)
.As matrizes dessa forma podem ser somadas, subtraídas, multiplicadas, invertidas e os resultados imitam o que acontece com os próprios números.Assim, para todos os efeitos práticos, pode-se dizer que, por exemplo., diag(5, 5)
é 5.
No entanto, Python ainda não sabe como lidar com expressões do formulário A + 1
ou 5 * B
onde A
e B
são matrizes.Se você estiver interessado, você deve por todos os meios ir e fazer o seguinte exercício ou olhar para a minha implementação (que usa um recurso Python legal chamado decorador);caso contrário, apenas saiba que foi implementado.
- Exercício para gurus: Alterar os operadores em um
Matrix
classe de modo que em todas as operações padrão em que um dos operandos é uma matriz e outro um número, o número é automaticamente convertido para odiag
matrix.Adicione também comparação para igualdade.
Aqui está um exemplo de teste:
print( 3 * A - B / 2 + 5 )
Agora aqui está o primeiro interessante número complexo:a matriz J
, introduzido no início e igual a Matrix((0, 1, -1, 0))
, tem uma propriedade engraçada que J * J == -1
(experimente!).Isso significa J
não é certamente um número normal, mas, como acabei de dizer, matrizes e números misturam-se facilmente.Por exemplo,
(1 + J) * (2 + J) == 2 + 2 * J + 1 * J + J * J = 1 + 3 * J
utilizar as regras enumeradas há algum tempo.O que acontece se testarmos isso em Python?
(1 + J) * (2 + J) == 1 + 3*J
Isso deve dizer alegremente True
.Outro exemplo:
(3 + 4*J) / (1 - 2*J) == -1 + 2*J
Como você deve ter adivinhado, os matemáticos não chamam esses 'números loucos', mas eles fazem algo semelhante-Eles chamam expressões da forma a + b*J
números complexos.Porque esses ainda são exemplos de nossa Matrix
classe, podemos fazer muitas operações com aqueles:adição, subtração, multiplicação, divisão, potência - tudo já está implementado!As matrizes não são incríveis?
Esqueci a questão de como imprimir o resultado de uma operação como E = (1 + 2*J) * (1 + 3*J)
para que pareça uma expressão com J
em vez de um 2x2
matrix.Se o examinar cuidadosamente,
você verá que precisa imprimir a coluna da esquerda dessa matriz no formato ... + ...J
(Só mais uma coisa boa:é exactamente E(x_axis)
!) Aqueles que sabem a diferença entre str()
e repr()
deve ver que é natural nomear uma função que produziria expressão de tal forma como repr()
.
Exercício: Escreva a função
Matrix.__repr__
isso faria exatamente isso e tentaria alguns testes com ele, como(1 + J) ** 3
, primeiro computando o resultado no papel e depois tentando com Python.Questão matemática: Qual é o determinante de
a + b*J
?Se você sabe o que valor absoluto do número complexo é:como eles estão conectados?Qual é o valor absoluto dea
?dea*J
?
3.Matrizes:A (R)evolução
Na parte final desta trilogia, veremos que tudo é uma matriz.Vamos começar pelo general M x N
matrizes, e descobrir como os vetores podem ser pensados como 1 x N
matrizes e por que os números são iguais às matrizes diagonais.Como uma nota lateral, exploraremos os números complexos como 2 x 2
matrizes.
Finalmente, aprenderemos a escrever transformações afins e projetivas usando matrizes.
As aulas previstas são [MNMatrix, NVector, Affine, Projective]
.
Eu acho que se você foi capaz de suportar comigo até aqui, você poderia estar interessado nesta sequela, então eu gostaria de ouvir se eu deveria continuar com isso (e onde, já que tenho certeza de que estou além do que considerou razoável comprimento de um único documento).
Outras dicas
MIT tem um monte de materiais de seus cursos de matemática on-line em http://ocw.mit.edu / OcwWeb / Matemática / . Depois de ter o básico para baixo, eles têm as notas de física on-line também.
http://en.wikipedia.org/wiki/Computer_graphics . dois dos principais conceitos são http://mathworld.wolfram.com/LinearTransformation.html , e http://mathworld.wolfram.com/AffineTransformation.html .
Este documento MIT é um must-have para obter conhecimento forte sobre os conceitos básicos de Transformação.
Um dos melhores livros para iniciantes é Carl Meyer de "Matriz de Análise e Aplicada Álgebra Linear".
Você pode visualizar todo o livro on-line aqui (embora tenha uma marca d'água de direitos autorais): http://www.matrixanalysis.com/DownloadChapters.html
Você pode querer dar uma olhada em Capítulo 5 pg. 326-332, que abrange as rotações em 3 dimensões computação gráfica
Você pode querer olhar para geométrica linear álgebra por I-Hsiung Lin, Yixiong Lin (ISBN: 9812560874). O livro é especificamente voltada para o que você quer (linear transformações de espaços vetoriais 2 e 3 dimensões) e trata-o com uma abordagem geométrica na íntegra, detalhe progressiva (300 páginas para cada dimensão). Eu tenho medo que não é livre para comprar, mas você deve ser capaz de encontrá-lo em qualquer boa biblioteca universitária. Caso contrário Bookfinder deve ajudá-lo a obtê-lo a um preço relativamente modesto.
O Jim Hefferon livre Álgebra Linear livro é realmente bom. Ao contrário de muitos ebooks gratuitos, Jim tem claramente tomado a tempo para elaborar um excelente leitor e introdução à álgebra linear. Não é excessivamente sobrecarregados com escrita matemática formal, que é muitas vezes demasiado denso, com teoremas e provas para ser facilmente compreensível. Ele também contém vários realmente excelentes exemplos de aplicações do mundo real da álgebra linear - transformações de coordenadas sendo apenas um exemplo. Você não pode bater o preço, e ele também vem com soluções opcionais para os exercícios.
P.S. Se transformações de coordenadas são sua coisa, você pode estar interessado em geometria diferencial depois que você fez com a álgebra linear.
Essas são as informações que eu encontrei. Alguns deles podem ser valiosas para você:
Teoria:
- Woflrams informação sobre matrizes e os adicionais sobre Wikipedia
- Matrizes por Pam Norton -. muito bom livro, disponível no Google Books gratuitamente
- projeções ortográficas e perspectiva
- 3D transformações no MSDN
(Buscando "Matrizes" em livros do Google lhe dá muita lecutures, alguns dos quais estão diretamente relacionados com transformações - este é um dos primeiros resultados, mas eu animá-lo para verificar mais.)
- esta , ou talvez este ou este são facilmente encontrados com a ajuda do Google, por isso não vou postar mais.
- Havia também algumas perguntas sobre matrizes no StackOverflow.com: Usando matrizes de transformação 3d Como aplicar uma matriz de transformação? são apenas alguns exemplos primeira, você pode encontrar mais procurando o matriz ou matemática etiquetas.
Eu também incentivar (Eu não sei se esta é a palavra certa, estou apenas aprendendo Inglês) Você, a olhar para este tipo de informação em um desses livros (embora eles não são livres, mas você pode encontrar grandes partes mais velhos no Google Livros):
- Jogo gemas de programação 7
- Jogo gemas de programação 6
- Jogo gemas de programação 5
- Jogo gemas de programação 4
- Jogo gemas de programação 3
- Jogo gemas de programação 2
- Jogo gemas programação
Cada um desses tem seção sobre gemas de matemática - e existem muitos truques lá. Esses livros valem cada centavo.
Há também gemas GPU programação, assim você pode experimentá-los também.
Práticas:
- OpenGl Livro a Wikipedia tem seção sobre matrizes em OpenGL (Também, utilizando matrizes em OpenGl é descrito aqui e aqui )
- sala de desenho 3D em DirectX + info sobre transformações de matriz.
Se eu vou encontrar mais, vou editar e adicionar links aqui, mas para ser honesto - eu encontrei aquelas ligações em cerca de 10 minutos de usar o Google. a maioria do mundo populares navegador armazena dados sobre tudo - e sim, matrizes "tudo" significa muito.
Cheers, Mate.
Eu acho que você deve passar alguns dias fazendo produtos de ponto e produtos cruzados com vetores em 3D. Então aprenda a relação entre trig e vetores. Depois que as matrizes fará muito mais sentido para você.
O curso de MIT-OCW em Álgebra Linear por Gilbert Strang. palestras incríveis por um homem incrível; se o seu entendimento de matrizes é exclusivamente derivado de fontes (como MATLAB) Programação em seguida, um curso de Álgebra Linear vai certamente dar-lhe os fundamentos de fazer coisas loucas com matrizes.
http://www.ocw.cn /OcwWeb/Mathematics/18-06Spring-2005/VideoLectures/index.htm