55462


文字列から、MathMLのコードを生成するプログラム **test001.py**  
を書いています。

**test001.py**

[code]

    import sys
    sys.path.append('/home/vagrant/.local/lib/python3.4/site-packages')
    from sympy import *
    from sympy.printing.mathml import mathml
    
    def returnMathML(value):
        str = "<math>"
        if '=' in value:#文字列中に=(イコール)が含まれている場合
            str += mathml(Eq(*map(sympify, value.split('='))),printer='presentation')
        else:
            str += mathml(sympify(value),printer='presentation')
        str += "</math>"
        return str
    
    print(returnMathML("A"))
    
[/code]

**test001.py** を実行すると、以下のようにMathMLのコードが出力されます。

[code]

    <math><mi>A</mi></math>
    
[/code]

**test001.py**
の15行目で、渡す引数を"y=a*x**2+b*x+c"に変更して以下のように書き換えて実行してもMathMLのコードが出力されます。

・引数を"y=a*x**2+b*x+c"に変更した場合

[code]

    print(returnMathML("y=a*x**2+b*x+c"))
    
[/code]

・引数を"y=a*x**2+b*x+c"に変更した場合の実行結果

[code]

    $ python test001.py
    <math><mrow><mi>y</mi><mo>=</mo><mrow><mrow><mi>a</mi><mo>&InvisibleTimes;</mo><msup><mi>x</mi><mn>2</mn></msup></mrow><mo>+</mo><mrow><mi>b</mi><mo>&InvisibleTimes;</mo><mi>x</mi></mrow><mo>+</mo><mi>c</mi></mrow></mrow></math>
    
[/code]

ただ、文字列に大文字の"S"が加わると、エラーが出てしまいます。

・引数を"S"に変更した場合

[code]

    print(returnMathML("S"))
    
[/code]

・引数を"S"に変更した場合の実行結果

[code]

    $ python test001.py
    Traceback (most recent call last):
      File "test001.py", line 15, in <module>
        print(returnMathML("S"))
      File "test001.py", line 11, in returnMathML
        str += mathml(sympify(value),printer='presentation')
      File "/home/vagrant/.pyenv/versions/3.6.7/lib/python3.6/site-packages/sympy/printing/mathml.py", line 1904, in mathml
        return MathMLPresentationPrinter(settings).doprint(expr)
      File "/home/vagrant/.pyenv/versions/3.6.7/lib/python3.6/site-packages/sympy/printing/mathml.py", line 68, in doprint
        unistr = mathML.toxml()
    AttributeError: 'str' object has no attribute 'toxml'
    
[/code]

これはおそらく、[sympify関数のエイリアスが「S」](https://ja.stackoverflow.com/questions/55375/python3-6%E3%81%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%97%E3%81%9F%E3%82%89-python2-7%E3%81%A7%E4%BD%BF%E3%81%88%E3%81%A6%E3%81%9F%E3%82%82%E3%81%AE%E3%81%8C%E5%8B%95%E4%BD%9C%E3%81%97%E3%81%AA%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F)であるため、名前かぶりが起きているんではないかと思います。

大文字のS以外の、BやCやDといったアルファベットはprintすることが出来ました。また、小文字のsなども大丈夫でした。大文字のSだけがうまく出力できません。

以下のように、面積の"S"を表すのに使用したいです。

[code]

    print(returnMathML("S=abs(a)*(β-α)**3/6"))
    
[/code]

どうすればこの問題を解決できますでしょうか？


CC BY-SA 4.0
2019-06-02T17:26:49.913
55460
2019-06-02T21:54:08.643
2019-06-02T17:37:37.793
22541
22541
question
python sympy mathjax
sympifyで大文字の"S"を数式に変換するには (Python Sympy)


おっしゃるとおり、`S` が `sympify` 関数のエイリアスになっているのが原因です。`sympify()` による string から SymPy
オブジェクトへの変換は内部的に `from sympy import *` された状態で行われるので、`"S"` は `Symbol("S")` ではなく
`sympify` として扱われます。

この問題を回避するためには、`sympify` のオプショナル引数 `locals` に `"S"` が `Symbol("S")`
であると追加した上で呼び出す必要があります。

[code]

    str += mathml(sympify(value, locals={"S": Symbol("S")}), printer='presentation')
    
[/code]

このことは [SymPy
のドキュメントに書かれており](https://docs.sympy.org/latest/modules/core.html?highlight=sympify#module-
sympy.core.sympify)、こちらには `locals` の設定方法が詳細に書かれています。

ところで[こちらのドキュメント](https://docs.sympy.org/latest/gotchas.html)によると、他にも注意すべき文字があります。一般の文字列に対して
`returnMathML` 関数を使うことになるのであれば、これらの対応をどうするか決めなければいけません。たとえば `"O"` はデフォルトでは
big-O の O として扱われますが、文脈によってそれで良い場合とそれでは困る場合がありそうです。

> Lastly, it is recommended that you not use `I`, `K`, `S`, `N`, `C`, `O`, or
> `Q` for variable or symbol names, (中略). You can use the mnemonic `OSINEQ` to
> remember what Symbols are defined by default in SymPy. Or better yet, always
> use lowercase letters for Symbol names. Python will not prevent you from
> overriding default SymPy names or functions, so be careful.

(中略)

> If you want _all_ single-letter and Greek-letter variables to be symbols
> then you can use the clashing-symbols dictionaries that have been defined
> there as private variables: _clash1 (single-letter variables), _clash2 (the
> multi-letter Greek names) or _clash (both single and multi-letter names that
> are defined in abc).
[code]

>     >>> from sympy.abc import _clash1
>     >>> _clash1
>     {'C': C, 'E': E, 'I': I, 'N': N, 'O': O, 'Q': Q, 'S': S}
>     >>> sympify('I & Q', _clash1)
>     I & Q
>  
[/code]


CC BY-SA 4.0
2019-06-02T21:36:09.393
55462
2019-06-02T21:54:08.643
2020-06-17T08:14:45.997
-1
19110
55460
answer