This question could be related to:
Python Sympy solve returns list vs. dictionary
or
Are quoted dictionary keys an absolute must?
I have this Sympy code, in one of my first attempts to SymPy library:
import sympy as sym
from sympy.parsing.sympy_parser import parse_expr
from sympy import symbols, Eq, solve
class FunZ:
def __init__(self, f):
self.x, self.y = sym.symbols('x y')
self.f = parse_expr(f)
# print('f : ', self.f)
def evalu(self, xx, yy):
return float(self.f.subs({self.x: xx, self.y: yy}).evalf())
def derX(self, xx, yy):
self.dx = sym.diff(self.f, self.x)
# print('dx : ', self.dx)
return float(self.dx.subs({self.x: xx, self.y: yy}).evalf())
def derY(self, xx, yy):
self.dy = sym.diff(self.f, self.y)
# print('dy :', self.dy)
return float(self.dy.subs({self.x: xx, self.y: yy}).evalf())
def derXY(self, xx, yy):
return [float(self.derX(xx, yy)), float(self.derY(xx, yy))]
def minim(self):
self.dx = sym.diff(self.f, self.x)
self.dy = sym.diff(self.f, self.y)
print('dx : ', self.dx)
print('dy : ', self.dy)
eq1 = Eq(self.dx ,0)
eq2 = Eq(self.dy ,0)
solu = solve((eq1,eq2), (self.x, self.y), dict = False) #### HERE dict = False
print(solu, type(solu))
return solu
funz = FunZ('x**2 y**2 2*y 2')
dict_min = funz.minim()
print(dict_min, type(dict_min))
for keys in dict_min:
print('key : ', keys, 'value : ', dict_min[keys])
print('values :' , dict_min.values())
# print(dict_min[x]) ###### ---> NameError: name 'x' is not defined
print(dict_min['x']) ####### -----> KeyError: 'x'
my output looks like :
dx : 2*x
dy : 2*y 2
{x: 0, y: -1} <class 'dict'>
{x: 0, y: -1} <class 'dict'>
key : x value : 0
key : y value : -1
values : dict_values([0, -1])
Traceback (most recent call last):
File .....", line 88, in <module>
print(dict_min['x']) ####### -----> KeyError: 'x'
KeyError: 'x'
or
print(dict_min[x]) ###### ---> NameError: name 'x' is not defined
NameError: name 'x' is not defined
I can get x, y with print('values :' , list(dict_min.values()))
---> values : [0, -1]
If I set the flag dict to True in solu = solve((eq1,eq2), (self.x, self.y), dict = True)
, I get [{x: 0, y: -1}] <class 'list'>
as a result
Any idea about what is going on? Is it related on how I defined my Funz class? the results seem plausible to me, but this dict stuff is driving me crazy.
CodePudding user response:
You can't access via dict_min[x]
or dict_min["x"]
because x
is of type sympy.core.symbol.Symbol
. The keys of this dict are of type sympy.core.symbol.Symbol
.
dict_min[x]
does not work because no x
variable is defined in your code.
dict_min["x"]
does not work because here you define x
as a string
, but the key named x
in dict_min
is of type sympy.core.symbol.Symbol
.
There is no problem with your class.
However, you can do this:
dict_min[funz.x]
or:
x = funz.x
dict_min[x]
So, dict_min
is not a strange dict
type from sympy, that's a classic Python dict
which keys are of type sympy.core.symbol.Symbol
. The keys are the symbols of your equation. Perhaps it was confusing because your symbols x
and y
were defined in your class and via sym.symbols('x y')
.
If you want to ALWAYS get a list
:
In minim
, you should set dict=True
instead of False
. By doing this, you will "always get a list of solution mappings" (https://docs.sympy.org/latest/modules/solvers/solvers.html).
Yes, the goal of dict=True
is to ensure that the returned variable will be of type list
. I agree that could seems a bit strange.
Some informations about this flag from the source code of solve(): https://github.com/sympy/sympy/blob/master/sympy/solvers/solvers.py#L406
And here is the effect of the flag is_dict
: https://github.com/sympy/sympy/blob/master/sympy/solvers/solvers.py#L1249
As for sympy 1.9.