Parsing string with equation that contains speciality function

48 views
Skip to first unread message

d...@inlet.geol.sc.edu

unread,
Aug 14, 2015, 1:49:47 PM8/14/15
to sympy
Sorry if this ends up being a re-post, I submitted a similar question and I do not think it went through.

I am working on a project that uses a statistical modelling program whose output is a linear regression model. THe program has a unique way of
representing various well know equations such as polynomials or quadratic:

VB_POLY(variable_to_be_used,0.79425485,0.0074458634,-3.6000059e-05)

I can have one or more of these I store in an ini file and retrieve them when the prediction engine is run, a full equation would look like:

-10.5296e-01 + 22.1357e-02*tide_hi_8726243 + 68.1223e-02*VB_POLY(sarasota_bay_nexrad_summary_144,0.79425485,0.0074458634,-3.6000059e-05) + 91.2317e-02*VB_POLY(c10_min_salinity_24,-641.91178,36.505262,-0.51822633)

With the items such as tide_hi_8726243 and sarasota_bay_nexrad_summary_144 being data whose value I provide in a dictionary when I execute parse_expr.

mlr_result = parse_expr(self.formula, self.data_used)


I've defined a VB_POLY class, the eval method is only for testing at the moment, as:

class VB_POLY(Function):
  nargs
= (1, 4)

 
@classmethod
 
def eval(cls, obs_var, a, b, c):
   
print "%s %s %s %s" % (obs_var, a, b, c)
   
return

The eval method never seems to be called, I'm not sure what I'm missing and would appreciate any pointers.

Thanks,
Dan

d...@inlet.geol.sc.edu

unread,
Aug 15, 2015, 7:22:34 AM8/15/15
to sympy
Here is a more complete VB_POLY class:
class VB_POLY(Function):
  nargs
= (1, 4)

 
@classmethod

 
def eval(cls, X_val, a_val, b_val, c_val):
    X
,a,b,c = symbols('X a b c')
    poly_func
= a + b * X + c * X^2
    poly_func
.subs({X: symFloat(X_val), a: symFloat(a_val), b: symFloat(b_val), c: symFloat(c_val)})
   
print "%f %f %f %f" % (X_val, a_val, b_val, c_val)
   
return poly_func.evalf()


I've also tried using sympify on the expression with evalf():
    sym_expr = sympify(self.formula)
    observation_variables
= sym_expr.free_symbols
    mlr_symbols
= {}
   
for obs_var in observation_variables:
     
if obs_var.name in data:
        mlr_symbols
[obs_var] = symFloat(data[obs_var.name])
       
if data[obs_var.name] == wq_defines.NO_DATA:


solved_eq = sym_expr.evalf(subs=mlr_symbols)

After evalf() is called, the solved_eq has not substituted the values for the Symbols and the VB_POLY class eval functio

d...@inlet.geol.sc.edu

unread,
Aug 17, 2015, 1:02:56 PM8/17/15
to sympy
I've reworked the VB_POLY class to use the Poly function:
class VB_POLY(Function):
  nargs
= (1, 4)

 
@classmethod

 
def eval(cls, obs_symbol, a_val, b_val, c_val):
    a
,b,c = symbols('a b c')
    poly_func
= poly(a + b * obs_symbol + c * obs_symbol**2)
   
return poly_func.evalf(subs={a: symFloat(a_val), b: symFloat(b_val), c: symFloat(c_val)})

I've modify the sympify call as:
sym_expr = sympify(self.formula, {'VB_POLY': VB_POLY})

That seems to call the eval function in the VB_POLY class, however at that point, I don't have the value for obs_symbol it is defined later.

    observation_variables = sym_expr.free_symbols
    mlr_symbols
= {}
   
for obs_var in observation_variables:

     
self.data_used[obs_var.name] = None
     
if obs_var.name in data:
       
self.data_used[obs_var.name] = data[obs_var.name]

        mlr_symbols
[obs_var] = symFloat(data[obs_var.name])
       
if data[obs_var.name] == wq_defines.NO_DATA:

          valid_data
= False
     
else:
        valid_data
= False

    solved_eq
= sym_expr.evalf(subs=mlr_symbols)


After evalf() is executed, the equation has not been numerically solved, it is still the symbolic definition. Is what I am attempting even possible?



Message has been deleted

d...@inlet.geol.sc.edu

unread,
Aug 17, 2015, 4:18:51 PM8/17/15
to sympy
Ok, with help from this thread: https://groups.google.com/forum/#!searchin/sympy/sympify$20function/sympy/dKiX0QHIFB4/pVFvdoDVlJwJ, I was able to answer my own question.


class VB_POLY(Function):
  nargs
= (1, 4)


 
def _eval_evalf(self, nprec):
    obs_symbol
,a,b,c = symbols('obs_symbol a b c')

    poly_func
= poly(a + b * obs_symbol + c * obs_symbol**2)

    result
= poly_func.evalf(subs={obs_symbol: symFloat(self.args[0]), a: symFloat(self.args[1]), b: symFloat(self.args[2]), c: symFloat(self.args[3])})
   
return result


The key is implementing the _eval_evalf function. I tried to set the evaluate flag to False to prevent my previous version that used eval to not evaluate immediately, but had no success.
Reply all
Reply to author
Forward
0 new messages