標籤:

如何使用Python求導?

Python初學者,想學習一下使用Python求導,方便以後各種使用,目標是能輸入函數和x後輸出導函數和導x,能輸出複合函數求導和導函數運演算法則。求給出思路或者範例。


符號計算:

from sympy import *
x=Symbol("x")
diff(1/(1+x**2),x)


我來貢獻一個腦洞:有壯士能夠研究如何從 AST 分析入手來求導嗎?

晚上睡不著,小小研究了下,有初步成果,拋磚引玉:

import ast
import astunparse

class BrainHoleDiff(ast.NodeTransformer):
def has_symbol(self, node):
return node.id == "x"

def expr_parse(self, expr):
node = ast.parse(expr)
return node.body[0].value

def visit_Call(self, node):
func_name = node.func.id
if not self.has_symbol(node.args[0]):
return self.generic_visit(node)

if func_name == "sin":
node.func.id = "cos"
elif func_name == "cos":
node = self.expr_parse("-sin(x)")
elif func_name == "ln":
node = self.expr_parse("1.0/x")
elif func_name == "pow":
times = node.args[1].n
node = self.expr_parse("%s*pow(x, %s)" % (times, times - 1))

return node

def __call__(self, expr):
ast_node = ast.parse(expr)
ast_node = self.visit(ast_node)
return astunparse.unparse(ast_node)

diff = BrainHoleDiff()

print diff("3*sin(x)-cos(x)") # 3*cos(x) + sin(x)
print diff("ln(x)") # 1.0/x
print diff("3*ln(x)+sin(x)-pow(x, 3)+cos(x)") # 3.0/x+cos(x)-3*pow(x, 2)-sin(x)
print eval(diff("pow(x, 3)-pow(x, 2)"), {"x": 1}) # 1

依賴於 astunparse,請用 pip 安裝。

如果結果有任何不對,只能說明我數學太渣了。。。

其實也不是強依賴於 astunparse,更新個修改版本:

import ast

class BrainHoleDiff(ast.NodeTransformer):
def __init__(self, expr):
self.expr = expr
self.ast_node = self.visit(ast.parse(expr, "&<&>", "eval"))
self.code = compile(self.ast_node, "&<&>", "eval")
super(BrainHoleDiff, self).__init__()

def has_symbol(self, node):
return node.id == "x"

def expr_parse(self, expr):
node = ast.parse(expr)
return node.body[0].value

def visit_Call(self, node):
func_name = node.func.id
if not self.has_symbol(node.args[0]):
return self.generic_visit(node)

if func_name == "sin":
node.func.id = "cos"
elif func_name == "cos":
node = self.expr_parse("-sin(x)")
elif func_name == "ln":
node = self.expr_parse("1.0/x")
elif func_name == "pow":
times = node.args[1].n
node = self.expr_parse("%s*pow(x, %s)" % (times, times - 1))

return node

def as_expr(self):
import astunparse
return astunparse.unparse(self.ast_node)

def calc(self, x):
return eval(self.code, {"x": x})

print BrainHoleDiff("3*sin(x)-cos(x)").as_expr() # ((3 * cos(x)) - (- sin(x)))
print BrainHoleDiff("ln(x)").as_expr() # (1.0 / x)
print BrainHoleDiff("3*ln(x)+sin(x)-pow(x, 3)+cos(x)").as_expr() # ((((3 * (1.0 / x)) + cos(x)) - (3 * pow(x, 2))) + (- sin(x)))
print BrainHoleDiff("pow(x, 3)-pow(x, 2)").calc(1) # 1


def deriv(f):
dx=0.00000001
return lambda x: (f(x+dx)-f(x))/dx

print(deriv(lambda x:x**3)(9))

數學弱渣只會用定義法


符號計算,果斷sympy


推薦閱讀:

用 Python 可以建網站嗎?
python主要用於什麼開發?
VisPy 中文文檔:APP模塊
Django許可權機制的實現
基於ArcGIS的python編程 5、Arcpy的一個簡單應用(近鄰分析工具進行點線拓撲)

TAG:Python |