Python Sympy任意逼近任意Sympy表达式?

Python Sympy任意逼近任意Sympy表达式?,python,sympy,approximation,mpmath,Python,Sympy,Approximation,Mpmath,我发现自己想要使用作为mpmath软件包一部分提供的Approximations,但对它们应该做什么感到困惑: Symphy表达式和Symphy.mpmath表达式之间的区别到底是什么 如果我想在不了解mpmath软件包的情况下对符号表达式进行泰勒近似,我可以执行以下操作: #Imports import sympy import sympy.parsing import sympy.parsing.sympy_parser import Library_TaylorApproximation

我发现自己想要使用作为mpmath软件包一部分提供的Approximations,但对它们应该做什么感到困惑:

Symphy表达式和Symphy.mpmath表达式之间的区别到底是什么

如果我想在不了解mpmath软件包的情况下对符号表达式进行泰勒近似,我可以执行以下操作:

#Imports
import sympy
import sympy.parsing
import sympy.parsing.sympy_parser
import Library_TaylorApproximation

#Create a sympy expression to approximate
ExampleStringExpression = 'sin(x)'
ExampleSympyExpression = sympy.parsing.sympy_parser.parse_expr(ExampleStringExpression)


#Create a taylor expantion sympy expression around the point x=0
SympyTaylorApproximation = sympy.series( 
    ExampleSympyExpression,
    sympy.Symbol('x'),
    1, 
    4,
    ).removeO()

#Cast the sympy expressions to python functions which can be evaluated:
VariableNames = [str(var) for var in SympyTaylorApproximation.free_symbols]
PythonFunctionOriginal =  sympy.lambdify(VariableNames, ExampleSympyExpression)
PythonFunctionApproximation = sympy.lambdify(VariableNames, SympyTaylorApproximation)

#Evaluate the approximation and the original at a point:
print PythonFunctionOriginal(2)
print PythonFunctionApproximation(2)

#>>> 0.909297426826
#>>> 0.870987413961
但是,如果我尝试根据文档对mpmath执行相同的操作:

TaylorCoefficients = sympy.mpmath.taylor(ExampleSympyExpression, 1, 4 )
print 'TaylorCoefficients', TaylorCoefficients

#>>> TypeError: 'sin' object is not callable
我可以尝试在其中填充python函数(可调用):

但是上面的内容没有任何意义,因为我知道不能对python函数进行派生

我可以调用mpmath函数
sin

TaylorCoefficients = sympy.mpmath.taylor(sympy.mpmath.sin, 1, 4 )
print 'TaylorCoefficients', TaylorCoefficients
#>>> TaylorCoefficients [mpf('0.8414709848078965'), mpf('0.54030230586813977'), mpf('-0.42073549240394825'), mpf('-0.090050384311356632'), mpf('0.035061291033662352')]
但是我不能用我想要的方式来操纵它->如果我想要的话

SinTimesCos = sympy.mpmath.sin*sympy.mpmath.cos
TaylorCoefficients = sympy.mpmath.taylor(SinTimesCos, 1, 4 )
print 'TaylorCoefficients', TaylorCoefficients
#>>> TypeError: unsupported operand type(s) for *: 'function' and 'function'
什么是mpmath函数

它不是symphy表达式,也不是python函数。如何对任意表达式进行操作

似乎我不能在文档中对任意的symphy表达式进行近似。

如何进行任意近似(Pade/Cheby-Chev/Fourier) 对任意的同情表达

编辑:

因此,我正在寻找的一个示例是以下近似值:

#Start with a sympy expression of (a, b, x)
expressionString = 'cos(a*x)*sin(b*x)*(x**2)'
expressionSympy = sympy.parsing.sympy_parser.parse_expr(expressionString)

#Do not want to decide on value of `a or b` in advance.
#Do want approximation with respect to x:

wantedSympyExpression = SympyChebyChev( expressionSympy, sympy.Symbol('x') ) 
结果可以是作为
a
b
函数的系数表达式列表:

wantedSympyExpressionCoefficients = [ Coef0Expression(a,b), Coef1Expression(a,b), ... , CoefNExpression(a,b)]
wantedSympyExpression = Coef0Expression(a,b) + Coef1Expression(a,b) *(x**2) + ... + CoefNExpression(a,b) (x**N)
或者结果可能是整个sympy表达式本身(它本身是
a
b
的函数):


请注意,
a
b
不是在执行近似之前选择的

mpmath函数是普通的Python函数。他们只是用任意精度的算术来计算

但是上面的内容没有任何意义,因为我知道不能对python函数进行派生

你不能象征性地求导数,但是你可以通过多次求值函数和使用数值微分技术来计算导数的近似值。这就是sympy.mpmath.taylor所做的。引用文件:

使用高阶数值微分法计算系数。函数必须能够计算到任意精度


如果您有一个SymPy表达式,并且希望将其计算为任意精度,请使用
evalf
,如

sympy.sin(1).evalf(100)

在计算之前,可以使用
sin(x).evalf(100,subs={x:1})
x
替换为
1
evalf
在引擎盖下使用mpmath,因此这将提供与mpmath相同的结果,但无需直接使用mpmath

编辑:重读我的答案->我想有一天我会为实际使用这个的人填补一些缺失的部分。下面我标记了我如何命名我的库,以及需要什么样的导入。目前我没有时间成为sympy的真正贡献者,但我觉得这个功能肯定会被其他数学/物理教授/学生使用

注:由于篇幅原因,以下两个库被省略,我将在将来的某个日期抛出一个指向我的repo的链接

import Library_SympyExpressionToPythonFunction
创建一个python可调用函数对象,该对象在sympy表达式中具有相同的自由变量参数(数量和名称)

import Library_SympyExpressionToStringExpression
字面上就是str(SympyExpression)

图书馆_generatechebyshevppolynomial::

#-------------------------------------------------------------------------------


import pprint
import Library_SympyExpressionToPythonFunction
import Library_SympyExpressionToStringExpression
import sympy
import sympy.core

def Main(
    ApproximationSymbol = sympy.Symbol('x'),
    ResultType = 'sympy',
    Kind= None,
    Order= None,
    ReturnAll = False,
    CheckArguments = True,
    PrintExtra = False,
    ):

    Result = None

    if (CheckArguments):
        ArgumentErrorMessage = ""

        if (len(ArgumentErrorMessage) > 0 ):
            if(PrintExtra):
                print "ArgumentErrorMessage:\n", ArgumentErrorMessage
            raise Exception(ArgumentErrorMessage)

    ChebyChevPolynomials = []
    ChebyChevPolynomials.append(sympy.sympify(1.))
    ChebyChevPolynomials.append(ApproximationSymbol)

    #Generate the polynomial with sympy:
    for Term in range(Order + 1)[2:]:
        Tn = ChebyChevPolynomials[Term - 1]
        Tnminus1 = ChebyChevPolynomials[Term - 2]
        Tnplus1 = 2*ApproximationSymbol*Tn - Tnminus1

        ChebyChevPolynomials.append(Tnplus1.simplify().expand().trigsimp())

    if(PrintExtra): print 'ChebyChevPolynomials'
    if(PrintExtra): pprint.pprint(ChebyChevPolynomials)


    if (ReturnAll):
        Result = []
        for SympyChebyChevPolynomial in ChebyChevPolynomials:
            if (ResultType == 'python'):
                Result.append(Library_SympyExpressionToPythonFunction.Main(SympyChebyChevPolynomial))
            elif (ResultType == 'string'):
                Result.append(Library_SympyExpressionToStringExpression.Main(SympyChebyChevPolynomial))
            else:
                Result.append(SympyChebyChevPolynomial)

    else:
        SympyExpression = ChebyChevPolynomials[Order] #the last one

        #If the result type is something other than sympy, we can cast it into that type here:
        if (ResultType == 'python'):
            Result = Library_SympyExpressionToPythonFunction.Main(SympyExpression)
        elif (ResultType == 'string'):
            Result = Library_SympyExpressionToStringExpression.Main(SympyExpression)
        else:
            Result = SympyExpression



    return Result 


#-------------------------------------------------------------------------------
图书馆\u Sympychebyshevapproximation维度

#-------------------------------------------------------------------------------


import numpy
import sympy
import sympy.mpmath
import pprint
import Library_SympyExpressionToPythonFunction
import Library_GenerateChebyShevPolynomial

def Main(
    SympyExpression= None,
    DomainMinimumPoint= None,
    DomainMaximumPoint= None,
    ApproximationOrder= None,
    CheckArguments = True,
    PrintExtra = False,
    ):

    #Tsymb = sympy.Symbol('t')
    Xsymb = sympy.Symbol('x')
    DomainStart = DomainMinimumPoint[0]
    print 'DomainStart', DomainStart
    DomainEnd = DomainMaximumPoint[0]
    print 'DomainEnd', DomainEnd

    #Transform the coefficients and the result to be on arbitrary inverval instead of from 0 to 1
    DomainWidth = DomainEnd - DomainStart
    DomainCenter = (DomainEnd - DomainStart) / 2.
    t = (Xsymb*(DomainWidth) + DomainStart + DomainEnd) / 2.
    x = (2.*Xsymb - DomainStart - DomainEnd) / (DomainWidth)
    SympyExpression = SympyExpression.subs(Xsymb, t)

    #GET THE COEFFICIENTS:
    Coefficients = []
    for CoefficientNumber in range(ApproximationOrder):
        if(PrintExtra): print 'CoefficientNumber', CoefficientNumber

        Coefficient = 0.0
        for k in range(1, ApproximationOrder + 1):
            if(PrintExtra): print '  k', k

            CoefficientFunctionPart = SympyExpression.subs(Xsymb, sympy.cos( sympy.pi*( float(k) - .5 )/ float(ApproximationOrder) )  )
            if(PrintExtra): print '  CoefficientFunctionPart', CoefficientFunctionPart

            CeofficientCosArg = float(CoefficientNumber)*( float(k) - .5 )/ float( ApproximationOrder)
            if(PrintExtra): print '  ',CoefficientNumber,'*','(',k,'-.5)/(', ApproximationOrder ,') == ', CeofficientCosArg

            CoefficientCosPart      =   sympy.cos( sympy.pi*CeofficientCosArg )
            if(PrintExtra): print '  CoefficientCosPart', CoefficientCosPart

            Coefficient += CoefficientFunctionPart*CoefficientCosPart

        if(PrintExtra): print 'Coefficient==', Coefficient

        Coefficient = (2./ApproximationOrder)*Coefficient.evalf(10)

        if(PrintExtra): print 'Coefficient==', Coefficient

        Coefficients.append(Coefficient)

    print '\n\nCoefficients'
    pprint.pprint( Coefficients )


    #GET THE POLYNOMIALS:
    ChebyShevPolynomials = Library_GenerateChebyShevPolynomial.Main(
        ResultType = 'sympy',
        Kind= 1,
        Order= ApproximationOrder-1,
        ReturnAll = True,
        )

    print '\nChebyShevPolynomials'
    pprint.pprint( ChebyShevPolynomials )


    Result = 0.0 -.5*(Coefficients[0])
    for Coefficient, ChebyShevPolynomial in zip(Coefficients, ChebyShevPolynomials):
        Result += Coefficient*ChebyShevPolynomial

    #Transform the coefficients and the result to be on arbitrary inverval instead of from 0 to 1
    Result = Result.subs(Xsymb, x)

    return Result
------------------------------------------------------------------------------ 示例\u SympychebyshevapproximationDimension:

#------------------------------------------------------------------------------
import sympy
import sympy.mpmath
import matplotlib.pyplot as plt
import json
import pprint




import Library_GenerateBesselFunction
import Library_SympyChebyShevApproximationOneDimension
import Library_SympyExpressionToPythonFunction
import Library_GraphOneDimensionalFunction


ApproximationOrder = 10

#CREATE THE EXAMPLE EXRESSION:
Kind = 1
Order = 2
ExampleSympyExpression = sympy.sin(sympy.Symbol('x'))

"""
Library_GenerateBesselFunction.Main(
    ResultType =  'sympy',
    Kind =  Kind,
    Order =  Order,
    VariableNames = ['x'],
    ) 
"""
PythonOriginalFunction = Library_SympyExpressionToPythonFunction.Main( 
    ExampleSympyExpression ,
    FloatPrecision = 100,
    )

#CREATE THE NATIVE CHEBY APPROXIMATION

ChebyDomainMin = 5.
ChebyDomainMax = 10.
ChebyDomain = [ChebyDomainMin, ChebyDomainMax]
ChebyExpandedPolynomialCoefficients, ChebyError = sympy.mpmath.chebyfit(
    PythonOriginalFunction, 
    ChebyDomain, 
    ApproximationOrder, 
    error=True
    )
print 'ChebyExpandedPolynomialCoefficients'
pprint.pprint( ChebyExpandedPolynomialCoefficients )
def PythonChebyChevApproximation(Point):
    Result = sympy.mpmath.polyval(ChebyExpandedPolynomialCoefficients, Point)
    return Result


#CREATE THE GENERIC ONE DIMENSIONAL CHEBY APPROXIMATION:
SympyChebyApproximation = Library_SympyChebyShevApproximationOneDimension.Main(
    SympyExpression = ExampleSympyExpression*sympy.cos( sympy.Symbol('a') ),
    ApproximationSymbol = sympy.Symbol('x'),
    DomainMinimumPoint = [ChebyDomainMin],
    DomainMaximumPoint = [ChebyDomainMax],
    ApproximationOrder = ApproximationOrder
    )


print 'SympyChebyApproximation', SympyChebyApproximation

SympyChebyApproximation = SympyChebyApproximation.subs(sympy.Symbol('a'), 0.0)

print 'SympyChebyApproximation', SympyChebyApproximation

PythonCastedChebyChevApproximationGeneric = Library_SympyExpressionToPythonFunction.Main( 
    SympyChebyApproximation ,
    FloatPrecision = 100,
    )

print 'PythonCastedChebyChevApproximationGeneric(1)', PythonCastedChebyChevApproximationGeneric(1.)

所以-my
PythonFunctionOriginal
不能计算为任意精度?@DAdams:正确。这就是为什么泰勒级数的高阶项最终为零的原因。这个答案对于解释npmath函数的作用非常有洞察力。也许我们可以将这个答案,以及问题
Symphy表达式和Symphy.mpmath表达式之间的区别到底是什么?
转移到另一页?如果这样做有效:这将是公认的答案-我欠你一个惊喜。好吧-如果我替换每个变量,但我不能接受它作为答案——因为对于泰勒版本,我可以决定携带一个变量,进行近似,然后我的近似可以生成另一个辛表达式。这个npmath的东西不允许我得到一个symphy表达式作为另一个symphy表达式的近似值。不过,你仍然可以获得五杆高分!我不清楚你的问题是什么。你能举个例子吗?如果它不适合评论,你可以提出一个新问题。我希望为任意符号表达式的切比雪夫/帕德/傅立叶生成一组符号系数。为了清楚起见,我编辑了问题的最后几行。最好把它写成一个新问题。这回答了您原来的问题(“sympy表达式和mpmath表达式之间有什么区别?”)。很抱歉问题的混淆^^这就是我要问的。
#-------------------------------------------------------------------------------


import numpy
import sympy
import sympy.mpmath
import pprint
import Library_SympyExpressionToPythonFunction
import Library_GenerateChebyShevPolynomial

def Main(
    SympyExpression= None,
    DomainMinimumPoint= None,
    DomainMaximumPoint= None,
    ApproximationOrder= None,
    CheckArguments = True,
    PrintExtra = False,
    ):

    #Tsymb = sympy.Symbol('t')
    Xsymb = sympy.Symbol('x')
    DomainStart = DomainMinimumPoint[0]
    print 'DomainStart', DomainStart
    DomainEnd = DomainMaximumPoint[0]
    print 'DomainEnd', DomainEnd

    #Transform the coefficients and the result to be on arbitrary inverval instead of from 0 to 1
    DomainWidth = DomainEnd - DomainStart
    DomainCenter = (DomainEnd - DomainStart) / 2.
    t = (Xsymb*(DomainWidth) + DomainStart + DomainEnd) / 2.
    x = (2.*Xsymb - DomainStart - DomainEnd) / (DomainWidth)
    SympyExpression = SympyExpression.subs(Xsymb, t)

    #GET THE COEFFICIENTS:
    Coefficients = []
    for CoefficientNumber in range(ApproximationOrder):
        if(PrintExtra): print 'CoefficientNumber', CoefficientNumber

        Coefficient = 0.0
        for k in range(1, ApproximationOrder + 1):
            if(PrintExtra): print '  k', k

            CoefficientFunctionPart = SympyExpression.subs(Xsymb, sympy.cos( sympy.pi*( float(k) - .5 )/ float(ApproximationOrder) )  )
            if(PrintExtra): print '  CoefficientFunctionPart', CoefficientFunctionPart

            CeofficientCosArg = float(CoefficientNumber)*( float(k) - .5 )/ float( ApproximationOrder)
            if(PrintExtra): print '  ',CoefficientNumber,'*','(',k,'-.5)/(', ApproximationOrder ,') == ', CeofficientCosArg

            CoefficientCosPart      =   sympy.cos( sympy.pi*CeofficientCosArg )
            if(PrintExtra): print '  CoefficientCosPart', CoefficientCosPart

            Coefficient += CoefficientFunctionPart*CoefficientCosPart

        if(PrintExtra): print 'Coefficient==', Coefficient

        Coefficient = (2./ApproximationOrder)*Coefficient.evalf(10)

        if(PrintExtra): print 'Coefficient==', Coefficient

        Coefficients.append(Coefficient)

    print '\n\nCoefficients'
    pprint.pprint( Coefficients )


    #GET THE POLYNOMIALS:
    ChebyShevPolynomials = Library_GenerateChebyShevPolynomial.Main(
        ResultType = 'sympy',
        Kind= 1,
        Order= ApproximationOrder-1,
        ReturnAll = True,
        )

    print '\nChebyShevPolynomials'
    pprint.pprint( ChebyShevPolynomials )


    Result = 0.0 -.5*(Coefficients[0])
    for Coefficient, ChebyShevPolynomial in zip(Coefficients, ChebyShevPolynomials):
        Result += Coefficient*ChebyShevPolynomial

    #Transform the coefficients and the result to be on arbitrary inverval instead of from 0 to 1
    Result = Result.subs(Xsymb, x)

    return Result
#------------------------------------------------------------------------------
import sympy
import sympy.mpmath
import matplotlib.pyplot as plt
import json
import pprint




import Library_GenerateBesselFunction
import Library_SympyChebyShevApproximationOneDimension
import Library_SympyExpressionToPythonFunction
import Library_GraphOneDimensionalFunction


ApproximationOrder = 10

#CREATE THE EXAMPLE EXRESSION:
Kind = 1
Order = 2
ExampleSympyExpression = sympy.sin(sympy.Symbol('x'))

"""
Library_GenerateBesselFunction.Main(
    ResultType =  'sympy',
    Kind =  Kind,
    Order =  Order,
    VariableNames = ['x'],
    ) 
"""
PythonOriginalFunction = Library_SympyExpressionToPythonFunction.Main( 
    ExampleSympyExpression ,
    FloatPrecision = 100,
    )

#CREATE THE NATIVE CHEBY APPROXIMATION

ChebyDomainMin = 5.
ChebyDomainMax = 10.
ChebyDomain = [ChebyDomainMin, ChebyDomainMax]
ChebyExpandedPolynomialCoefficients, ChebyError = sympy.mpmath.chebyfit(
    PythonOriginalFunction, 
    ChebyDomain, 
    ApproximationOrder, 
    error=True
    )
print 'ChebyExpandedPolynomialCoefficients'
pprint.pprint( ChebyExpandedPolynomialCoefficients )
def PythonChebyChevApproximation(Point):
    Result = sympy.mpmath.polyval(ChebyExpandedPolynomialCoefficients, Point)
    return Result


#CREATE THE GENERIC ONE DIMENSIONAL CHEBY APPROXIMATION:
SympyChebyApproximation = Library_SympyChebyShevApproximationOneDimension.Main(
    SympyExpression = ExampleSympyExpression*sympy.cos( sympy.Symbol('a') ),
    ApproximationSymbol = sympy.Symbol('x'),
    DomainMinimumPoint = [ChebyDomainMin],
    DomainMaximumPoint = [ChebyDomainMax],
    ApproximationOrder = ApproximationOrder
    )


print 'SympyChebyApproximation', SympyChebyApproximation

SympyChebyApproximation = SympyChebyApproximation.subs(sympy.Symbol('a'), 0.0)

print 'SympyChebyApproximation', SympyChebyApproximation

PythonCastedChebyChevApproximationGeneric = Library_SympyExpressionToPythonFunction.Main( 
    SympyChebyApproximation ,
    FloatPrecision = 100,
    )

print 'PythonCastedChebyChevApproximationGeneric(1)', PythonCastedChebyChevApproximationGeneric(1.)