[英]How can I dynamically generate a python symbol statement?
I am trying to write a routine that normalizes (rewrites) a mathematical equation that may have more than one symbol on the LHS
so that it only has one. 我正在尝试编写一个例程,该例程对
LHS
上可能有多个符号的数学方程进行规范化(重写),因此它只有一个符号。
The following code illustrates what I want to do 以下代码说明了我想做什么
Assume I have an equation 假设我有一个方程
ln(x)-ln(x1)= -(a+by)
I want to solve for x or return 我想求解x或返回
x=x1*exp(-a+by)
Using sympy
I can do the following 使用
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)]
I am trying to automate this for a range of input lines as follows 我正在尝试如下自动进行一系列输入
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)
Generates the result 产生结果
eval(ss2)=symbols(sym1)
^
SyntaxError: can't assign to function call
Any help for this py
noob, would be greatly appreciated. 对于这个
py
新手的任何帮助,将不胜感激。
var('ab c')
will inject symbol name 'a', 'b', 'c' into the namespace but perhaps @Blorgbeard is asking about lists or dicts because instead of creating many symbols you could put the symbols in a dictionary and then access them by name: var('ab c')
会将符号名称'a','b','c'注入到名称空间中,但是@Blorgbeard可能会询问列表或字典,因为与其创建许多符号,您还可以将这些符号放入字典中,然后然后按名称访问它们:
>>> 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)]
So it is not actually necessary to use eval
or to have a variable matching a symbol name: S
can convert a string to an expression and free_symbols
can identify which symbols are present. 因此,实际上没有必要使用
eval
或具有与符号名称匹配的变量: S
可以将字符串转换为表达式,而free_symbols
可以识别存在哪些符号。 Putting them in a dictionary with keys being the Symbol name allows them to be retrieved from the dictionary with a string. 将它们放在字典中,键为符号名称,可以使用字符串从字典中检索它们。
I think what you want to generate a string from these two statements and then you can eval that string 我认为您想从这两个语句生成一个字符串,然后可以评估该字符串
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_)'
The first line says - give me a string but run the python code between the {}
before returning it. 第一行说-给我一个字符串,但是在返回之前在
{}
之间运行python代码。 For instance 例如
print(f'Adding two numbers: (2+3) = {2 + 3}')
>> Adding two numbers: (2+3) = 5
First, maybe this could help make your code a bit denser. 首先,也许这可以使您的代码更加密集。
If I understand correctly, you're trying to assign a variable using a list of names. 如果我理解正确,您正在尝试使用名称列表来分配变量。 You could use
vars()[x]=
: 您可以使用
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
A colleague of mine (Ib Hansen) gave me a very nice and elegant solution to the original problem (how to solve for the complicated expression) that by-passed the string manipulation solution that my original question was struggling with and which most answers addressed. 我的一位同事(Ib Hansen)为我提供了一个很好而优雅的解决方案,解决了最初的问题(如何解决复杂的表达式),该解决方案绕过了我原来的难题所困扰的字符串处理解决方案,并且大多数答案都得到了解决。
His solution is to use sympify and solve from sympy 他的解决方案是使用症状和从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}'
This works perfectly 这完美地工作
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)
with result 结果
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.