get sqrt to work

384 views
Skip to first unread message

Zohreh Karimzadeh

unread,
Aug 17, 2022, 9:38:16 AM8/17/22
to sympy
Dear sympy group
Thanks for your sympy.

I am working on a code, after creating my big expression using sympy it includes sqrt.

I need to lambdify my expression to make it consistent with numpy and other suffs.

expr =10 * sp.sqrt(sp.symbols('x'))

model_func = sp.lambdify('x', expr)

But I found my expression after lambdifying becomes somethings like this:

10*sqrt(x)

while I need :

10*numpy.sqrt(x)

Could possibly let me know how get sqrt to work with numpy?

Regards,

Zohreh


 

Peter Stahlecker

unread,
Aug 17, 2022, 11:16:26 AM8/17/22
to sy...@googlegroups.com
I use lambdify(....) a lot, but always like this:

x = sympy.symbols('x')
expr = symy.S(10.) * sympy.sqrt(x)
expr_lam = sympy.lambdify([x], expr)

a = expr_lam(10.)

This seems to work for me.

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/1f0b313f-31c5-402e-991e-142a556016f4n%40googlegroups.com.
--
Best regards,

Peter Stahlecker

Aaron Meurer

unread,
Aug 17, 2022, 1:00:29 PM8/17/22
to sy...@googlegroups.com
This isn't the case in your example code, but sometimes what can happen is that you have a symbol x with some assumptions, and if you use lambdify('x', ...) it will create a symbol x with no assumptions, which SymPy will treat as a different symbol. The best thing to do is to use

x = symbols('x', ...)

and always use x for the symbol, instead of the string 'x'.

Aaron Meurer

--

Zohreh Karimzadeh

unread,
Aug 17, 2022, 1:02:03 PM8/17/22
to sy...@googlegroups.com
Here is my code:
import matplotlib.pyplot as plt
import numpy as np
import sympy as sp
import pandas as pd
#exp_NaCl path: F:\Zohreh\MainZohreh\postdoc-field\CSU\Duplicat_Pure
df = pd.read_excel(r'F:\Zohreh\MainZohreh\postdoc-field\CSU\Duplicat_Pure\data.xlsx', sheet_name='NaCl_exp')
XNa = df['XNa']
XCl = df['XCl']
Xwater = df['Xwater']
Y = df['gama_x']
L=['WwaterNaCl', 'UwaterNaCl', 'VwaterNaCl', 'XCl', 'XNa', 'Xwater', 'BNaCl']
for j in range(len(L)):
locals()[L[j]] = sp.symbols(L[j])
expr = -0.0118343195266272*BNaCl*XCl*XNa*(-2*(9.19238815542512*sqrt(XNa) + 9.19238815542512*sqrt(XCl + XNa) + 1)*exp(-9.19238815542512*sqrt(XNa) - 9.19238815542512*sqrt(XCl + XNa)) + 2)/((XCl + XNa)*(sqrt(XNa) + sqrt(XCl + XNa))**2) + 0.00591715976331361*BNaCl*XCl*(-2*(9.19238815542512*sqrt(XNa) + 9.19238815542512*sqrt(XCl + XNa) + 1)*exp(-9.19238815542512*sqrt(XNa) - 9.19238815542512*sqrt(XCl + XNa)) + 2)/(sqrt(XNa) + sqrt(XCl + XNa))**2 + 0.00591715976331361*BNaCl*XNa*(-2*(9.19238815542512*sqrt(XNa) + 9.19238815542512*sqrt(XCl + XNa) + 1)*exp(-9.19238815542512*sqrt(XNa) - 9.19238815542512*sqrt(XCl + XNa)) + 2)/(sqrt(XNa) + sqrt(XCl + XNa))**2 - 1.0*Cl*WwaterNaCl*Xwater*(0.5*XCl + 0.5*XNa + 0.5)/XCl - 0.5*Cl*WwaterNaCl/XCl - 4.0*UwaterNaCl*XCl*XNa*Xwater + 2.0*UwaterNaCl*XCl*Xwater + 2.0*UwaterNaCl*XNa*Xwater - 4.0*UwaterNaCl*XNa - 6.0*VwaterNaCl*XCl*XNa*Xwater**2 - 4.0*VwaterNaCl*XCl*Xwater**2 + 2.0*VwaterNaCl*XNa*Xwater**2 - 1.0*WwaterNaCl*Xwater*(0.5*XCl + 0.5*XNa + 0.5) + 2.0*WwaterNaCl*Xwater - 0.5*WwaterNaCl - 1.45739430799067*(0.707106781186548*sqrt(XNa) + 0.707106781186548*sqrt(XCl + XNa))*(-XCl - XNa + 1)/(9.19238815542512*sqrt(XNa) + 9.19238815542512*sqrt(XCl + XNa) + 1) - 1.45739430799067*(0.707106781186548*sqrt(XNa) + 0.707106781186548*sqrt(XCl + XNa))*(-1.4142135623731*sqrt(XNa) - 1.4142135623731*sqrt(XCl + XNa) + 1)/(9.19238815542512*sqrt(XNa) + 9.19238815542512*sqrt(XCl + XNa) + 1) - 0.448429017843282*log(9.19238815542512*sqrt(XNa) + 9.19238815542512*sqrt(XCl + XNa) + 1)
model_func = sp.lambdify(L, expr )

def f(param):
BNaCl = param[0]
UwaterNaCl = param[1]
VwaterNaCl = param[2]
WwaterNaCl = param[3]
Y_est = model_func
return np.sum((np.log(Y) - Y_est)**2)


bnds = [(1, np.inf), (0, 1), (0, 1), (-1, np.inf)]
x0 = (1, 0.01, 0.98, 1)
con = {"type": "eq", "fun": c}

result = minimize(f, x0, bounds=bnds)

print(result.fun)
print(result.message)
print(result.x[0], result.x[1], result.x[2], result.x[3])
while I got :
NameError: name 'sqrt' is not defined

Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))


data.xlsx

Zohreh Karimzadeh

unread,
Aug 17, 2022, 1:04:55 PM8/17/22
to sy...@googlegroups.com
It means it has nothing to do with sqrt or exp?????

Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

Oscar Benjamin

unread,
Aug 17, 2022, 2:17:51 PM8/17/22
to sympy
The function created by lambdify does use numpy. The code 10*sqrt(x)
will be executed in a namespace where sqrt refers to numpy.sqrt.

--
Oscar

Aaron Meurer

unread,
Aug 17, 2022, 4:47:43 PM8/17/22
to sy...@googlegroups.com
Your expression uses "sqrt" but you haven't imported it from anywhere, since you only did "import sympy as sp". You need to use sp.sqrt. 

Aaron Meurer

Zohreh Karimzadeh

unread,
Aug 17, 2022, 10:21:02 PM8/17/22
to sy...@googlegroups.com
Before run I import sp.sqrt or sp.exp but after run they get disappeared.  My expression is big and dynamically created  and not possible to parse and subs np.exp or sp.exp.

Zohreh Karimzadeh

Contact me on
           +989102116325
                     and at
     z.kari...@gmail.com
                                 🌧️🌍🌱
   

Peter Stahlecker

unread,
Aug 18, 2022, 2:12:44 AM8/18/22
to sy...@googlegroups.com
I use lambdify quite a bit, on rather large expressions.
Basically, it always works like this for me:

import sympy as sm
x1, x2, …, xn = sm.symbols(‚x1, x2, ….., xn‘)
….
expr = some expression of generally with me: sm.sin, sm.cos, sm.exp, sm.sqrt,
            sm.Heaviside, etc..
This expression may have 50,000 terms, may be an (axb) matrix, whatever.

expr_lam = sm.lambdify([x1, x2, …,xn], expr)

Now I can evaluate expr_lam(…) like I would evaluate any numpy function.

I have no idea, what expr_lam looks like, I would not know how to look at it.
I assume, it converts sm.sin(..) to np.sin(…), etc

This is how it works for me.
As I do not really understand your points, like ‚dynamically created‘, ‚parse and subs‘, this may be of not help at all for you.

Peter


Peter Stahlecker

unread,
Aug 18, 2022, 4:34:48 AM8/18/22
to sy...@googlegroups.com
I am certainly no expert in sympy or inpython, but maybe one more point:

I think, it is ‚dangerous‘ to do it like this:

from sympy import sqrt, sin, cos and then use sqrt, sin, cos later.
I could imagine, that lambdify gets confused.

I feel, it is better to do it like this:
import sympy as sp
Import numpy as np

and the write np.sqrt, or sp.sqrt, whichever you want in the context.
Then it is clear, which sqrt is meant.

Zohreh Karimzadeh

unread,
Aug 18, 2022, 6:35:16 AM8/18/22
to sy...@googlegroups.com
the following code is ok when expression is passed as :

import numpy as np
from scipy.optimize import minimize, curve_fit
from lmfit import Model, Parameters

L = np.array([0.299, 0.295, 0.290, 0.284, 0.279, 0.273, 0.268, 0.262, 0.256, 0.250])
K = np.array([2.954, 3.056, 3.119, 3.163, 3.215, 3.274, 3.351, 3.410, 3.446, 3.416])
VA = np.array([0.919, 0.727, 0.928, 0.629, 0.656, 0.854, 0.955, 0.981, 0.908, 0.794])


def f(param):
gamma = param[0]
alpha = param[1]
beta = param[2]
eta = param[3]
VA_est = gamma - (1 / eta) * np.log(alpha * L ** -eta + beta * K ** -eta)

return np.sum((np.log(VA) - VA_est) ** 2)



bnds = [(1, np.inf), (0, 1), (0, 1), (-1, np.inf)]
x0 = (1, 0.01, 0.98, 1)
result = minimize(f, x0, bounds=bnds)
print(result.message)
print(result.x[0], result.x[1], result.x[2], result.x[3])

but when the expression is passed as the following way:

import numpy as np
import sympy as sp
from scipy.optimize import minimize, curve_fit
from lmfit import Model, Parameters

L = np.array([0.299, 0.295, 0.290, 0.284, 0.279, 0.273, 0.268, 0.262, 0.256, 0.250])
K = np.array([2.954, 3.056, 3.119, 3.163, 3.215, 3.274, 3.351, 3.410, 3.446, 3.416])
VA = np.array([0.919, 0.727, 0.928, 0.629, 0.656, 0.854, 0.955, 0.981, 0.908, 0.794])


def f(param):
gamma, alpha, beta, eta = sp.symbols('gamma, alpha, beta, eta')
gamma = param[0]
alpha = param[1]
beta = param[2]
eta = param[3]
Vi_est = gamma - (1 / eta) * sp.log(alpha * L ** -eta + beta * K ** -eta)
Vlam_est = sp.lambdify((gamma, alpha, beta, eta), Vi_est)

return np.sum((np.log(VA) - Vlam_est) ** 2)



bnds = [(1, np.inf), (0, 1), (0, 1), (-1, np.inf)]
x0 = (1, 0.01, 0.98, 1)

result = minimize(f, x0, bounds=bnds)

print(result.message)
print(result.x[0], result.x[1], result.x[2], result.x[3])

I face difficulty:
*********************************************
Traceback (most recent call last):
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\sympy\core\cache.py", line 70, in wrapper
    retval = cfunc(*args, **kwargs)
TypeError: unhashable type: 'numpy.ndarray'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\sympy\core\cache.py", line 70, in wrapper
    retval = cfunc(*args, **kwargs)
TypeError: unhashable type: 'numpy.ndarray'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "F:\Zohreh\MainZohreh\postdoc-field\CSU\pythonProject\fit_test_2.py", line 26, in <module>

    result = minimize(f, x0, bounds=bnds)
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\scipy\optimize\_minimize.py", line 692, in minimize
    res = _minimize_lbfgsb(fun, x0, args, jac, bounds,
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\scipy\optimize\_lbfgsb_py.py", line 308, in _minimize_lbfgsb
    sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps,
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\scipy\optimize\_optimize.py", line 263, in _prepare_scalar_function
    sf = ScalarFunction(fun, x0, args, grad, hess,
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\scipy\optimize\_differentiable_functions.py", line 158, in __init__
    self._update_fun()
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\scipy\optimize\_differentiable_functions.py", line 251, in _update_fun
    self._update_fun_impl()
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\scipy\optimize\_differentiable_functions.py", line 155, in update_fun
    self.f = fun_wrapped(self.x)
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\scipy\optimize\_differentiable_functions.py", line 137, in fun_wrapped
    fx = fun(np.copy(x), *args)
  File "F:\Zohreh\MainZohreh\postdoc-field\CSU\pythonProject\fit_test_2.py", line 17, in f
    Vi_est = gamma - (1 / eta) * sp.log(alpha * L ** -eta + beta * K ** -eta)
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\sympy\core\cache.py", line 74, in wrapper
    retval = func(*args, **kwargs)
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\sympy\core\function.py", line 476, in __new__
    result = super().__new__(cls, *args, **options)
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\sympy\core\cache.py", line 74, in wrapper
    retval = func(*args, **kwargs)
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\sympy\core\function.py", line 288, in __new__
    evaluated = cls.eval(*args)
  File "C:\Users\Zohreh\AppData\Roaming\Python\Python310\site-packages\sympy\functions\elementary\exponential.py", line 718, in eval
    coeff = arg.as_coefficient(I)
AttributeError: 'ImmutableDenseNDimArray' object has no attribute 'as_coefficient'








Zohreh Karimzadeh
https://www.researchgate.net/profile/Zohreh-Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
z.kari...@gmail.com
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))


Peter Stahlecker

unread,
Aug 18, 2022, 6:58:18 AM8/18/22
to sy...@googlegroups.com
In your first return statement, where it works, you seem to return a number.
In your second return, your a ‚mixture‘ of numbers and functions:
Vlam_est is a function, which requires four arguments as per its definition. Would you not have to return Vlam_est(alpha, beta, gamma, eta) ?

Zohreh Karimzadeh

unread,
Aug 18, 2022, 7:18:20 AM8/18/22
to sy...@googlegroups.com
It seems always an expression of parameters and independent variables is needed to be passed to fit and find parameters.

Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

Peter Stahlecker

unread,
Aug 18, 2022, 7:38:54 AM8/18/22
to sy...@googlegroups.com
I just have no idea what

np.sum((np.log(AV) + Vlam_est)**2)

could possibly mean.  np.log(VA) is an array of floats, that is an array of numbers.
Vlam_est is a function. How you can add numbers and a function I do not know..
Vlam_est will become an array of numbers, once you give it the arguments.

NB: 
it seems, that Vi_est uses the arguments alpha,.., eta, L, K
When you lambdify it, you skipped the arguments L and K. 
Any reason for this? 

Zohreh Karimzadeh

unread,
Aug 18, 2022, 7:56:09 AM8/18/22
to sy...@googlegroups.com
L and K are independent variables that will be passed to minimize.

Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

Peter Stahlecker

unread,
Aug 18, 2022, 8:05:25 AM8/18/22
to sy...@googlegroups.com
Whatever they are, I believe your second return statement does not work, because you are adding ‚things‘ which cannot be added.
I do not understand your program, but I do understand, that your second return statement cannot work.

Zohreh Karimzadeh

unread,
Aug 18, 2022, 8:08:36 AM8/18/22
to sy...@googlegroups.com
thank you very much.

Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

Peter Stahlecker

unread,
Aug 18, 2022, 8:19:36 AM8/18/22
to sy...@googlegroups.com
Most welcome! If I was of help, great! If not, I still enjoyed our conversation.

Zohreh Karimzadeh

unread,
Aug 18, 2022, 8:35:00 AM8/18/22
to sy...@googlegroups.com
Very useful, can I ask a question?
If you need to make your expression in a symbolic way using sympy which includes log or exp. Which fitting library would you recommend to easily pass your sympy expression and get your fitted parameters.
Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

gu...@uwosh.edu

unread,
Aug 18, 2022, 8:42:22 AM8/18/22
to sympy
Based on my experience developing fitting tools to be used by undergraduates (see https://jupyterphysscilab.github.io/jupyter_Pandas_GUI/) I think your choice of lmfit and scipy.optimize are good options.

Jonathan

Zohreh Karimzadeh

unread,
Aug 18, 2022, 8:51:35 AM8/18/22
to sy...@googlegroups.com
But not working here.

Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

Peter Stahlecker

unread,
Aug 18, 2022, 8:55:02 AM8/18/22
to sy...@googlegroups.com
Dear Zohreh,
Sorry, but I am of no help with this.
I have never used lmfit in any serious way, so I barely know it exists.
( i have made so many mistakes with sympy.lambdify(..) so I know it a bit by now)

Peter

gu...@uwosh.edu

unread,
Aug 18, 2022, 8:55:40 AM8/18/22
to sympy
I think they should work. I think you are not passing them the correct information from your model function. To restate Peter's comments in a different way. The model function must return numerical values which can be compared to your data for the fit algorithms to work. Do not try to do any fitting until you have your model function doing that.

Jonathan

Zohreh Karimzadeh

unread,
Aug 18, 2022, 9:03:09 AM8/18/22
to sy...@googlegroups.com
Thanks I will work on it,

Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

Aaron Meurer

unread,
Aug 18, 2022, 3:33:56 PM8/18/22
to sy...@googlegroups.com
Instead of generating a separate lambdified function for every input, you may find it simpler to lambdify a single function with your params as extra symbolic parameters, then pass those in using the args() argument to minimize().

Aaron Meurer

Zohreh Karimzadeh

unread,
Aug 19, 2022, 11:11:20 AM8/19/22
to sy...@googlegroups.com
I am new at python and using your comment seems hard to me could possibly let me know know it by example or any key words if is there.

Chris Smith

unread,
Aug 19, 2022, 12:47:19 PM8/19/22
to sympy
If you are trying to fit data, see the recent post about Trendy which might already do what you are trying to do. Or maybe you could look and see how lambdify is used in that project.


/c

Peter Stahlecker

unread,
Aug 19, 2022, 9:45:10 PM8/19/22
to sy...@googlegroups.com
Maybe a dumb question from my part:

do I understand you correctly:

For given L, K, VA you try to find the alpha, beta, gamma, eta which minimize
the function np.sum(….)   ?
 
Is my understanding correct?

Zohreh Karimzadeh

unread,
Aug 20, 2022, 12:48:18 AM8/20/22
to sy...@googlegroups.com

Peter Stahlecker

unread,
Aug 20, 2022, 1:05:03 AM8/20/22
to sy...@googlegroups.com
But would then this not be a simpler way, without any lambdify ?

def func_to_be_minimized(alpha, beta, gamma, eta, L, K, VA):
   ……
   ……
   return  np.sum(…….)

X0 = (…..)
args = (L. K, VA)
resultat = minimize(func_to_be_minimized, X0, args = args, bounds =…)

args contains the variables of your function, which will not be minimized.

You may have to play around with args = (L. K, VA) a bit, because minimize ‚hands over‘ whatever is in args to your function in a certain way, and your function must accept them this way. (I never know exactly how to do it, as I do not use it often at all, so I just play around until it works) 



Zohreh Karimzadeh

unread,
Aug 20, 2022, 2:24:47 AM8/20/22
to sy...@googlegroups.com
You mean I should make independent variables acceptable as args  to minimizer,?

prashant raj

unread,
Aug 20, 2022, 2:26:18 AM8/20/22
to sy...@googlegroups.com
Hey this Prashant. How you reached me?

Zohreh Karimzadeh

unread,
Aug 20, 2022, 2:27:19 AM8/20/22
to sy...@googlegroups.com
I am thinking of passing results of sympy expression as string and pars it to replace log or exp to np.log,... and use it without lambdifed form.

Zohreh Karimzadeh

unread,
Aug 20, 2022, 2:29:34 AM8/20/22
to sy...@googlegroups.com

I am thinking of passing results of sympy expression as string and pars it to replace log or exp to np.log,... and use it without lambdifed form. Am I going in right way.
Show quoted text

Peter Stahlecker

unread,
Aug 20, 2022, 3:02:36 AM8/20/22
to sy...@googlegroups.com
args is a standard key word with minimize, just look it up to see how it works.
Say, you have F(a, d, c, m ,e, f) as a function.
If you give the ‚starting guess‘ as x0 = (1, ,2, 3), it will minimize the function by varying the first three variables in the parameter list of F, that is a, d, c.
Balance parameters you have to give with the args keyword.
If you read the minimizer operations instructions, it will tell you how minimizer hands over the values in args to your function F. And your F must ‚understand this‘.

Zohreh Karimzadeh

unread,
Aug 20, 2022, 6:00:12 AM8/20/22
to sy...@googlegroups.com
Thank millions I will give it a try.

Peter Stahlecker

unread,
Aug 20, 2022, 11:09:14 AM8/20/22
to sy...@googlegroups.com
Most welcome!
Like I said, passing args = (L, K , VA) to your function F may take a little 'playing around'.

Oscar

unread,
Aug 22, 2022, 10:23:07 AM8/22/22
to sympy
On Saturday, 20 August 2022 at 16:09:14 UTC+1 peter.st...@gmail.com wrote:
Most welcome!
Like I said, passing args = (L, K , VA) to your function F may take a little 'playing around'.

This is one way to do it:

import numpy as np
import sympy as sp
from scipy.optimize import minimize, curve_fit

L_vals = np.array([0.299, 0.295, 0.290, 0.284, 0.279, 0.273, 0.268, 0.262, 0.256, 0.250])
K_vals = np.array([2.954, 3.056, 3.119, 3.163, 3.215, 3.274, 3.351, 3.410, 3.446, 3.416])
VA_vals = np.array([0.919, 0.727, 0.928, 0.629, 0.656, 0.854, 0.955, 0.981, 0.908, 0.794])

gamma, alpha, beta, eta, L, K, VA = sp.symbols('gamma, alpha, beta, eta, L, K, VA')


Vi_est = gamma - (1 / eta) * sp.log(alpha * L ** -eta + beta * K ** -eta)

# Note that the first entry in the args tuple is a 4 tuple
# That is needed to unpack the arguments from an array
f_Vi_est = sp.lambdify(((gamma, alpha, beta, eta), L, K, VA), Vi_est)

def f(param):
    Vi_est_vals = f_Vi_est(param, L_vals, K_vals, VA_vals)
    return np.sum((np.log(VA_vals) - Vi_est_vals) ** 2)



bnds = [(1, np.inf), (0, 1), (0, 1), (-1, np.inf)]
x0 = (1, 0.01, 0.98, 1)

result = minimize(f, x0, bounds=bnds)

print(result.message)
print(result.x[0], result.x[1], result.x[2], result.x[3])

# Output:
# CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL
# 1.0 0.5587146900213987 0.9371431014439708 5.87304177555323

--
Oscar

Peter Stahlecker

unread,
Aug 22, 2022, 10:36:46 AM8/22/22
to sy...@googlegroups.com
Dear Oscar,

Thanks for your hint about these parameters!.
Probably dumb question of mine:
Could one not define f_Vi_est directly as

def_Vi_est(gamma, alfa, beta, eta, L, K, VA):
       Vi_est  = gamma - (1  /  eta)…..
       return np.sum(…..)

without any ‚lambdification‘?

Thanks! Peter

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.

Oscar Benjamin

unread,
Aug 22, 2022, 11:12:27 AM8/22/22
to sympy
On Mon, 22 Aug 2022 at 15:36, Peter Stahlecker
<peter.st...@gmail.com> wrote:
>
> Dear Oscar,
>
> Thanks for your hint about these parameters!.
> Probably dumb question of mine:
> Could one not define f_Vi_est directly as
>
> def_Vi_est(gamma, alfa, beta, eta, L, K, VA):
> Vi_est = gamma - (1 / eta)…..
> return np.sum(…..)
>
> without any ‚lambdification‘?

Yes. In an earlier post the OP showed that they had working code like
that but wanted to know how to do it using SymPy and lambdify. I
presume there is a reason for wanting to use SymPy there (perhaps to
accomplish something slightly different from the exact code shown).
It's also possible that there isn't any actual reason to use SymPy for
this at all though.

--
Oscar

Zohreh Karimzadeh

unread,
Aug 22, 2022, 8:44:01 PM8/22/22
to sy...@googlegroups.com
Dear Oscar
BIG help !
Here I seriously need to use sympy to generate my params dynamically.
All Bests 
Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.

Peter Stahlecker

unread,
Aug 22, 2022, 8:46:59 PM8/22/22
to sy...@googlegroups.com
Dear Zohreh,

Just for my understanding:
1.
You params are alpha, betta ,gamma, eta (?)
2.
What do you mean by generating them dynamically?

Peter

Zohreh Karimzadeh

unread,
Aug 23, 2022, 12:56:34 AM8/23/22
to sy...@googlegroups.com
Not these model and parameters, My model is very complicated wit large number of parameters:
image.png
As a very simple example I raise this question.
Zohreh Karimzadeh

Contact me on
           +989102116325
                     and at
     z.kari...@gmail.com
                                 🌧️🌍🌱
   

Zohreh Karimzadeh

unread,
Aug 23, 2022, 1:01:02 AM8/23/22
to sy...@googlegroups.com
As following, I should generate each parameters dynamically (for 20-30 terms):
term_vnca = 0
for k in anion:
for j in cation:
for i in neutral:
term_vnca += term_vncX - 4 * 3 * sp.symbols(f'X{str(k)}') * sp.symbols('X{0}'.format(str(i))) \
** 2 * sp.symbols(f'V{str(i)}{str(j)}{str(k)}')
lnfXs = term_wnca + term_unca + term_vnca + termx_w_solvent1 + termx_w_solvent2
Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

gu...@uwosh.edu

unread,
Aug 24, 2022, 11:03:18 AM8/24/22
to sympy
Zohreh,

I pulled the paper. I see no reason you need to use SymPy to do the numerical fitting. I would approach this by inputting the species in a dictionary or list and then use that to call functions that generate the computed value for  each term/sum. Are you trying to keep track of the complete symbolic expression or do a numerical calculation?

If you are using chemical symbols or reactions, are  you taking advantage of ChemPy?

Jonathan

Zohreh Karimzadeh

unread,
Aug 24, 2022, 12:11:58 PM8/24/22
to sy...@googlegroups.com
I should extract the required model for each system of chemicals and do a least squre for derived model and parameters to find the parameters for each chemical systems. 

gu...@uwosh.edu

unread,
Aug 24, 2022, 1:02:32 PM8/24/22
to sympy
Zohreh,

The code snippets you have provided do not suggest you are doing anything that requires sympy. So, I am confused. It looks like you need a function that generates a string of the summations in your expression, when passed species. I think there is a fixed number of parameters for each species. You are probably better off building the string for your expressions without involving sympy. I am thinking something like this to define part of your fit function:


def term(species_name):
    return(species_name+'_param1*conc_'+species_name+'+'+species_name+'_param2*np.sqrt(conc_'+species_name+')')
Then
term('Cl')
returns
'Cl_param1*conc_Cl+Cl_param2*np.sqrt(conc_Cl)'

Then build your overall expression from these pieces. Then do a fit with initial guesses for all the parameters.

That's how I would do it unless I am manipulating the expressions using sympy first.

Jonathan

Zohreh Karimzadeh

unread,
Aug 25, 2022, 10:42:32 PM8/25/22
to sy...@googlegroups.com
As can be seen in the former script, parameter names should be made in a dynamic way.
 I am wondering how using for loop in string can be simultaneously handled. 
Regards,
Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

Peter Stahlecker

unread,
Aug 25, 2022, 11:29:02 PM8/25/22
to sy...@googlegroups.com
Dear Zohreh,

I think, you should describe precisely what you want, rather than referring to previous correspondence.
Someone out there (likely not me) might have a solution to what you need - but cannot be bothered to read through you previous correspondence.

1.
Parameter names should be made in a dynamic way.
what exactly do you mean by this?
Better give an example of what you would like to do.

2.
how using for loop in string can be simultaneously handled.
I have no idea, what your question is - and I am afraid, not many people understand. 
Better give an example of what you want to do.

Peter

Zohreh Karimzadeh

unread,
Aug 26, 2022, 6:03:00 AM8/26/22
to sy...@googlegroups.com
Jonathan has recommended to use string instead of sympy approche to
derive your model and -parameters.
But I stated that my model is driven dynamically. It means, as an
example for one term in model I have:

term_unca = 0
for k in anion:
for j in cation:
for i in neutral:
term_unca += term_uncX - 2 *
sp.symbols('X{0}'.format(str(i))) * sp.symbols(f'X{str(j)}') * \
sp.symbols(f'X{str(k)}') * ((cation[j] +
anion[k]) ** 2 / (cation[j] * anion[k])) \
* sp.symbols(f'U{str(i)}{str(j)}{str(k)}')
This way all the parameters should be created for each run of fitting.


Zohreh Karimzadeh
https://www.researchgate.net/profile/Zohreh-Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
z.kari...@gmail.com
+989102116325
((((((((((((((((Value Water)))))))))))))))

Zohreh Karimzadeh
https://www.researchgate.net/profile/Zohreh-Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
z.kari...@gmail.com
+989102116325
((((((((((((((((Value Water)))))))))))))))


> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CABKqA0b261cO3ixRjsp_YPU0Yk1ahRVgnEytcOkLrQUW-eHdwQ%40mail.gmail.com.

gu...@uwosh.edu

unread,
Aug 26, 2022, 9:34:25 AM8/26/22
to sympy
Zohreh,

It is still unclear what you are actually doing. I can think of two possibilities (are either of them correct?):

1) You ultimately pass a string expression to lmfit or some other fitting package that is parsed into a numpy expression for fitting or something similar. So I am suggesting that you remove the intermediate step of creating a sympy expression to make things more efficient. You can generate the string expression dynamically in essentially the same way you are currently generating the sympy expression, but avoid having the intermediate step of using sympy to generate the expression and then using it to generate a string expression that is parsed again.

2) Alternatively, you may be making your own model function (I believe for lmfit). In that case you need to generate a function that does a calculation. I see no reason it has to have human readable names for the parameters in the actual calculation. However, you could connect them with human readable names through a dictionary or something like that.

If you want a string, your code is almost there. As long as the elements of cation and anion are strings. Just replace things like sp.symbols('X{0}'.format(str(i))) with 'X_'+str(i). But maybe that is not what you are doing.

Jonathan

Zohreh Karimzadeh

unread,
Aug 26, 2022, 10:24:32 PM8/26/22
to sy...@googlegroups.com
Dear Jonathan
Thank you for your reply.
About using strings instead of sympy good idea, It is necessary to
know that there are bunch of functions that are inserted in the main
model as one of them :

anion = {'Cl': 1}
cation = {'Na': 1}
ionic_dic = dict()
for d in (cation, anion):
ionic_dic.update(d)
def ionicstr():
Ionic = 0
sqrt_I = 0
for k1 in ionic_dic:
Ionic += 0.5 * (sp.symbols('X{0}'.format(str(k1))) *
(ionic_dic[k1] ** 2))
sqrt_I += sp.sqrt(Ionic)
print(Ionic, sqrt_I)
return Ionic, sqrt_I
AS can be seen while all of these kinds of functions must be evaluated
or substituted in the main model.
Is it still possible to use strings instead of sympy??
Regards,
Zohreh
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/ec94798a-fcdc-4df8-b80e-2642f5a60ec5n%40googlegroups.com.

gu...@uwosh.edu

unread,
Aug 31, 2022, 4:12:58 PM8/31/22
to sympy
Zohreh,

I cannot tell you what is your best choice until you tell me what you are doing after you build the expression. Is it 1 or 2, as I asked before?

1) You ultimately pass a string expression to lmfit or some other fitting package that is parsed into a numpy expression for fitting or something similar.

2)You are making your own model function that returns a number every time it is called by some other package (fitting?).

Please explain exactly how you wish to use the expression you are developing and, if you are using it with another tool, which one?

Regards,
Jonathan

Zohreh Karimzadeh

unread,
Sep 1, 2022, 8:11:34 AM9/1/22
to sy...@googlegroups.com
Dear Jhonoton
If my best choice is the first then I have will have difficulty to pass some stuff in my string, as an example:

cation = {'Na': 1,'Cl':2}
anion = {'Cl': 1}

ionic_dic = dict()
for d in (cation, anion):
ionic_dic.update(d)
def ionicstr():
Ionic = 0
sqrt_I = 0
for k1 in ionic_dic:
        Ionic += 0.5 * (('X'+str(k1)) * (ionic_dic[k1] ** 2))
sqrt_I += (Ionic) ** 0.5
        print(Ionic, sqrt_I)
return Ionic, sqrt_I
def term():
for i in cation:
A ='X' + str(i) + str(ionicstr()[0])
print(A)
return A
term()
Is there any way to pass computed ionicstr()[0] to string??
Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))


gu...@uwosh.edu

unread,
Sep 1, 2022, 9:54:41 AM9/1/22
to sympy
You are mixing numerical and string expressions. You must make everything a string expression.
Example
Ionic = 0
Ionic += 0.5 * (('X'+str(k1)) * (ionic_dic[k1] ** 2))
Should be
Ionic = ""
Ionic += "+0.5 * ((X"+str(k1)+") * ("+str(ionic_dic[k1])+'"** 2))"

Chris Smith

unread,
Sep 1, 2022, 5:25:37 PM9/1/22
to sympy
This is somewhat painful to read because none of the code snippets are formatted as Python code. If possible, please post working code snippets.

As to using string or SymPy (and then converting to string): I prefer the latter because you get automatic syntax checking and a good visual of the object you are building. So I would do something like:

anion = {'Cl': 1}
cation = {'Na': 1, 'Mg': 2}

def ionic(*ions):
    I = 0
    for itype in ions:
        for k1 in itype:
            I += 0.5 * (Symbol('X{0}'.format(str(k1))) * (itype[k1] ** 2))
    return I

str(ionic(anion, cation)) ->  '0.5*XCl + 2.0*XMg + 0.5*XNa'

/c

Zohreh Karimzadeh

unread,
Sep 1, 2022, 10:54:27 PM9/1/22
to sy...@googlegroups.com
 Jonothon,
 thank you for answering
Chris,
Thanks, your point sounds cool. But if I make the object in a symbolic way and then change them to string, there are some sympy.exp and sympy.log that make problems. What is your suggestion on this problem?
Regards
 

Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))

Chris Smith

unread,
Sep 2, 2022, 8:00:53 AM9/2/22
to sympy
You can replace any function with any other using `subs`, so just replace them with a function that has the name you want (and you can make up the name and even include punctuation):

Snag_5ac96126.png

Note that in the last case *SymPy* will not be able to evaluate the expression but if you pass the string version to a function that knows how to interpret `np.exp` as numpy's version of `exp` then it will evaluate.

/c

Zohreh Karimzadeh

unread,
Sep 2, 2022, 9:30:52 PM9/2/22
to sy...@googlegroups.com
You mean I can use the numpyprint of sympy and then pass it to fit?
You received this message because you are subscribed to a topic in the Google Groups "sympy" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sympy/CAGn_agpz6M/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sympy+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/a9bd0c6b-75f7-4711-9e02-19c06648c86dn%40googlegroups.com.

Chris Smith

unread,
Sep 3, 2022, 1:26:43 PM9/3/22
to sympy
I don't know about numpyprint. I am just noting that you can get a well-defined mathematical expression to print as a string with certain function having a "np." prefix (if that is what you want). And it doesn't require any string parsing on your part. This string (if that is what you want) can be passed to whatever needs a string.

/c

Zohreh Karimzadeh

unread,
Sep 6, 2022, 5:45:51 AM9/6/22
to sy...@googlegroups.com
Dear Oscar
Really you are saving me in my project. I have one important issue to ask. Please let me know. My problem in fitting has been done, based on your brilliant suggestion. While

import numpy as np
import sympy as sp
from scipy.optimize import minimize, curve_fit

L_vals = np.array([0.299, 0.295, 0.290, 0.284, 0.279, 0.273, 0.268, 0.262, 0.256, 0.250])
K_vals = np.array([2.954, 3.056, 3.119, 3.163, 3.215, 3.274, 3.351, 3.410, 3.446, 3.416])
VA_vals = np.array([0.919, 0.727, 0.928, 0.629, 0.656, 0.854, 0.955, 0.981, 0.908, 0.794])

gamma, alpha, beta, eta, L, K, VA = sp.symbols('gamma, alpha, beta, eta, L, K, VA')

Vi_est = gamma - (1 / eta) * sp.log(alpha * L ** -eta + beta * K ** -eta)

# Note that the first entry in the args tuple is a 4 tuple
# That is needed to unpack the arguments from an array
f_Vi_est = sp.lambdify(((gamma, alpha, beta, eta), L, K, VA), Vi_est)

def f(param):
Vi_est_vals = f_Vi_est(param, L_vals, K_vals, VA_vals)
return np.sum((np.log(VA_vals) - Vi_est_vals) ** 2)


bnds = [(1, np.inf), (0, 1), (0, 1), (-1, np.inf)]
x0 = (1, 0.01, 0.98, 1)

result = minimize(f, x0, bounds=bnds)

print(result.message)
print(result.x[0], result.x[1], result.x[2], result.x[3])
1.  
f_Vi_est = sp.lambdify(((gamma, alpha, beta, eta), L, K, VA), Vi_est)
 2. 
Vi_est_vals = f_Vi_est(param, L_vals, K_vals, VA_vals)
  These two lines really make my project impossible. Since based on what the user is sending  in the code I must make these two lines dynamically. I mean how can I make them independent. I just have Vi_est(as any string resulted from sympy computation) and a list or dict of [gamma, alpha, beta, eat] and [L, K, VA] that are changing in each iteration.  How these lines can be written to make it dynamic. It is impossible to do the job this way.
Regards,

Zohreh Karimzadeh
Skype Name 49a52224a8b6b38b
Twitter Account @zohrehkarimzad1
+989102116325                                                        
((((((((((((((((Value Water)))))))))))))))


--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages