Home > Software engineering >  Sympy solve returns strange dictionary, when it should not return any
Sympy solve returns strange dictionary, when it should not return any

Time:12-05

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.

  • Related