matrixcache.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. """A cache for storing small matrices in multiple formats."""
  2. from sympy.core.numbers import (I, Rational, pi)
  3. from sympy.core.power import Pow
  4. from sympy.functions.elementary.exponential import exp
  5. from sympy.matrices.dense import Matrix
  6. from sympy.physics.quantum.matrixutils import (
  7. to_sympy, to_numpy, to_scipy_sparse
  8. )
  9. class MatrixCache:
  10. """A cache for small matrices in different formats.
  11. This class takes small matrices in the standard ``sympy.Matrix`` format,
  12. and then converts these to both ``numpy.matrix`` and
  13. ``scipy.sparse.csr_matrix`` matrices. These matrices are then stored for
  14. future recovery.
  15. """
  16. def __init__(self, dtype='complex'):
  17. self._cache = {}
  18. self.dtype = dtype
  19. def cache_matrix(self, name, m):
  20. """Cache a matrix by its name.
  21. Parameters
  22. ----------
  23. name : str
  24. A descriptive name for the matrix, like "identity2".
  25. m : list of lists
  26. The raw matrix data as a SymPy Matrix.
  27. """
  28. try:
  29. self._sympy_matrix(name, m)
  30. except ImportError:
  31. pass
  32. try:
  33. self._numpy_matrix(name, m)
  34. except ImportError:
  35. pass
  36. try:
  37. self._scipy_sparse_matrix(name, m)
  38. except ImportError:
  39. pass
  40. def get_matrix(self, name, format):
  41. """Get a cached matrix by name and format.
  42. Parameters
  43. ----------
  44. name : str
  45. A descriptive name for the matrix, like "identity2".
  46. format : str
  47. The format desired ('sympy', 'numpy', 'scipy.sparse')
  48. """
  49. m = self._cache.get((name, format))
  50. if m is not None:
  51. return m
  52. raise NotImplementedError(
  53. 'Matrix with name %s and format %s is not available.' %
  54. (name, format)
  55. )
  56. def _store_matrix(self, name, format, m):
  57. self._cache[(name, format)] = m
  58. def _sympy_matrix(self, name, m):
  59. self._store_matrix(name, 'sympy', to_sympy(m))
  60. def _numpy_matrix(self, name, m):
  61. m = to_numpy(m, dtype=self.dtype)
  62. self._store_matrix(name, 'numpy', m)
  63. def _scipy_sparse_matrix(self, name, m):
  64. # TODO: explore different sparse formats. But sparse.kron will use
  65. # coo in most cases, so we use that here.
  66. m = to_scipy_sparse(m, dtype=self.dtype)
  67. self._store_matrix(name, 'scipy.sparse', m)
  68. sqrt2_inv = Pow(2, Rational(-1, 2), evaluate=False)
  69. # Save the common matrices that we will need
  70. matrix_cache = MatrixCache()
  71. matrix_cache.cache_matrix('eye2', Matrix([[1, 0], [0, 1]]))
  72. matrix_cache.cache_matrix('op11', Matrix([[0, 0], [0, 1]])) # |1><1|
  73. matrix_cache.cache_matrix('op00', Matrix([[1, 0], [0, 0]])) # |0><0|
  74. matrix_cache.cache_matrix('op10', Matrix([[0, 0], [1, 0]])) # |1><0|
  75. matrix_cache.cache_matrix('op01', Matrix([[0, 1], [0, 0]])) # |0><1|
  76. matrix_cache.cache_matrix('X', Matrix([[0, 1], [1, 0]]))
  77. matrix_cache.cache_matrix('Y', Matrix([[0, -I], [I, 0]]))
  78. matrix_cache.cache_matrix('Z', Matrix([[1, 0], [0, -1]]))
  79. matrix_cache.cache_matrix('S', Matrix([[1, 0], [0, I]]))
  80. matrix_cache.cache_matrix('T', Matrix([[1, 0], [0, exp(I*pi/4)]]))
  81. matrix_cache.cache_matrix('H', sqrt2_inv*Matrix([[1, 1], [1, -1]]))
  82. matrix_cache.cache_matrix('Hsqrt2', Matrix([[1, 1], [1, -1]]))
  83. matrix_cache.cache_matrix(
  84. 'SWAP', Matrix([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]))
  85. matrix_cache.cache_matrix('ZX', sqrt2_inv*Matrix([[1, 1], [1, -1]]))
  86. matrix_cache.cache_matrix('ZY', Matrix([[I, 0], [0, -I]]))