我正在尝试编写一个归一化(重写(数学方程的例程,该数学方程可能在 LHS
上可能有一个以上的符号,以便它只有一个。
以下代码说明了我想做的
假设我有一个方程
ln(x)-ln(x1)= -(a+by)
我想解决x或返回
x=x1*exp(-a+by)
使用sympy
我可以做以下
from sympy import *
formula=' log(x)-log(x1) =-(a+b*y)'
lhs,rhs=formula.split('=',1)
x,x_1,y,a,b,y=symbols('x x_1 y a b y')
r=sympy.solve(eval(lhs)-eval(rhs),x)
r
==>
Output: [x1*exp(-a - b*y)]
我试图在一系列输入线上自动化此功能,如下所示
from sympy import *
import re
# eventually to be read ina loop from a file
formula="DLOG(SAUMMCREDBISCN/SAUNECONPRVTXN) =-0.142368233181-0.22796245228*(LOG(SAUMMCREDBISCN(-1)/SAUNECONPRVTXN(-1))+0.2*((SAUMMLOANINTRCN(-1)-SAUINTR(-1))/100)-LOG(SAUNYGDPMKTPKN(-1)))+0.576050997065*SAUNYGDPGAP_/100"
#try to convert formula into a string containing just the synbols
sym1=formula.replace("*"," ")
sym1=sym1.replace("DLOG"," ")
sym1=sym1.replace("LOG"," ")
sym1=sym1.replace("EXP"," ")
sym1=sym1.replace("RECODE"," ")
sym1=re.sub('[()/+-=]',' ',sym1)
sym1=re.sub(' +',' ',sym1)
#This logic works for this particular formula
sym1
#now generate a string that has, instead of spaces between symbols
ss2=sym1.replace(' ',',')
#This is the part that does not work I want to generate a command that effectively says
#symbol,symbol2,..,symboln=symbols('symbol1 symbol2 ... symboln')
#tried this but it fails
eval(ss2)=symbols(sym1)
生成结果
eval(ss2)=symbols(sym1)
^
SyntaxError: can't assign to function call
此py
菜鸟的任何帮助,将不胜感激。
var('a b c')
会在名称空间中注入符号名称'a'',''','c'字典中的符号,然后按名称访问:
>>> formula=' log(x)-log(x1) =-(a+b*y)'
>>> eq = Eq(*map(S, formula.split('=', 1)))
>>> v = dict([(i.name, i) for i in eq.free_symbols]); v
{'y': y, 'b': b, 'x': x, 'x1': x1, 'a': a}
>>> solve(eq, v['x'])
[x1*exp(-a - b*y)]
因此,实际上并不需要使用eval
或具有匹配符号名称的变量:S
可以将字符串转换为表达式,而free_symbols
可以识别存在哪些符号。将它们放入带有键为符号名称的字典中,可以从字典中从字典中检索它们。
我认为您想从这两个语句中生成一个字符串,然后您可以评估该字符串
str_eq = f'{ss2} = {symbols(sym1)}'
print(str_eq)
>>' ,SAUMMCREDBISCN,SAUNECONPRVTXN,SAUMMCREDBISCN,SAUNECONPRVTXN,SAUMMLOANINTRCN,SAUINTR,SAUNYGDPMKTPKN,SAUNYGDPGAP_, = (SAUMMCREDBISCN, SAUNECONPRVTXN, SAUMMCREDBISCN, SAUNECONPRVTXN, SAUMMLOANINTRCN, SAUINTR, SAUNYGDPMKTPKN, SAUNYGDPGAP_)'
第一行说 - 给我一个字符串,但在返回 {}
之间的python代码。例如
print(f'Adding two numbers: (2+3) = {2 + 3}')
>> Adding two numbers: (2+3) = 5
首先,也许这可能有助于使您的代码变得更密集。
如果我正确理解,您正在尝试使用名称列表分配变量。您可以使用vars()[x]=
:
import re
from sympy import symbols
symbol_names = re.findall("SAU[A-Z_]+",formula)
symbol_objs = symbols(symbol_names)
for sym_name,sym_obj in zip(symbol_names,symbol_objs):
vars()[sym] = sym_obj
我的同事(ib Hansen(为我提供了一个非常好的优雅的解决方案(如何解决复杂表达(,该解决方案又通过了弦乐操作解决方案,这是我的最初的问题正在挣扎,并且大多数答案都解决了。
他的解决方案是使用 Sompify 和 solve from Sympy
from sympy import sympify, solve
import re
def normalize(var,eq,simplify=False,manual=False):
'''normalize an equation with respect to var using sympy'''
lhs, rhs = eq.split('=')
kat = sympify(f'Eq({lhs},{rhs})')
var_sym = sympify(var)
out = str(solve(kat, var_sym,simplify=simplify,manual=manual))[1:-1]
return f'{var} = {out}'
这很好
from sympy import sympify, solve
import re
def norm(var,eq,simplify=False,manual=False):
'''normalize an equation with respect to var using sympy'''
lhs, rhs = eq.split('=')
kat = sympify(f'Eq({lhs},{rhs})')
var_sym = sympify(var)
out = str(solve(kat, var_sym,simplify=simplify,manual=manual))[1:-1] # simplify takes for ever
return f'{var} = {out}'
``` Re write equation spelling out the dlog (delta log) function that python does no know, and putting log into lowe case '''
test8=norm('saummcredbiscn','log(saummcredbiscn/sauneconprvtxn) -log(saummcredbiscn(-1)/sauneconprvtxn(-1)) =-0.142368233181-0.22796245228*(log(saummcredbiscn(-1)/sauneconprvtxn(-1))+0.2*((saummloanintrcn(-1)-sauintr(-1))/100)-log(saunygdpmktpkn(-1)))+0.576050997065*saunygdpgap_/100')
print (test8)
结果
saummcredbiscn = 0.867301828366361*sauneconprvtxn*(saummcredbiscn(-1.0)/sauneconprvtxn(-1.0))**(19300938693/25000000000)*saunygdpmktpkn(-1.0)**(5699061307/25000000000)*exp(0.00576050997065*saunygdpgap_ + 0.00045592490456*sauintr(-1.0) - 0.00045592490456*saummloanintrcn(-1.0)