str.py 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. """
  2. A Printer for generating readable representation of most SymPy classes.
  3. """
  4. from __future__ import annotations
  5. from typing import Any
  6. from sympy.core import S, Rational, Pow, Basic, Mul, Number
  7. from sympy.core.mul import _keep_coeff
  8. from sympy.core.relational import Relational
  9. from sympy.core.sorting import default_sort_key
  10. from sympy.core.sympify import SympifyError
  11. from sympy.utilities.iterables import sift
  12. from .precedence import precedence, PRECEDENCE
  13. from .printer import Printer, print_function
  14. from mpmath.libmp import prec_to_dps, to_str as mlib_to_str
  15. class StrPrinter(Printer):
  16. printmethod = "_sympystr"
  17. _default_settings: dict[str, Any] = {
  18. "order": None,
  19. "full_prec": "auto",
  20. "sympy_integers": False,
  21. "abbrev": False,
  22. "perm_cyclic": True,
  23. "min": None,
  24. "max": None,
  25. }
  26. _relationals: dict[str, str] = {}
  27. def parenthesize(self, item, level, strict=False):
  28. if (precedence(item) < level) or ((not strict) and precedence(item) <= level):
  29. return "(%s)" % self._print(item)
  30. else:
  31. return self._print(item)
  32. def stringify(self, args, sep, level=0):
  33. return sep.join([self.parenthesize(item, level) for item in args])
  34. def emptyPrinter(self, expr):
  35. if isinstance(expr, str):
  36. return expr
  37. elif isinstance(expr, Basic):
  38. return repr(expr)
  39. else:
  40. return str(expr)
  41. def _print_Add(self, expr, order=None):
  42. terms = self._as_ordered_terms(expr, order=order)
  43. prec = precedence(expr)
  44. l = []
  45. for term in terms:
  46. t = self._print(term)
  47. if t.startswith('-') and not term.is_Add:
  48. sign = "-"
  49. t = t[1:]
  50. else:
  51. sign = "+"
  52. if precedence(term) < prec or term.is_Add:
  53. l.extend([sign, "(%s)" % t])
  54. else:
  55. l.extend([sign, t])
  56. sign = l.pop(0)
  57. if sign == '+':
  58. sign = ""
  59. return sign + ' '.join(l)
  60. def _print_BooleanTrue(self, expr):
  61. return "True"
  62. def _print_BooleanFalse(self, expr):
  63. return "False"
  64. def _print_Not(self, expr):
  65. return '~%s' %(self.parenthesize(expr.args[0],PRECEDENCE["Not"]))
  66. def _print_And(self, expr):
  67. args = list(expr.args)
  68. for j, i in enumerate(args):
  69. if isinstance(i, Relational) and (
  70. i.canonical.rhs is S.NegativeInfinity):
  71. args.insert(0, args.pop(j))
  72. return self.stringify(args, " & ", PRECEDENCE["BitwiseAnd"])
  73. def _print_Or(self, expr):
  74. return self.stringify(expr.args, " | ", PRECEDENCE["BitwiseOr"])
  75. def _print_Xor(self, expr):
  76. return self.stringify(expr.args, " ^ ", PRECEDENCE["BitwiseXor"])
  77. def _print_AppliedPredicate(self, expr):
  78. return '%s(%s)' % (
  79. self._print(expr.function), self.stringify(expr.arguments, ", "))
  80. def _print_Basic(self, expr):
  81. l = [self._print(o) for o in expr.args]
  82. return expr.__class__.__name__ + "(%s)" % ", ".join(l)
  83. def _print_BlockMatrix(self, B):
  84. if B.blocks.shape == (1, 1):
  85. self._print(B.blocks[0, 0])
  86. return self._print(B.blocks)
  87. def _print_Catalan(self, expr):
  88. return 'Catalan'
  89. def _print_ComplexInfinity(self, expr):
  90. return 'zoo'
  91. def _print_ConditionSet(self, s):
  92. args = tuple([self._print(i) for i in (s.sym, s.condition)])
  93. if s.base_set is S.UniversalSet:
  94. return 'ConditionSet(%s, %s)' % args
  95. args += (self._print(s.base_set),)
  96. return 'ConditionSet(%s, %s, %s)' % args
  97. def _print_Derivative(self, expr):
  98. dexpr = expr.expr
  99. dvars = [i[0] if i[1] == 1 else i for i in expr.variable_count]
  100. return 'Derivative(%s)' % ", ".join((self._print(arg) for arg in [dexpr] + dvars))
  101. def _print_dict(self, d):
  102. keys = sorted(d.keys(), key=default_sort_key)
  103. items = []
  104. for key in keys:
  105. item = "%s: %s" % (self._print(key), self._print(d[key]))
  106. items.append(item)
  107. return "{%s}" % ", ".join(items)
  108. def _print_Dict(self, expr):
  109. return self._print_dict(expr)
  110. def _print_RandomDomain(self, d):
  111. if hasattr(d, 'as_boolean'):
  112. return 'Domain: ' + self._print(d.as_boolean())
  113. elif hasattr(d, 'set'):
  114. return ('Domain: ' + self._print(d.symbols) + ' in ' +
  115. self._print(d.set))
  116. else:
  117. return 'Domain on ' + self._print(d.symbols)
  118. def _print_Dummy(self, expr):
  119. return '_' + expr.name
  120. def _print_EulerGamma(self, expr):
  121. return 'EulerGamma'
  122. def _print_Exp1(self, expr):
  123. return 'E'
  124. def _print_ExprCondPair(self, expr):
  125. return '(%s, %s)' % (self._print(expr.expr), self._print(expr.cond))
  126. def _print_Function(self, expr):
  127. return expr.func.__name__ + "(%s)" % self.stringify(expr.args, ", ")
  128. def _print_GoldenRatio(self, expr):
  129. return 'GoldenRatio'
  130. def _print_Heaviside(self, expr):
  131. # Same as _print_Function but uses pargs to suppress default 1/2 for
  132. # 2nd args
  133. return expr.func.__name__ + "(%s)" % self.stringify(expr.pargs, ", ")
  134. def _print_TribonacciConstant(self, expr):
  135. return 'TribonacciConstant'
  136. def _print_ImaginaryUnit(self, expr):
  137. return 'I'
  138. def _print_Infinity(self, expr):
  139. return 'oo'
  140. def _print_Integral(self, expr):
  141. def _xab_tostr(xab):
  142. if len(xab) == 1:
  143. return self._print(xab[0])
  144. else:
  145. return self._print((xab[0],) + tuple(xab[1:]))
  146. L = ', '.join([_xab_tostr(l) for l in expr.limits])
  147. return 'Integral(%s, %s)' % (self._print(expr.function), L)
  148. def _print_Interval(self, i):
  149. fin = 'Interval{m}({a}, {b})'
  150. a, b, l, r = i.args
  151. if a.is_infinite and b.is_infinite:
  152. m = ''
  153. elif a.is_infinite and not r:
  154. m = ''
  155. elif b.is_infinite and not l:
  156. m = ''
  157. elif not l and not r:
  158. m = ''
  159. elif l and r:
  160. m = '.open'
  161. elif l:
  162. m = '.Lopen'
  163. else:
  164. m = '.Ropen'
  165. return fin.format(**{'a': a, 'b': b, 'm': m})
  166. def _print_AccumulationBounds(self, i):
  167. return "AccumBounds(%s, %s)" % (self._print(i.min),
  168. self._print(i.max))
  169. def _print_Inverse(self, I):
  170. return "%s**(-1)" % self.parenthesize(I.arg, PRECEDENCE["Pow"])
  171. def _print_Lambda(self, obj):
  172. expr = obj.expr
  173. sig = obj.signature
  174. if len(sig) == 1 and sig[0].is_symbol:
  175. sig = sig[0]
  176. return "Lambda(%s, %s)" % (self._print(sig), self._print(expr))
  177. def _print_LatticeOp(self, expr):
  178. args = sorted(expr.args, key=default_sort_key)
  179. return expr.func.__name__ + "(%s)" % ", ".join(self._print(arg) for arg in args)
  180. def _print_Limit(self, expr):
  181. e, z, z0, dir = expr.args
  182. return "Limit(%s, %s, %s, dir='%s')" % tuple(map(self._print, (e, z, z0, dir)))
  183. def _print_list(self, expr):
  184. return "[%s]" % self.stringify(expr, ", ")
  185. def _print_List(self, expr):
  186. return self._print_list(expr)
  187. def _print_MatrixBase(self, expr):
  188. return expr._format_str(self)
  189. def _print_MatrixElement(self, expr):
  190. return self.parenthesize(expr.parent, PRECEDENCE["Atom"], strict=True) \
  191. + '[%s, %s]' % (self._print(expr.i), self._print(expr.j))
  192. def _print_MatrixSlice(self, expr):
  193. def strslice(x, dim):
  194. x = list(x)
  195. if x[2] == 1:
  196. del x[2]
  197. if x[0] == 0:
  198. x[0] = ''
  199. if x[1] == dim:
  200. x[1] = ''
  201. return ':'.join((self._print(arg) for arg in x))
  202. return (self.parenthesize(expr.parent, PRECEDENCE["Atom"], strict=True) + '[' +
  203. strslice(expr.rowslice, expr.parent.rows) + ', ' +
  204. strslice(expr.colslice, expr.parent.cols) + ']')
  205. def _print_DeferredVector(self, expr):
  206. return expr.name
  207. def _print_Mul(self, expr):
  208. prec = precedence(expr)
  209. # Check for unevaluated Mul. In this case we need to make sure the
  210. # identities are visible, multiple Rational factors are not combined
  211. # etc so we display in a straight-forward form that fully preserves all
  212. # args and their order.
  213. args = expr.args
  214. if args[0] is S.One or any(
  215. isinstance(a, Number) or
  216. a.is_Pow and all(ai.is_Integer for ai in a.args)
  217. for a in args[1:]):
  218. d, n = sift(args, lambda x:
  219. isinstance(x, Pow) and bool(x.exp.as_coeff_Mul()[0] < 0),
  220. binary=True)
  221. for i, di in enumerate(d):
  222. if di.exp.is_Number:
  223. e = -di.exp
  224. else:
  225. dargs = list(di.exp.args)
  226. dargs[0] = -dargs[0]
  227. e = Mul._from_args(dargs)
  228. d[i] = Pow(di.base, e, evaluate=False) if e - 1 else di.base
  229. pre = []
  230. # don't parenthesize first factor if negative
  231. if n and not n[0].is_Add and n[0].could_extract_minus_sign():
  232. pre = [self._print(n.pop(0))]
  233. nfactors = pre + [self.parenthesize(a, prec, strict=False)
  234. for a in n]
  235. if not nfactors:
  236. nfactors = ['1']
  237. # don't parenthesize first of denominator unless singleton
  238. if len(d) > 1 and d[0].could_extract_minus_sign():
  239. pre = [self._print(d.pop(0))]
  240. else:
  241. pre = []
  242. dfactors = pre + [self.parenthesize(a, prec, strict=False)
  243. for a in d]
  244. n = '*'.join(nfactors)
  245. d = '*'.join(dfactors)
  246. if len(dfactors) > 1:
  247. return '%s/(%s)' % (n, d)
  248. elif dfactors:
  249. return '%s/%s' % (n, d)
  250. return n
  251. c, e = expr.as_coeff_Mul()
  252. if c < 0:
  253. expr = _keep_coeff(-c, e)
  254. sign = "-"
  255. else:
  256. sign = ""
  257. a = [] # items in the numerator
  258. b = [] # items that are in the denominator (if any)
  259. pow_paren = [] # Will collect all pow with more than one base element and exp = -1
  260. if self.order not in ('old', 'none'):
  261. args = expr.as_ordered_factors()
  262. else:
  263. # use make_args in case expr was something like -x -> x
  264. args = Mul.make_args(expr)
  265. # Gather args for numerator/denominator
  266. def apow(i):
  267. b, e = i.as_base_exp()
  268. eargs = list(Mul.make_args(e))
  269. if eargs[0] is S.NegativeOne:
  270. eargs = eargs[1:]
  271. else:
  272. eargs[0] = -eargs[0]
  273. e = Mul._from_args(eargs)
  274. if isinstance(i, Pow):
  275. return i.func(b, e, evaluate=False)
  276. return i.func(e, evaluate=False)
  277. for item in args:
  278. if (item.is_commutative and
  279. isinstance(item, Pow) and
  280. bool(item.exp.as_coeff_Mul()[0] < 0)):
  281. if item.exp is not S.NegativeOne:
  282. b.append(apow(item))
  283. else:
  284. if (len(item.args[0].args) != 1 and
  285. isinstance(item.base, (Mul, Pow))):
  286. # To avoid situations like #14160
  287. pow_paren.append(item)
  288. b.append(item.base)
  289. elif item.is_Rational and item is not S.Infinity:
  290. if item.p != 1:
  291. a.append(Rational(item.p))
  292. if item.q != 1:
  293. b.append(Rational(item.q))
  294. else:
  295. a.append(item)
  296. a = a or [S.One]
  297. a_str = [self.parenthesize(x, prec, strict=False) for x in a]
  298. b_str = [self.parenthesize(x, prec, strict=False) for x in b]
  299. # To parenthesize Pow with exp = -1 and having more than one Symbol
  300. for item in pow_paren:
  301. if item.base in b:
  302. b_str[b.index(item.base)] = "(%s)" % b_str[b.index(item.base)]
  303. if not b:
  304. return sign + '*'.join(a_str)
  305. elif len(b) == 1:
  306. return sign + '*'.join(a_str) + "/" + b_str[0]
  307. else:
  308. return sign + '*'.join(a_str) + "/(%s)" % '*'.join(b_str)
  309. def _print_MatMul(self, expr):
  310. c, m = expr.as_coeff_mmul()
  311. sign = ""
  312. if c.is_number:
  313. re, im = c.as_real_imag()
  314. if im.is_zero and re.is_negative:
  315. expr = _keep_coeff(-c, m)
  316. sign = "-"
  317. elif re.is_zero and im.is_negative:
  318. expr = _keep_coeff(-c, m)
  319. sign = "-"
  320. return sign + '*'.join(
  321. [self.parenthesize(arg, precedence(expr)) for arg in expr.args]
  322. )
  323. def _print_ElementwiseApplyFunction(self, expr):
  324. return "{}.({})".format(
  325. expr.function,
  326. self._print(expr.expr),
  327. )
  328. def _print_NaN(self, expr):
  329. return 'nan'
  330. def _print_NegativeInfinity(self, expr):
  331. return '-oo'
  332. def _print_Order(self, expr):
  333. if not expr.variables or all(p is S.Zero for p in expr.point):
  334. if len(expr.variables) <= 1:
  335. return 'O(%s)' % self._print(expr.expr)
  336. else:
  337. return 'O(%s)' % self.stringify((expr.expr,) + expr.variables, ', ', 0)
  338. else:
  339. return 'O(%s)' % self.stringify(expr.args, ', ', 0)
  340. def _print_Ordinal(self, expr):
  341. return expr.__str__()
  342. def _print_Cycle(self, expr):
  343. return expr.__str__()
  344. def _print_Permutation(self, expr):
  345. from sympy.combinatorics.permutations import Permutation, Cycle
  346. from sympy.utilities.exceptions import sympy_deprecation_warning
  347. perm_cyclic = Permutation.print_cyclic
  348. if perm_cyclic is not None:
  349. sympy_deprecation_warning(
  350. f"""
  351. Setting Permutation.print_cyclic is deprecated. Instead use
  352. init_printing(perm_cyclic={perm_cyclic}).
  353. """,
  354. deprecated_since_version="1.6",
  355. active_deprecations_target="deprecated-permutation-print_cyclic",
  356. stacklevel=7,
  357. )
  358. else:
  359. perm_cyclic = self._settings.get("perm_cyclic", True)
  360. if perm_cyclic:
  361. if not expr.size:
  362. return '()'
  363. # before taking Cycle notation, see if the last element is
  364. # a singleton and move it to the head of the string
  365. s = Cycle(expr)(expr.size - 1).__repr__()[len('Cycle'):]
  366. last = s.rfind('(')
  367. if not last == 0 and ',' not in s[last:]:
  368. s = s[last:] + s[:last]
  369. s = s.replace(',', '')
  370. return s
  371. else:
  372. s = expr.support()
  373. if not s:
  374. if expr.size < 5:
  375. return 'Permutation(%s)' % self._print(expr.array_form)
  376. return 'Permutation([], size=%s)' % self._print(expr.size)
  377. trim = self._print(expr.array_form[:s[-1] + 1]) + ', size=%s' % self._print(expr.size)
  378. use = full = self._print(expr.array_form)
  379. if len(trim) < len(full):
  380. use = trim
  381. return 'Permutation(%s)' % use
  382. def _print_Subs(self, obj):
  383. expr, old, new = obj.args
  384. if len(obj.point) == 1:
  385. old = old[0]
  386. new = new[0]
  387. return "Subs(%s, %s, %s)" % (
  388. self._print(expr), self._print(old), self._print(new))
  389. def _print_TensorIndex(self, expr):
  390. return expr._print()
  391. def _print_TensorHead(self, expr):
  392. return expr._print()
  393. def _print_Tensor(self, expr):
  394. return expr._print()
  395. def _print_TensMul(self, expr):
  396. # prints expressions like "A(a)", "3*A(a)", "(1+x)*A(a)"
  397. sign, args = expr._get_args_for_traditional_printer()
  398. return sign + "*".join(
  399. [self.parenthesize(arg, precedence(expr)) for arg in args]
  400. )
  401. def _print_TensAdd(self, expr):
  402. return expr._print()
  403. def _print_ArraySymbol(self, expr):
  404. return self._print(expr.name)
  405. def _print_ArrayElement(self, expr):
  406. return "%s[%s]" % (
  407. self.parenthesize(expr.name, PRECEDENCE["Func"], True), ", ".join([self._print(i) for i in expr.indices]))
  408. def _print_PermutationGroup(self, expr):
  409. p = [' %s' % self._print(a) for a in expr.args]
  410. return 'PermutationGroup([\n%s])' % ',\n'.join(p)
  411. def _print_Pi(self, expr):
  412. return 'pi'
  413. def _print_PolyRing(self, ring):
  414. return "Polynomial ring in %s over %s with %s order" % \
  415. (", ".join((self._print(rs) for rs in ring.symbols)),
  416. self._print(ring.domain), self._print(ring.order))
  417. def _print_FracField(self, field):
  418. return "Rational function field in %s over %s with %s order" % \
  419. (", ".join((self._print(fs) for fs in field.symbols)),
  420. self._print(field.domain), self._print(field.order))
  421. def _print_FreeGroupElement(self, elm):
  422. return elm.__str__()
  423. def _print_GaussianElement(self, poly):
  424. return "(%s + %s*I)" % (poly.x, poly.y)
  425. def _print_PolyElement(self, poly):
  426. return poly.str(self, PRECEDENCE, "%s**%s", "*")
  427. def _print_FracElement(self, frac):
  428. if frac.denom == 1:
  429. return self._print(frac.numer)
  430. else:
  431. numer = self.parenthesize(frac.numer, PRECEDENCE["Mul"], strict=True)
  432. denom = self.parenthesize(frac.denom, PRECEDENCE["Atom"], strict=True)
  433. return numer + "/" + denom
  434. def _print_Poly(self, expr):
  435. ATOM_PREC = PRECEDENCE["Atom"] - 1
  436. terms, gens = [], [ self.parenthesize(s, ATOM_PREC) for s in expr.gens ]
  437. for monom, coeff in expr.terms():
  438. s_monom = []
  439. for i, e in enumerate(monom):
  440. if e > 0:
  441. if e == 1:
  442. s_monom.append(gens[i])
  443. else:
  444. s_monom.append(gens[i] + "**%d" % e)
  445. s_monom = "*".join(s_monom)
  446. if coeff.is_Add:
  447. if s_monom:
  448. s_coeff = "(" + self._print(coeff) + ")"
  449. else:
  450. s_coeff = self._print(coeff)
  451. else:
  452. if s_monom:
  453. if coeff is S.One:
  454. terms.extend(['+', s_monom])
  455. continue
  456. if coeff is S.NegativeOne:
  457. terms.extend(['-', s_monom])
  458. continue
  459. s_coeff = self._print(coeff)
  460. if not s_monom:
  461. s_term = s_coeff
  462. else:
  463. s_term = s_coeff + "*" + s_monom
  464. if s_term.startswith('-'):
  465. terms.extend(['-', s_term[1:]])
  466. else:
  467. terms.extend(['+', s_term])
  468. if terms[0] in ('-', '+'):
  469. modifier = terms.pop(0)
  470. if modifier == '-':
  471. terms[0] = '-' + terms[0]
  472. format = expr.__class__.__name__ + "(%s, %s"
  473. from sympy.polys.polyerrors import PolynomialError
  474. try:
  475. format += ", modulus=%s" % expr.get_modulus()
  476. except PolynomialError:
  477. format += ", domain='%s'" % expr.get_domain()
  478. format += ")"
  479. for index, item in enumerate(gens):
  480. if len(item) > 2 and (item[:1] == "(" and item[len(item) - 1:] == ")"):
  481. gens[index] = item[1:len(item) - 1]
  482. return format % (' '.join(terms), ', '.join(gens))
  483. def _print_UniversalSet(self, p):
  484. return 'UniversalSet'
  485. def _print_AlgebraicNumber(self, expr):
  486. if expr.is_aliased:
  487. return self._print(expr.as_poly().as_expr())
  488. else:
  489. return self._print(expr.as_expr())
  490. def _print_Pow(self, expr, rational=False):
  491. """Printing helper function for ``Pow``
  492. Parameters
  493. ==========
  494. rational : bool, optional
  495. If ``True``, it will not attempt printing ``sqrt(x)`` or
  496. ``x**S.Half`` as ``sqrt``, and will use ``x**(1/2)``
  497. instead.
  498. See examples for additional details
  499. Examples
  500. ========
  501. >>> from sympy import sqrt, StrPrinter
  502. >>> from sympy.abc import x
  503. How ``rational`` keyword works with ``sqrt``:
  504. >>> printer = StrPrinter()
  505. >>> printer._print_Pow(sqrt(x), rational=True)
  506. 'x**(1/2)'
  507. >>> printer._print_Pow(sqrt(x), rational=False)
  508. 'sqrt(x)'
  509. >>> printer._print_Pow(1/sqrt(x), rational=True)
  510. 'x**(-1/2)'
  511. >>> printer._print_Pow(1/sqrt(x), rational=False)
  512. '1/sqrt(x)'
  513. Notes
  514. =====
  515. ``sqrt(x)`` is canonicalized as ``Pow(x, S.Half)`` in SymPy,
  516. so there is no need of defining a separate printer for ``sqrt``.
  517. Instead, it should be handled here as well.
  518. """
  519. PREC = precedence(expr)
  520. if expr.exp is S.Half and not rational:
  521. return "sqrt(%s)" % self._print(expr.base)
  522. if expr.is_commutative:
  523. if -expr.exp is S.Half and not rational:
  524. # Note: Don't test "expr.exp == -S.Half" here, because that will
  525. # match -0.5, which we don't want.
  526. return "%s/sqrt(%s)" % tuple((self._print(arg) for arg in (S.One, expr.base)))
  527. if expr.exp is -S.One:
  528. # Similarly to the S.Half case, don't test with "==" here.
  529. return '%s/%s' % (self._print(S.One),
  530. self.parenthesize(expr.base, PREC, strict=False))
  531. e = self.parenthesize(expr.exp, PREC, strict=False)
  532. if self.printmethod == '_sympyrepr' and expr.exp.is_Rational and expr.exp.q != 1:
  533. # the parenthesized exp should be '(Rational(a, b))' so strip parens,
  534. # but just check to be sure.
  535. if e.startswith('(Rational'):
  536. return '%s**%s' % (self.parenthesize(expr.base, PREC, strict=False), e[1:-1])
  537. return '%s**%s' % (self.parenthesize(expr.base, PREC, strict=False), e)
  538. def _print_UnevaluatedExpr(self, expr):
  539. return self._print(expr.args[0])
  540. def _print_MatPow(self, expr):
  541. PREC = precedence(expr)
  542. return '%s**%s' % (self.parenthesize(expr.base, PREC, strict=False),
  543. self.parenthesize(expr.exp, PREC, strict=False))
  544. def _print_Integer(self, expr):
  545. if self._settings.get("sympy_integers", False):
  546. return "S(%s)" % (expr)
  547. return str(expr.p)
  548. def _print_Integers(self, expr):
  549. return 'Integers'
  550. def _print_Naturals(self, expr):
  551. return 'Naturals'
  552. def _print_Naturals0(self, expr):
  553. return 'Naturals0'
  554. def _print_Rationals(self, expr):
  555. return 'Rationals'
  556. def _print_Reals(self, expr):
  557. return 'Reals'
  558. def _print_Complexes(self, expr):
  559. return 'Complexes'
  560. def _print_EmptySet(self, expr):
  561. return 'EmptySet'
  562. def _print_EmptySequence(self, expr):
  563. return 'EmptySequence'
  564. def _print_int(self, expr):
  565. return str(expr)
  566. def _print_mpz(self, expr):
  567. return str(expr)
  568. def _print_Rational(self, expr):
  569. if expr.q == 1:
  570. return str(expr.p)
  571. else:
  572. if self._settings.get("sympy_integers", False):
  573. return "S(%s)/%s" % (expr.p, expr.q)
  574. return "%s/%s" % (expr.p, expr.q)
  575. def _print_PythonRational(self, expr):
  576. if expr.q == 1:
  577. return str(expr.p)
  578. else:
  579. return "%d/%d" % (expr.p, expr.q)
  580. def _print_Fraction(self, expr):
  581. if expr.denominator == 1:
  582. return str(expr.numerator)
  583. else:
  584. return "%s/%s" % (expr.numerator, expr.denominator)
  585. def _print_mpq(self, expr):
  586. if expr.denominator == 1:
  587. return str(expr.numerator)
  588. else:
  589. return "%s/%s" % (expr.numerator, expr.denominator)
  590. def _print_Float(self, expr):
  591. prec = expr._prec
  592. if prec < 5:
  593. dps = 0
  594. else:
  595. dps = prec_to_dps(expr._prec)
  596. if self._settings["full_prec"] is True:
  597. strip = False
  598. elif self._settings["full_prec"] is False:
  599. strip = True
  600. elif self._settings["full_prec"] == "auto":
  601. strip = self._print_level > 1
  602. low = self._settings["min"] if "min" in self._settings else None
  603. high = self._settings["max"] if "max" in self._settings else None
  604. rv = mlib_to_str(expr._mpf_, dps, strip_zeros=strip, min_fixed=low, max_fixed=high)
  605. if rv.startswith('-.0'):
  606. rv = '-0.' + rv[3:]
  607. elif rv.startswith('.0'):
  608. rv = '0.' + rv[2:]
  609. if rv.startswith('+'):
  610. # e.g., +inf -> inf
  611. rv = rv[1:]
  612. return rv
  613. def _print_Relational(self, expr):
  614. charmap = {
  615. "==": "Eq",
  616. "!=": "Ne",
  617. ":=": "Assignment",
  618. '+=': "AddAugmentedAssignment",
  619. "-=": "SubAugmentedAssignment",
  620. "*=": "MulAugmentedAssignment",
  621. "/=": "DivAugmentedAssignment",
  622. "%=": "ModAugmentedAssignment",
  623. }
  624. if expr.rel_op in charmap:
  625. return '%s(%s, %s)' % (charmap[expr.rel_op], self._print(expr.lhs),
  626. self._print(expr.rhs))
  627. return '%s %s %s' % (self.parenthesize(expr.lhs, precedence(expr)),
  628. self._relationals.get(expr.rel_op) or expr.rel_op,
  629. self.parenthesize(expr.rhs, precedence(expr)))
  630. def _print_ComplexRootOf(self, expr):
  631. return "CRootOf(%s, %d)" % (self._print_Add(expr.expr, order='lex'),
  632. expr.index)
  633. def _print_RootSum(self, expr):
  634. args = [self._print_Add(expr.expr, order='lex')]
  635. if expr.fun is not S.IdentityFunction:
  636. args.append(self._print(expr.fun))
  637. return "RootSum(%s)" % ", ".join(args)
  638. def _print_GroebnerBasis(self, basis):
  639. cls = basis.__class__.__name__
  640. exprs = [self._print_Add(arg, order=basis.order) for arg in basis.exprs]
  641. exprs = "[%s]" % ", ".join(exprs)
  642. gens = [ self._print(gen) for gen in basis.gens ]
  643. domain = "domain='%s'" % self._print(basis.domain)
  644. order = "order='%s'" % self._print(basis.order)
  645. args = [exprs] + gens + [domain, order]
  646. return "%s(%s)" % (cls, ", ".join(args))
  647. def _print_set(self, s):
  648. items = sorted(s, key=default_sort_key)
  649. args = ', '.join(self._print(item) for item in items)
  650. if not args:
  651. return "set()"
  652. return '{%s}' % args
  653. def _print_FiniteSet(self, s):
  654. from sympy.sets.sets import FiniteSet
  655. items = sorted(s, key=default_sort_key)
  656. args = ', '.join(self._print(item) for item in items)
  657. if any(item.has(FiniteSet) for item in items):
  658. return 'FiniteSet({})'.format(args)
  659. return '{{{}}}'.format(args)
  660. def _print_Partition(self, s):
  661. items = sorted(s, key=default_sort_key)
  662. args = ', '.join(self._print(arg) for arg in items)
  663. return 'Partition({})'.format(args)
  664. def _print_frozenset(self, s):
  665. if not s:
  666. return "frozenset()"
  667. return "frozenset(%s)" % self._print_set(s)
  668. def _print_Sum(self, expr):
  669. def _xab_tostr(xab):
  670. if len(xab) == 1:
  671. return self._print(xab[0])
  672. else:
  673. return self._print((xab[0],) + tuple(xab[1:]))
  674. L = ', '.join([_xab_tostr(l) for l in expr.limits])
  675. return 'Sum(%s, %s)' % (self._print(expr.function), L)
  676. def _print_Symbol(self, expr):
  677. return expr.name
  678. _print_MatrixSymbol = _print_Symbol
  679. _print_RandomSymbol = _print_Symbol
  680. def _print_Identity(self, expr):
  681. return "I"
  682. def _print_ZeroMatrix(self, expr):
  683. return "0"
  684. def _print_OneMatrix(self, expr):
  685. return "1"
  686. def _print_Predicate(self, expr):
  687. return "Q.%s" % expr.name
  688. def _print_str(self, expr):
  689. return str(expr)
  690. def _print_tuple(self, expr):
  691. if len(expr) == 1:
  692. return "(%s,)" % self._print(expr[0])
  693. else:
  694. return "(%s)" % self.stringify(expr, ", ")
  695. def _print_Tuple(self, expr):
  696. return self._print_tuple(expr)
  697. def _print_Transpose(self, T):
  698. return "%s.T" % self.parenthesize(T.arg, PRECEDENCE["Pow"])
  699. def _print_Uniform(self, expr):
  700. return "Uniform(%s, %s)" % (self._print(expr.a), self._print(expr.b))
  701. def _print_Quantity(self, expr):
  702. if self._settings.get("abbrev", False):
  703. return "%s" % expr.abbrev
  704. return "%s" % expr.name
  705. def _print_Quaternion(self, expr):
  706. s = [self.parenthesize(i, PRECEDENCE["Mul"], strict=True) for i in expr.args]
  707. a = [s[0]] + [i+"*"+j for i, j in zip(s[1:], "ijk")]
  708. return " + ".join(a)
  709. def _print_Dimension(self, expr):
  710. return str(expr)
  711. def _print_Wild(self, expr):
  712. return expr.name + '_'
  713. def _print_WildFunction(self, expr):
  714. return expr.name + '_'
  715. def _print_WildDot(self, expr):
  716. return expr.name
  717. def _print_WildPlus(self, expr):
  718. return expr.name
  719. def _print_WildStar(self, expr):
  720. return expr.name
  721. def _print_Zero(self, expr):
  722. if self._settings.get("sympy_integers", False):
  723. return "S(0)"
  724. return "0"
  725. def _print_DMP(self, p):
  726. try:
  727. if p.ring is not None:
  728. # TODO incorporate order
  729. return self._print(p.ring.to_sympy(p))
  730. except SympifyError:
  731. pass
  732. cls = p.__class__.__name__
  733. rep = self._print(p.rep)
  734. dom = self._print(p.dom)
  735. ring = self._print(p.ring)
  736. return "%s(%s, %s, %s)" % (cls, rep, dom, ring)
  737. def _print_DMF(self, expr):
  738. return self._print_DMP(expr)
  739. def _print_Object(self, obj):
  740. return 'Object("%s")' % obj.name
  741. def _print_IdentityMorphism(self, morphism):
  742. return 'IdentityMorphism(%s)' % morphism.domain
  743. def _print_NamedMorphism(self, morphism):
  744. return 'NamedMorphism(%s, %s, "%s")' % \
  745. (morphism.domain, morphism.codomain, morphism.name)
  746. def _print_Category(self, category):
  747. return 'Category("%s")' % category.name
  748. def _print_Manifold(self, manifold):
  749. return manifold.name.name
  750. def _print_Patch(self, patch):
  751. return patch.name.name
  752. def _print_CoordSystem(self, coords):
  753. return coords.name.name
  754. def _print_BaseScalarField(self, field):
  755. return field._coord_sys.symbols[field._index].name
  756. def _print_BaseVectorField(self, field):
  757. return 'e_%s' % field._coord_sys.symbols[field._index].name
  758. def _print_Differential(self, diff):
  759. field = diff._form_field
  760. if hasattr(field, '_coord_sys'):
  761. return 'd%s' % field._coord_sys.symbols[field._index].name
  762. else:
  763. return 'd(%s)' % self._print(field)
  764. def _print_Tr(self, expr):
  765. #TODO : Handle indices
  766. return "%s(%s)" % ("Tr", self._print(expr.args[0]))
  767. def _print_Str(self, s):
  768. return self._print(s.name)
  769. def _print_AppliedBinaryRelation(self, expr):
  770. rel = expr.function
  771. return '%s(%s, %s)' % (self._print(rel),
  772. self._print(expr.lhs),
  773. self._print(expr.rhs))
  774. @print_function(StrPrinter)
  775. def sstr(expr, **settings):
  776. """Returns the expression as a string.
  777. For large expressions where speed is a concern, use the setting
  778. order='none'. If abbrev=True setting is used then units are printed in
  779. abbreviated form.
  780. Examples
  781. ========
  782. >>> from sympy import symbols, Eq, sstr
  783. >>> a, b = symbols('a b')
  784. >>> sstr(Eq(a + b, 0))
  785. 'Eq(a + b, 0)'
  786. """
  787. p = StrPrinter(settings)
  788. s = p.doprint(expr)
  789. return s
  790. class StrReprPrinter(StrPrinter):
  791. """(internal) -- see sstrrepr"""
  792. def _print_str(self, s):
  793. return repr(s)
  794. def _print_Str(self, s):
  795. # Str does not to be printed same as str here
  796. return "%s(%s)" % (s.__class__.__name__, self._print(s.name))
  797. @print_function(StrReprPrinter)
  798. def sstrrepr(expr, **settings):
  799. """return expr in mixed str/repr form
  800. i.e. strings are returned in repr form with quotes, and everything else
  801. is returned in str form.
  802. This function could be useful for hooking into sys.displayhook
  803. """
  804. p = StrReprPrinter(settings)
  805. s = p.doprint(expr)
  806. return s