1
votes

I create a dictionary from values I get from a database that fit certain criteria. Therefore I don’t know beforehand neither the number nor the values of the elements in the dictionary.

For example, I get something like this:

ditc1 = {"P01":{"F1":0.4,"P02":0.6}, "P02":{"F2":0.3, "P03":0.7}, "P03":{"F3":0.2, "P02":0.8}}

What I would like to do is to dynamically create mathematical equations from this elements like this:…

P01 = 0.4*F1 + 0.6*P02

P02 = 0.3*F2 + 0.7*P03

P03 = 0.2*F3 + 0.8*P02

I need the references across the equations to stay the same (e.g P02 in the first equation is P02 from the second equation), so I can solve those equations with regard to the P0X elements.

Is there a way to do this?

2

2 Answers

3
votes

You don't have to worry about re-creating Symbol objects for your variables. SymPy will create singleton objects for you, each time you call Symbol('P01') the same single object is returned:

>>> from sympy import Symbol
>>> p = Symbol('P01')
>>> p
P01
>>> p is Symbol('P01')
True

So just convert your structure to SymPy objects directly and SymPy will know that P02 is the same symbol in both the P02 = ... equality expression and the 0.6*P02 multiplication.

Because you presumably can have an arbitrary number of elements in the nested dictionary, you can use sympy.Add() to build the addition from any number of components. I'm going to assume you want to record the = symbol in the equation too, so use sympy.Eq() for that:

from sympy import Symbol, Add, Eq

expressions = []
for p, equation_components in ditc1.items():
    p = Symbol(p)
    expression = []
    for name, multiplier in equation_components.items():
        expression.append(Symbol(name) * multiplier)
    expressions.append(Eq(p, Add(*expression)))

This produces

>>> from sympy import pprint
>>> for expr in expressions:
...     pprint(expr)
...
P₀₁ = 0.4⋅F₁ + 0.6⋅P₀₂
P₀₂ = 0.3⋅F₂ + 0.7⋅P₀₃
P₀₃ = 0.2⋅F₃ + 0.8⋅P₀₂

If you want to play with this here is a SymPy Live version.

0
votes

I was just thinking about converting a simple dictionary of symbols and expressions to a list of equations like

>>> d2e = lambda d: [*map(lambda i:Eq(*i), d.items())]
>>> d2e({x:y+1, z:2})
[Eq(x, y + 1), Eq(z, 2)]

That could be used with your dictionary by turning it into a sympified form (which can be done with a call to Dict:

>>> s = Dict(dict1)

Then the dictionaries appearing as values can be converted to expressions:

>>> s = {k: Add(*[s*n for s,n in v.items()]) for k,v in s.items()}; s
{P01: 0.4*F1 + 0.6*P02, P02: 0.3*F2 + 0.7*P03, P03: 0.2*F3 + 0.8*P02}

And then the dictionary can be converted to a list of expressions; the first of which is shown:

>>> d2e(s)[:1]
[Eq(P01, 0.4*F1 + 0.6*P02)]

(And those values can be solved to give a dictionary where values are independent of the P values with a call like solve(d2e(s), list(s), dict=True).)