m2m模型翻译
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.

368 lines
12 KiB

7 months ago
  1. from sympy.core.function import Derivative
  2. from sympy.core.function import UndefinedFunction, AppliedUndef
  3. from sympy.core.symbol import Symbol
  4. from sympy.interactive.printing import init_printing
  5. from sympy.printing.latex import LatexPrinter
  6. from sympy.printing.pretty.pretty import PrettyPrinter
  7. from sympy.printing.pretty.pretty_symbology import center_accent
  8. from sympy.printing.str import StrPrinter
  9. from sympy.printing.precedence import PRECEDENCE
  10. __all__ = ['vprint', 'vsstrrepr', 'vsprint', 'vpprint', 'vlatex',
  11. 'init_vprinting']
  12. class VectorStrPrinter(StrPrinter):
  13. """String Printer for vector expressions. """
  14. def _print_Derivative(self, e):
  15. from sympy.physics.vector.functions import dynamicsymbols
  16. t = dynamicsymbols._t
  17. if (bool(sum([i == t for i in e.variables])) &
  18. isinstance(type(e.args[0]), UndefinedFunction)):
  19. ol = str(e.args[0].func)
  20. for i, v in enumerate(e.variables):
  21. ol += dynamicsymbols._str
  22. return ol
  23. else:
  24. return StrPrinter().doprint(e)
  25. def _print_Function(self, e):
  26. from sympy.physics.vector.functions import dynamicsymbols
  27. t = dynamicsymbols._t
  28. if isinstance(type(e), UndefinedFunction):
  29. return StrPrinter().doprint(e).replace("(%s)" % t, '')
  30. return e.func.__name__ + "(%s)" % self.stringify(e.args, ", ")
  31. class VectorStrReprPrinter(VectorStrPrinter):
  32. """String repr printer for vector expressions."""
  33. def _print_str(self, s):
  34. return repr(s)
  35. class VectorLatexPrinter(LatexPrinter):
  36. """Latex Printer for vector expressions. """
  37. def _print_Function(self, expr, exp=None):
  38. from sympy.physics.vector.functions import dynamicsymbols
  39. func = expr.func.__name__
  40. t = dynamicsymbols._t
  41. if hasattr(self, '_print_' + func) and \
  42. not isinstance(type(expr), UndefinedFunction):
  43. return getattr(self, '_print_' + func)(expr, exp)
  44. elif isinstance(type(expr), UndefinedFunction) and (expr.args == (t,)):
  45. # treat this function like a symbol
  46. expr = Symbol(func)
  47. if exp is not None:
  48. # copied from LatexPrinter._helper_print_standard_power, which
  49. # we can't call because we only have exp as a string.
  50. base = self.parenthesize(expr, PRECEDENCE['Pow'])
  51. base = self.parenthesize_super(base)
  52. return r"%s^{%s}" % (base, exp)
  53. else:
  54. return super()._print(expr)
  55. else:
  56. return super()._print_Function(expr, exp)
  57. def _print_Derivative(self, der_expr):
  58. from sympy.physics.vector.functions import dynamicsymbols
  59. # make sure it is in the right form
  60. der_expr = der_expr.doit()
  61. if not isinstance(der_expr, Derivative):
  62. return r"\left(%s\right)" % self.doprint(der_expr)
  63. # check if expr is a dynamicsymbol
  64. t = dynamicsymbols._t
  65. expr = der_expr.expr
  66. red = expr.atoms(AppliedUndef)
  67. syms = der_expr.variables
  68. test1 = not all(True for i in red if i.free_symbols == {t})
  69. test2 = not all(t == i for i in syms)
  70. if test1 or test2:
  71. return super()._print_Derivative(der_expr)
  72. # done checking
  73. dots = len(syms)
  74. base = self._print_Function(expr)
  75. base_split = base.split('_', 1)
  76. base = base_split[0]
  77. if dots == 1:
  78. base = r"\dot{%s}" % base
  79. elif dots == 2:
  80. base = r"\ddot{%s}" % base
  81. elif dots == 3:
  82. base = r"\dddot{%s}" % base
  83. elif dots == 4:
  84. base = r"\ddddot{%s}" % base
  85. else: # Fallback to standard printing
  86. return super()._print_Derivative(der_expr)
  87. if len(base_split) != 1:
  88. base += '_' + base_split[1]
  89. return base
  90. class VectorPrettyPrinter(PrettyPrinter):
  91. """Pretty Printer for vectorialexpressions. """
  92. def _print_Derivative(self, deriv):
  93. from sympy.physics.vector.functions import dynamicsymbols
  94. # XXX use U('PARTIAL DIFFERENTIAL') here ?
  95. t = dynamicsymbols._t
  96. dot_i = 0
  97. syms = list(reversed(deriv.variables))
  98. while len(syms) > 0:
  99. if syms[-1] == t:
  100. syms.pop()
  101. dot_i += 1
  102. else:
  103. return super()._print_Derivative(deriv)
  104. if not (isinstance(type(deriv.expr), UndefinedFunction)
  105. and (deriv.expr.args == (t,))):
  106. return super()._print_Derivative(deriv)
  107. else:
  108. pform = self._print_Function(deriv.expr)
  109. # the following condition would happen with some sort of non-standard
  110. # dynamic symbol I guess, so we'll just print the SymPy way
  111. if len(pform.picture) > 1:
  112. return super()._print_Derivative(deriv)
  113. # There are only special symbols up to fourth-order derivatives
  114. if dot_i >= 5:
  115. return super()._print_Derivative(deriv)
  116. # Deal with special symbols
  117. dots = {0 : "",
  118. 1 : "\N{COMBINING DOT ABOVE}",
  119. 2 : "\N{COMBINING DIAERESIS}",
  120. 3 : "\N{COMBINING THREE DOTS ABOVE}",
  121. 4 : "\N{COMBINING FOUR DOTS ABOVE}"}
  122. d = pform.__dict__
  123. #if unicode is false then calculate number of apostrophes needed and add to output
  124. if not self._use_unicode:
  125. apostrophes = ""
  126. for i in range(0, dot_i):
  127. apostrophes += "'"
  128. d['picture'][0] += apostrophes + "(t)"
  129. else:
  130. d['picture'] = [center_accent(d['picture'][0], dots[dot_i])]
  131. return pform
  132. def _print_Function(self, e):
  133. from sympy.physics.vector.functions import dynamicsymbols
  134. t = dynamicsymbols._t
  135. # XXX works only for applied functions
  136. func = e.func
  137. args = e.args
  138. func_name = func.__name__
  139. pform = self._print_Symbol(Symbol(func_name))
  140. # If this function is an Undefined function of t, it is probably a
  141. # dynamic symbol, so we'll skip the (t). The rest of the code is
  142. # identical to the normal PrettyPrinter code
  143. if not (isinstance(func, UndefinedFunction) and (args == (t,))):
  144. return super()._print_Function(e)
  145. return pform
  146. def vprint(expr, **settings):
  147. r"""Function for printing of expressions generated in the
  148. sympy.physics vector package.
  149. Extends SymPy's StrPrinter, takes the same setting accepted by SymPy's
  150. :func:`~.sstr`, and is equivalent to ``print(sstr(foo))``.
  151. Parameters
  152. ==========
  153. expr : valid SymPy object
  154. SymPy expression to print.
  155. settings : args
  156. Same as the settings accepted by SymPy's sstr().
  157. Examples
  158. ========
  159. >>> from sympy.physics.vector import vprint, dynamicsymbols
  160. >>> u1 = dynamicsymbols('u1')
  161. >>> print(u1)
  162. u1(t)
  163. >>> vprint(u1)
  164. u1
  165. """
  166. outstr = vsprint(expr, **settings)
  167. import builtins
  168. if (outstr != 'None'):
  169. builtins._ = outstr
  170. print(outstr)
  171. def vsstrrepr(expr, **settings):
  172. """Function for displaying expression representation's with vector
  173. printing enabled.
  174. Parameters
  175. ==========
  176. expr : valid SymPy object
  177. SymPy expression to print.
  178. settings : args
  179. Same as the settings accepted by SymPy's sstrrepr().
  180. """
  181. p = VectorStrReprPrinter(settings)
  182. return p.doprint(expr)
  183. def vsprint(expr, **settings):
  184. r"""Function for displaying expressions generated in the
  185. sympy.physics vector package.
  186. Returns the output of vprint() as a string.
  187. Parameters
  188. ==========
  189. expr : valid SymPy object
  190. SymPy expression to print
  191. settings : args
  192. Same as the settings accepted by SymPy's sstr().
  193. Examples
  194. ========
  195. >>> from sympy.physics.vector import vsprint, dynamicsymbols
  196. >>> u1, u2 = dynamicsymbols('u1 u2')
  197. >>> u2d = dynamicsymbols('u2', level=1)
  198. >>> print("%s = %s" % (u1, u2 + u2d))
  199. u1(t) = u2(t) + Derivative(u2(t), t)
  200. >>> print("%s = %s" % (vsprint(u1), vsprint(u2 + u2d)))
  201. u1 = u2 + u2'
  202. """
  203. string_printer = VectorStrPrinter(settings)
  204. return string_printer.doprint(expr)
  205. def vpprint(expr, **settings):
  206. r"""Function for pretty printing of expressions generated in the
  207. sympy.physics vector package.
  208. Mainly used for expressions not inside a vector; the output of running
  209. scripts and generating equations of motion. Takes the same options as
  210. SymPy's :func:`~.pretty_print`; see that function for more information.
  211. Parameters
  212. ==========
  213. expr : valid SymPy object
  214. SymPy expression to pretty print
  215. settings : args
  216. Same as those accepted by SymPy's pretty_print.
  217. """
  218. pp = VectorPrettyPrinter(settings)
  219. # Note that this is copied from sympy.printing.pretty.pretty_print:
  220. # XXX: this is an ugly hack, but at least it works
  221. use_unicode = pp._settings['use_unicode']
  222. from sympy.printing.pretty.pretty_symbology import pretty_use_unicode
  223. uflag = pretty_use_unicode(use_unicode)
  224. try:
  225. return pp.doprint(expr)
  226. finally:
  227. pretty_use_unicode(uflag)
  228. def vlatex(expr, **settings):
  229. r"""Function for printing latex representation of sympy.physics.vector
  230. objects.
  231. For latex representation of Vectors, Dyadics, and dynamicsymbols. Takes the
  232. same options as SymPy's :func:`~.latex`; see that function for more information;
  233. Parameters
  234. ==========
  235. expr : valid SymPy object
  236. SymPy expression to represent in LaTeX form
  237. settings : args
  238. Same as latex()
  239. Examples
  240. ========
  241. >>> from sympy.physics.vector import vlatex, ReferenceFrame, dynamicsymbols
  242. >>> N = ReferenceFrame('N')
  243. >>> q1, q2 = dynamicsymbols('q1 q2')
  244. >>> q1d, q2d = dynamicsymbols('q1 q2', 1)
  245. >>> q1dd, q2dd = dynamicsymbols('q1 q2', 2)
  246. >>> vlatex(N.x + N.y)
  247. '\\mathbf{\\hat{n}_x} + \\mathbf{\\hat{n}_y}'
  248. >>> vlatex(q1 + q2)
  249. 'q_{1} + q_{2}'
  250. >>> vlatex(q1d)
  251. '\\dot{q}_{1}'
  252. >>> vlatex(q1 * q2d)
  253. 'q_{1} \\dot{q}_{2}'
  254. >>> vlatex(q1dd * q1 / q1d)
  255. '\\frac{q_{1} \\ddot{q}_{1}}{\\dot{q}_{1}}'
  256. """
  257. latex_printer = VectorLatexPrinter(settings)
  258. return latex_printer.doprint(expr)
  259. def init_vprinting(**kwargs):
  260. """Initializes time derivative printing for all SymPy objects, i.e. any
  261. functions of time will be displayed in a more compact notation. The main
  262. benefit of this is for printing of time derivatives; instead of
  263. displaying as ``Derivative(f(t),t)``, it will display ``f'``. This is
  264. only actually needed for when derivatives are present and are not in a
  265. physics.vector.Vector or physics.vector.Dyadic object. This function is a
  266. light wrapper to :func:`~.init_printing`. Any keyword
  267. arguments for it are valid here.
  268. {0}
  269. Examples
  270. ========
  271. >>> from sympy import Function, symbols
  272. >>> t, x = symbols('t, x')
  273. >>> omega = Function('omega')
  274. >>> omega(x).diff()
  275. Derivative(omega(x), x)
  276. >>> omega(t).diff()
  277. Derivative(omega(t), t)
  278. Now use the string printer:
  279. >>> from sympy.physics.vector import init_vprinting
  280. >>> init_vprinting(pretty_print=False)
  281. >>> omega(x).diff()
  282. Derivative(omega(x), x)
  283. >>> omega(t).diff()
  284. omega'
  285. """
  286. kwargs['str_printer'] = vsstrrepr
  287. kwargs['pretty_printer'] = vpprint
  288. kwargs['latex_printer'] = vlatex
  289. init_printing(**kwargs)
  290. params = init_printing.__doc__.split('Examples\n ========')[0] # type: ignore
  291. init_vprinting.__doc__ = init_vprinting.__doc__.format(params) # type: ignore