Simetricamente matriz adressable
-
07-07-2019 - |
Pergunta
Eu estou olhando para criar uma matriz 2-D de inteiros com simétrica endereçamento (isto é, matriz [2,3] e a matriz [3,2] irá devolver o mesmo valor) no pitão. Os inteiros terá adição e subtração feito sobre eles, e ser usadas para comparações lógicas. Minha idéia inicial era criar o inteiro objetos na frente e tentar preencher uma lista de listas com alguns python equivalente de ponteiros. Eu não tenho certeza de como fazê-lo, no entanto. Qual é a melhor maneira de implementar isso, e eu deveria estar usando listas ou outra estrutura de dados?
Solução
A maneira mais simples e mais limpa é usar apenas um dicionário com tuplas ordenadas como chaves. As tuplas corresponder com o seu índice de matriz. __getitem__
Override e __setitem__
para acessar o dicionário por tuplas ordenadas; aqui está uma classe de exemplo:
class Matrix(dict):
def __getitem__(self, index):
return super(Matrix, self).__getitem__(tuple(sorted(index)))
def __setitem__(self, index, value):
return super(Matrix, self).__setitem__(tuple(sorted(index)), value)
E, em seguida, usá-lo como este:
>>> matrix = Matrix()
>>> matrix[2,3] = 1066
>>> print matrix
{(2, 3): 1066}
>>> matrix[2,3]
1066
>>> matrix[3,2]
1066
>>> matrix[1,1]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "z.py", line 3, in __getitem__
return super(Matrix, self).__getitem__(tuple(sorted(index)))
KeyError: (1, 1)
Outras dicas
Golub e Van Loan de "Matrix Computations" livro descreve um esquema de endereçamento viável:
Você arruma os dados em um vetor e acesso da seguinte forma, assumindo i> = j:
a_ij = A.vec((j-1)n - j(j-1)/2 + i)
Você é provavelmente melhor fora de usar uma matriz numpy praça cheia. Sim, desperdiça metade da memória que armazena valores redundantes, mas rolando sua própria matriz simétrica em Python vai perder ainda mais memória e CPU por armazenar e processar os inteiros como objetos Python.
Você só precisa armazenar o triângulo inferior da matriz. Tipicamente, isto é feito com um n (n + 1) / 2 lista comprimento. Você vai precisar sobrecarregar o método __getitem__
para interpretar o que os meios de entrada.