2016-08-26 10 views
2

sympyからccode()を使用して、sageの有効なCコードに大きな式を変換しようとしています。しかし、私の表現には多くの二乗と立方体があります。 pow(x、2)はx * xよりもはるかに遅いので、私は式の中で変換前にそれらの項を拡張しようとしています。 this会話に基づいて、私は次のコードを書いた:2乗とキューブの項を乗算に変換する

from sympy import Symbol, Mul, Pow, pprint, Matrix, symbols 
    from sympy.core import numbers 


    def pow_to_mul(expr): 
     """ 
     Convert integer powers in an expression to Muls, like a**2 => a*a. 
     """ 
     pows = list(expr.atoms(Pow)) 
     pows = [p for p in pows if p.as_base_exp()[1]>=0] 
     if any(not e.is_Integer for b, e in (i.as_base_exp() for i in pows)): 

       raise ValueError("A power contains a non-integer exponent") 
     repl = zip(pows, (Mul(*[b]*e,evaluate=False) for b,e in (i.as_base_exp() for i in pows))) 
     return expr.subs(repl) 

それは部分的に動作しますが、限り電源は乗算の引数であるとして失敗します。

>>>_=var('x') 
    >>>print pow_to_mul((x^3+2*x^2)._sympy_()) 
    2*x**2 + x*x*x 
    >>>print pow_to_mul((x^2/(1+x^2)+(1-x^2)/(1+x^2))._sympy_()) 
    x**2/(x*x + 1) - (x*x - 1)/(x*x + 1) 

なぜ?そして私はそれをどのように変えることができますか? ありがとう、

+1

正確に失敗しましたか? '+(1-x^2)/(1 + x^2)'は ' - (x * x-1)/(x * x + 1)'と同じです。 –

+0

最初の例では、 'x^3 + 2 * x^2'は' 2 * x ** 2 + x * x * x'と同じです。シーケンスは切り替えられ、演算子のスタイルは変わりませんでしたが、数学的には同じです。あなたが何を求めているのかは不明です。 '**'は時には ''と ''にすることができる '^'と区別するために "力に"使われます。 –

+0

問題は、ccode(x * x)はx * xを返し、ccode(x^2)またはccode(x ** 2)はpow(x、2)を返します。 Cプログラムに入ると、後者は本当に最適ではありません。したがって、私は2 * x * x + x * x * xを期待しています。 – Domino

答えて

1

-ffast-mathでコンパイルすると、コンパイラはこの最適化を行います。あなたは古代のコンパイラを使用している場合や、ビルドプロセスで使用される最適化のレベルに影響を与えることができない、あなたは(SymPyマスターブランチを使用して)CCODEにユーザー定義関数を渡すことがあります。

>>> ccode(x**97 + 4*x**7 + 5*x**3 + 3**pi, user_functions={'Pow': [ 
... (lambda b, e: e.is_Integer and e < 42, lambda b, e: '*'.join([b]*int(e))), 
... (lambda b, e: not e.is_Integer, 'pow')]}) 
'pow(x, 97) + 4*x*x*x*x*x*x*x + 5*x*x*x + pow(3, M_PI)' 
+0

これは私が探しているもののようです。しかし、文字列を与えるラムダは評価されないので、例の出力は次のようになります。 'pow(x、97)+ 4 * at 0x8bc791b4>(x、7)+ 5 * at 0x8bc791b4 >(x、3)+ pow(3、M_PI) ' – Domino

+0

マスターブランチとは何ですか? 84db5141以降が必要です。 –

+0

OK、それが問題でした。私は何の悪いコマンドを入力したかわからないが、sympyはローカルでのみ更新されていた。私は最近、申し訳ありませんgitを学んだ。 ご協力いただきありがとうございます。 – Domino