55595


以下のように、Pythonの文字列をsimpifyで数式に変換し、  
mathmlコマンドで数式をMathML形式に変換すると

[code]

    from sympy import *
    from sympy.printing.mathml import mathml
    
    print(mathml(sympify("(2*x + 3*y + 1)*(4*x**2 - 6*x*y - 2*x + 9*y**2 - 3*y + 1)"),printer='presentation'))
    
[/code]

以下のようなコードが出力されます。

[code]

    <mrow><mrow><mrow><mn>2</mn><mo>&InvisibleTimes;</mo><mi>x</mi></mrow><mo>+</mo><mrow><mn>3</mn><mo>&InvisibleTimes;</mo><mi>y</mi></mrow><mo>+</mo><mn>1</mn></mrow><mo>&InvisibleTimes;</mo><mrow><mrow><mn>4</mn><mo>&InvisibleTimes;</mo><msup><mi>x</mi><mn>2</mn></msup></mrow><mo>-</mo><mrow><mn>6</mn><mo>&InvisibleTimes;</mo><mi>x</mi><mo>&InvisibleTimes;</mo><mi>y</mi></mrow><mo>-</mo><mrow><mn>2</mn><mo>&InvisibleTimes;</mo><mi>x</mi></mrow><mo>+</mo><mrow><mn>9</mn><mo>&InvisibleTimes;</mo><msup><mi>y</mi><mn>2</mn></msup></mrow><mo>-</mo><mrow><mn>3</mn><mo>&InvisibleTimes;</mo><mi>y</mi></mrow><mo>+</mo><mn>1</mn></mrow></mrow>
    
[/code]

出力されたコードをHTMLに埋め込んで以下のようにしてみました。

**test.html**

[code]

    <html>
    <head>
      <script async="" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML"></script>
    </head>
    <body>
    <math>
    <mrow><mrow><mrow><mn>2</mn><mo>&InvisibleTimes;</mo><mi>x</mi></mrow><mo>+</mo><mrow><mn>3</mn><mo>&InvisibleTimes;</mo><mi>y</mi></mrow><mo>+</mo><mn>1</mn></mrow><mo>&InvisibleTimes;</mo><mrow><mrow><mn>4</mn><mo>&InvisibleTimes;</mo><msup><mi>x</mi><mn>2</mn></msup></mrow><mo>-</mo><mrow><mn>6</mn><mo>&InvisibleTimes;</mo><mi>x</mi><mo>&InvisibleTimes;</mo><mi>y</mi></mrow><mo>-</mo><mrow><mn>2</mn><mo>&InvisibleTimes;</mo><mi>x</mi></mrow><mo>+</mo><mrow><mn>9</mn><mo>&InvisibleTimes;</mo><msup><mi>y</mi><mn>2</mn></msup></mrow><mo>-</mo><mrow><mn>3</mn><mo>&InvisibleTimes;</mo><mi>y</mi></mrow><mo>+</mo><mn>1</mn></mrow></mrow>
    </math>
    </body>
    </html>
    
[/code]

しかし、このコードだと、下記の画像のように括弧が欠けた出力になってしまいます。  
これはやはりライブラリ側のコードを書き換えるしかないでしょうか？

[![画像の説明をここに入力](https://i.stack.imgur.com/8lgJ5.jpg)](https://i.stack.imgur.com/8lgJ5.jpg)


CC BY-SA 4.0
2019-06-06T09:39:22.810
55578
2019-06-06T21:25:58.087
22541
question
python sympy mathjax
sympy.printing.mathmlで括弧()の扱いについて


原因は[ここ](https://github.com/sympy/sympy/blob/master/sympy/printing/mathml.py#L606)での処理にあります。

[code]

    for term in terms:
        x = self._print(term)
        mrow.appendChild(x)
    
[/code]

Integral や power(`**`) などでは演算の優先順位を評価して、必要な場合には式を `()`
で囲む処理が行われています。ですので、multiply でも以下の様に変更すると期待する出力が得られる様になります。

[code]

    for term in terms:
        mrow.appendChild(self.parenthesize(term, PRECEDENCE['Mul']))
    
[/code]

sympy の repository に pull request を送ってみるのが順当な対処なのでしょうが、手っ取り早く
MathMLPresentationPrinter._print_Mul
メソッドを置き換えてしまう方法もあります。ただし、置き換えるのは特定のインスタンスオブジェクトの _print_Mul メソッドのみです。

[code]

    from sympy import *
    from sympy.core.function import _coeff_isneg
    from sympy.printing.mathml import mathml, MathMLPresentationPrinter
    from sympy.printing.precedence import precedence_traditional, PRECEDENCE
    import types
    
    def _patched_print_Mul(self, expr):
        def multiply(expr, mrow):
            from sympy.simplify import fraction
            numer, denom = fraction(expr)
            if denom is not S.One:
                frac = self.dom.createElement('mfrac')
                if self._settings["fold_short_frac"] and len(str(expr)) < 7:
                    frac.setAttribute('bevelled', 'true')
                xnum = self._print(numer)
                xden = self._print(denom)
                frac.appendChild(xnum)
                frac.appendChild(xden)
                mrow.appendChild(frac)
                return mrow
            coeff, terms = expr.as_coeff_mul()
            if coeff is S.One and len(terms) == 1:
                mrow.appendChild(self._print(terms[0]))
                return mrow
            if self.order != 'old':
                terms = Mul._from_args(terms).as_ordered_factors()
            if coeff != 1:
                x = self._print(coeff)
                y = self.dom.createElement('mo')
                y.appendChild(self.dom.createTextNode(self.mathml_tag(expr)))
                mrow.appendChild(x)
                mrow.appendChild(y)
            for term in terms:
                mrow.appendChild(self.parenthesize(term, PRECEDENCE['Mul']))
                if not term == terms[-1]:
                    y = self.dom.createElement('mo')
                    y.appendChild(self.dom.createTextNode(self.mathml_tag(expr)))
                    mrow.appendChild(y)
            return mrow
        mrow = self.dom.createElement('mrow')
        if _coeff_isneg(expr):
            x = self.dom.createElement('mo')
            x.appendChild(self.dom.createTextNode('-'))
            mrow.appendChild(x)
            mrow = multiply(-expr, mrow)
        else:
            mrow = multiply(expr, mrow)
        return mrow
    
    ## Replace _print_Mul method
    s = MathMLPresentationPrinter()
    s._print_Mul = types.MethodType(_patched_print_Mul, s)
    s.doprint(S("(2*x + 3*y + 1)*(4*x**2 - 6*x*y - 2*x + 9*y**2 - 3*y + 1)"))
    
[/code]

**出力**

[code]

    <mrow><mfenced><mrow><mrow><mn>2</mn><mo>&InvisibleTimes;</mo><mi>x</mi></mrow><mo>+</mo><mrow><mn>3</mn><mo>&InvisibleTimes;</mo><mi>y</mi></mrow><mo>+</mo><mn>1</mn></mrow></mfenced><mo>&InvisibleTimes;</mo><mfenced><mrow><mrow><mn>4</mn><mo>&InvisibleTimes;</mo><msup><mi>x</mi><mn>2</mn></msup></mrow><mo>-</mo><mrow><mn>6</mn><mo>&InvisibleTimes;</mo><mi>x</mi><mo>&InvisibleTimes;</mo><mi>y</mi></mrow><mo>-</mo><mrow><mn>2</mn><mo>&InvisibleTimes;</mo><mi>x</mi></mrow><mo>+</mo><mrow><mn>9</mn><mo>&InvisibleTimes;</mo><msup><mi>y</mi><mn>2</mn></msup></mrow><mo>-</mo><mrow><mn>3</mn><mo>&InvisibleTimes;</mo><mi>y</mi></mrow><mo>+</mo><mn>1</mn></mrow></mfenced></mrow>
    
[/code]

[![数式](https://i.stack.imgur.com/2iKTm.png)](https://i.stack.imgur.com/2iKTm.png)


CC BY-SA 4.0
2019-06-06T21:25:58.087
55595
2019-06-06T21:25:58.087
55578
answer