Python - dynamically create equations from a dictionary - python

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?

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.

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).)

Related

Transform a list of lists into another format

I have a list of lists that looks like this:
names_list = [
["first='Katie'", "last='Beckett'"],
["first='David'", "last='Seal'"],
["first='Eric'", "last='Swartz'"]
]
I want to transform it into this format:
object.filter(first='Katie', last="Beckett') | object.filter(first='David', last='Seal' | object.filter(first='Eric', last="Swartz')
This is what I've been trying:
def convert(list):
for i in list:
return reduce(lambda x,y: objects.filter + '(' + x + ', ' + y + ')' , i)
map(lambda i: convert(i), names_list ))
The "programming by accident" approach (ie trying anything aphazardly without the slightest understanding and hoping it will magically "kind of work") won't take you very far. You need to understand what you're doing and why.
First point: your target is a Python expression, not data, so what you want is not to "transform" your source data "into another format" but to dynamically build (and eval) the expression from your source data.
Second point: your source data format is just plain wrong, you don't want litteral "first=<...>" strings here but very obviously a list of dicts ie:
names_list = [
{"first":'Katie', "last":'Beckett'},
{"first":'David', "last":'Seal'},
{"first":'Eric', "last":'Swartz'}
]
This allow you to use dict unpacking in a function call, ie:
target = names_list[0]
result = object.filter(**target)
Third point: objects.filter + '(' + x + ', ' + y + ')' doesn't mean anything - trying to add a function and a string just won't work. Don't try to build Python expressions as string anyway, Python is expressive and dynamic enough to let you solve those kind of problems without such dirty hacks.
What you want here is to 1. build a sequence of calls (well results of the calls that is) to object.filter() then 2. "or" these results together.
The first step is quite easy:
items = [object.filter(**target) for target in names_list]
The second step is to "reduce" this sequence using the "biwise or" operator (|). reduce() is indeed the right function for this, you just need a function taking two of your items and "or'ing" them. The naive approach is to use a lambda:
result = reduce(lambda y, x: x | y, items)
but this is a case of reinventing the wheel since Python's operators (well, most of them) exist in a function version in the operator module:
import operator
result = reduce(operator.or_, items)

How to add two odd lists into one list in python?

I am very new to Python, and I'm trying to combine elements from two lists and produce a string from the combination.
My variables are:
fro = ['USD']
to = ['AUD', 'CAD', 'EUR']
I want output like this in a string:
pairs = "USDAUD,USDCAD,USDEUR"
Thanks a ton in advance for your help.
Why not use a generator expression like this:
fro = ['USD']
to = ['AUD', 'CAD', 'EUR']
pairs = ','.join(fro[0] + x for x in to)
Note that from is a reserved keyword and is thus not a valid variable name.
Output:
>>>pairs
'USDAUD,USDCAD,USDEUR'
If you were ever curious as to whether something you wish to use as a variable name is a keyword (and thus an illegal variable name) or not, you can always check with something like this:
>>> import keyword
>>> keyword.iskeyword("from")
True
Elizion's answer is nice and succinct, but as a beginner you may want to approach it without using an intermediate/advanced structure like a generator:
fro = ['USD']
to = ['AUD', 'CAD', 'EUR']
pairs = ""
for word in to:
pairs += fro[0] + word + ","
Removing the trailing comma:
pairs = pairs[:-1]
Elizion is absolutely correct.
If you have list elements varies dynamically, you can use this line:
absolutely pythonic way!!
pair_elem = ','.join('%s%s' % (x, y) for y in to for x in fro)
And conventional way is like, iterate list elems:
for multiple in to:
for single in fro:
pairs = ",".join(single + multiple)

All possible combinations of dictionary values given input string. Python

I'm trying to get all possible strings from the values in a dictionary given a particular key. For example, 'A' could mean either 'aaa','aba', or 'aac' and 'B' could mean either 'bbb','bab', or 'bbc', etc.
I've given an example of the output where it shows most combinations of the possible strings
import itertools
in_ = 'ABC'
D = {'A':['aaa','aba','aac'],'B':['bbb','bab','bbc'],'C':['ccc','cac','ccb']}
#out_ = ['aaabbbccc','ababbbccc','aacbbbccc','aaababccc','aaabbcccc','aaabbbcac','aaabbbccb'...]
I started writing the code but it started to get REALLY messy and I feel that there is a way to use itertools or something more pythonic to achieve this goal
output = []
for char in in_:
out_string = ''
while char:
for v in D[char]:
while v:
for char2 in in_:
out_string
#not pythonic . . .
Well, you've got itertools imported there. Let's use it! We want to take the Cartesian product D['A'] × D['B'] × D['C'], so we'll do precisely that using itertools.product.
import itertools
in_ = 'ABC'
D = {'A':['aaa','aba','aac'],'B':['bbb','bab','bbc'],'C':['ccc','cac','ccb']}
iterables = [D[character] for character in in_]
out_ = [''.join(tup) for tup in itertools.product(*iterables)]
Now, out_ is:
['aaabbbccc', 'aaabbbcac', 'aaabbbccb', 'aaababccc', 'aaababcac', 'aaababccb',
'aaabbcccc', 'aaabbccac', 'aaabbcccb', 'ababbbccc', 'ababbbcac', 'ababbbccb',
'abababccc', 'abababcac', 'abababccb', 'ababbcccc', 'ababbccac', 'ababbcccb',
'aacbbbccc', 'aacbbbcac', 'aacbbbccb', 'aacbabccc', 'aacbabcac', 'aacbabccb',
'aacbbcccc', 'aacbbccac', 'aacbbcccb']
Is that the result you were going for?

Python compiled eval?

my situation is as follows:
I have a large table like object which is accessed with a string key and integer index; i.e. lookup is like this: value = table.get("Key", index) .
I would like to give the user the opportunity to enter an arbitrary algebraic expression involving the string keys. The code code should then iterate over the second index and evaluate the expression repeatedly.
So for user input like this: "KeyA + 2*math.abs(KeyC)" I would like to run python code resembling:
for index in index_list:
answer = table.get("KeyA", index) + 2*math.abs(table.get("Keyc",index))
I guess can parse the expression using one of the Python Parser libraries I found on the internet, but it is not by any means clear to me how actually "run" the parsed code. Any suggestions?
If your end users can enter variables in figure brackets, {..}, you can use str.format to format your string
>>> expression = '{a}*{b}'
>>> values = {'a': 10, 'b': 20, 'c': 30}
>>> expression.format(**values)
'10*20'
Here values dictionary might be filled with table.get for all keys found in expression, for example with a regular expression:
>>> import re
>>> regexp = re.compile('{(.*?)}')
>>> keys = regexp.findall(expression)
>>> keys
['a', 'b']
>>> table_get = lambda *x: np.random.randint(5)
>>> values = {k: table_get(k) for k in keys}
>>> expression.format(**values)
'1*4'
Then you can refer to Safe way to parse user-supplied mathematical formula in Python for safe expression parsing and evaluation.

Generate a list of variables in SymPy [duplicate]

I am coding a function that solves an arbitrary number of simultaneous equations. The number of equations is set by one of the parameters of the function and each equation is built from a number of symbols - as many symbols as there are equations. This means that I can't simply hardcode the equations, or even the symbols needed to put together the equations; the function needs to be able to handle any number of equations. So, my question is, how do I produce a list of symbols?
I have one possible solution, but my gut tells me that it's not going to be very efficient. Please let me know if there is a better way of doing this.
I'm new to SymPy and am still feeling my way about. As far as I can see, Symbols need to be defined with a string. Therefore, I can produce a series strings via appending an incrementing number to a letter (say 't0', 't1', etc), add them to a list and then create the symbols using those strings as parameters. Those symbols would themselves be stored in a list and would be used to produce the equations.
def solveEquations(numEquations):
symbolNameList = []
symbolList = []
equationList = []
for i in range(numEquations):
name = 't' + str(i)
symbolNameList.append(name)
symbolList.append(Symbol(name))
for i in range(numEquations):
equation = 0
for sym in symbolList:
equation += sym ** i # Or whatever structure the equation needs
equationList.append(equation)
#Then go on to solve the equations...
Is this the best way of doing this, or is there a more efficient approach?
The symbols function can be used to easily generate lists of symbols
In [1]: symbols('a0:3')
Out[1]: (a₀, a₁, a₂)
In [2]: numEquations = 15
In [3]: symbols('a0:%d'%numEquations)
Out[3]: (a₀, a₁, a₂, a₃, a₄, a₅, a₆, a₇, a₈, a₉, a₁₀, a₁₁, a₁₂, a₁₃, a₁₄)
numbered_symbols("t") will return a generator that generates t0, t1, t2, etc. You can use the start parameter to choose a different starting value. And if you want to use dummy variables, use numbered_symbols("t", cls=Dummy).
Don't know if add any more useful information to the topic, but I use the following method to create a list of symbolic variables:
x = [sympy.symbols('x%d' % i) for i in range(3)]
And then I can use it normally in an equation:
eq = x[0]**2 + x[1]*2 + x[2]
print(sympy.diff(eq,x[0]))
>>> 2*x0
With locals() and dictionary comprehension, you could iteratively generate both symbols and python local variables with a similar name. For example:
>>> symbols_dict = dict(('a%d'%k, symbols('a%d'%k)) for k in range(3))
>>> locals().update(symbols_dict)
Checking that it works:
>>> print(expand((a0+a2)*(a0+a1**2)))
a0**2 + a0*a1**2 + a0*a2 + a1**2*a2
You could make a subclass of dict which automatically returns Symbols:
import sympy as sym
class SymDict(dict):
# http://stackoverflow.com/a/3405143/190597
def __missing__(self, key):
self[key]=sym.Symbol(key)
return self[key]
def solveEquations(numEquations):
symbol = SymDict()
symbolList = ['t'+str(i) for i in range(numEquations)]
equationList = [sum(symbol[s]**i for s in symbolList)
for i in range(numEquations)]
print(equationList)
solveEquations(3)
# [3, t0 + t1 + t2, t0**2 + t1**2 + t2**2]
I like the approach given by #j-p-sena and what I am going to suggest looks a lot like it. The difference is that you don't have to know how many symbols you are going to need -- you will just have access to as many as you need by index. Use the IndexedBase as your symbol:
>>> x = IndexedBase('x') # you've got access to a virtual array of x values
>>> solve(x[1]**2 + 1/x[4], x[4])
[-1/x[1]**2]
For display purposes you might want to create a replacement dictionary. To create numbered symbols you could do
>>> reps = dict(zip([x[i] for i in range(n_used+1)], numbered_symbols('c')))
>>> (x[2]**2 + 1/x[4]).subs(reps)
c2**2 + 1/c4
Or, if you are using less than 26 symbols you could use letters with
>>> reps = dict(zip([x[i] for i in range(n_used+1)], symbols('a:z')))
>>> (x[2]**2 + 1/x[4]).subs(reps)
c**2 + 1/e
BTW, x is an IndexedBase and x[1] is an Indexed object whose .base is x and whose .indices are a tuple of whatever numbers appear in the brackets. Both the IndexedBase and Indexed will show up in a .free_symbols query.
>>> (x[1,2] + 3).free_symbols
{x, x[1, 2]}
>>> x[1, 2].indices
(1, 2)
>>> x[1].base
x
Your approach is fine, though there's no need to store the symbol names separately (you can access a symbol's name via its name property).
Also, you could express the symbol creation a little more concisely (though no more efficiently), e.g.:
symbolList = map(lambda i: Symbol('t' + str(i)), xrange(numEquations))
However, for your use case (temporary variables), dummy variables are probably the way to go:
symbolList = map(Dummy, xrange(numEquations))
This isn't really any more efficient, since internally the Dummy class is also using a counter to generate unique names, but it's a bit cleaner and clearer.

Categories