Dask delayed: pass combination of two lists - python

I have a feeling this should be easily possible, but I fail to pass combinations of (lazy) lists to a delayed function:
def test(a,b):
return(str(a)+','+str(b))
a = [1,2] #not lazy for example
b = [3,4] #not lazy
c = dask.delayed(test)(a,b)
c = c.compute()
out:
'[1,2][3,4]'
desired output:
['1,3','1,4','2,3','2,4']
Also tried:
def test(c):
a = c[0]
b = c[1]
return(str(a)+','+str(b))
def combine_a_b(a,b):
return([(i,j) for i in a for j in b])
c = dask.delayed(combine_a_b)(a,b)
c = dask.delayed(test)(c)
c = c.compute()
out:
'(1,3)(1,4)'
What am I doing wrong here?

Related

sympy .subs() built-in function doesn't work

I'm trying to implement the multivariate chain rule using python, when I try to substitute one of the elements using the built-in sympy function expr.subs() I won't get an answer.
The exercise goes as follows:
Compute df/dx of the following function using the chain rule:
a = x^2
b = exp(a)
c = a + b
d = log(c)
e = sin(c)
f = d + e
⁡
And this is the code:
a, b, c, d, e, f = sym.symbols('a b c d e f')
f = d + e
dfd = sym.diff(f, d)
dfe = sym.diff(f, e)
df = sym.Matrix([[dfd, dfe]])
d = sym.log(c)
e = sym.sin(c)
ddc = sym.diff(d)
dde = sym.diff(e)
dd = sym.Matrix([[ddc],[dde]])
dfdd = df#dd
c = a + b
dca = sym.diff(c, a)
dcb = sym.diff(c, b)
dc = sym. Matrix([[dca, dcb]])
dfdc = dfdd#dc
a = x**2
b = sym.exp(a)
result = dfdc.subs(c, (a + b))
result
The result the function .subs() doesn't substitute anything and I don't know why, I tried substituting it using other ways to write the function, like:
dfdc.subs({c : (a + b)})
dfdc.subs(c, a + b)
And even tried to just substitute it for an integer to see it that would work and neither does it.
What am I doing wrong?
The c in your dfdc expression was created before you set c=a+b. So it still appears as c in dfdc. However, by the time you want to do your subs, the c symbol is declared as c=a+b, and so your substitute really reads
dfdc.subs(a+b, a+b)
And that does nothing.
In order to really use c there, do
dfdc.subs(sym.Symbol('c'), a+b)

How to test all possible values ​for all variables to get the maximum result for the function

I have three variables called a, b and c, each of these can assume a different value defined in a range. I'd like to create a function that tests every possible variable value and gives me their best combination for the output 'f'.
a = list(range(1, 10, 2))
b = list(range(5, 8, 1))
c = list(range(1, 3, 1))
def all_combinations (a, b, c):
#something
f = a + (b * a) - (c*(a ^ b))
return BEST a, b, c for my f
it's possible to do it ? what is the best way to do it?
You can use itertools.product() to get all the possible combinations of a, b, and c.
Then calculate your formula for each unique combination of a b c, keep track of the result, and if the result is better than the previous best, save the current values of a b c.
import itertools
def all_combinations (alist, blist, clist):
best_a = 0
best_b = 0
best_c = 0
best_f = 0
for a,b,c in itertools.product(alist, blist, clist):
f = a + (b * a) - (c*(a ^ b))
if f > best_f: # use your own definition of "better"
best_a = a
best_b = b
best_c = c
best_f = f
return best_a, best_b, best_c
First of all, you said I have three variables called a, b and c, each of these can assume a different value defined in a range. Note that the variables in your code are actually equal to three lists of integers, not three integers.
The naive algorithm to test all possible combinations is 3 nested for loops. Here I assume that by "best" you mean "maximum value":
def all_combinations (list1, list2, list3):
best_f, best_a, best_b, best_c = None, None, None, None
for a in list1:
for b in list2:
for c in list3:
f = a + (b * a) - (c*(a ^ b))
# here you have to define what f being "better" than best_f means:
if not f or f > best_f:
best_f = f
best_a = a
best_b = b
best_c = c
return best_a, best_b, best_c
If you're sure those are the only values you want to test, then the following will work. Otherwise you might want to look into scipy.optimize.
from itertools import product
import numpy as np
parameters = list(product(a, b, c))
results = [my_fun(*x) for x in parameters]
print(parameters[np.argmax(results)])
obviously replace np.argmax with np.argmin if you want to minimize the function

Accessing only one of the return values from a function

How do I only access one of the values:
my code:
def test():
a = 4
b = 5
c = 6
return a, b, c
a = test().a # only want "a" from the function
You can ignore the other values by using a placeholder _
def test():
a = 4
b = 5
c = 6
return a, b, c
#Ignore b and c
a, _, _ = test()
print(a)
#4
Or you could return a dictionary of values and access a from the dictionary
def test():
a = 4
b = 5
c = 6
return locals()
print(test()['a'])
#4
Or you could just use indexing to find the first element of the returned tuple, given you know a is the first element, as per Tim's Answer above
def test():
a = 4
b = 5
c = 6
return a, b, c
print(test()[0])
#a
The function test() returns a tuple so in order to access a you would have to use the following code:
a = test()[0]
You could return a dictionary instead:
def test():
a = 4
b = 5
c = 6
return {"a":a, "b":b, "c":c}
print(test()["a"])
4
If you want to stick with your current approach, then the best you might be able to do would be to just print the first element from the tuple returned:
print(test()[0])
But this of course means that the caller would have to know that a happens to coincide with the first value.
There are a few ways to do this.
a, b, c = test() # ignore b and c
a, *_ = test() # ignore _ which captures b and c
a = test()[0]
a = test()
a[0] # which is equal to the 'a' inside the test function.

Subtraction between two nested lists of strings in Python

I am trying to follow the used structure in this question for nested lists but I'm confused and don't know how to figure it out. Suppose that to subtract the two lists a = ['5', '35.1', 'FFD'] and b = ['8.5', '11.3', 'AMM'], the following code is used for reaching to equation c = b - a:
diffs = []
for i, j in zip(a, b):
try:
diffs.append(str(float(j) - float(i)))
except ValueError:
diffs.append('-'.join([j, i]))
>>> print(diffs)
['3.5', '-23.8', 'AMM-FFD']
My question is, how do I get C = B - A by considering the following structure:
A = [['X1','X2'],['52.3','119.4'],['45.1','111']]
B = [['Y1','Y2'],['66.9','65'],['99','115.5']]
C = [['Y1-X1','Y2-X2'],['14.6','-54.4'],['53.9','4.5']]
and how do I the first and second elements of each internal list, something like:
Array 1 = ['Y1-X1', '14.6', '53.9']
Array 2 = ['Y2-X2', '-54.4', '4.5']
I appreciate any kind of help.
Well, if it's guaranteed that the lists will always be 2 levels nested, you can simply add one more loop:
diffs_lists = []
for i, j in zip(a, b):
diffs = []
for k, l in zip(i, j):
try:
diffs.append(str(float(k) - float(l)))
except ValueError:
diffs.append('-'.join([k, l]))
diffs_lists.append(diffs)
To separate the result in two as you asked, simply use zip:
zip(*diffs_lists)
You just need another level of looping:
res = []
for a, b in zip(A, B):
diffs = []
res.append(diffs)
for i, j in zip(a, b):
try:
diffs.append(str(float(j) - float(i)))
except ValueError:
diffs.append('-'.join([j, i]))
print(res)
#[['Y1-X1', 'Y2-X2'], ['14.600000000000009', '-54.400000000000006'], ['53.9', '4.5']]
print(list(zip(*res)))
#[('Y1-X1', '14.600000000000009', '53.9'), ('Y2-X2', '-54.400000000000006', '4.5')]
diffs=[]
for sub_b, sub_a in zip(b, a):
curr = []
for atom_b, atom_a in zip(sub_b, sub_a):
try:
curr.append(float(atom_b) - float(atom_a))
except ValueError:
curr.append('-'.join([atom_b, atom_a]))
diffs.append(curr)
ans1, ans2 = zip(*diffs)
The zip function can also be used to unzip iterables.
Suppose you have a list_diffs function, that is basically the code you provided:
list_diffs(a, b):
diffs = []
for i, j in zip(a, b):
try:
diffs.append(str(float(j) - float(i)))
except ValueError:
diffs.append('-'.join([j, i]))
return diffs
Then, the C you want is just a list whose elements are diffs between elements of A and elements of B. So the following gives you C:
C = []
for i in range(len(A)):
C.append(list_diffs(A[i], B[i]))
To get the lists of the first and of the second elements:
array1 = [c[0] for c in C]
array2 = [c[1] for c in C]
In case you need this to work with arbitrary amount of nesting you could use recursion:
def subtract(x, y):
diffs = []
for a, b in zip(x, y):
try:
if isinstance(a, list):
diffs.append(subtract(a, b))
else:
diffs.append(str(float(b) - float(a)))
except ValueError:
diffs.append('-'.join([b, a]))
return diffs
As others have pointed out zip can be used for unzipping:
res = subtract(A, B)
t1, t2 = zip(*res)
print(t1)
print(t2)
Output:
('Y1-X1', '14.6', '53.9')
('Y2-X2', '-54.4', '4.5')
i try it with a recursive method
A = [['X1','X2'],['52.3','119.4'],['45.1','111']]
B = [['Y1','Y2'],['66.9','65'],['99','115.5']]
C = [['Y1-X1','Y2-X2'],['14.6','-54.4'],['53.9','4.5']]
Array_a,Array_b = [[] for __ in range(2)]
def diff(B,A):
_a = 0
for b,a in zip(B,A):
if isinstance(b,list):
diff(b,a)
else:
try:
Array_b.append(float(b)-float(a)) if _a else Array_a.append(float(b)-float(a))
_a = True
except (ValueError,TypeError) as e:
Array_b.append("{0}-{1}".format(b,a)) if _a else Array_a.append("{0}-{1}".format(b,a))
_a = True
return (Array_a,Array_b)
print (diff(B,A))
>>>(['Y1-X1', 14.600000000000009, 53.9], ['Y2-X2', -54.400000000000006, 4.5])

Easiest way to initialize a large number of variables

Assume you are given a large number of variables that need to be initialized to None. A naive way to do this would be to count the number of variables on the left, and create a list of the same size on the right:
a, b, c, d, e, f, g, h, i, j = [None]*10
Is there a way to do this without having to count the variables? If one uses this pattern often, it could become tedious to have to count the number of variables.
a = b = c = d = e = f = g = h = i = j = None
Note: don't use this for mutable types. If you're curious why, this demonstrates:
>>> a = b = []
>>> a.append(1)
>>> a
[1]
>>> b
[1]
Is there a reason you're not doing this?
a = b = c = d = e = f = g = h = i = j = None
I'm not too familiar with the intricacies of Python's syntax so please correct me if I'm wrong.

Categories

Resources