<jupyter_start><jupyter_text>Table of Contents* [1. Demonstration of the ``numpy.polynomial`` package](1.-Demonstration-of-the-numpy.polynomial-package)	* [1.1 And especially a small hand-made pretty printing function for ``Polynomial`` objects](1.1-And-especially-a-small-hand-made-pretty-printing-function-for-Polynomial-objects)	* [1.2 First goal: pretty print in ASCII text](1.2-First-goal:-pretty-print-in-ASCII-text)	* [1.3 Second goal: pretty-print in $\LaTeX{}$ code](1.3-Second-goal:-pretty-print-in-$\LaTeX{}$-code)	* [1.4 A bonus for the end: add this pretty-printer as the default one in IPython:](1.4-A-bonus-for-the-end:-add-this-pretty-printer-as-the-default-one-in-IPython:)  1. Demonstration of the ``numpy.polynomial`` package  1.1 And especially a small hand-made pretty printing function for ``Polynomial`` objects For both [Python 2](https://docs.python.org/2/) and [Python 3](https://docs.python.org/3/), [numpy](https://numpy.org) has a very nice module to work with [polynomials](https://en.wikipedia.org/wiki/Polynomial): [numpy.polynomial](https://docs.scipy.org/doc/numpy/reference/routines.polynomials.classes.html).If you are not familiar with it, I **highly** recommend you to read [this tutorial](https://docs.scipy.org/doc/numpy/reference/routines.polynomials.classes.htmlbasics).> - Note: this small tutorial was inspired by [this question asked on StackOverflow](https://stackoverflow.com/questions/28646336/pretty-printing-polynomials-in-ipython-notebook/3751003637510036) (and by my answer).> - This [Jupyter Notebook](http://jupyter.org/) was written by [<NAME>](https://github.com/Naereen/). ----Now, let assume you already know everything about Python, and the ``numpy.polynomial`` package.So you know that it should be imported like this:<jupyter_code>from numpy.polynomial import Polynomial as P<jupyter_output><empty_output><jupyter_text>And we can then define the monome $X$ as ``P([0, 1])``, defined by the list of its coefficients in the *canonical* basis $(X_i)_{i \in \mathbb{N}}$:<jupyter_code>X = P([0, 1])
print("We defined the monome X =", X)
X<jupyter_output>We defined the monome X = poly([ 0.  1.])<jupyter_text>The main issue with this output (either ``poly([ 0.  1.])`` or ``Polynomial([ 0.,  1.], [-1,  1], [-1,  1])``) is its lack of *sexyness*: it gives the required information (coefficients, domain, window etc, see [here](https://docs.scipy.org/doc/numpy/reference/generated/numpy.polynomial.polynomial.Polynomial.htmlnumpy.polynomial.polynomial.Polynomial) for more details) but it is too far from the mathematical notation.If we define $Q(X) = 1 + 17 X^3$, we would like Python (or IPython, or in this case, the Jupyter Notebook) to display this polynomial nicely, either as ASCII text: ``1 + 17 * X**3`` (valid Python code), or as a nice $\LaTeX{}$ code: ``1 + 17 X^3``.<jupyter_code>Q = 1 + 17 * X ** 3
print("Q(X) =", Q)
Q<jupyter_output>Q(X) = poly([  1.   0.   0.  17.])<jupyter_text>----  1.2 First goal: pretty print in ASCII text Our first task will be to implement a small function, or an overload of the [numpy.polynomial.Polynomial](https://docs.scipy.org/doc/numpy/reference/generated/numpy.polynomial.polynomial.Polynomial.html) class to be able to pretty-print a ``Polynomial`` object nicely.> Note: more details, along with a documentation, some examples and a fully [pylint](https://www.pylint.org/)-compatible code are available on this [Bitbucket snippet](https://bitbucket.org/snippets/): [bitbucket.org/snippets/lbesson/j6dpz](https://bitbucket.org/snippets/lbesson/j6dpzfile-nicedisplay_numpy_polynomial_Polynomial.py). The function ``prettyprintPolynomial`` defined below implements a natural strategy to print a polynomial: it prints the coefficients, as ``a_i * X**i``, in increasing order.This function takes care of all the special cases:- it removes a trailing ``.0`` if one coefficient is an integer,- it displays the coefficient between ``(`` and ``)`` if it is negative,- it only displays the non-zero coefficients,- if one coefficient is ``1``, no need to display it.<jupyter_code>def prettyprintPolynomial(p):
    """ Small function to print nicely the polynomial p as we write it in maths, in ASCII text."""
    coefs = p.coef  # List of coefficient, sorted by increasing degrees
    res = ""  # The resulting string
    for i, a in enumerate(coefs):
        if int(a) == a:  # Remove the trailing .0
            a = int(a)
        if i == 0:  # First coefficient, no need for X
            if a > 0:
                res += "{a} + ".format(a=a)
            elif a < 0:  # Negative a is printed like (a)
                res += "({a}) + ".format(a=a)
            # a = 0 is not displayed 
        elif i == 1:  # Second coefficient, only X and not X**i
            if a == 1:  # a = 1 does not need to be displayed
                res += "X + "
            elif a > 0:
                res += "{a} * X + ".format(a=a)
            elif a < 0:
                res += "({a}) * X + ".format(a=a)
        else:
            if a == 1:
                res += "X**{i} + ".format(i=i)
            elif a > 0:
                res += "{a} * X**{i} + ".format(a=a, i=i)
            elif a < 0:
                res += "({a}) * X**{i} + ".format(a=a, i=i)
    return res[:-3] if res else ""<jupyter_output><empty_output><jupyter_text>We can check its behavior on some small polynomials:<jupyter_code>print("X =", prettyprintPolynomial(X))
print("Q(X) =", prettyprintPolynomial(Q))
Q3 = -1 - 2*X - 17*X**3
print("Q_3(X) =", prettyprintPolynomial(Q3))
print("- Q_3(X) =", prettyprintPolynomial(-Q3))<jupyter_output>Q_3(X) = (-1) + (-2) * X + (-17) * X**3
- Q_3(X) = 1 + 2 * X + 17 * X**3<jupyter_text>We can create a more complicated polynomial $Q_4(X) = (1 + 2 X + 17 X^3) ^ {12}$ and check that it is also nicely printed:<jupyter_code>Q4 = (1 + 2*X + 17*X**3) ** 12
print("Q_4(X) =", prettyprintPolynomial(Q4))<jupyter_output>Q_4(X) = 1 + 24 * X + 264 * X**2 + 1964 * X**3 + 12408 * X**4 + 70224 * X**5 + 347490 * X**6 + 1559976 * X**7 + 6575976 * X**8 + 25536412 * X**9 + 92228664 * X**10 + 318098112 * X**11 + 1029784111 * X**12 + 3135774576 * X**13 + 9208582032 * X**14 + 25554505944 * X**15 + 67047551472 * X**16 + 171037015776 * X**17 + 411810470236 * X**18 + 939707466192 * X**19 + 2104452578448 * X**20 + 4397274411288 * X**21 + 8746569014832 * X**22 + 17281727001792 * X**23 + 30879457534959 * X**24 + 53623057787640 * X**25 + 93271621727592 * X**26 + 136585330694780 * X**27 + 211783995908760 * X**28 + 313071993952080 * X**29 + 341770260064354 * X**30 + 532222389718536 * X**31 + 532222389718536 * X**32 + 411262755691596 * X**33 + 822525511383192 * X**34 + 582622237229761 * X**36<jupyter_text>----  1.3 Second goal: pretty-print in $\LaTeX{}$ code We will simply modify the function ``prettyprintPolynomial`` to use $\LaTeX{}$ code instead of ASCII text: the string has to be between ``$``, the multiplications are without symbols (e.g., $17 X$ for ``17 * X``), and the powers are with the ``^`` symbol instead of ``**`` :<jupyter_code>def Polynomial_to_LaTeX(p):
    """ Small function to print nicely the polynomial p as we write it in maths, in LaTeX code."""
    coefs = p.coef  # List of coefficient, sorted by increasing degrees
    res = ""  # The resulting string
    for i, a in enumerate(coefs):
        if int(a) == a:  # Remove the trailing .0
            a = int(a)
        if i == 0:  # First coefficient, no need for X
            if a > 0:
                res += "{a} + ".format(a=a)
            elif a < 0:  # Negative a is printed like (a)
                res += "({a}) + ".format(a=a)
            # a = 0 is not displayed 
        elif i == 1:  # Second coefficient, only X and not X**i
            if a == 1:  # a = 1 does not need to be displayed
                res += "X + "
            elif a > 0:
                res += "{a} \;X + ".format(a=a)
            elif a < 0:
                res += "({a}) \;X + ".format(a=a)
        else:
            if a == 1:
                # A special care needs to be addressed to put the exponent in {..} in LaTeX
                res += "X^{i} + ".format(i="{%d}" % i)
            elif a > 0:
                res += "{a} \;X^{i} + ".format(a=a, i="{%d}" % i)
            elif a < 0:
                res += "({a}) \;X^{i} + ".format(a=a, i="{%d}" % i)
    return "$" + res[:-3] + "$" if res else ""<jupyter_output><empty_output><jupyter_text>We can quickly try the same examples as before:<jupyter_code>print("X =", Polynomial_to_LaTeX(X))
print("Q(X) =", Polynomial_to_LaTeX(Q))<jupyter_output>X = $X$
Q(X) = $1 + 17 \;X^{3}$<jupyter_text>But we want the $\LaTeX{}$ code to be pretty-printed by IPython, not just displayed like this.For this, the internal function ``Latex`` from the module ``IPython.display`` is required:<jupyter_code>from IPython.display import Latex
print("X =")
Latex(Polynomial_to_LaTeX(X))
print("Q(X) =")
Latex(Polynomial_to_LaTeX(Q))<jupyter_output>Q(X) =<jupyter_text>Allright! It starts to look like what we wanted!Let's try with a bigger polynomial, as we did before:<jupyter_code>Q4 = (1 + 2*X + 17*X**3) ** 12
print("Q_4(X) =")
Latex(Polynomial_to_LaTeX(Q4))<jupyter_output>Q_4(X) =<jupyter_text>Way nicer! Yay! ----  1.4 A bonus for the end: add this pretty-printer as the default one in IPython: This manipulation is showed in [IPython's documentation](https://nbviewer.jupyter.org/github/ipython/ipython/blob/3607712653c66d63e0d7f13f073bde8c0f209ba8/docs/examples/notebooks/display_protocol.ipynb).But we can configure IPython to do this automatically for us as follows.We hook into the IPython display system and instruct it to use ``Polynomial_to_LaTeX`` for the ``latex`` mimetype, when encountering objects of the ``Polynomial`` type defined in the ``numpy.polynomial.polynomial`` module:<jupyter_code>ip = get_ipython()
latex_formatter = ip.display_formatter.formatters['text/latex']
latex_formatter.for_type_by_name('numpy.polynomial.polynomial',
                                 'Polynomial', Polynomial_to_LaTeX)<jupyter_output><empty_output><jupyter_text>Once our special printer has been loaded, all polynomials will be represented by their mathematical form instead (as $\LaTeX{}$ code displayed with [MathJax](https://www.mathjax.org/)):<jupyter_code>X<jupyter_output><empty_output><jupyter_text>One a last example:<jupyter_code>P = ((1 + X**2)**16)**16 % (1 - X**16)
print("str(P) =", str(P))
print("repr(P) =", repr(P))
P<jupyter_output>str(P) = poly([  1.44740112e+76   0.00000000e+00   1.44740112e+76   0.00000000e+00
   1.44740112e+76   0.00000000e+00   1.44740111e+76   0.00000000e+00
   1.44740111e+76   0.00000000e+00   1.44740111e+76   0.00000000e+00
   1.44740112e+76   0.00000000e+00   1.44740112e+76])
repr(P) = Polynomial([  1.44740112e+76,   0.00000000e+00,   1.44740112e+76,
         0.00000000e+00,   1.44740112e+76,   0.00000000e+00,
         1.44740111e+76,   0.00000000e+00,   1.44740111e+76,
         0.00000000e+00,   1.44740111e+76,   0.00000000e+00,
         1.44740112e+76,   0.00000000e+00,   1.44740112e+76], [-1.,  1.], [-1.,  1.])
{'fraction_non_alphanumeric': 0.15314337403889644, 'fraction_numerical': 0.09000452284034374, 'mean_word_length': 3.44551668677121, 'pattern_counts': {'":': 0, '<': 52, '<?xml version=': 0, '>': 55, 'https://': 15, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 14, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '155322', 'license': 'MIT', 'n_tokens_mistral': 4616, 'n_tokens_neox': 3938, 'n_words': 1110, 'path': 'Demonstration of numpy.polynomial.Polynomial and nice display with LaTeX and MathJax (python3).ipynb', 'repo_name': 'doc22940/notebooks-2', 'size': '11062'}