图片解析应用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.7 KiB

  1. '''Functions returning normal forms of matrices'''
  2. from sympy.polys.domains.integerring import ZZ
  3. from sympy.polys.polytools import Poly
  4. from sympy.polys.matrices import DomainMatrix
  5. from sympy.polys.matrices.normalforms import (
  6. smith_normal_form as _snf,
  7. invariant_factors as _invf,
  8. hermite_normal_form as _hnf,
  9. )
  10. def _to_domain(m, domain=None):
  11. """Convert Matrix to DomainMatrix"""
  12. # XXX: deprecated support for RawMatrix:
  13. ring = getattr(m, "ring", None)
  14. m = m.applyfunc(lambda e: e.as_expr() if isinstance(e, Poly) else e)
  15. dM = DomainMatrix.from_Matrix(m)
  16. domain = domain or ring
  17. if domain is not None:
  18. dM = dM.convert_to(domain)
  19. return dM
  20. def smith_normal_form(m, domain=None):
  21. '''
  22. Return the Smith Normal Form of a matrix `m` over the ring `domain`.
  23. This will only work if the ring is a principal ideal domain.
  24. Examples
  25. ========
  26. >>> from sympy import Matrix, ZZ
  27. >>> from sympy.matrices.normalforms import smith_normal_form
  28. >>> m = Matrix([[12, 6, 4], [3, 9, 6], [2, 16, 14]])
  29. >>> print(smith_normal_form(m, domain=ZZ))
  30. Matrix([[1, 0, 0], [0, 10, 0], [0, 0, -30]])
  31. '''
  32. dM = _to_domain(m, domain)
  33. return _snf(dM).to_Matrix()
  34. def invariant_factors(m, domain=None):
  35. '''
  36. Return the tuple of abelian invariants for a matrix `m`
  37. (as in the Smith-Normal form)
  38. References
  39. ==========
  40. .. [1] https://en.wikipedia.org/wiki/Smith_normal_form#Algorithm
  41. .. [2] http://sierra.nmsu.edu/morandi/notes/SmithNormalForm.pdf
  42. '''
  43. dM = _to_domain(m, domain)
  44. factors = _invf(dM)
  45. factors = tuple(dM.domain.to_sympy(f) for f in factors)
  46. # XXX: deprecated.
  47. if hasattr(m, "ring"):
  48. if m.ring.is_PolynomialRing:
  49. K = m.ring
  50. to_poly = lambda f: Poly(f, K.symbols, domain=K.domain)
  51. factors = tuple(to_poly(f) for f in factors)
  52. return factors
  53. def hermite_normal_form(A, *, D=None, check_rank=False):
  54. r"""
  55. Compute the Hermite Normal Form of a Matrix *A* of integers.
  56. Examples
  57. ========
  58. >>> from sympy import Matrix
  59. >>> from sympy.matrices.normalforms import hermite_normal_form
  60. >>> m = Matrix([[12, 6, 4], [3, 9, 6], [2, 16, 14]])
  61. >>> print(hermite_normal_form(m))
  62. Matrix([[10, 0, 2], [0, 15, 3], [0, 0, 2]])
  63. Parameters
  64. ==========
  65. A : $m \times n$ ``Matrix`` of integers.
  66. D : int, optional
  67. Let $W$ be the HNF of *A*. If known in advance, a positive integer *D*
  68. being any multiple of $\det(W)$ may be provided. In this case, if *A*
  69. also has rank $m$, then we may use an alternative algorithm that works
  70. mod *D* in order to prevent coefficient explosion.
  71. check_rank : boolean, optional (default=False)
  72. The basic assumption is that, if you pass a value for *D*, then
  73. you already believe that *A* has rank $m$, so we do not waste time
  74. checking it for you. If you do want this to be checked (and the
  75. ordinary, non-modulo *D* algorithm to be used if the check fails), then
  76. set *check_rank* to ``True``.
  77. Returns
  78. =======
  79. ``Matrix``
  80. The HNF of matrix *A*.
  81. Raises
  82. ======
  83. DMDomainError
  84. If the domain of the matrix is not :ref:`ZZ`.
  85. DMShapeError
  86. If the mod *D* algorithm is used but the matrix has more rows than
  87. columns.
  88. References
  89. ==========
  90. .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.*
  91. (See Algorithms 2.4.5 and 2.4.8.)
  92. """
  93. # Accept any of Python int, SymPy Integer, and ZZ itself:
  94. if D is not None and not ZZ.of_type(D):
  95. D = ZZ(int(D))
  96. return _hnf(A._rep, D=D, check_rank=check_rank).to_Matrix()