eigen.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. """
  2. Routines for computing eigenvectors with DomainMatrix.
  3. """
  4. from sympy.core.symbol import Dummy
  5. from ..agca.extensions import FiniteExtension
  6. from ..factortools import dup_factor_list
  7. from ..polyroots import roots
  8. from ..polytools import Poly
  9. from ..rootoftools import CRootOf
  10. from .domainmatrix import DomainMatrix
  11. def dom_eigenvects(A, l=Dummy('lambda')):
  12. charpoly = A.charpoly()
  13. rows, cols = A.shape
  14. domain = A.domain
  15. _, factors = dup_factor_list(charpoly, domain)
  16. rational_eigenvects = []
  17. algebraic_eigenvects = []
  18. for base, exp in factors:
  19. if len(base) == 2:
  20. field = domain
  21. eigenval = -base[1] / base[0]
  22. EE_items = [
  23. [eigenval if i == j else field.zero for j in range(cols)]
  24. for i in range(rows)]
  25. EE = DomainMatrix(EE_items, (rows, cols), field)
  26. basis = (A - EE).nullspace()
  27. rational_eigenvects.append((field, eigenval, exp, basis))
  28. else:
  29. minpoly = Poly.from_list(base, l, domain=domain)
  30. field = FiniteExtension(minpoly)
  31. eigenval = field(l)
  32. AA_items = [
  33. [Poly.from_list([item], l, domain=domain).rep for item in row]
  34. for row in A.rep.to_ddm()]
  35. AA_items = [[field(item) for item in row] for row in AA_items]
  36. AA = DomainMatrix(AA_items, (rows, cols), field)
  37. EE_items = [
  38. [eigenval if i == j else field.zero for j in range(cols)]
  39. for i in range(rows)]
  40. EE = DomainMatrix(EE_items, (rows, cols), field)
  41. basis = (AA - EE).nullspace()
  42. algebraic_eigenvects.append((field, minpoly, exp, basis))
  43. return rational_eigenvects, algebraic_eigenvects
  44. def dom_eigenvects_to_sympy(
  45. rational_eigenvects, algebraic_eigenvects,
  46. Matrix, **kwargs
  47. ):
  48. result = []
  49. for field, eigenvalue, multiplicity, eigenvects in rational_eigenvects:
  50. eigenvects = eigenvects.rep.to_ddm()
  51. eigenvalue = field.to_sympy(eigenvalue)
  52. new_eigenvects = [
  53. Matrix([field.to_sympy(x) for x in vect])
  54. for vect in eigenvects]
  55. result.append((eigenvalue, multiplicity, new_eigenvects))
  56. for field, minpoly, multiplicity, eigenvects in algebraic_eigenvects:
  57. eigenvects = eigenvects.rep.to_ddm()
  58. l = minpoly.gens[0]
  59. eigenvects = [[field.to_sympy(x) for x in vect] for vect in eigenvects]
  60. degree = minpoly.degree()
  61. minpoly = minpoly.as_expr()
  62. eigenvals = roots(minpoly, l, **kwargs)
  63. if len(eigenvals) != degree:
  64. eigenvals = [CRootOf(minpoly, l, idx) for idx in range(degree)]
  65. for eigenvalue in eigenvals:
  66. new_eigenvects = [
  67. Matrix([x.subs(l, eigenvalue) for x in vect])
  68. for vect in eigenvects]
  69. result.append((eigenvalue, multiplicity, new_eigenvects))
  70. return result