pretty.py 102 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922
  1. import itertools
  2. from sympy.core import S
  3. from sympy.core.add import Add
  4. from sympy.core.containers import Tuple
  5. from sympy.core.function import Function
  6. from sympy.core.mul import Mul
  7. from sympy.core.numbers import Number, Rational
  8. from sympy.core.power import Pow
  9. from sympy.core.sorting import default_sort_key
  10. from sympy.core.symbol import Symbol
  11. from sympy.core.sympify import SympifyError
  12. from sympy.printing.conventions import requires_partial
  13. from sympy.printing.precedence import PRECEDENCE, precedence, precedence_traditional
  14. from sympy.printing.printer import Printer, print_function
  15. from sympy.printing.str import sstr
  16. from sympy.utilities.iterables import has_variety
  17. from sympy.utilities.exceptions import sympy_deprecation_warning
  18. from sympy.printing.pretty.stringpict import prettyForm, stringPict
  19. from sympy.printing.pretty.pretty_symbology import hobj, vobj, xobj, \
  20. xsym, pretty_symbol, pretty_atom, pretty_use_unicode, greek_unicode, U, \
  21. pretty_try_use_unicode, annotated
  22. # rename for usage from outside
  23. pprint_use_unicode = pretty_use_unicode
  24. pprint_try_use_unicode = pretty_try_use_unicode
  25. class PrettyPrinter(Printer):
  26. """Printer, which converts an expression into 2D ASCII-art figure."""
  27. printmethod = "_pretty"
  28. _default_settings = {
  29. "order": None,
  30. "full_prec": "auto",
  31. "use_unicode": None,
  32. "wrap_line": True,
  33. "num_columns": None,
  34. "use_unicode_sqrt_char": True,
  35. "root_notation": True,
  36. "mat_symbol_style": "plain",
  37. "imaginary_unit": "i",
  38. "perm_cyclic": True
  39. }
  40. def __init__(self, settings=None):
  41. Printer.__init__(self, settings)
  42. if not isinstance(self._settings['imaginary_unit'], str):
  43. raise TypeError("'imaginary_unit' must a string, not {}".format(self._settings['imaginary_unit']))
  44. elif self._settings['imaginary_unit'] not in ("i", "j"):
  45. raise ValueError("'imaginary_unit' must be either 'i' or 'j', not '{}'".format(self._settings['imaginary_unit']))
  46. def emptyPrinter(self, expr):
  47. return prettyForm(str(expr))
  48. @property
  49. def _use_unicode(self):
  50. if self._settings['use_unicode']:
  51. return True
  52. else:
  53. return pretty_use_unicode()
  54. def doprint(self, expr):
  55. return self._print(expr).render(**self._settings)
  56. # empty op so _print(stringPict) returns the same
  57. def _print_stringPict(self, e):
  58. return e
  59. def _print_basestring(self, e):
  60. return prettyForm(e)
  61. def _print_atan2(self, e):
  62. pform = prettyForm(*self._print_seq(e.args).parens())
  63. pform = prettyForm(*pform.left('atan2'))
  64. return pform
  65. def _print_Symbol(self, e, bold_name=False):
  66. symb = pretty_symbol(e.name, bold_name)
  67. return prettyForm(symb)
  68. _print_RandomSymbol = _print_Symbol
  69. def _print_MatrixSymbol(self, e):
  70. return self._print_Symbol(e, self._settings['mat_symbol_style'] == "bold")
  71. def _print_Float(self, e):
  72. # we will use StrPrinter's Float printer, but we need to handle the
  73. # full_prec ourselves, according to the self._print_level
  74. full_prec = self._settings["full_prec"]
  75. if full_prec == "auto":
  76. full_prec = self._print_level == 1
  77. return prettyForm(sstr(e, full_prec=full_prec))
  78. def _print_Cross(self, e):
  79. vec1 = e._expr1
  80. vec2 = e._expr2
  81. pform = self._print(vec2)
  82. pform = prettyForm(*pform.left('('))
  83. pform = prettyForm(*pform.right(')'))
  84. pform = prettyForm(*pform.left(self._print(U('MULTIPLICATION SIGN'))))
  85. pform = prettyForm(*pform.left(')'))
  86. pform = prettyForm(*pform.left(self._print(vec1)))
  87. pform = prettyForm(*pform.left('('))
  88. return pform
  89. def _print_Curl(self, e):
  90. vec = e._expr
  91. pform = self._print(vec)
  92. pform = prettyForm(*pform.left('('))
  93. pform = prettyForm(*pform.right(')'))
  94. pform = prettyForm(*pform.left(self._print(U('MULTIPLICATION SIGN'))))
  95. pform = prettyForm(*pform.left(self._print(U('NABLA'))))
  96. return pform
  97. def _print_Divergence(self, e):
  98. vec = e._expr
  99. pform = self._print(vec)
  100. pform = prettyForm(*pform.left('('))
  101. pform = prettyForm(*pform.right(')'))
  102. pform = prettyForm(*pform.left(self._print(U('DOT OPERATOR'))))
  103. pform = prettyForm(*pform.left(self._print(U('NABLA'))))
  104. return pform
  105. def _print_Dot(self, e):
  106. vec1 = e._expr1
  107. vec2 = e._expr2
  108. pform = self._print(vec2)
  109. pform = prettyForm(*pform.left('('))
  110. pform = prettyForm(*pform.right(')'))
  111. pform = prettyForm(*pform.left(self._print(U('DOT OPERATOR'))))
  112. pform = prettyForm(*pform.left(')'))
  113. pform = prettyForm(*pform.left(self._print(vec1)))
  114. pform = prettyForm(*pform.left('('))
  115. return pform
  116. def _print_Gradient(self, e):
  117. func = e._expr
  118. pform = self._print(func)
  119. pform = prettyForm(*pform.left('('))
  120. pform = prettyForm(*pform.right(')'))
  121. pform = prettyForm(*pform.left(self._print(U('NABLA'))))
  122. return pform
  123. def _print_Laplacian(self, e):
  124. func = e._expr
  125. pform = self._print(func)
  126. pform = prettyForm(*pform.left('('))
  127. pform = prettyForm(*pform.right(')'))
  128. pform = prettyForm(*pform.left(self._print(U('INCREMENT'))))
  129. return pform
  130. def _print_Atom(self, e):
  131. try:
  132. # print atoms like Exp1 or Pi
  133. return prettyForm(pretty_atom(e.__class__.__name__, printer=self))
  134. except KeyError:
  135. return self.emptyPrinter(e)
  136. # Infinity inherits from Number, so we have to override _print_XXX order
  137. _print_Infinity = _print_Atom
  138. _print_NegativeInfinity = _print_Atom
  139. _print_EmptySet = _print_Atom
  140. _print_Naturals = _print_Atom
  141. _print_Naturals0 = _print_Atom
  142. _print_Integers = _print_Atom
  143. _print_Rationals = _print_Atom
  144. _print_Complexes = _print_Atom
  145. _print_EmptySequence = _print_Atom
  146. def _print_Reals(self, e):
  147. if self._use_unicode:
  148. return self._print_Atom(e)
  149. else:
  150. inf_list = ['-oo', 'oo']
  151. return self._print_seq(inf_list, '(', ')')
  152. def _print_subfactorial(self, e):
  153. x = e.args[0]
  154. pform = self._print(x)
  155. # Add parentheses if needed
  156. if not ((x.is_Integer and x.is_nonnegative) or x.is_Symbol):
  157. pform = prettyForm(*pform.parens())
  158. pform = prettyForm(*pform.left('!'))
  159. return pform
  160. def _print_factorial(self, e):
  161. x = e.args[0]
  162. pform = self._print(x)
  163. # Add parentheses if needed
  164. if not ((x.is_Integer and x.is_nonnegative) or x.is_Symbol):
  165. pform = prettyForm(*pform.parens())
  166. pform = prettyForm(*pform.right('!'))
  167. return pform
  168. def _print_factorial2(self, e):
  169. x = e.args[0]
  170. pform = self._print(x)
  171. # Add parentheses if needed
  172. if not ((x.is_Integer and x.is_nonnegative) or x.is_Symbol):
  173. pform = prettyForm(*pform.parens())
  174. pform = prettyForm(*pform.right('!!'))
  175. return pform
  176. def _print_binomial(self, e):
  177. n, k = e.args
  178. n_pform = self._print(n)
  179. k_pform = self._print(k)
  180. bar = ' '*max(n_pform.width(), k_pform.width())
  181. pform = prettyForm(*k_pform.above(bar))
  182. pform = prettyForm(*pform.above(n_pform))
  183. pform = prettyForm(*pform.parens('(', ')'))
  184. pform.baseline = (pform.baseline + 1)//2
  185. return pform
  186. def _print_Relational(self, e):
  187. op = prettyForm(' ' + xsym(e.rel_op) + ' ')
  188. l = self._print(e.lhs)
  189. r = self._print(e.rhs)
  190. pform = prettyForm(*stringPict.next(l, op, r), binding=prettyForm.OPEN)
  191. return pform
  192. def _print_Not(self, e):
  193. from sympy.logic.boolalg import (Equivalent, Implies)
  194. if self._use_unicode:
  195. arg = e.args[0]
  196. pform = self._print(arg)
  197. if isinstance(arg, Equivalent):
  198. return self._print_Equivalent(arg, altchar="\N{LEFT RIGHT DOUBLE ARROW WITH STROKE}")
  199. if isinstance(arg, Implies):
  200. return self._print_Implies(arg, altchar="\N{RIGHTWARDS ARROW WITH STROKE}")
  201. if arg.is_Boolean and not arg.is_Not:
  202. pform = prettyForm(*pform.parens())
  203. return prettyForm(*pform.left("\N{NOT SIGN}"))
  204. else:
  205. return self._print_Function(e)
  206. def __print_Boolean(self, e, char, sort=True):
  207. args = e.args
  208. if sort:
  209. args = sorted(e.args, key=default_sort_key)
  210. arg = args[0]
  211. pform = self._print(arg)
  212. if arg.is_Boolean and not arg.is_Not:
  213. pform = prettyForm(*pform.parens())
  214. for arg in args[1:]:
  215. pform_arg = self._print(arg)
  216. if arg.is_Boolean and not arg.is_Not:
  217. pform_arg = prettyForm(*pform_arg.parens())
  218. pform = prettyForm(*pform.right(' %s ' % char))
  219. pform = prettyForm(*pform.right(pform_arg))
  220. return pform
  221. def _print_And(self, e):
  222. if self._use_unicode:
  223. return self.__print_Boolean(e, "\N{LOGICAL AND}")
  224. else:
  225. return self._print_Function(e, sort=True)
  226. def _print_Or(self, e):
  227. if self._use_unicode:
  228. return self.__print_Boolean(e, "\N{LOGICAL OR}")
  229. else:
  230. return self._print_Function(e, sort=True)
  231. def _print_Xor(self, e):
  232. if self._use_unicode:
  233. return self.__print_Boolean(e, "\N{XOR}")
  234. else:
  235. return self._print_Function(e, sort=True)
  236. def _print_Nand(self, e):
  237. if self._use_unicode:
  238. return self.__print_Boolean(e, "\N{NAND}")
  239. else:
  240. return self._print_Function(e, sort=True)
  241. def _print_Nor(self, e):
  242. if self._use_unicode:
  243. return self.__print_Boolean(e, "\N{NOR}")
  244. else:
  245. return self._print_Function(e, sort=True)
  246. def _print_Implies(self, e, altchar=None):
  247. if self._use_unicode:
  248. return self.__print_Boolean(e, altchar or "\N{RIGHTWARDS ARROW}", sort=False)
  249. else:
  250. return self._print_Function(e)
  251. def _print_Equivalent(self, e, altchar=None):
  252. if self._use_unicode:
  253. return self.__print_Boolean(e, altchar or "\N{LEFT RIGHT DOUBLE ARROW}")
  254. else:
  255. return self._print_Function(e, sort=True)
  256. def _print_conjugate(self, e):
  257. pform = self._print(e.args[0])
  258. return prettyForm( *pform.above( hobj('_', pform.width())) )
  259. def _print_Abs(self, e):
  260. pform = self._print(e.args[0])
  261. pform = prettyForm(*pform.parens('|', '|'))
  262. return pform
  263. _print_Determinant = _print_Abs
  264. def _print_floor(self, e):
  265. if self._use_unicode:
  266. pform = self._print(e.args[0])
  267. pform = prettyForm(*pform.parens('lfloor', 'rfloor'))
  268. return pform
  269. else:
  270. return self._print_Function(e)
  271. def _print_ceiling(self, e):
  272. if self._use_unicode:
  273. pform = self._print(e.args[0])
  274. pform = prettyForm(*pform.parens('lceil', 'rceil'))
  275. return pform
  276. else:
  277. return self._print_Function(e)
  278. def _print_Derivative(self, deriv):
  279. if requires_partial(deriv.expr) and self._use_unicode:
  280. deriv_symbol = U('PARTIAL DIFFERENTIAL')
  281. else:
  282. deriv_symbol = r'd'
  283. x = None
  284. count_total_deriv = 0
  285. for sym, num in reversed(deriv.variable_count):
  286. s = self._print(sym)
  287. ds = prettyForm(*s.left(deriv_symbol))
  288. count_total_deriv += num
  289. if (not num.is_Integer) or (num > 1):
  290. ds = ds**prettyForm(str(num))
  291. if x is None:
  292. x = ds
  293. else:
  294. x = prettyForm(*x.right(' '))
  295. x = prettyForm(*x.right(ds))
  296. f = prettyForm(
  297. binding=prettyForm.FUNC, *self._print(deriv.expr).parens())
  298. pform = prettyForm(deriv_symbol)
  299. if (count_total_deriv > 1) != False:
  300. pform = pform**prettyForm(str(count_total_deriv))
  301. pform = prettyForm(*pform.below(stringPict.LINE, x))
  302. pform.baseline = pform.baseline + 1
  303. pform = prettyForm(*stringPict.next(pform, f))
  304. pform.binding = prettyForm.MUL
  305. return pform
  306. def _print_Cycle(self, dc):
  307. from sympy.combinatorics.permutations import Permutation, Cycle
  308. # for Empty Cycle
  309. if dc == Cycle():
  310. cyc = stringPict('')
  311. return prettyForm(*cyc.parens())
  312. dc_list = Permutation(dc.list()).cyclic_form
  313. # for Identity Cycle
  314. if dc_list == []:
  315. cyc = self._print(dc.size - 1)
  316. return prettyForm(*cyc.parens())
  317. cyc = stringPict('')
  318. for i in dc_list:
  319. l = self._print(str(tuple(i)).replace(',', ''))
  320. cyc = prettyForm(*cyc.right(l))
  321. return cyc
  322. def _print_Permutation(self, expr):
  323. from sympy.combinatorics.permutations import Permutation, Cycle
  324. perm_cyclic = Permutation.print_cyclic
  325. if perm_cyclic is not None:
  326. sympy_deprecation_warning(
  327. f"""
  328. Setting Permutation.print_cyclic is deprecated. Instead use
  329. init_printing(perm_cyclic={perm_cyclic}).
  330. """,
  331. deprecated_since_version="1.6",
  332. active_deprecations_target="deprecated-permutation-print_cyclic",
  333. stacklevel=7,
  334. )
  335. else:
  336. perm_cyclic = self._settings.get("perm_cyclic", True)
  337. if perm_cyclic:
  338. return self._print_Cycle(Cycle(expr))
  339. lower = expr.array_form
  340. upper = list(range(len(lower)))
  341. result = stringPict('')
  342. first = True
  343. for u, l in zip(upper, lower):
  344. s1 = self._print(u)
  345. s2 = self._print(l)
  346. col = prettyForm(*s1.below(s2))
  347. if first:
  348. first = False
  349. else:
  350. col = prettyForm(*col.left(" "))
  351. result = prettyForm(*result.right(col))
  352. return prettyForm(*result.parens())
  353. def _print_Integral(self, integral):
  354. f = integral.function
  355. # Add parentheses if arg involves addition of terms and
  356. # create a pretty form for the argument
  357. prettyF = self._print(f)
  358. # XXX generalize parens
  359. if f.is_Add:
  360. prettyF = prettyForm(*prettyF.parens())
  361. # dx dy dz ...
  362. arg = prettyF
  363. for x in integral.limits:
  364. prettyArg = self._print(x[0])
  365. # XXX qparens (parens if needs-parens)
  366. if prettyArg.width() > 1:
  367. prettyArg = prettyForm(*prettyArg.parens())
  368. arg = prettyForm(*arg.right(' d', prettyArg))
  369. # \int \int \int ...
  370. firstterm = True
  371. s = None
  372. for lim in integral.limits:
  373. # Create bar based on the height of the argument
  374. h = arg.height()
  375. H = h + 2
  376. # XXX hack!
  377. ascii_mode = not self._use_unicode
  378. if ascii_mode:
  379. H += 2
  380. vint = vobj('int', H)
  381. # Construct the pretty form with the integral sign and the argument
  382. pform = prettyForm(vint)
  383. pform.baseline = arg.baseline + (
  384. H - h)//2 # covering the whole argument
  385. if len(lim) > 1:
  386. # Create pretty forms for endpoints, if definite integral.
  387. # Do not print empty endpoints.
  388. if len(lim) == 2:
  389. prettyA = prettyForm("")
  390. prettyB = self._print(lim[1])
  391. if len(lim) == 3:
  392. prettyA = self._print(lim[1])
  393. prettyB = self._print(lim[2])
  394. if ascii_mode: # XXX hack
  395. # Add spacing so that endpoint can more easily be
  396. # identified with the correct integral sign
  397. spc = max(1, 3 - prettyB.width())
  398. prettyB = prettyForm(*prettyB.left(' ' * spc))
  399. spc = max(1, 4 - prettyA.width())
  400. prettyA = prettyForm(*prettyA.right(' ' * spc))
  401. pform = prettyForm(*pform.above(prettyB))
  402. pform = prettyForm(*pform.below(prettyA))
  403. if not ascii_mode: # XXX hack
  404. pform = prettyForm(*pform.right(' '))
  405. if firstterm:
  406. s = pform # first term
  407. firstterm = False
  408. else:
  409. s = prettyForm(*s.left(pform))
  410. pform = prettyForm(*arg.left(s))
  411. pform.binding = prettyForm.MUL
  412. return pform
  413. def _print_Product(self, expr):
  414. func = expr.term
  415. pretty_func = self._print(func)
  416. horizontal_chr = xobj('_', 1)
  417. corner_chr = xobj('_', 1)
  418. vertical_chr = xobj('|', 1)
  419. if self._use_unicode:
  420. # use unicode corners
  421. horizontal_chr = xobj('-', 1)
  422. corner_chr = '\N{BOX DRAWINGS LIGHT DOWN AND HORIZONTAL}'
  423. func_height = pretty_func.height()
  424. first = True
  425. max_upper = 0
  426. sign_height = 0
  427. for lim in expr.limits:
  428. pretty_lower, pretty_upper = self.__print_SumProduct_Limits(lim)
  429. width = (func_height + 2) * 5 // 3 - 2
  430. sign_lines = [horizontal_chr + corner_chr + (horizontal_chr * (width-2)) + corner_chr + horizontal_chr]
  431. for _ in range(func_height + 1):
  432. sign_lines.append(' ' + vertical_chr + (' ' * (width-2)) + vertical_chr + ' ')
  433. pretty_sign = stringPict('')
  434. pretty_sign = prettyForm(*pretty_sign.stack(*sign_lines))
  435. max_upper = max(max_upper, pretty_upper.height())
  436. if first:
  437. sign_height = pretty_sign.height()
  438. pretty_sign = prettyForm(*pretty_sign.above(pretty_upper))
  439. pretty_sign = prettyForm(*pretty_sign.below(pretty_lower))
  440. if first:
  441. pretty_func.baseline = 0
  442. first = False
  443. height = pretty_sign.height()
  444. padding = stringPict('')
  445. padding = prettyForm(*padding.stack(*[' ']*(height - 1)))
  446. pretty_sign = prettyForm(*pretty_sign.right(padding))
  447. pretty_func = prettyForm(*pretty_sign.right(pretty_func))
  448. pretty_func.baseline = max_upper + sign_height//2
  449. pretty_func.binding = prettyForm.MUL
  450. return pretty_func
  451. def __print_SumProduct_Limits(self, lim):
  452. def print_start(lhs, rhs):
  453. op = prettyForm(' ' + xsym("==") + ' ')
  454. l = self._print(lhs)
  455. r = self._print(rhs)
  456. pform = prettyForm(*stringPict.next(l, op, r))
  457. return pform
  458. prettyUpper = self._print(lim[2])
  459. prettyLower = print_start(lim[0], lim[1])
  460. return prettyLower, prettyUpper
  461. def _print_Sum(self, expr):
  462. ascii_mode = not self._use_unicode
  463. def asum(hrequired, lower, upper, use_ascii):
  464. def adjust(s, wid=None, how='<^>'):
  465. if not wid or len(s) > wid:
  466. return s
  467. need = wid - len(s)
  468. if how in ('<^>', "<") or how not in list('<^>'):
  469. return s + ' '*need
  470. half = need//2
  471. lead = ' '*half
  472. if how == ">":
  473. return " "*need + s
  474. return lead + s + ' '*(need - len(lead))
  475. h = max(hrequired, 2)
  476. d = h//2
  477. w = d + 1
  478. more = hrequired % 2
  479. lines = []
  480. if use_ascii:
  481. lines.append("_"*(w) + ' ')
  482. lines.append(r"\%s`" % (' '*(w - 1)))
  483. for i in range(1, d):
  484. lines.append('%s\\%s' % (' '*i, ' '*(w - i)))
  485. if more:
  486. lines.append('%s)%s' % (' '*(d), ' '*(w - d)))
  487. for i in reversed(range(1, d)):
  488. lines.append('%s/%s' % (' '*i, ' '*(w - i)))
  489. lines.append("/" + "_"*(w - 1) + ',')
  490. return d, h + more, lines, more
  491. else:
  492. w = w + more
  493. d = d + more
  494. vsum = vobj('sum', 4)
  495. lines.append("_"*(w))
  496. for i in range(0, d):
  497. lines.append('%s%s%s' % (' '*i, vsum[2], ' '*(w - i - 1)))
  498. for i in reversed(range(0, d)):
  499. lines.append('%s%s%s' % (' '*i, vsum[4], ' '*(w - i - 1)))
  500. lines.append(vsum[8]*(w))
  501. return d, h + 2*more, lines, more
  502. f = expr.function
  503. prettyF = self._print(f)
  504. if f.is_Add: # add parens
  505. prettyF = prettyForm(*prettyF.parens())
  506. H = prettyF.height() + 2
  507. # \sum \sum \sum ...
  508. first = True
  509. max_upper = 0
  510. sign_height = 0
  511. for lim in expr.limits:
  512. prettyLower, prettyUpper = self.__print_SumProduct_Limits(lim)
  513. max_upper = max(max_upper, prettyUpper.height())
  514. # Create sum sign based on the height of the argument
  515. d, h, slines, adjustment = asum(
  516. H, prettyLower.width(), prettyUpper.width(), ascii_mode)
  517. prettySign = stringPict('')
  518. prettySign = prettyForm(*prettySign.stack(*slines))
  519. if first:
  520. sign_height = prettySign.height()
  521. prettySign = prettyForm(*prettySign.above(prettyUpper))
  522. prettySign = prettyForm(*prettySign.below(prettyLower))
  523. if first:
  524. # change F baseline so it centers on the sign
  525. prettyF.baseline -= d - (prettyF.height()//2 -
  526. prettyF.baseline)
  527. first = False
  528. # put padding to the right
  529. pad = stringPict('')
  530. pad = prettyForm(*pad.stack(*[' ']*h))
  531. prettySign = prettyForm(*prettySign.right(pad))
  532. # put the present prettyF to the right
  533. prettyF = prettyForm(*prettySign.right(prettyF))
  534. # adjust baseline of ascii mode sigma with an odd height so that it is
  535. # exactly through the center
  536. ascii_adjustment = ascii_mode if not adjustment else 0
  537. prettyF.baseline = max_upper + sign_height//2 + ascii_adjustment
  538. prettyF.binding = prettyForm.MUL
  539. return prettyF
  540. def _print_Limit(self, l):
  541. e, z, z0, dir = l.args
  542. E = self._print(e)
  543. if precedence(e) <= PRECEDENCE["Mul"]:
  544. E = prettyForm(*E.parens('(', ')'))
  545. Lim = prettyForm('lim')
  546. LimArg = self._print(z)
  547. if self._use_unicode:
  548. LimArg = prettyForm(*LimArg.right('\N{BOX DRAWINGS LIGHT HORIZONTAL}\N{RIGHTWARDS ARROW}'))
  549. else:
  550. LimArg = prettyForm(*LimArg.right('->'))
  551. LimArg = prettyForm(*LimArg.right(self._print(z0)))
  552. if str(dir) == '+-' or z0 in (S.Infinity, S.NegativeInfinity):
  553. dir = ""
  554. else:
  555. if self._use_unicode:
  556. dir = '\N{SUPERSCRIPT PLUS SIGN}' if str(dir) == "+" else '\N{SUPERSCRIPT MINUS}'
  557. LimArg = prettyForm(*LimArg.right(self._print(dir)))
  558. Lim = prettyForm(*Lim.below(LimArg))
  559. Lim = prettyForm(*Lim.right(E), binding=prettyForm.MUL)
  560. return Lim
  561. def _print_matrix_contents(self, e):
  562. """
  563. This method factors out what is essentially grid printing.
  564. """
  565. M = e # matrix
  566. Ms = {} # i,j -> pretty(M[i,j])
  567. for i in range(M.rows):
  568. for j in range(M.cols):
  569. Ms[i, j] = self._print(M[i, j])
  570. # h- and v- spacers
  571. hsep = 2
  572. vsep = 1
  573. # max width for columns
  574. maxw = [-1] * M.cols
  575. for j in range(M.cols):
  576. maxw[j] = max([Ms[i, j].width() for i in range(M.rows)] or [0])
  577. # drawing result
  578. D = None
  579. for i in range(M.rows):
  580. D_row = None
  581. for j in range(M.cols):
  582. s = Ms[i, j]
  583. # reshape s to maxw
  584. # XXX this should be generalized, and go to stringPict.reshape ?
  585. assert s.width() <= maxw[j]
  586. # hcenter it, +0.5 to the right 2
  587. # ( it's better to align formula starts for say 0 and r )
  588. # XXX this is not good in all cases -- maybe introduce vbaseline?
  589. wdelta = maxw[j] - s.width()
  590. wleft = wdelta // 2
  591. wright = wdelta - wleft
  592. s = prettyForm(*s.right(' '*wright))
  593. s = prettyForm(*s.left(' '*wleft))
  594. # we don't need vcenter cells -- this is automatically done in
  595. # a pretty way because when their baselines are taking into
  596. # account in .right()
  597. if D_row is None:
  598. D_row = s # first box in a row
  599. continue
  600. D_row = prettyForm(*D_row.right(' '*hsep)) # h-spacer
  601. D_row = prettyForm(*D_row.right(s))
  602. if D is None:
  603. D = D_row # first row in a picture
  604. continue
  605. # v-spacer
  606. for _ in range(vsep):
  607. D = prettyForm(*D.below(' '))
  608. D = prettyForm(*D.below(D_row))
  609. if D is None:
  610. D = prettyForm('') # Empty Matrix
  611. return D
  612. def _print_MatrixBase(self, e):
  613. D = self._print_matrix_contents(e)
  614. D.baseline = D.height()//2
  615. D = prettyForm(*D.parens('[', ']'))
  616. return D
  617. def _print_TensorProduct(self, expr):
  618. # This should somehow share the code with _print_WedgeProduct:
  619. if self._use_unicode:
  620. circled_times = "\u2297"
  621. else:
  622. circled_times = ".*"
  623. return self._print_seq(expr.args, None, None, circled_times,
  624. parenthesize=lambda x: precedence_traditional(x) <= PRECEDENCE["Mul"])
  625. def _print_WedgeProduct(self, expr):
  626. # This should somehow share the code with _print_TensorProduct:
  627. if self._use_unicode:
  628. wedge_symbol = "\u2227"
  629. else:
  630. wedge_symbol = '/\\'
  631. return self._print_seq(expr.args, None, None, wedge_symbol,
  632. parenthesize=lambda x: precedence_traditional(x) <= PRECEDENCE["Mul"])
  633. def _print_Trace(self, e):
  634. D = self._print(e.arg)
  635. D = prettyForm(*D.parens('(',')'))
  636. D.baseline = D.height()//2
  637. D = prettyForm(*D.left('\n'*(0) + 'tr'))
  638. return D
  639. def _print_MatrixElement(self, expr):
  640. from sympy.matrices import MatrixSymbol
  641. if (isinstance(expr.parent, MatrixSymbol)
  642. and expr.i.is_number and expr.j.is_number):
  643. return self._print(
  644. Symbol(expr.parent.name + '_%d%d' % (expr.i, expr.j)))
  645. else:
  646. prettyFunc = self._print(expr.parent)
  647. prettyFunc = prettyForm(*prettyFunc.parens())
  648. prettyIndices = self._print_seq((expr.i, expr.j), delimiter=', '
  649. ).parens(left='[', right=']')[0]
  650. pform = prettyForm(binding=prettyForm.FUNC,
  651. *stringPict.next(prettyFunc, prettyIndices))
  652. # store pform parts so it can be reassembled e.g. when powered
  653. pform.prettyFunc = prettyFunc
  654. pform.prettyArgs = prettyIndices
  655. return pform
  656. def _print_MatrixSlice(self, m):
  657. # XXX works only for applied functions
  658. from sympy.matrices import MatrixSymbol
  659. prettyFunc = self._print(m.parent)
  660. if not isinstance(m.parent, MatrixSymbol):
  661. prettyFunc = prettyForm(*prettyFunc.parens())
  662. def ppslice(x, dim):
  663. x = list(x)
  664. if x[2] == 1:
  665. del x[2]
  666. if x[0] == 0:
  667. x[0] = ''
  668. if x[1] == dim:
  669. x[1] = ''
  670. return prettyForm(*self._print_seq(x, delimiter=':'))
  671. prettyArgs = self._print_seq((ppslice(m.rowslice, m.parent.rows),
  672. ppslice(m.colslice, m.parent.cols)), delimiter=', ').parens(left='[', right=']')[0]
  673. pform = prettyForm(
  674. binding=prettyForm.FUNC, *stringPict.next(prettyFunc, prettyArgs))
  675. # store pform parts so it can be reassembled e.g. when powered
  676. pform.prettyFunc = prettyFunc
  677. pform.prettyArgs = prettyArgs
  678. return pform
  679. def _print_Transpose(self, expr):
  680. pform = self._print(expr.arg)
  681. from sympy.matrices import MatrixSymbol
  682. if not isinstance(expr.arg, MatrixSymbol) and expr.arg.is_MatrixExpr:
  683. pform = prettyForm(*pform.parens())
  684. pform = pform**(prettyForm('T'))
  685. return pform
  686. def _print_Adjoint(self, expr):
  687. pform = self._print(expr.arg)
  688. if self._use_unicode:
  689. dag = prettyForm('\N{DAGGER}')
  690. else:
  691. dag = prettyForm('+')
  692. from sympy.matrices import MatrixSymbol
  693. if not isinstance(expr.arg, MatrixSymbol) and expr.arg.is_MatrixExpr:
  694. pform = prettyForm(*pform.parens())
  695. pform = pform**dag
  696. return pform
  697. def _print_BlockMatrix(self, B):
  698. if B.blocks.shape == (1, 1):
  699. return self._print(B.blocks[0, 0])
  700. return self._print(B.blocks)
  701. def _print_MatAdd(self, expr):
  702. s = None
  703. for item in expr.args:
  704. pform = self._print(item)
  705. if s is None:
  706. s = pform # First element
  707. else:
  708. coeff = item.as_coeff_mmul()[0]
  709. if S(coeff).could_extract_minus_sign():
  710. s = prettyForm(*stringPict.next(s, ' '))
  711. pform = self._print(item)
  712. else:
  713. s = prettyForm(*stringPict.next(s, ' + '))
  714. s = prettyForm(*stringPict.next(s, pform))
  715. return s
  716. def _print_MatMul(self, expr):
  717. args = list(expr.args)
  718. from sympy.matrices.expressions.hadamard import HadamardProduct
  719. from sympy.matrices.expressions.kronecker import KroneckerProduct
  720. from sympy.matrices.expressions.matadd import MatAdd
  721. for i, a in enumerate(args):
  722. if (isinstance(a, (Add, MatAdd, HadamardProduct, KroneckerProduct))
  723. and len(expr.args) > 1):
  724. args[i] = prettyForm(*self._print(a).parens())
  725. else:
  726. args[i] = self._print(a)
  727. return prettyForm.__mul__(*args)
  728. def _print_Identity(self, expr):
  729. if self._use_unicode:
  730. return prettyForm('\N{MATHEMATICAL DOUBLE-STRUCK CAPITAL I}')
  731. else:
  732. return prettyForm('I')
  733. def _print_ZeroMatrix(self, expr):
  734. if self._use_unicode:
  735. return prettyForm('\N{MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO}')
  736. else:
  737. return prettyForm('0')
  738. def _print_OneMatrix(self, expr):
  739. if self._use_unicode:
  740. return prettyForm('\N{MATHEMATICAL DOUBLE-STRUCK DIGIT ONE}')
  741. else:
  742. return prettyForm('1')
  743. def _print_DotProduct(self, expr):
  744. args = list(expr.args)
  745. for i, a in enumerate(args):
  746. args[i] = self._print(a)
  747. return prettyForm.__mul__(*args)
  748. def _print_MatPow(self, expr):
  749. pform = self._print(expr.base)
  750. from sympy.matrices import MatrixSymbol
  751. if not isinstance(expr.base, MatrixSymbol):
  752. pform = prettyForm(*pform.parens())
  753. pform = pform**(self._print(expr.exp))
  754. return pform
  755. def _print_HadamardProduct(self, expr):
  756. from sympy.matrices.expressions.hadamard import HadamardProduct
  757. from sympy.matrices.expressions.matadd import MatAdd
  758. from sympy.matrices.expressions.matmul import MatMul
  759. if self._use_unicode:
  760. delim = pretty_atom('Ring')
  761. else:
  762. delim = '.*'
  763. return self._print_seq(expr.args, None, None, delim,
  764. parenthesize=lambda x: isinstance(x, (MatAdd, MatMul, HadamardProduct)))
  765. def _print_HadamardPower(self, expr):
  766. # from sympy import MatAdd, MatMul
  767. if self._use_unicode:
  768. circ = pretty_atom('Ring')
  769. else:
  770. circ = self._print('.')
  771. pretty_base = self._print(expr.base)
  772. pretty_exp = self._print(expr.exp)
  773. if precedence(expr.exp) < PRECEDENCE["Mul"]:
  774. pretty_exp = prettyForm(*pretty_exp.parens())
  775. pretty_circ_exp = prettyForm(
  776. binding=prettyForm.LINE,
  777. *stringPict.next(circ, pretty_exp)
  778. )
  779. return pretty_base**pretty_circ_exp
  780. def _print_KroneckerProduct(self, expr):
  781. from sympy.matrices.expressions.matadd import MatAdd
  782. from sympy.matrices.expressions.matmul import MatMul
  783. if self._use_unicode:
  784. delim = ' \N{N-ARY CIRCLED TIMES OPERATOR} '
  785. else:
  786. delim = ' x '
  787. return self._print_seq(expr.args, None, None, delim,
  788. parenthesize=lambda x: isinstance(x, (MatAdd, MatMul)))
  789. def _print_FunctionMatrix(self, X):
  790. D = self._print(X.lamda.expr)
  791. D = prettyForm(*D.parens('[', ']'))
  792. return D
  793. def _print_TransferFunction(self, expr):
  794. if not expr.num == 1:
  795. num, den = expr.num, expr.den
  796. res = Mul(num, Pow(den, -1, evaluate=False), evaluate=False)
  797. return self._print_Mul(res)
  798. else:
  799. return self._print(1)/self._print(expr.den)
  800. def _print_Series(self, expr):
  801. args = list(expr.args)
  802. for i, a in enumerate(expr.args):
  803. args[i] = prettyForm(*self._print(a).parens())
  804. return prettyForm.__mul__(*args)
  805. def _print_MIMOSeries(self, expr):
  806. from sympy.physics.control.lti import MIMOParallel
  807. args = list(expr.args)
  808. pretty_args = []
  809. for i, a in enumerate(reversed(args)):
  810. if (isinstance(a, MIMOParallel) and len(expr.args) > 1):
  811. expression = self._print(a)
  812. expression.baseline = expression.height()//2
  813. pretty_args.append(prettyForm(*expression.parens()))
  814. else:
  815. expression = self._print(a)
  816. expression.baseline = expression.height()//2
  817. pretty_args.append(expression)
  818. return prettyForm.__mul__(*pretty_args)
  819. def _print_Parallel(self, expr):
  820. s = None
  821. for item in expr.args:
  822. pform = self._print(item)
  823. if s is None:
  824. s = pform # First element
  825. else:
  826. s = prettyForm(*stringPict.next(s))
  827. s.baseline = s.height()//2
  828. s = prettyForm(*stringPict.next(s, ' + '))
  829. s = prettyForm(*stringPict.next(s, pform))
  830. return s
  831. def _print_MIMOParallel(self, expr):
  832. from sympy.physics.control.lti import TransferFunctionMatrix
  833. s = None
  834. for item in expr.args:
  835. pform = self._print(item)
  836. if s is None:
  837. s = pform # First element
  838. else:
  839. s = prettyForm(*stringPict.next(s))
  840. s.baseline = s.height()//2
  841. s = prettyForm(*stringPict.next(s, ' + '))
  842. if isinstance(item, TransferFunctionMatrix):
  843. s.baseline = s.height() - 1
  844. s = prettyForm(*stringPict.next(s, pform))
  845. # s.baseline = s.height()//2
  846. return s
  847. def _print_Feedback(self, expr):
  848. from sympy.physics.control import TransferFunction, Series
  849. num, tf = expr.sys1, TransferFunction(1, 1, expr.var)
  850. num_arg_list = list(num.args) if isinstance(num, Series) else [num]
  851. den_arg_list = list(expr.sys2.args) if \
  852. isinstance(expr.sys2, Series) else [expr.sys2]
  853. if isinstance(num, Series) and isinstance(expr.sys2, Series):
  854. den = Series(*num_arg_list, *den_arg_list)
  855. elif isinstance(num, Series) and isinstance(expr.sys2, TransferFunction):
  856. if expr.sys2 == tf:
  857. den = Series(*num_arg_list)
  858. else:
  859. den = Series(*num_arg_list, expr.sys2)
  860. elif isinstance(num, TransferFunction) and isinstance(expr.sys2, Series):
  861. if num == tf:
  862. den = Series(*den_arg_list)
  863. else:
  864. den = Series(num, *den_arg_list)
  865. else:
  866. if num == tf:
  867. den = Series(*den_arg_list)
  868. elif expr.sys2 == tf:
  869. den = Series(*num_arg_list)
  870. else:
  871. den = Series(*num_arg_list, *den_arg_list)
  872. denom = prettyForm(*stringPict.next(self._print(tf)))
  873. denom.baseline = denom.height()//2
  874. denom = prettyForm(*stringPict.next(denom, ' + ')) if expr.sign == -1 \
  875. else prettyForm(*stringPict.next(denom, ' - '))
  876. denom = prettyForm(*stringPict.next(denom, self._print(den)))
  877. return self._print(num)/denom
  878. def _print_MIMOFeedback(self, expr):
  879. from sympy.physics.control import MIMOSeries, TransferFunctionMatrix
  880. inv_mat = self._print(MIMOSeries(expr.sys2, expr.sys1))
  881. plant = self._print(expr.sys1)
  882. _feedback = prettyForm(*stringPict.next(inv_mat))
  883. _feedback = prettyForm(*stringPict.right("I + ", _feedback)) if expr.sign == -1 \
  884. else prettyForm(*stringPict.right("I - ", _feedback))
  885. _feedback = prettyForm(*stringPict.parens(_feedback))
  886. _feedback.baseline = 0
  887. _feedback = prettyForm(*stringPict.right(_feedback, '-1 '))
  888. _feedback.baseline = _feedback.height()//2
  889. _feedback = prettyForm.__mul__(_feedback, prettyForm(" "))
  890. if isinstance(expr.sys1, TransferFunctionMatrix):
  891. _feedback.baseline = _feedback.height() - 1
  892. _feedback = prettyForm(*stringPict.next(_feedback, plant))
  893. return _feedback
  894. def _print_TransferFunctionMatrix(self, expr):
  895. mat = self._print(expr._expr_mat)
  896. mat.baseline = mat.height() - 1
  897. subscript = greek_unicode['tau'] if self._use_unicode else r'{t}'
  898. mat = prettyForm(*mat.right(subscript))
  899. return mat
  900. def _print_BasisDependent(self, expr):
  901. from sympy.vector import Vector
  902. if not self._use_unicode:
  903. raise NotImplementedError("ASCII pretty printing of BasisDependent is not implemented")
  904. if expr == expr.zero:
  905. return prettyForm(expr.zero._pretty_form)
  906. o1 = []
  907. vectstrs = []
  908. if isinstance(expr, Vector):
  909. items = expr.separate().items()
  910. else:
  911. items = [(0, expr)]
  912. for system, vect in items:
  913. inneritems = list(vect.components.items())
  914. inneritems.sort(key = lambda x: x[0].__str__())
  915. for k, v in inneritems:
  916. #if the coef of the basis vector is 1
  917. #we skip the 1
  918. if v == 1:
  919. o1.append("" +
  920. k._pretty_form)
  921. #Same for -1
  922. elif v == -1:
  923. o1.append("(-1) " +
  924. k._pretty_form)
  925. #For a general expr
  926. else:
  927. #We always wrap the measure numbers in
  928. #parentheses
  929. arg_str = self._print(
  930. v).parens()[0]
  931. o1.append(arg_str + ' ' + k._pretty_form)
  932. vectstrs.append(k._pretty_form)
  933. #outstr = u("").join(o1)
  934. if o1[0].startswith(" + "):
  935. o1[0] = o1[0][3:]
  936. elif o1[0].startswith(" "):
  937. o1[0] = o1[0][1:]
  938. #Fixing the newlines
  939. lengths = []
  940. strs = ['']
  941. flag = []
  942. for i, partstr in enumerate(o1):
  943. flag.append(0)
  944. # XXX: What is this hack?
  945. if '\n' in partstr:
  946. tempstr = partstr
  947. tempstr = tempstr.replace(vectstrs[i], '')
  948. if '\N{right parenthesis extension}' in tempstr: # If scalar is a fraction
  949. for paren in range(len(tempstr)):
  950. flag[i] = 1
  951. if tempstr[paren] == '\N{right parenthesis extension}':
  952. tempstr = tempstr[:paren] + '\N{right parenthesis extension}'\
  953. + ' ' + vectstrs[i] + tempstr[paren + 1:]
  954. break
  955. elif '\N{RIGHT PARENTHESIS LOWER HOOK}' in tempstr:
  956. flag[i] = 1
  957. tempstr = tempstr.replace('\N{RIGHT PARENTHESIS LOWER HOOK}',
  958. '\N{RIGHT PARENTHESIS LOWER HOOK}'
  959. + ' ' + vectstrs[i])
  960. else:
  961. tempstr = tempstr.replace('\N{RIGHT PARENTHESIS UPPER HOOK}',
  962. '\N{RIGHT PARENTHESIS UPPER HOOK}'
  963. + ' ' + vectstrs[i])
  964. o1[i] = tempstr
  965. o1 = [x.split('\n') for x in o1]
  966. n_newlines = max([len(x) for x in o1]) # Width of part in its pretty form
  967. if 1 in flag: # If there was a fractional scalar
  968. for i, parts in enumerate(o1):
  969. if len(parts) == 1: # If part has no newline
  970. parts.insert(0, ' ' * (len(parts[0])))
  971. flag[i] = 1
  972. for i, parts in enumerate(o1):
  973. lengths.append(len(parts[flag[i]]))
  974. for j in range(n_newlines):
  975. if j+1 <= len(parts):
  976. if j >= len(strs):
  977. strs.append(' ' * (sum(lengths[:-1]) +
  978. 3*(len(lengths)-1)))
  979. if j == flag[i]:
  980. strs[flag[i]] += parts[flag[i]] + ' + '
  981. else:
  982. strs[j] += parts[j] + ' '*(lengths[-1] -
  983. len(parts[j])+
  984. 3)
  985. else:
  986. if j >= len(strs):
  987. strs.append(' ' * (sum(lengths[:-1]) +
  988. 3*(len(lengths)-1)))
  989. strs[j] += ' '*(lengths[-1]+3)
  990. return prettyForm('\n'.join([s[:-3] for s in strs]))
  991. def _print_NDimArray(self, expr):
  992. from sympy.matrices.immutable import ImmutableMatrix
  993. if expr.rank() == 0:
  994. return self._print(expr[()])
  995. level_str = [[]] + [[] for i in range(expr.rank())]
  996. shape_ranges = [list(range(i)) for i in expr.shape]
  997. # leave eventual matrix elements unflattened
  998. mat = lambda x: ImmutableMatrix(x, evaluate=False)
  999. for outer_i in itertools.product(*shape_ranges):
  1000. level_str[-1].append(expr[outer_i])
  1001. even = True
  1002. for back_outer_i in range(expr.rank()-1, -1, -1):
  1003. if len(level_str[back_outer_i+1]) < expr.shape[back_outer_i]:
  1004. break
  1005. if even:
  1006. level_str[back_outer_i].append(level_str[back_outer_i+1])
  1007. else:
  1008. level_str[back_outer_i].append(mat(
  1009. level_str[back_outer_i+1]))
  1010. if len(level_str[back_outer_i + 1]) == 1:
  1011. level_str[back_outer_i][-1] = mat(
  1012. [[level_str[back_outer_i][-1]]])
  1013. even = not even
  1014. level_str[back_outer_i+1] = []
  1015. out_expr = level_str[0][0]
  1016. if expr.rank() % 2 == 1:
  1017. out_expr = mat([out_expr])
  1018. return self._print(out_expr)
  1019. def _printer_tensor_indices(self, name, indices, index_map={}):
  1020. center = stringPict(name)
  1021. top = stringPict(" "*center.width())
  1022. bot = stringPict(" "*center.width())
  1023. last_valence = None
  1024. prev_map = None
  1025. for i, index in enumerate(indices):
  1026. indpic = self._print(index.args[0])
  1027. if ((index in index_map) or prev_map) and last_valence == index.is_up:
  1028. if index.is_up:
  1029. top = prettyForm(*stringPict.next(top, ","))
  1030. else:
  1031. bot = prettyForm(*stringPict.next(bot, ","))
  1032. if index in index_map:
  1033. indpic = prettyForm(*stringPict.next(indpic, "="))
  1034. indpic = prettyForm(*stringPict.next(indpic, self._print(index_map[index])))
  1035. prev_map = True
  1036. else:
  1037. prev_map = False
  1038. if index.is_up:
  1039. top = stringPict(*top.right(indpic))
  1040. center = stringPict(*center.right(" "*indpic.width()))
  1041. bot = stringPict(*bot.right(" "*indpic.width()))
  1042. else:
  1043. bot = stringPict(*bot.right(indpic))
  1044. center = stringPict(*center.right(" "*indpic.width()))
  1045. top = stringPict(*top.right(" "*indpic.width()))
  1046. last_valence = index.is_up
  1047. pict = prettyForm(*center.above(top))
  1048. pict = prettyForm(*pict.below(bot))
  1049. return pict
  1050. def _print_Tensor(self, expr):
  1051. name = expr.args[0].name
  1052. indices = expr.get_indices()
  1053. return self._printer_tensor_indices(name, indices)
  1054. def _print_TensorElement(self, expr):
  1055. name = expr.expr.args[0].name
  1056. indices = expr.expr.get_indices()
  1057. index_map = expr.index_map
  1058. return self._printer_tensor_indices(name, indices, index_map)
  1059. def _print_TensMul(self, expr):
  1060. sign, args = expr._get_args_for_traditional_printer()
  1061. args = [
  1062. prettyForm(*self._print(i).parens()) if
  1063. precedence_traditional(i) < PRECEDENCE["Mul"] else self._print(i)
  1064. for i in args
  1065. ]
  1066. pform = prettyForm.__mul__(*args)
  1067. if sign:
  1068. return prettyForm(*pform.left(sign))
  1069. else:
  1070. return pform
  1071. def _print_TensAdd(self, expr):
  1072. args = [
  1073. prettyForm(*self._print(i).parens()) if
  1074. precedence_traditional(i) < PRECEDENCE["Mul"] else self._print(i)
  1075. for i in expr.args
  1076. ]
  1077. return prettyForm.__add__(*args)
  1078. def _print_TensorIndex(self, expr):
  1079. sym = expr.args[0]
  1080. if not expr.is_up:
  1081. sym = -sym
  1082. return self._print(sym)
  1083. def _print_PartialDerivative(self, deriv):
  1084. if self._use_unicode:
  1085. deriv_symbol = U('PARTIAL DIFFERENTIAL')
  1086. else:
  1087. deriv_symbol = r'd'
  1088. x = None
  1089. for variable in reversed(deriv.variables):
  1090. s = self._print(variable)
  1091. ds = prettyForm(*s.left(deriv_symbol))
  1092. if x is None:
  1093. x = ds
  1094. else:
  1095. x = prettyForm(*x.right(' '))
  1096. x = prettyForm(*x.right(ds))
  1097. f = prettyForm(
  1098. binding=prettyForm.FUNC, *self._print(deriv.expr).parens())
  1099. pform = prettyForm(deriv_symbol)
  1100. if len(deriv.variables) > 1:
  1101. pform = pform**self._print(len(deriv.variables))
  1102. pform = prettyForm(*pform.below(stringPict.LINE, x))
  1103. pform.baseline = pform.baseline + 1
  1104. pform = prettyForm(*stringPict.next(pform, f))
  1105. pform.binding = prettyForm.MUL
  1106. return pform
  1107. def _print_Piecewise(self, pexpr):
  1108. P = {}
  1109. for n, ec in enumerate(pexpr.args):
  1110. P[n, 0] = self._print(ec.expr)
  1111. if ec.cond == True:
  1112. P[n, 1] = prettyForm('otherwise')
  1113. else:
  1114. P[n, 1] = prettyForm(
  1115. *prettyForm('for ').right(self._print(ec.cond)))
  1116. hsep = 2
  1117. vsep = 1
  1118. len_args = len(pexpr.args)
  1119. # max widths
  1120. maxw = [max([P[i, j].width() for i in range(len_args)])
  1121. for j in range(2)]
  1122. # FIXME: Refactor this code and matrix into some tabular environment.
  1123. # drawing result
  1124. D = None
  1125. for i in range(len_args):
  1126. D_row = None
  1127. for j in range(2):
  1128. p = P[i, j]
  1129. assert p.width() <= maxw[j]
  1130. wdelta = maxw[j] - p.width()
  1131. wleft = wdelta // 2
  1132. wright = wdelta - wleft
  1133. p = prettyForm(*p.right(' '*wright))
  1134. p = prettyForm(*p.left(' '*wleft))
  1135. if D_row is None:
  1136. D_row = p
  1137. continue
  1138. D_row = prettyForm(*D_row.right(' '*hsep)) # h-spacer
  1139. D_row = prettyForm(*D_row.right(p))
  1140. if D is None:
  1141. D = D_row # first row in a picture
  1142. continue
  1143. # v-spacer
  1144. for _ in range(vsep):
  1145. D = prettyForm(*D.below(' '))
  1146. D = prettyForm(*D.below(D_row))
  1147. D = prettyForm(*D.parens('{', ''))
  1148. D.baseline = D.height()//2
  1149. D.binding = prettyForm.OPEN
  1150. return D
  1151. def _print_ITE(self, ite):
  1152. from sympy.functions.elementary.piecewise import Piecewise
  1153. return self._print(ite.rewrite(Piecewise))
  1154. def _hprint_vec(self, v):
  1155. D = None
  1156. for a in v:
  1157. p = a
  1158. if D is None:
  1159. D = p
  1160. else:
  1161. D = prettyForm(*D.right(', '))
  1162. D = prettyForm(*D.right(p))
  1163. if D is None:
  1164. D = stringPict(' ')
  1165. return D
  1166. def _hprint_vseparator(self, p1, p2, left=None, right=None, delimiter='', ifascii_nougly=False):
  1167. if ifascii_nougly and not self._use_unicode:
  1168. return self._print_seq((p1, '|', p2), left=left, right=right,
  1169. delimiter=delimiter, ifascii_nougly=True)
  1170. tmp = self._print_seq((p1, p2,), left=left, right=right, delimiter=delimiter)
  1171. sep = stringPict(vobj('|', tmp.height()), baseline=tmp.baseline)
  1172. return self._print_seq((p1, sep, p2), left=left, right=right,
  1173. delimiter=delimiter)
  1174. def _print_hyper(self, e):
  1175. # FIXME refactor Matrix, Piecewise, and this into a tabular environment
  1176. ap = [self._print(a) for a in e.ap]
  1177. bq = [self._print(b) for b in e.bq]
  1178. P = self._print(e.argument)
  1179. P.baseline = P.height()//2
  1180. # Drawing result - first create the ap, bq vectors
  1181. D = None
  1182. for v in [ap, bq]:
  1183. D_row = self._hprint_vec(v)
  1184. if D is None:
  1185. D = D_row # first row in a picture
  1186. else:
  1187. D = prettyForm(*D.below(' '))
  1188. D = prettyForm(*D.below(D_row))
  1189. # make sure that the argument `z' is centred vertically
  1190. D.baseline = D.height()//2
  1191. # insert horizontal separator
  1192. P = prettyForm(*P.left(' '))
  1193. D = prettyForm(*D.right(' '))
  1194. # insert separating `|`
  1195. D = self._hprint_vseparator(D, P)
  1196. # add parens
  1197. D = prettyForm(*D.parens('(', ')'))
  1198. # create the F symbol
  1199. above = D.height()//2 - 1
  1200. below = D.height() - above - 1
  1201. sz, t, b, add, img = annotated('F')
  1202. F = prettyForm('\n' * (above - t) + img + '\n' * (below - b),
  1203. baseline=above + sz)
  1204. add = (sz + 1)//2
  1205. F = prettyForm(*F.left(self._print(len(e.ap))))
  1206. F = prettyForm(*F.right(self._print(len(e.bq))))
  1207. F.baseline = above + add
  1208. D = prettyForm(*F.right(' ', D))
  1209. return D
  1210. def _print_meijerg(self, e):
  1211. # FIXME refactor Matrix, Piecewise, and this into a tabular environment
  1212. v = {}
  1213. v[(0, 0)] = [self._print(a) for a in e.an]
  1214. v[(0, 1)] = [self._print(a) for a in e.aother]
  1215. v[(1, 0)] = [self._print(b) for b in e.bm]
  1216. v[(1, 1)] = [self._print(b) for b in e.bother]
  1217. P = self._print(e.argument)
  1218. P.baseline = P.height()//2
  1219. vp = {}
  1220. for idx in v:
  1221. vp[idx] = self._hprint_vec(v[idx])
  1222. for i in range(2):
  1223. maxw = max(vp[(0, i)].width(), vp[(1, i)].width())
  1224. for j in range(2):
  1225. s = vp[(j, i)]
  1226. left = (maxw - s.width()) // 2
  1227. right = maxw - left - s.width()
  1228. s = prettyForm(*s.left(' ' * left))
  1229. s = prettyForm(*s.right(' ' * right))
  1230. vp[(j, i)] = s
  1231. D1 = prettyForm(*vp[(0, 0)].right(' ', vp[(0, 1)]))
  1232. D1 = prettyForm(*D1.below(' '))
  1233. D2 = prettyForm(*vp[(1, 0)].right(' ', vp[(1, 1)]))
  1234. D = prettyForm(*D1.below(D2))
  1235. # make sure that the argument `z' is centred vertically
  1236. D.baseline = D.height()//2
  1237. # insert horizontal separator
  1238. P = prettyForm(*P.left(' '))
  1239. D = prettyForm(*D.right(' '))
  1240. # insert separating `|`
  1241. D = self._hprint_vseparator(D, P)
  1242. # add parens
  1243. D = prettyForm(*D.parens('(', ')'))
  1244. # create the G symbol
  1245. above = D.height()//2 - 1
  1246. below = D.height() - above - 1
  1247. sz, t, b, add, img = annotated('G')
  1248. F = prettyForm('\n' * (above - t) + img + '\n' * (below - b),
  1249. baseline=above + sz)
  1250. pp = self._print(len(e.ap))
  1251. pq = self._print(len(e.bq))
  1252. pm = self._print(len(e.bm))
  1253. pn = self._print(len(e.an))
  1254. def adjust(p1, p2):
  1255. diff = p1.width() - p2.width()
  1256. if diff == 0:
  1257. return p1, p2
  1258. elif diff > 0:
  1259. return p1, prettyForm(*p2.left(' '*diff))
  1260. else:
  1261. return prettyForm(*p1.left(' '*-diff)), p2
  1262. pp, pm = adjust(pp, pm)
  1263. pq, pn = adjust(pq, pn)
  1264. pu = prettyForm(*pm.right(', ', pn))
  1265. pl = prettyForm(*pp.right(', ', pq))
  1266. ht = F.baseline - above - 2
  1267. if ht > 0:
  1268. pu = prettyForm(*pu.below('\n'*ht))
  1269. p = prettyForm(*pu.below(pl))
  1270. F.baseline = above
  1271. F = prettyForm(*F.right(p))
  1272. F.baseline = above + add
  1273. D = prettyForm(*F.right(' ', D))
  1274. return D
  1275. def _print_ExpBase(self, e):
  1276. # TODO should exp_polar be printed differently?
  1277. # what about exp_polar(0), exp_polar(1)?
  1278. base = prettyForm(pretty_atom('Exp1', 'e'))
  1279. return base ** self._print(e.args[0])
  1280. def _print_Exp1(self, e):
  1281. return prettyForm(pretty_atom('Exp1', 'e'))
  1282. def _print_Function(self, e, sort=False, func_name=None, left='(',
  1283. right=')'):
  1284. # optional argument func_name for supplying custom names
  1285. # XXX works only for applied functions
  1286. return self._helper_print_function(e.func, e.args, sort=sort, func_name=func_name, left=left, right=right)
  1287. def _print_mathieuc(self, e):
  1288. return self._print_Function(e, func_name='C')
  1289. def _print_mathieus(self, e):
  1290. return self._print_Function(e, func_name='S')
  1291. def _print_mathieucprime(self, e):
  1292. return self._print_Function(e, func_name="C'")
  1293. def _print_mathieusprime(self, e):
  1294. return self._print_Function(e, func_name="S'")
  1295. def _helper_print_function(self, func, args, sort=False, func_name=None,
  1296. delimiter=', ', elementwise=False, left='(',
  1297. right=')'):
  1298. if sort:
  1299. args = sorted(args, key=default_sort_key)
  1300. if not func_name and hasattr(func, "__name__"):
  1301. func_name = func.__name__
  1302. if func_name:
  1303. prettyFunc = self._print(Symbol(func_name))
  1304. else:
  1305. prettyFunc = prettyForm(*self._print(func).parens())
  1306. if elementwise:
  1307. if self._use_unicode:
  1308. circ = pretty_atom('Modifier Letter Low Ring')
  1309. else:
  1310. circ = '.'
  1311. circ = self._print(circ)
  1312. prettyFunc = prettyForm(
  1313. binding=prettyForm.LINE,
  1314. *stringPict.next(prettyFunc, circ)
  1315. )
  1316. prettyArgs = prettyForm(*self._print_seq(args, delimiter=delimiter).parens(
  1317. left=left, right=right))
  1318. pform = prettyForm(
  1319. binding=prettyForm.FUNC, *stringPict.next(prettyFunc, prettyArgs))
  1320. # store pform parts so it can be reassembled e.g. when powered
  1321. pform.prettyFunc = prettyFunc
  1322. pform.prettyArgs = prettyArgs
  1323. return pform
  1324. def _print_ElementwiseApplyFunction(self, e):
  1325. func = e.function
  1326. arg = e.expr
  1327. args = [arg]
  1328. return self._helper_print_function(func, args, delimiter="", elementwise=True)
  1329. @property
  1330. def _special_function_classes(self):
  1331. from sympy.functions.special.tensor_functions import KroneckerDelta
  1332. from sympy.functions.special.gamma_functions import gamma, lowergamma
  1333. from sympy.functions.special.zeta_functions import lerchphi
  1334. from sympy.functions.special.beta_functions import beta
  1335. from sympy.functions.special.delta_functions import DiracDelta
  1336. from sympy.functions.special.error_functions import Chi
  1337. return {KroneckerDelta: [greek_unicode['delta'], 'delta'],
  1338. gamma: [greek_unicode['Gamma'], 'Gamma'],
  1339. lerchphi: [greek_unicode['Phi'], 'lerchphi'],
  1340. lowergamma: [greek_unicode['gamma'], 'gamma'],
  1341. beta: [greek_unicode['Beta'], 'B'],
  1342. DiracDelta: [greek_unicode['delta'], 'delta'],
  1343. Chi: ['Chi', 'Chi']}
  1344. def _print_FunctionClass(self, expr):
  1345. for cls in self._special_function_classes:
  1346. if issubclass(expr, cls) and expr.__name__ == cls.__name__:
  1347. if self._use_unicode:
  1348. return prettyForm(self._special_function_classes[cls][0])
  1349. else:
  1350. return prettyForm(self._special_function_classes[cls][1])
  1351. func_name = expr.__name__
  1352. return prettyForm(pretty_symbol(func_name))
  1353. def _print_GeometryEntity(self, expr):
  1354. # GeometryEntity is based on Tuple but should not print like a Tuple
  1355. return self.emptyPrinter(expr)
  1356. def _print_lerchphi(self, e):
  1357. func_name = greek_unicode['Phi'] if self._use_unicode else 'lerchphi'
  1358. return self._print_Function(e, func_name=func_name)
  1359. def _print_dirichlet_eta(self, e):
  1360. func_name = greek_unicode['eta'] if self._use_unicode else 'dirichlet_eta'
  1361. return self._print_Function(e, func_name=func_name)
  1362. def _print_Heaviside(self, e):
  1363. func_name = greek_unicode['theta'] if self._use_unicode else 'Heaviside'
  1364. if e.args[1]==1/2:
  1365. pform = prettyForm(*self._print(e.args[0]).parens())
  1366. pform = prettyForm(*pform.left(func_name))
  1367. return pform
  1368. else:
  1369. return self._print_Function(e, func_name=func_name)
  1370. def _print_fresnels(self, e):
  1371. return self._print_Function(e, func_name="S")
  1372. def _print_fresnelc(self, e):
  1373. return self._print_Function(e, func_name="C")
  1374. def _print_airyai(self, e):
  1375. return self._print_Function(e, func_name="Ai")
  1376. def _print_airybi(self, e):
  1377. return self._print_Function(e, func_name="Bi")
  1378. def _print_airyaiprime(self, e):
  1379. return self._print_Function(e, func_name="Ai'")
  1380. def _print_airybiprime(self, e):
  1381. return self._print_Function(e, func_name="Bi'")
  1382. def _print_LambertW(self, e):
  1383. return self._print_Function(e, func_name="W")
  1384. def _print_Covariance(self, e):
  1385. return self._print_Function(e, func_name="Cov")
  1386. def _print_Variance(self, e):
  1387. return self._print_Function(e, func_name="Var")
  1388. def _print_Probability(self, e):
  1389. return self._print_Function(e, func_name="P")
  1390. def _print_Expectation(self, e):
  1391. return self._print_Function(e, func_name="E", left='[', right=']')
  1392. def _print_Lambda(self, e):
  1393. expr = e.expr
  1394. sig = e.signature
  1395. if self._use_unicode:
  1396. arrow = " \N{RIGHTWARDS ARROW FROM BAR} "
  1397. else:
  1398. arrow = " -> "
  1399. if len(sig) == 1 and sig[0].is_symbol:
  1400. sig = sig[0]
  1401. var_form = self._print(sig)
  1402. return prettyForm(*stringPict.next(var_form, arrow, self._print(expr)), binding=8)
  1403. def _print_Order(self, expr):
  1404. pform = self._print(expr.expr)
  1405. if (expr.point and any(p != S.Zero for p in expr.point)) or \
  1406. len(expr.variables) > 1:
  1407. pform = prettyForm(*pform.right("; "))
  1408. if len(expr.variables) > 1:
  1409. pform = prettyForm(*pform.right(self._print(expr.variables)))
  1410. elif len(expr.variables):
  1411. pform = prettyForm(*pform.right(self._print(expr.variables[0])))
  1412. if self._use_unicode:
  1413. pform = prettyForm(*pform.right(" \N{RIGHTWARDS ARROW} "))
  1414. else:
  1415. pform = prettyForm(*pform.right(" -> "))
  1416. if len(expr.point) > 1:
  1417. pform = prettyForm(*pform.right(self._print(expr.point)))
  1418. else:
  1419. pform = prettyForm(*pform.right(self._print(expr.point[0])))
  1420. pform = prettyForm(*pform.parens())
  1421. pform = prettyForm(*pform.left("O"))
  1422. return pform
  1423. def _print_SingularityFunction(self, e):
  1424. if self._use_unicode:
  1425. shift = self._print(e.args[0]-e.args[1])
  1426. n = self._print(e.args[2])
  1427. base = prettyForm("<")
  1428. base = prettyForm(*base.right(shift))
  1429. base = prettyForm(*base.right(">"))
  1430. pform = base**n
  1431. return pform
  1432. else:
  1433. n = self._print(e.args[2])
  1434. shift = self._print(e.args[0]-e.args[1])
  1435. base = self._print_seq(shift, "<", ">", ' ')
  1436. return base**n
  1437. def _print_beta(self, e):
  1438. func_name = greek_unicode['Beta'] if self._use_unicode else 'B'
  1439. return self._print_Function(e, func_name=func_name)
  1440. def _print_betainc(self, e):
  1441. func_name = "B'"
  1442. return self._print_Function(e, func_name=func_name)
  1443. def _print_betainc_regularized(self, e):
  1444. func_name = 'I'
  1445. return self._print_Function(e, func_name=func_name)
  1446. def _print_gamma(self, e):
  1447. func_name = greek_unicode['Gamma'] if self._use_unicode else 'Gamma'
  1448. return self._print_Function(e, func_name=func_name)
  1449. def _print_uppergamma(self, e):
  1450. func_name = greek_unicode['Gamma'] if self._use_unicode else 'Gamma'
  1451. return self._print_Function(e, func_name=func_name)
  1452. def _print_lowergamma(self, e):
  1453. func_name = greek_unicode['gamma'] if self._use_unicode else 'lowergamma'
  1454. return self._print_Function(e, func_name=func_name)
  1455. def _print_DiracDelta(self, e):
  1456. if self._use_unicode:
  1457. if len(e.args) == 2:
  1458. a = prettyForm(greek_unicode['delta'])
  1459. b = self._print(e.args[1])
  1460. b = prettyForm(*b.parens())
  1461. c = self._print(e.args[0])
  1462. c = prettyForm(*c.parens())
  1463. pform = a**b
  1464. pform = prettyForm(*pform.right(' '))
  1465. pform = prettyForm(*pform.right(c))
  1466. return pform
  1467. pform = self._print(e.args[0])
  1468. pform = prettyForm(*pform.parens())
  1469. pform = prettyForm(*pform.left(greek_unicode['delta']))
  1470. return pform
  1471. else:
  1472. return self._print_Function(e)
  1473. def _print_expint(self, e):
  1474. if e.args[0].is_Integer and self._use_unicode:
  1475. return self._print_Function(Function('E_%s' % e.args[0])(e.args[1]))
  1476. return self._print_Function(e)
  1477. def _print_Chi(self, e):
  1478. # This needs a special case since otherwise it comes out as greek
  1479. # letter chi...
  1480. prettyFunc = prettyForm("Chi")
  1481. prettyArgs = prettyForm(*self._print_seq(e.args).parens())
  1482. pform = prettyForm(
  1483. binding=prettyForm.FUNC, *stringPict.next(prettyFunc, prettyArgs))
  1484. # store pform parts so it can be reassembled e.g. when powered
  1485. pform.prettyFunc = prettyFunc
  1486. pform.prettyArgs = prettyArgs
  1487. return pform
  1488. def _print_elliptic_e(self, e):
  1489. pforma0 = self._print(e.args[0])
  1490. if len(e.args) == 1:
  1491. pform = pforma0
  1492. else:
  1493. pforma1 = self._print(e.args[1])
  1494. pform = self._hprint_vseparator(pforma0, pforma1)
  1495. pform = prettyForm(*pform.parens())
  1496. pform = prettyForm(*pform.left('E'))
  1497. return pform
  1498. def _print_elliptic_k(self, e):
  1499. pform = self._print(e.args[0])
  1500. pform = prettyForm(*pform.parens())
  1501. pform = prettyForm(*pform.left('K'))
  1502. return pform
  1503. def _print_elliptic_f(self, e):
  1504. pforma0 = self._print(e.args[0])
  1505. pforma1 = self._print(e.args[1])
  1506. pform = self._hprint_vseparator(pforma0, pforma1)
  1507. pform = prettyForm(*pform.parens())
  1508. pform = prettyForm(*pform.left('F'))
  1509. return pform
  1510. def _print_elliptic_pi(self, e):
  1511. name = greek_unicode['Pi'] if self._use_unicode else 'Pi'
  1512. pforma0 = self._print(e.args[0])
  1513. pforma1 = self._print(e.args[1])
  1514. if len(e.args) == 2:
  1515. pform = self._hprint_vseparator(pforma0, pforma1)
  1516. else:
  1517. pforma2 = self._print(e.args[2])
  1518. pforma = self._hprint_vseparator(pforma1, pforma2, ifascii_nougly=False)
  1519. pforma = prettyForm(*pforma.left('; '))
  1520. pform = prettyForm(*pforma.left(pforma0))
  1521. pform = prettyForm(*pform.parens())
  1522. pform = prettyForm(*pform.left(name))
  1523. return pform
  1524. def _print_GoldenRatio(self, expr):
  1525. if self._use_unicode:
  1526. return prettyForm(pretty_symbol('phi'))
  1527. return self._print(Symbol("GoldenRatio"))
  1528. def _print_EulerGamma(self, expr):
  1529. if self._use_unicode:
  1530. return prettyForm(pretty_symbol('gamma'))
  1531. return self._print(Symbol("EulerGamma"))
  1532. def _print_Catalan(self, expr):
  1533. return self._print(Symbol("G"))
  1534. def _print_Mod(self, expr):
  1535. pform = self._print(expr.args[0])
  1536. if pform.binding > prettyForm.MUL:
  1537. pform = prettyForm(*pform.parens())
  1538. pform = prettyForm(*pform.right(' mod '))
  1539. pform = prettyForm(*pform.right(self._print(expr.args[1])))
  1540. pform.binding = prettyForm.OPEN
  1541. return pform
  1542. def _print_Add(self, expr, order=None):
  1543. terms = self._as_ordered_terms(expr, order=order)
  1544. pforms, indices = [], []
  1545. def pretty_negative(pform, index):
  1546. """Prepend a minus sign to a pretty form. """
  1547. #TODO: Move this code to prettyForm
  1548. if index == 0:
  1549. if pform.height() > 1:
  1550. pform_neg = '- '
  1551. else:
  1552. pform_neg = '-'
  1553. else:
  1554. pform_neg = ' - '
  1555. if (pform.binding > prettyForm.NEG
  1556. or pform.binding == prettyForm.ADD):
  1557. p = stringPict(*pform.parens())
  1558. else:
  1559. p = pform
  1560. p = stringPict.next(pform_neg, p)
  1561. # Lower the binding to NEG, even if it was higher. Otherwise, it
  1562. # will print as a + ( - (b)), instead of a - (b).
  1563. return prettyForm(binding=prettyForm.NEG, *p)
  1564. for i, term in enumerate(terms):
  1565. if term.is_Mul and term.could_extract_minus_sign():
  1566. coeff, other = term.as_coeff_mul(rational=False)
  1567. if coeff == -1:
  1568. negterm = Mul(*other, evaluate=False)
  1569. else:
  1570. negterm = Mul(-coeff, *other, evaluate=False)
  1571. pform = self._print(negterm)
  1572. pforms.append(pretty_negative(pform, i))
  1573. elif term.is_Rational and term.q > 1:
  1574. pforms.append(None)
  1575. indices.append(i)
  1576. elif term.is_Number and term < 0:
  1577. pform = self._print(-term)
  1578. pforms.append(pretty_negative(pform, i))
  1579. elif term.is_Relational:
  1580. pforms.append(prettyForm(*self._print(term).parens()))
  1581. else:
  1582. pforms.append(self._print(term))
  1583. if indices:
  1584. large = True
  1585. for pform in pforms:
  1586. if pform is not None and pform.height() > 1:
  1587. break
  1588. else:
  1589. large = False
  1590. for i in indices:
  1591. term, negative = terms[i], False
  1592. if term < 0:
  1593. term, negative = -term, True
  1594. if large:
  1595. pform = prettyForm(str(term.p))/prettyForm(str(term.q))
  1596. else:
  1597. pform = self._print(term)
  1598. if negative:
  1599. pform = pretty_negative(pform, i)
  1600. pforms[i] = pform
  1601. return prettyForm.__add__(*pforms)
  1602. def _print_Mul(self, product):
  1603. from sympy.physics.units import Quantity
  1604. # Check for unevaluated Mul. In this case we need to make sure the
  1605. # identities are visible, multiple Rational factors are not combined
  1606. # etc so we display in a straight-forward form that fully preserves all
  1607. # args and their order.
  1608. args = product.args
  1609. if args[0] is S.One or any(isinstance(arg, Number) for arg in args[1:]):
  1610. strargs = list(map(self._print, args))
  1611. # XXX: This is a hack to work around the fact that
  1612. # prettyForm.__mul__ absorbs a leading -1 in the args. Probably it
  1613. # would be better to fix this in prettyForm.__mul__ instead.
  1614. negone = strargs[0] == '-1'
  1615. if negone:
  1616. strargs[0] = prettyForm('1', 0, 0)
  1617. obj = prettyForm.__mul__(*strargs)
  1618. if negone:
  1619. obj = prettyForm('-' + obj.s, obj.baseline, obj.binding)
  1620. return obj
  1621. a = [] # items in the numerator
  1622. b = [] # items that are in the denominator (if any)
  1623. if self.order not in ('old', 'none'):
  1624. args = product.as_ordered_factors()
  1625. else:
  1626. args = list(product.args)
  1627. # If quantities are present append them at the back
  1628. args = sorted(args, key=lambda x: isinstance(x, Quantity) or
  1629. (isinstance(x, Pow) and isinstance(x.base, Quantity)))
  1630. # Gather terms for numerator/denominator
  1631. for item in args:
  1632. if item.is_commutative and item.is_Pow and item.exp.is_Rational and item.exp.is_negative:
  1633. if item.exp != -1:
  1634. b.append(Pow(item.base, -item.exp, evaluate=False))
  1635. else:
  1636. b.append(Pow(item.base, -item.exp))
  1637. elif item.is_Rational and item is not S.Infinity:
  1638. if item.p != 1:
  1639. a.append( Rational(item.p) )
  1640. if item.q != 1:
  1641. b.append( Rational(item.q) )
  1642. else:
  1643. a.append(item)
  1644. # Convert to pretty forms. Parentheses are added by `__mul__`.
  1645. a = [self._print(ai) for ai in a]
  1646. b = [self._print(bi) for bi in b]
  1647. # Construct a pretty form
  1648. if len(b) == 0:
  1649. return prettyForm.__mul__(*a)
  1650. else:
  1651. if len(a) == 0:
  1652. a.append( self._print(S.One) )
  1653. return prettyForm.__mul__(*a)/prettyForm.__mul__(*b)
  1654. # A helper function for _print_Pow to print x**(1/n)
  1655. def _print_nth_root(self, base, root):
  1656. bpretty = self._print(base)
  1657. # In very simple cases, use a single-char root sign
  1658. if (self._settings['use_unicode_sqrt_char'] and self._use_unicode
  1659. and root == 2 and bpretty.height() == 1
  1660. and (bpretty.width() == 1
  1661. or (base.is_Integer and base.is_nonnegative))):
  1662. return prettyForm(*bpretty.left('\N{SQUARE ROOT}'))
  1663. # Construct root sign, start with the \/ shape
  1664. _zZ = xobj('/', 1)
  1665. rootsign = xobj('\\', 1) + _zZ
  1666. # Constructing the number to put on root
  1667. rpretty = self._print(root)
  1668. # roots look bad if they are not a single line
  1669. if rpretty.height() != 1:
  1670. return self._print(base)**self._print(1/root)
  1671. # If power is half, no number should appear on top of root sign
  1672. exp = '' if root == 2 else str(rpretty).ljust(2)
  1673. if len(exp) > 2:
  1674. rootsign = ' '*(len(exp) - 2) + rootsign
  1675. # Stack the exponent
  1676. rootsign = stringPict(exp + '\n' + rootsign)
  1677. rootsign.baseline = 0
  1678. # Diagonal: length is one less than height of base
  1679. linelength = bpretty.height() - 1
  1680. diagonal = stringPict('\n'.join(
  1681. ' '*(linelength - i - 1) + _zZ + ' '*i
  1682. for i in range(linelength)
  1683. ))
  1684. # Put baseline just below lowest line: next to exp
  1685. diagonal.baseline = linelength - 1
  1686. # Make the root symbol
  1687. rootsign = prettyForm(*rootsign.right(diagonal))
  1688. # Det the baseline to match contents to fix the height
  1689. # but if the height of bpretty is one, the rootsign must be one higher
  1690. rootsign.baseline = max(1, bpretty.baseline)
  1691. #build result
  1692. s = prettyForm(hobj('_', 2 + bpretty.width()))
  1693. s = prettyForm(*bpretty.above(s))
  1694. s = prettyForm(*s.left(rootsign))
  1695. return s
  1696. def _print_Pow(self, power):
  1697. from sympy.simplify.simplify import fraction
  1698. b, e = power.as_base_exp()
  1699. if power.is_commutative:
  1700. if e is S.NegativeOne:
  1701. return prettyForm("1")/self._print(b)
  1702. n, d = fraction(e)
  1703. if n is S.One and d.is_Atom and not e.is_Integer and (e.is_Rational or d.is_Symbol) \
  1704. and self._settings['root_notation']:
  1705. return self._print_nth_root(b, d)
  1706. if e.is_Rational and e < 0:
  1707. return prettyForm("1")/self._print(Pow(b, -e, evaluate=False))
  1708. if b.is_Relational:
  1709. return prettyForm(*self._print(b).parens()).__pow__(self._print(e))
  1710. return self._print(b)**self._print(e)
  1711. def _print_UnevaluatedExpr(self, expr):
  1712. return self._print(expr.args[0])
  1713. def __print_numer_denom(self, p, q):
  1714. if q == 1:
  1715. if p < 0:
  1716. return prettyForm(str(p), binding=prettyForm.NEG)
  1717. else:
  1718. return prettyForm(str(p))
  1719. elif abs(p) >= 10 and abs(q) >= 10:
  1720. # If more than one digit in numer and denom, print larger fraction
  1721. if p < 0:
  1722. return prettyForm(str(p), binding=prettyForm.NEG)/prettyForm(str(q))
  1723. # Old printing method:
  1724. #pform = prettyForm(str(-p))/prettyForm(str(q))
  1725. #return prettyForm(binding=prettyForm.NEG, *pform.left('- '))
  1726. else:
  1727. return prettyForm(str(p))/prettyForm(str(q))
  1728. else:
  1729. return None
  1730. def _print_Rational(self, expr):
  1731. result = self.__print_numer_denom(expr.p, expr.q)
  1732. if result is not None:
  1733. return result
  1734. else:
  1735. return self.emptyPrinter(expr)
  1736. def _print_Fraction(self, expr):
  1737. result = self.__print_numer_denom(expr.numerator, expr.denominator)
  1738. if result is not None:
  1739. return result
  1740. else:
  1741. return self.emptyPrinter(expr)
  1742. def _print_ProductSet(self, p):
  1743. if len(p.sets) >= 1 and not has_variety(p.sets):
  1744. return self._print(p.sets[0]) ** self._print(len(p.sets))
  1745. else:
  1746. prod_char = "\N{MULTIPLICATION SIGN}" if self._use_unicode else 'x'
  1747. return self._print_seq(p.sets, None, None, ' %s ' % prod_char,
  1748. parenthesize=lambda set: set.is_Union or
  1749. set.is_Intersection or set.is_ProductSet)
  1750. def _print_FiniteSet(self, s):
  1751. items = sorted(s.args, key=default_sort_key)
  1752. return self._print_seq(items, '{', '}', ', ' )
  1753. def _print_Range(self, s):
  1754. if self._use_unicode:
  1755. dots = "\N{HORIZONTAL ELLIPSIS}"
  1756. else:
  1757. dots = '...'
  1758. if s.start.is_infinite and s.stop.is_infinite:
  1759. if s.step.is_positive:
  1760. printset = dots, -1, 0, 1, dots
  1761. else:
  1762. printset = dots, 1, 0, -1, dots
  1763. elif s.start.is_infinite:
  1764. printset = dots, s[-1] - s.step, s[-1]
  1765. elif s.stop.is_infinite:
  1766. it = iter(s)
  1767. printset = next(it), next(it), dots
  1768. elif len(s) > 4:
  1769. it = iter(s)
  1770. printset = next(it), next(it), dots, s[-1]
  1771. else:
  1772. printset = tuple(s)
  1773. return self._print_seq(printset, '{', '}', ', ' )
  1774. def _print_Interval(self, i):
  1775. if i.start == i.end:
  1776. return self._print_seq(i.args[:1], '{', '}')
  1777. else:
  1778. if i.left_open:
  1779. left = '('
  1780. else:
  1781. left = '['
  1782. if i.right_open:
  1783. right = ')'
  1784. else:
  1785. right = ']'
  1786. return self._print_seq(i.args[:2], left, right)
  1787. def _print_AccumulationBounds(self, i):
  1788. left = '<'
  1789. right = '>'
  1790. return self._print_seq(i.args[:2], left, right)
  1791. def _print_Intersection(self, u):
  1792. delimiter = ' %s ' % pretty_atom('Intersection', 'n')
  1793. return self._print_seq(u.args, None, None, delimiter,
  1794. parenthesize=lambda set: set.is_ProductSet or
  1795. set.is_Union or set.is_Complement)
  1796. def _print_Union(self, u):
  1797. union_delimiter = ' %s ' % pretty_atom('Union', 'U')
  1798. return self._print_seq(u.args, None, None, union_delimiter,
  1799. parenthesize=lambda set: set.is_ProductSet or
  1800. set.is_Intersection or set.is_Complement)
  1801. def _print_SymmetricDifference(self, u):
  1802. if not self._use_unicode:
  1803. raise NotImplementedError("ASCII pretty printing of SymmetricDifference is not implemented")
  1804. sym_delimeter = ' %s ' % pretty_atom('SymmetricDifference')
  1805. return self._print_seq(u.args, None, None, sym_delimeter)
  1806. def _print_Complement(self, u):
  1807. delimiter = r' \ '
  1808. return self._print_seq(u.args, None, None, delimiter,
  1809. parenthesize=lambda set: set.is_ProductSet or set.is_Intersection
  1810. or set.is_Union)
  1811. def _print_ImageSet(self, ts):
  1812. if self._use_unicode:
  1813. inn = "\N{SMALL ELEMENT OF}"
  1814. else:
  1815. inn = 'in'
  1816. fun = ts.lamda
  1817. sets = ts.base_sets
  1818. signature = fun.signature
  1819. expr = self._print(fun.expr)
  1820. # TODO: the stuff to the left of the | and the stuff to the right of
  1821. # the | should have independent baselines, that way something like
  1822. # ImageSet(Lambda(x, 1/x**2), S.Naturals) prints the "x in N" part
  1823. # centered on the right instead of aligned with the fraction bar on
  1824. # the left. The same also applies to ConditionSet and ComplexRegion
  1825. if len(signature) == 1:
  1826. S = self._print_seq((signature[0], inn, sets[0]),
  1827. delimiter=' ')
  1828. return self._hprint_vseparator(expr, S,
  1829. left='{', right='}',
  1830. ifascii_nougly=True, delimiter=' ')
  1831. else:
  1832. pargs = tuple(j for var, setv in zip(signature, sets) for j in
  1833. (var, ' ', inn, ' ', setv, ", "))
  1834. S = self._print_seq(pargs[:-1], delimiter='')
  1835. return self._hprint_vseparator(expr, S,
  1836. left='{', right='}',
  1837. ifascii_nougly=True, delimiter=' ')
  1838. def _print_ConditionSet(self, ts):
  1839. if self._use_unicode:
  1840. inn = "\N{SMALL ELEMENT OF}"
  1841. # using _and because and is a keyword and it is bad practice to
  1842. # overwrite them
  1843. _and = "\N{LOGICAL AND}"
  1844. else:
  1845. inn = 'in'
  1846. _and = 'and'
  1847. variables = self._print_seq(Tuple(ts.sym))
  1848. as_expr = getattr(ts.condition, 'as_expr', None)
  1849. if as_expr is not None:
  1850. cond = self._print(ts.condition.as_expr())
  1851. else:
  1852. cond = self._print(ts.condition)
  1853. if self._use_unicode:
  1854. cond = self._print(cond)
  1855. cond = prettyForm(*cond.parens())
  1856. if ts.base_set is S.UniversalSet:
  1857. return self._hprint_vseparator(variables, cond, left="{",
  1858. right="}", ifascii_nougly=True,
  1859. delimiter=' ')
  1860. base = self._print(ts.base_set)
  1861. C = self._print_seq((variables, inn, base, _and, cond),
  1862. delimiter=' ')
  1863. return self._hprint_vseparator(variables, C, left="{", right="}",
  1864. ifascii_nougly=True, delimiter=' ')
  1865. def _print_ComplexRegion(self, ts):
  1866. if self._use_unicode:
  1867. inn = "\N{SMALL ELEMENT OF}"
  1868. else:
  1869. inn = 'in'
  1870. variables = self._print_seq(ts.variables)
  1871. expr = self._print(ts.expr)
  1872. prodsets = self._print(ts.sets)
  1873. C = self._print_seq((variables, inn, prodsets),
  1874. delimiter=' ')
  1875. return self._hprint_vseparator(expr, C, left="{", right="}",
  1876. ifascii_nougly=True, delimiter=' ')
  1877. def _print_Contains(self, e):
  1878. var, set = e.args
  1879. if self._use_unicode:
  1880. el = " \N{ELEMENT OF} "
  1881. return prettyForm(*stringPict.next(self._print(var),
  1882. el, self._print(set)), binding=8)
  1883. else:
  1884. return prettyForm(sstr(e))
  1885. def _print_FourierSeries(self, s):
  1886. if s.an.formula is S.Zero and s.bn.formula is S.Zero:
  1887. return self._print(s.a0)
  1888. if self._use_unicode:
  1889. dots = "\N{HORIZONTAL ELLIPSIS}"
  1890. else:
  1891. dots = '...'
  1892. return self._print_Add(s.truncate()) + self._print(dots)
  1893. def _print_FormalPowerSeries(self, s):
  1894. return self._print_Add(s.infinite)
  1895. def _print_SetExpr(self, se):
  1896. pretty_set = prettyForm(*self._print(se.set).parens())
  1897. pretty_name = self._print(Symbol("SetExpr"))
  1898. return prettyForm(*pretty_name.right(pretty_set))
  1899. def _print_SeqFormula(self, s):
  1900. if self._use_unicode:
  1901. dots = "\N{HORIZONTAL ELLIPSIS}"
  1902. else:
  1903. dots = '...'
  1904. if len(s.start.free_symbols) > 0 or len(s.stop.free_symbols) > 0:
  1905. raise NotImplementedError("Pretty printing of sequences with symbolic bound not implemented")
  1906. if s.start is S.NegativeInfinity:
  1907. stop = s.stop
  1908. printset = (dots, s.coeff(stop - 3), s.coeff(stop - 2),
  1909. s.coeff(stop - 1), s.coeff(stop))
  1910. elif s.stop is S.Infinity or s.length > 4:
  1911. printset = s[:4]
  1912. printset.append(dots)
  1913. printset = tuple(printset)
  1914. else:
  1915. printset = tuple(s)
  1916. return self._print_list(printset)
  1917. _print_SeqPer = _print_SeqFormula
  1918. _print_SeqAdd = _print_SeqFormula
  1919. _print_SeqMul = _print_SeqFormula
  1920. def _print_seq(self, seq, left=None, right=None, delimiter=', ',
  1921. parenthesize=lambda x: False, ifascii_nougly=True):
  1922. try:
  1923. pforms = []
  1924. for item in seq:
  1925. pform = self._print(item)
  1926. if parenthesize(item):
  1927. pform = prettyForm(*pform.parens())
  1928. if pforms:
  1929. pforms.append(delimiter)
  1930. pforms.append(pform)
  1931. if not pforms:
  1932. s = stringPict('')
  1933. else:
  1934. s = prettyForm(*stringPict.next(*pforms))
  1935. # XXX: Under the tests from #15686 the above raises:
  1936. # AttributeError: 'Fake' object has no attribute 'baseline'
  1937. # This is caught below but that is not the right way to
  1938. # fix it.
  1939. except AttributeError:
  1940. s = None
  1941. for item in seq:
  1942. pform = self.doprint(item)
  1943. if parenthesize(item):
  1944. pform = prettyForm(*pform.parens())
  1945. if s is None:
  1946. # first element
  1947. s = pform
  1948. else :
  1949. s = prettyForm(*stringPict.next(s, delimiter))
  1950. s = prettyForm(*stringPict.next(s, pform))
  1951. if s is None:
  1952. s = stringPict('')
  1953. s = prettyForm(*s.parens(left, right, ifascii_nougly=ifascii_nougly))
  1954. return s
  1955. def join(self, delimiter, args):
  1956. pform = None
  1957. for arg in args:
  1958. if pform is None:
  1959. pform = arg
  1960. else:
  1961. pform = prettyForm(*pform.right(delimiter))
  1962. pform = prettyForm(*pform.right(arg))
  1963. if pform is None:
  1964. return prettyForm("")
  1965. else:
  1966. return pform
  1967. def _print_list(self, l):
  1968. return self._print_seq(l, '[', ']')
  1969. def _print_tuple(self, t):
  1970. if len(t) == 1:
  1971. ptuple = prettyForm(*stringPict.next(self._print(t[0]), ','))
  1972. return prettyForm(*ptuple.parens('(', ')', ifascii_nougly=True))
  1973. else:
  1974. return self._print_seq(t, '(', ')')
  1975. def _print_Tuple(self, expr):
  1976. return self._print_tuple(expr)
  1977. def _print_dict(self, d):
  1978. keys = sorted(d.keys(), key=default_sort_key)
  1979. items = []
  1980. for k in keys:
  1981. K = self._print(k)
  1982. V = self._print(d[k])
  1983. s = prettyForm(*stringPict.next(K, ': ', V))
  1984. items.append(s)
  1985. return self._print_seq(items, '{', '}')
  1986. def _print_Dict(self, d):
  1987. return self._print_dict(d)
  1988. def _print_set(self, s):
  1989. if not s:
  1990. return prettyForm('set()')
  1991. items = sorted(s, key=default_sort_key)
  1992. pretty = self._print_seq(items)
  1993. pretty = prettyForm(*pretty.parens('{', '}', ifascii_nougly=True))
  1994. return pretty
  1995. def _print_frozenset(self, s):
  1996. if not s:
  1997. return prettyForm('frozenset()')
  1998. items = sorted(s, key=default_sort_key)
  1999. pretty = self._print_seq(items)
  2000. pretty = prettyForm(*pretty.parens('{', '}', ifascii_nougly=True))
  2001. pretty = prettyForm(*pretty.parens('(', ')', ifascii_nougly=True))
  2002. pretty = prettyForm(*stringPict.next(type(s).__name__, pretty))
  2003. return pretty
  2004. def _print_UniversalSet(self, s):
  2005. if self._use_unicode:
  2006. return prettyForm("\N{MATHEMATICAL DOUBLE-STRUCK CAPITAL U}")
  2007. else:
  2008. return prettyForm('UniversalSet')
  2009. def _print_PolyRing(self, ring):
  2010. return prettyForm(sstr(ring))
  2011. def _print_FracField(self, field):
  2012. return prettyForm(sstr(field))
  2013. def _print_FreeGroupElement(self, elm):
  2014. return prettyForm(str(elm))
  2015. def _print_PolyElement(self, poly):
  2016. return prettyForm(sstr(poly))
  2017. def _print_FracElement(self, frac):
  2018. return prettyForm(sstr(frac))
  2019. def _print_AlgebraicNumber(self, expr):
  2020. if expr.is_aliased:
  2021. return self._print(expr.as_poly().as_expr())
  2022. else:
  2023. return self._print(expr.as_expr())
  2024. def _print_ComplexRootOf(self, expr):
  2025. args = [self._print_Add(expr.expr, order='lex'), expr.index]
  2026. pform = prettyForm(*self._print_seq(args).parens())
  2027. pform = prettyForm(*pform.left('CRootOf'))
  2028. return pform
  2029. def _print_RootSum(self, expr):
  2030. args = [self._print_Add(expr.expr, order='lex')]
  2031. if expr.fun is not S.IdentityFunction:
  2032. args.append(self._print(expr.fun))
  2033. pform = prettyForm(*self._print_seq(args).parens())
  2034. pform = prettyForm(*pform.left('RootSum'))
  2035. return pform
  2036. def _print_FiniteField(self, expr):
  2037. if self._use_unicode:
  2038. form = '\N{DOUBLE-STRUCK CAPITAL Z}_%d'
  2039. else:
  2040. form = 'GF(%d)'
  2041. return prettyForm(pretty_symbol(form % expr.mod))
  2042. def _print_IntegerRing(self, expr):
  2043. if self._use_unicode:
  2044. return prettyForm('\N{DOUBLE-STRUCK CAPITAL Z}')
  2045. else:
  2046. return prettyForm('ZZ')
  2047. def _print_RationalField(self, expr):
  2048. if self._use_unicode:
  2049. return prettyForm('\N{DOUBLE-STRUCK CAPITAL Q}')
  2050. else:
  2051. return prettyForm('QQ')
  2052. def _print_RealField(self, domain):
  2053. if self._use_unicode:
  2054. prefix = '\N{DOUBLE-STRUCK CAPITAL R}'
  2055. else:
  2056. prefix = 'RR'
  2057. if domain.has_default_precision:
  2058. return prettyForm(prefix)
  2059. else:
  2060. return self._print(pretty_symbol(prefix + "_" + str(domain.precision)))
  2061. def _print_ComplexField(self, domain):
  2062. if self._use_unicode:
  2063. prefix = '\N{DOUBLE-STRUCK CAPITAL C}'
  2064. else:
  2065. prefix = 'CC'
  2066. if domain.has_default_precision:
  2067. return prettyForm(prefix)
  2068. else:
  2069. return self._print(pretty_symbol(prefix + "_" + str(domain.precision)))
  2070. def _print_PolynomialRing(self, expr):
  2071. args = list(expr.symbols)
  2072. if not expr.order.is_default:
  2073. order = prettyForm(*prettyForm("order=").right(self._print(expr.order)))
  2074. args.append(order)
  2075. pform = self._print_seq(args, '[', ']')
  2076. pform = prettyForm(*pform.left(self._print(expr.domain)))
  2077. return pform
  2078. def _print_FractionField(self, expr):
  2079. args = list(expr.symbols)
  2080. if not expr.order.is_default:
  2081. order = prettyForm(*prettyForm("order=").right(self._print(expr.order)))
  2082. args.append(order)
  2083. pform = self._print_seq(args, '(', ')')
  2084. pform = prettyForm(*pform.left(self._print(expr.domain)))
  2085. return pform
  2086. def _print_PolynomialRingBase(self, expr):
  2087. g = expr.symbols
  2088. if str(expr.order) != str(expr.default_order):
  2089. g = g + ("order=" + str(expr.order),)
  2090. pform = self._print_seq(g, '[', ']')
  2091. pform = prettyForm(*pform.left(self._print(expr.domain)))
  2092. return pform
  2093. def _print_GroebnerBasis(self, basis):
  2094. exprs = [ self._print_Add(arg, order=basis.order)
  2095. for arg in basis.exprs ]
  2096. exprs = prettyForm(*self.join(", ", exprs).parens(left="[", right="]"))
  2097. gens = [ self._print(gen) for gen in basis.gens ]
  2098. domain = prettyForm(
  2099. *prettyForm("domain=").right(self._print(basis.domain)))
  2100. order = prettyForm(
  2101. *prettyForm("order=").right(self._print(basis.order)))
  2102. pform = self.join(", ", [exprs] + gens + [domain, order])
  2103. pform = prettyForm(*pform.parens())
  2104. pform = prettyForm(*pform.left(basis.__class__.__name__))
  2105. return pform
  2106. def _print_Subs(self, e):
  2107. pform = self._print(e.expr)
  2108. pform = prettyForm(*pform.parens())
  2109. h = pform.height() if pform.height() > 1 else 2
  2110. rvert = stringPict(vobj('|', h), baseline=pform.baseline)
  2111. pform = prettyForm(*pform.right(rvert))
  2112. b = pform.baseline
  2113. pform.baseline = pform.height() - 1
  2114. pform = prettyForm(*pform.right(self._print_seq([
  2115. self._print_seq((self._print(v[0]), xsym('=='), self._print(v[1])),
  2116. delimiter='') for v in zip(e.variables, e.point) ])))
  2117. pform.baseline = b
  2118. return pform
  2119. def _print_number_function(self, e, name):
  2120. # Print name_arg[0] for one argument or name_arg[0](arg[1])
  2121. # for more than one argument
  2122. pform = prettyForm(name)
  2123. arg = self._print(e.args[0])
  2124. pform_arg = prettyForm(" "*arg.width())
  2125. pform_arg = prettyForm(*pform_arg.below(arg))
  2126. pform = prettyForm(*pform.right(pform_arg))
  2127. if len(e.args) == 1:
  2128. return pform
  2129. m, x = e.args
  2130. # TODO: copy-pasted from _print_Function: can we do better?
  2131. prettyFunc = pform
  2132. prettyArgs = prettyForm(*self._print_seq([x]).parens())
  2133. pform = prettyForm(
  2134. binding=prettyForm.FUNC, *stringPict.next(prettyFunc, prettyArgs))
  2135. pform.prettyFunc = prettyFunc
  2136. pform.prettyArgs = prettyArgs
  2137. return pform
  2138. def _print_euler(self, e):
  2139. return self._print_number_function(e, "E")
  2140. def _print_catalan(self, e):
  2141. return self._print_number_function(e, "C")
  2142. def _print_bernoulli(self, e):
  2143. return self._print_number_function(e, "B")
  2144. _print_bell = _print_bernoulli
  2145. def _print_lucas(self, e):
  2146. return self._print_number_function(e, "L")
  2147. def _print_fibonacci(self, e):
  2148. return self._print_number_function(e, "F")
  2149. def _print_tribonacci(self, e):
  2150. return self._print_number_function(e, "T")
  2151. def _print_stieltjes(self, e):
  2152. if self._use_unicode:
  2153. return self._print_number_function(e, '\N{GREEK SMALL LETTER GAMMA}')
  2154. else:
  2155. return self._print_number_function(e, "stieltjes")
  2156. def _print_KroneckerDelta(self, e):
  2157. pform = self._print(e.args[0])
  2158. pform = prettyForm(*pform.right(prettyForm(',')))
  2159. pform = prettyForm(*pform.right(self._print(e.args[1])))
  2160. if self._use_unicode:
  2161. a = stringPict(pretty_symbol('delta'))
  2162. else:
  2163. a = stringPict('d')
  2164. b = pform
  2165. top = stringPict(*b.left(' '*a.width()))
  2166. bot = stringPict(*a.right(' '*b.width()))
  2167. return prettyForm(binding=prettyForm.POW, *bot.below(top))
  2168. def _print_RandomDomain(self, d):
  2169. if hasattr(d, 'as_boolean'):
  2170. pform = self._print('Domain: ')
  2171. pform = prettyForm(*pform.right(self._print(d.as_boolean())))
  2172. return pform
  2173. elif hasattr(d, 'set'):
  2174. pform = self._print('Domain: ')
  2175. pform = prettyForm(*pform.right(self._print(d.symbols)))
  2176. pform = prettyForm(*pform.right(self._print(' in ')))
  2177. pform = prettyForm(*pform.right(self._print(d.set)))
  2178. return pform
  2179. elif hasattr(d, 'symbols'):
  2180. pform = self._print('Domain on ')
  2181. pform = prettyForm(*pform.right(self._print(d.symbols)))
  2182. return pform
  2183. else:
  2184. return self._print(None)
  2185. def _print_DMP(self, p):
  2186. try:
  2187. if p.ring is not None:
  2188. # TODO incorporate order
  2189. return self._print(p.ring.to_sympy(p))
  2190. except SympifyError:
  2191. pass
  2192. return self._print(repr(p))
  2193. def _print_DMF(self, p):
  2194. return self._print_DMP(p)
  2195. def _print_Object(self, object):
  2196. return self._print(pretty_symbol(object.name))
  2197. def _print_Morphism(self, morphism):
  2198. arrow = xsym("-->")
  2199. domain = self._print(morphism.domain)
  2200. codomain = self._print(morphism.codomain)
  2201. tail = domain.right(arrow, codomain)[0]
  2202. return prettyForm(tail)
  2203. def _print_NamedMorphism(self, morphism):
  2204. pretty_name = self._print(pretty_symbol(morphism.name))
  2205. pretty_morphism = self._print_Morphism(morphism)
  2206. return prettyForm(pretty_name.right(":", pretty_morphism)[0])
  2207. def _print_IdentityMorphism(self, morphism):
  2208. from sympy.categories import NamedMorphism
  2209. return self._print_NamedMorphism(
  2210. NamedMorphism(morphism.domain, morphism.codomain, "id"))
  2211. def _print_CompositeMorphism(self, morphism):
  2212. circle = xsym(".")
  2213. # All components of the morphism have names and it is thus
  2214. # possible to build the name of the composite.
  2215. component_names_list = [pretty_symbol(component.name) for
  2216. component in morphism.components]
  2217. component_names_list.reverse()
  2218. component_names = circle.join(component_names_list) + ":"
  2219. pretty_name = self._print(component_names)
  2220. pretty_morphism = self._print_Morphism(morphism)
  2221. return prettyForm(pretty_name.right(pretty_morphism)[0])
  2222. def _print_Category(self, category):
  2223. return self._print(pretty_symbol(category.name))
  2224. def _print_Diagram(self, diagram):
  2225. if not diagram.premises:
  2226. # This is an empty diagram.
  2227. return self._print(S.EmptySet)
  2228. pretty_result = self._print(diagram.premises)
  2229. if diagram.conclusions:
  2230. results_arrow = " %s " % xsym("==>")
  2231. pretty_conclusions = self._print(diagram.conclusions)[0]
  2232. pretty_result = pretty_result.right(
  2233. results_arrow, pretty_conclusions)
  2234. return prettyForm(pretty_result[0])
  2235. def _print_DiagramGrid(self, grid):
  2236. from sympy.matrices import Matrix
  2237. matrix = Matrix([[grid[i, j] if grid[i, j] else Symbol(" ")
  2238. for j in range(grid.width)]
  2239. for i in range(grid.height)])
  2240. return self._print_matrix_contents(matrix)
  2241. def _print_FreeModuleElement(self, m):
  2242. # Print as row vector for convenience, for now.
  2243. return self._print_seq(m, '[', ']')
  2244. def _print_SubModule(self, M):
  2245. return self._print_seq(M.gens, '<', '>')
  2246. def _print_FreeModule(self, M):
  2247. return self._print(M.ring)**self._print(M.rank)
  2248. def _print_ModuleImplementedIdeal(self, M):
  2249. return self._print_seq([x for [x] in M._module.gens], '<', '>')
  2250. def _print_QuotientRing(self, R):
  2251. return self._print(R.ring) / self._print(R.base_ideal)
  2252. def _print_QuotientRingElement(self, R):
  2253. return self._print(R.data) + self._print(R.ring.base_ideal)
  2254. def _print_QuotientModuleElement(self, m):
  2255. return self._print(m.data) + self._print(m.module.killed_module)
  2256. def _print_QuotientModule(self, M):
  2257. return self._print(M.base) / self._print(M.killed_module)
  2258. def _print_MatrixHomomorphism(self, h):
  2259. matrix = self._print(h._sympy_matrix())
  2260. matrix.baseline = matrix.height() // 2
  2261. pform = prettyForm(*matrix.right(' : ', self._print(h.domain),
  2262. ' %s> ' % hobj('-', 2), self._print(h.codomain)))
  2263. return pform
  2264. def _print_Manifold(self, manifold):
  2265. return self._print(manifold.name)
  2266. def _print_Patch(self, patch):
  2267. return self._print(patch.name)
  2268. def _print_CoordSystem(self, coords):
  2269. return self._print(coords.name)
  2270. def _print_BaseScalarField(self, field):
  2271. string = field._coord_sys.symbols[field._index].name
  2272. return self._print(pretty_symbol(string))
  2273. def _print_BaseVectorField(self, field):
  2274. s = U('PARTIAL DIFFERENTIAL') + '_' + field._coord_sys.symbols[field._index].name
  2275. return self._print(pretty_symbol(s))
  2276. def _print_Differential(self, diff):
  2277. if self._use_unicode:
  2278. d = '\N{DOUBLE-STRUCK ITALIC SMALL D}'
  2279. else:
  2280. d = 'd'
  2281. field = diff._form_field
  2282. if hasattr(field, '_coord_sys'):
  2283. string = field._coord_sys.symbols[field._index].name
  2284. return self._print(d + ' ' + pretty_symbol(string))
  2285. else:
  2286. pform = self._print(field)
  2287. pform = prettyForm(*pform.parens())
  2288. return prettyForm(*pform.left(d))
  2289. def _print_Tr(self, p):
  2290. #TODO: Handle indices
  2291. pform = self._print(p.args[0])
  2292. pform = prettyForm(*pform.left('%s(' % (p.__class__.__name__)))
  2293. pform = prettyForm(*pform.right(')'))
  2294. return pform
  2295. def _print_primenu(self, e):
  2296. pform = self._print(e.args[0])
  2297. pform = prettyForm(*pform.parens())
  2298. if self._use_unicode:
  2299. pform = prettyForm(*pform.left(greek_unicode['nu']))
  2300. else:
  2301. pform = prettyForm(*pform.left('nu'))
  2302. return pform
  2303. def _print_primeomega(self, e):
  2304. pform = self._print(e.args[0])
  2305. pform = prettyForm(*pform.parens())
  2306. if self._use_unicode:
  2307. pform = prettyForm(*pform.left(greek_unicode['Omega']))
  2308. else:
  2309. pform = prettyForm(*pform.left('Omega'))
  2310. return pform
  2311. def _print_Quantity(self, e):
  2312. if e.name.name == 'degree':
  2313. pform = self._print("\N{DEGREE SIGN}")
  2314. return pform
  2315. else:
  2316. return self.emptyPrinter(e)
  2317. def _print_AssignmentBase(self, e):
  2318. op = prettyForm(' ' + xsym(e.op) + ' ')
  2319. l = self._print(e.lhs)
  2320. r = self._print(e.rhs)
  2321. pform = prettyForm(*stringPict.next(l, op, r))
  2322. return pform
  2323. def _print_Str(self, s):
  2324. return self._print(s.name)
  2325. @print_function(PrettyPrinter)
  2326. def pretty(expr, **settings):
  2327. """Returns a string containing the prettified form of expr.
  2328. For information on keyword arguments see pretty_print function.
  2329. """
  2330. pp = PrettyPrinter(settings)
  2331. # XXX: this is an ugly hack, but at least it works
  2332. use_unicode = pp._settings['use_unicode']
  2333. uflag = pretty_use_unicode(use_unicode)
  2334. try:
  2335. return pp.doprint(expr)
  2336. finally:
  2337. pretty_use_unicode(uflag)
  2338. def pretty_print(expr, **kwargs):
  2339. """Prints expr in pretty form.
  2340. pprint is just a shortcut for this function.
  2341. Parameters
  2342. ==========
  2343. expr : expression
  2344. The expression to print.
  2345. wrap_line : bool, optional (default=True)
  2346. Line wrapping enabled/disabled.
  2347. num_columns : int or None, optional (default=None)
  2348. Number of columns before line breaking (default to None which reads
  2349. the terminal width), useful when using SymPy without terminal.
  2350. use_unicode : bool or None, optional (default=None)
  2351. Use unicode characters, such as the Greek letter pi instead of
  2352. the string pi.
  2353. full_prec : bool or string, optional (default="auto")
  2354. Use full precision.
  2355. order : bool or string, optional (default=None)
  2356. Set to 'none' for long expressions if slow; default is None.
  2357. use_unicode_sqrt_char : bool, optional (default=True)
  2358. Use compact single-character square root symbol (when unambiguous).
  2359. root_notation : bool, optional (default=True)
  2360. Set to 'False' for printing exponents of the form 1/n in fractional form.
  2361. By default exponent is printed in root form.
  2362. mat_symbol_style : string, optional (default="plain")
  2363. Set to "bold" for printing MatrixSymbols using a bold mathematical symbol face.
  2364. By default the standard face is used.
  2365. imaginary_unit : string, optional (default="i")
  2366. Letter to use for imaginary unit when use_unicode is True.
  2367. Can be "i" (default) or "j".
  2368. """
  2369. print(pretty(expr, **kwargs))
  2370. pprint = pretty_print
  2371. def pager_print(expr, **settings):
  2372. """Prints expr using the pager, in pretty form.
  2373. This invokes a pager command using pydoc. Lines are not wrapped
  2374. automatically. This routine is meant to be used with a pager that allows
  2375. sideways scrolling, like ``less -S``.
  2376. Parameters are the same as for ``pretty_print``. If you wish to wrap lines,
  2377. pass ``num_columns=None`` to auto-detect the width of the terminal.
  2378. """
  2379. from pydoc import pager
  2380. from locale import getpreferredencoding
  2381. if 'num_columns' not in settings:
  2382. settings['num_columns'] = 500000 # disable line wrap
  2383. pager(pretty(expr, **settings).encode(getpreferredencoding()))