backend.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import os
  2. USE_SYMENGINE = os.getenv('USE_SYMENGINE', '0')
  3. USE_SYMENGINE = USE_SYMENGINE.lower() in ('1', 't', 'true') # type: ignore
  4. if USE_SYMENGINE:
  5. from symengine import (Symbol, Integer, sympify as sympify_symengine, S,
  6. SympifyError, exp, log, gamma, sqrt, I, E, pi, Matrix,
  7. sin, cos, tan, cot, csc, sec, asin, acos, atan, acot, acsc, asec,
  8. sinh, cosh, tanh, coth, asinh, acosh, atanh, acoth,
  9. lambdify, symarray, diff, zeros, eye, diag, ones,
  10. expand, Function, symbols, var, Add, Mul, Derivative,
  11. ImmutableMatrix, MatrixBase, Rational, Basic)
  12. from symengine.lib.symengine_wrapper import gcd as igcd
  13. from symengine import AppliedUndef
  14. def sympify(a, *, strict=False):
  15. """
  16. Notes
  17. =====
  18. SymEngine's ``sympify`` does not accept keyword arguments and is
  19. therefore not compatible with SymPy's ``sympify`` with ``strict=True``
  20. (which ensures that only the types for which an explicit conversion has
  21. been defined are converted). This wrapper adds an additional parameter
  22. ``strict`` (with default ``False``) that will raise a ``SympifyError``
  23. if ``strict=True`` and the argument passed to the parameter ``a`` is a
  24. string.
  25. See Also
  26. ========
  27. sympify: Converts an arbitrary expression to a type that can be used
  28. inside SymPy.
  29. """
  30. # The parameter ``a`` is used for this function to keep compatibility
  31. # with the SymEngine docstring.
  32. if strict and isinstance(a, str):
  33. raise SympifyError(a)
  34. return sympify_symengine(a)
  35. # Keep the SymEngine docstring and append the additional "Notes" and "See
  36. # Also" sections. Replacement of spaces is required to correctly format the
  37. # indentation of the combined docstring.
  38. sympify.__doc__ = (
  39. sympify_symengine.__doc__
  40. + sympify.__doc__.replace(' ', ' ') # type: ignore
  41. )
  42. else:
  43. from sympy.core.add import Add
  44. from sympy.core.basic import Basic
  45. from sympy.core.function import (diff, Function, AppliedUndef,
  46. expand, Derivative)
  47. from sympy.core.mul import Mul
  48. from sympy.core.intfunc import igcd
  49. from sympy.core.numbers import pi, I, Integer, Rational, E
  50. from sympy.core.singleton import S
  51. from sympy.core.symbol import Symbol, var, symbols
  52. from sympy.core.sympify import SympifyError, sympify
  53. from sympy.functions.elementary.exponential import log, exp
  54. from sympy.functions.elementary.hyperbolic import (coth, sinh,
  55. acosh, acoth, tanh, asinh, atanh, cosh)
  56. from sympy.functions.elementary.miscellaneous import sqrt
  57. from sympy.functions.elementary.trigonometric import (csc,
  58. asec, cos, atan, sec, acot, asin, tan, sin, cot, acsc, acos)
  59. from sympy.functions.special.gamma_functions import gamma
  60. from sympy.matrices.dense import (eye, zeros, diag, Matrix,
  61. ones, symarray)
  62. from sympy.matrices.immutable import ImmutableMatrix
  63. from sympy.matrices.matrixbase import MatrixBase
  64. from sympy.utilities.lambdify import lambdify
  65. #
  66. # XXX: Handling of immutable and mutable matrices in SymEngine is inconsistent
  67. # with SymPy's matrix classes in at least SymEngine version 0.7.0. Until that
  68. # is fixed the function below is needed for consistent behaviour when
  69. # attempting to simplify a matrix.
  70. #
  71. # Expected behaviour of a SymPy mutable/immutable matrix .simplify() method:
  72. #
  73. # Matrix.simplify() : works in place, returns None
  74. # ImmutableMatrix.simplify() : returns a simplified copy
  75. #
  76. # In SymEngine both mutable and immutable matrices simplify in place and return
  77. # None. This is inconsistent with the matrix being "immutable" and also the
  78. # returned None leads to problems in the mechanics module.
  79. #
  80. # The simplify function should not be used because simplify(M) sympifies the
  81. # matrix M and the SymEngine matrices all sympify to SymPy matrices. If we want
  82. # to work with SymEngine matrices then we need to use their .simplify() method
  83. # but that method does not work correctly with immutable matrices.
  84. #
  85. # The _simplify_matrix function can be removed when the SymEngine bug is fixed.
  86. # Since this should be a temporary problem we do not make this function part of
  87. # the public API.
  88. #
  89. # SymEngine issue: https://github.com/symengine/symengine.py/issues/363
  90. #
  91. def _simplify_matrix(M):
  92. """Return a simplified copy of the matrix M"""
  93. if not isinstance(M, (Matrix, ImmutableMatrix)):
  94. raise TypeError("The matrix M must be an instance of Matrix or ImmutableMatrix")
  95. Mnew = M.as_mutable() # makes a copy if mutable
  96. Mnew.simplify()
  97. if isinstance(M, ImmutableMatrix):
  98. Mnew = Mnew.as_immutable()
  99. return Mnew
  100. __all__ = [
  101. 'Symbol', 'Integer', 'sympify', 'S', 'SympifyError', 'exp', 'log',
  102. 'gamma', 'sqrt', 'I', 'E', 'pi', 'Matrix', 'sin', 'cos', 'tan', 'cot',
  103. 'csc', 'sec', 'asin', 'acos', 'atan', 'acot', 'acsc', 'asec', 'sinh',
  104. 'cosh', 'tanh', 'coth', 'asinh', 'acosh', 'atanh', 'acoth', 'lambdify',
  105. 'symarray', 'diff', 'zeros', 'eye', 'diag', 'ones', 'expand', 'Function',
  106. 'symbols', 'var', 'Add', 'Mul', 'Derivative', 'ImmutableMatrix',
  107. 'MatrixBase', 'Rational', 'Basic', 'igcd', 'AppliedUndef',
  108. ]