segunda-feira, 16 de novembro de 2009

Matrizes

Todos temos ideia do que são matrizes e das diversas operações que com elas podemos fazer. Existem em Python módulos que nos permitem manipular de forma eficiente matrizes, como por exemplo Numpy and SciPy. Também o pacote Matplotlib, e o módulo nele integrado pylab, permitem efectuar operações com matrizes. Mas, admitamos que não temos e que necessitamos de definir uma representação para matrizes e implementar as operações básicas. O modo mais correcto de o fazer seria definir um novo tipo de dados e implementá-lo como uma classe. Mas isso remete-nos para a programação orientada aos objectos, território ainda por nós não explorado. Vamos então caçar com gato.


Uma matriz vai ser representada como uma lista de listas. Cada elemento será uma linha da matriz. A partir desta decisão, as implementações das operações elementares decorrem naturalmente:


def addMatrix(A,B):
""" Soma duas matrizes."""
sizeL=len(A)
sizeC=len(A[0])
C=nullMatrix(sizeL,sizeC)
# Soma
for i in range(sizeL):
for j in range(sizeC):
C[i][j]=A[i][j]+B[i][j]
return C

def prodMatrix(A,B):
"""Multiplica duas matrizes."""
sizeL=len(A)
sizeC=len(A[0])
C=nullMatrix(sizeL,sizeC)
# Multiplica
for i in range(sizeL):
for j in range(sizeC):
val=0
for k in range(len(B)):
val = val + A[i][k]*B[k][j]
C[i][j]=val
return C

def transposeMatrix(M):
"""Calcula a transposta de uma matriz."""
aux=[]
for j in range(len(M[0])):
linha=[]
for i in range(len(M)):
linha.append(M[i][j])
aux.append(linha)
return aux

Como se nota estas operações têm todas uma forma semelhante, envolvendo um ciclo dentro de outro ciclo, isso mesmo consequência da representação escolhida. Para testar estas operações podemos definir operações auxiliares:

import random

def cria_matriz(lin,col):
A=[]
for i in range(lin):
linha=[]
for j in range(col):
linha = linha + [random.randint(1,10)]
A= A + [linha]
return A

def mostra_matriz(matriz):
print 'Matriz'
for i in range(len(matriz)):
for j in range(len(matriz[0])):
print matriz[i][j],'\t',
print
print '_' * 10

E pronto. Divirta-se!

9 comentários:

  1. Lembrando que essa transposta só funciona com matriz quadrada.

    ResponderEliminar
    Respostas
    1. Caro Guilherme,

      Não é verdade o que diz. Por definição qualquer matriz, quadrada ou não, tem uma transposta: a coluna i passa a linha i. O programa acima faz isso mesmo.
      Já agora apresento-lhe uma versão mais pitónica para o mesmo problema.

      def transposta_b(mat):
      """Transposta de uma matriz."""
      return [list(linha) for linha in zip(*mat)]

      Boas programaçaões.
      EC

      Eliminar
  2. Ajuda bastante para fazer programas mais complexos cujos passos supracitados são a base. Muito útil! Obrigado.

    ResponderEliminar
  3. como que eu encontro o determinante de uma matriz ?

    ResponderEliminar
  4. como que eu posso encontrar o determinante de uma matriz ?

    ResponderEliminar
  5. O determinante de uma matriz depende da dimensão da matriz. tirando o caso n=1 que é trivial, os casos n=2 e n=3 têm umas fórmulas simples. Por exemplo, para uma matriz 2X2 temos det(m) = a11*a22 - a21*a12. Para n>3 usa-se um processo de redução mais complexo. Se fizer uma consulta na Wikipédia encontrará as fórmulas. Em Python a forma mais simples de calcular o determinante é usar o método det do módulo linalg do Numpy: numpy.linalg.det(M).

    ResponderEliminar
  6. uma função tão simples e tão usada (somar matrizes) e é preciso escrever toda uma rotina para o python fazer isto...

    ResponderEliminar
  7. É verdade o que diz e eu também o disse. Acontece que este é um blogue de suporte a uma cadeira de introdução à programação e por isso nos ficamos pelos conceitos básicos. Neste caso a ideia de usar dois ciclos para estruturas bi-dimensionais. Mas está à vontade para enviar outra solução mais simples.

    ResponderEliminar