str.py 33 KB

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