Python: minimize multiple functions with multiple variables - python

I am trying to minimize 2 functions with 2 variables at the same time.
I have a set of data and 2 equations like:
B1 = 4
P1 = 6
G1 = 2
E1 = 3
F1 = B - G - E = -1
F2 = P - G - E = 1
Given a new B2 = 5 and P2 = 6 I would like to calculate the variables G2, E2 so that the difference between the old values F1 = -1 and F2 = 1 and the new values F3 and F4 are minimized:
B2 = 5
P2 = 6
G2 = ?
E2 = ?
F3 = B2 - G2 - E2 ---> as close as possible to F1
F4 = P2 - G2 - E2 ---> as close as possible to F2
I was trying:
def diff(param):
G2, E2 = param
return abs(B1 - G2 - E2 - F1)
x0 = [2,2]
res = minimize(diff, x0)
This resolve properly the minimization that gives F3 = F1 = -1, but does not solve my intention to also minimize the difference (F4 - F2).
Do you know how to include also the second minimization problem?
thank you in advance

I am not sure if my approach is too naive (it probably is, to be honest), but considering that you want to minimize two differences, meaning that each difference must tend to zero, then why don't you try to minimize the sum of the differences? This sum should also tend to zero. It would look like that:
from scipy.optimize import minimize
def diff(x):
G2, E2 = x
return (abs(B2 - G2 - E2 - F1 + P2 - G2 - E2 - F2))
B1 = 4
P1 = 6
G1 = 2
E1 = 3
F1 = B1 - G1 - E1
F2 = P1 - G1 - E1
B2 = 5
P2 = 6
res = minimize(diff, x0=(1, 1))
res.x returns [2.75, 2.75], which gives F3 = -0.5, F4 = 0.5.

Related

how to covert code from pine script to python

how to convert this type of code from pine script to python
pine script code
get2PoleSSF(src, length) =>
PI = 2 * asin(1)
arg = sqrt(2) * PI / length
a1 = exp(-arg)
b1 = 2 * a1 * cos(arg)
c2 = b1
c3 = -pow(a1, 2)
c1 = 1 - c2 - c3
ssf = 0.0
ssf := c1 * src + c2 * nz(ssf[1]) + c3 * nz(ssf[2])
this is the part im trying to convert it to python
the value of of the code
I tried this
def get2PoleSSD(src,length):
PI = 2* np.arcsin(1)
arg = np.sqrt(2)* PI / length
a1 = np.exp(-arg)
b1 = 2 * a1 *np. cos(arg)
c2 = b1
c3 = -pow(a1, 2)
c1 = 1 - c2 - c3
df['ssf'] = 0.0
df['ssf'] = c1* src
df['ssf_1p'] = df['ssf'].shift(1)
df['ssf_2p'] = df['ssf'].shift(2)
df['ssf_n'] = c1 * src + c2 * df['ssf_1p'] + c3 * df['ssf_2p']
the value from my code
but the value doesn't match at all

Sampling with fixed column ratio in pandas

I have this dataframe:
record = {
'F1': ['x1', 'x2','x3', 'x4','x5','x6','x7'],
'F2': ['a1', 'a2','a3', 'a4','a5','a6','a7'],
'Sex': ['F', 'M','F', 'M','M','M','F'] }
# Creating a dataframe
df = pd.DataFrame(record)
I would like to create for example 2 samples of this dataframe while keeping a fixed ratio of 50-50 on the Sex column.
I tried like this:
df_dict ={}
for i in range(2):
df_dict['df{}'.format(i)] = df.sample(frac=0.50, random_state=123)
But the output I get does not seem to match my expectation:
df_dict["df0"]
# Output:
F1 F2 Sex
1 x2 a2 M
3 x4 a4 M
4 x5 a5 M
0 x1 a1 F
Any help ?
Might not be the best idea, but I believe it might help you to solve your problem somehow:
n = 2
fDf = df[df["Sex"] == "F"].sample(frac=0.5, random_state=123).iloc[:n]
mDf = df[df["Sex"] == "M"].sample(frac=0.5, random_state=123).iloc[:n]
fDf.append(mDf)
Output
F1 F2 Sex
0 x1 a1 F
2 x3 a3 F
5 x6 a6 M
1 x2 a2 M
This should also work
n = 2
df.groupby('Sex', group_keys=False).apply(lambda x: x.sample(n))
Don't use frac that will give your a fraction of each group, but n that will give you a fixed value per group:
df.groupby('Sex').sample(n=2)
example output:
F1 F2 Sex
2 x3 a3 F
0 x1 a1 F
3 x4 a4 M
4 x5 a5 M
using a custom ratio
ratios = {'F':0.4, 'M':0.6} # sum should be 1
# total number desired
total = 4
# note that the exact number in the output depends
# on the rounding method to convert to int
# round should give the correct number but floor/ceil might
# under/over-sample
# see below for an example
s = pd.Series(ratios)*total
# convert to integer (chose your method, ceil/floor/round...)
s = np.ceil(s).astype(int)
df.groupby('Sex').apply(lambda x: x.sample(n=s[x.name])).droplevel(0)
example output:
F1 F2 Sex
0 x1 a1 F
6 x7 a7 F
4 x5 a5 M
3 x4 a4 M
1 x2 a2 M

Solve nonlinear equations with sympy, but i got results with a small imaginary part

I am trying to solve a system of nonlinear equations with Sympy and Python.
The result is almost right, but always with a extremly small imaginary part, and the process is time consuming.
I also try the same computation under Matlab, the result is pretty good and fast.
I know that small imaginary part can be ignored. But I think there must be something wrong in my code which result in slowly and imaginary part. Can any one help me with this?
Python:3.6
Sympy:1.1.1
import sympy
A1, B1, C1, D1, E1, F1 = (0.0019047619047619048,
-1.7494954273533616e-19,
0.0004761904761904762,
-8.747477136766808e-18,
0.047619047619047616,
1.0)
A2, B2, C2, D2, E2, F2 = (8.264462809917356e-05,
-0.0,
0.00033057851239669424,
-0.008264462809917356,
-0.03305785123966942,
1.0)
k, b = sympy.symbols('k b')
eq1 = B1 ** 2 * b ** 2 + 2 * B1 * D1 * b - 2 * B1 * E1 * b * k - 4 * F1 * B1 * k + D1 ** 2 + 2 * D1 * E1 * k + \
4 * C1 * D1 * b * k + E1 ** 2 * k ** 2 - 4 * A1 * E1 * b - 4 * A1 * C1 * b ** 2 - 4 * C1 * F1 * k ** 2 - 4 * A1 * F1
eq2 = B2 ** 2 * b ** 2 + 2 * B2 * D2 * b - 2 * B2 * E2 * b * k - 4 * F2 * B2 * k + D2 ** 2 + 2 * D2 * E2 * k + \
4 * C2 * D2 * b * k + E2 ** 2 * k ** 2 - 4 * A2 * E2 * b - 4 * A2 * C2 * b ** 2 - 4 * C2 * F2 * k ** 2 - 4 * A2 * F2
s=sympy.solve([eq1,eq2],[k,b])
print(s)
That's what I got under Python and Sympy, with an extremely small imaginary part. And it almost takes 10 seconds. That is not acceptable for my whole project.
[(1.07269682322063 + 2.8315655624133e-28*I, -27.3048937553762 + 0.e-27*I),
(1.79271658724978 - 2.83156477591471e-28*I, -76.8585791921325 - 0.e-27*I),
(2.34194482854222 + 2.83156702952074e-28*I, -19.2027508047623 - 0.e-26*I),
(5.20930842765403 - 2.83156580622397e-28*I, -105.800442914396 - 7.59430998293648e-28*I)]
That's what I got under MATLAB with 'solve'. It's pretty fast. That's what I wanted.
k =
5.2093
1.7927
1.0727
2.3419
b =
-105.8
-76.859
-27.305
-19.203
SymPy intends to be a symbolic package, not numeric, so the results should be expected. There is, however, the function nsolve that can be used to find numerical solutions. There is no dedicated method (that I am aware of) that will compute all roots of a polynomial -- in this case, a pair of quadratics -- in SymPy/mpmath. You would have to find roots one by one:
>>> list(nsolve((eq1, eq2), (k,b), (1, 1)))
[1.07269682322063, -27.3048937553762]
But one can use the existing tools to build a solver for such equations. The following is an example (with the potential for lots of numerical issues in corner cases):
def n2solve(eq1, eq2, x, y, n):
"""Return numerical solutions for 2 equations in
x and y where each is polynomial of order 2 or less
as would be true for equations describing geometrical
objects.
Examples
========
>>> n2solve(x**2 + y, y**2 - 3*x*y + 4, x, y, 3)
(-2.82, -7.96)
(-1.34, -1.80)
"""
from sympy.core.containers import Tuple
from sympy.solvers.solvers import unrad, solve
eqs = Tuple(eq1, eq2)
sym = set([x, y])
assert all(i.free_symbols == sym for i in eqs)
anx = solve(eq1, x)[0]
yeq = eq2.subs(x, anx)
z = unrad(yeq)
z = z[0] if z else yeq
yy = real_roots(z)
def norm(x,y):
return abs((x**2+y**2).n(2))
got=[]
for yi in yy:
yi = yi.n(n)
ty = eqs.subs(y, yi)
for xi in real_roots(ty[0]):
xi = xi.n(n)
got.append((norm(*ty.subs(x, xi)), xi, yi))
return sorted([(x,y) for e,x,y in sorted(got)[:len(got)//2]])
This gives the following solutions for the equations posed in the question:
[(1.07, -27.3),
(1.79, -76.9),
(2.34, -19.2),
(5.21, -106.)]

Custom function + groupby Pandas with different conditions on grouped by variables

I want to generate some weights using groupby on a data that originally looks like this :
V1 V2 MONTH CHOICES PRIORITY
X T1 M1 C1 1
X T1 M1 C2 0
X T1 M1 C3 0
X T2 M1 C1 1
X T2 M1 C5 0
X T2 M1 C6 0
X T2 M1 C2 1
X T1 M2 C1 1
X T1 M2 C2 0
X T1 M2 C3 0
X T2 M2 C1 0
X T2 M2 C5 1
X T2 M2 C6 0
X T2 M2 C2 1
Basically, when the MONTH is different than M1, I want to have flagged choices with weights equal to double any non flagged choice.
Example : if you have (C1, C2, C3) and C1 is the only one flagged, weights would be : 0.5 / 0.25 / 0.25.
On the same time, for the first month, I want the weights to be solely focused on flagged choices. Previous example would become (1/0/0).
Precision about the data :
For a given tuple (V1,V2,MONTH), we can have at most two choices flagged as priorities (no priority at all is a possibility).
Here's what I've tried :
def weights_preferences(data):
if (data.MONTH.values != 'M1'):
data['WEIGHTS'] = 1/(len(data)+data[data.PRIORITY==1].shape[0])
data['WEIGHTS'] = data.apply(lambda x : 2*x.WEIGHTS if x.PRIORITY==1 else x.WEIGHTS, axis=1)
elif data.MONTH.values == 'M1' & data[data.PRIORITY==1].shape[0]==0 :
data['WEIGHTS'] = 1/(len(data))
else :
if data[data.PREFERENCE==1].shape[0]==1 :
data['WEIGHTS'] = [1 if x[1].PRIORITY==1 else 0 for x in data.iterrows()]
else :
data['WEIGHTS'] = [0.5 if x[1].PRIORITY==1 else 0 for x in data.iterrows()]
return data
tmp = tmp.groupby(['V1','V2','MONTH']).apply(weights_preferences)
The problem is that since I groupby 'MONTH', it seems that the value no longer appears in data on which 'weights_preferences' is applied.
P.S : Output would look like this
V1 V2 MONTH CHOICES PRIORITY WEIGHTS
X T1 M1 C1 1 1
X T1 M1 C2 0 0
X T1 M1 C3 0 0
X T2 M1 C1 1 0.5
X T2 M1 C5 0 0
X T2 M1 C6 0 0
X T2 M1 C2 1 0.5
X T1 M2 C1 1 0.5
X T1 M2 C2 0 0.25
X T1 M2 C3 0 0.25
X T2 M2 C1 0 0.16
X T2 M2 C5 1 0.33
X T2 M2 C6 0 0.16
X T2 M2 C2 1 0.33
Any suggestions are very welcomed !
Thanks.

Print list-matrix combination

I am trying to print a combination of np.array values, a string and and some values I get from an iterator.
The code looks like this:
import numpy as np
site = np.genfromtxt('.....\Plot_1.txt', dtype=None, delimiter='\t')
c1 = np.array([148, 108])
c2 = np.array([181, 147])
c3 = np.array([173, 153])
c4 = np.array([98, 221])
c5 = np.array([43, 153])
trees_list = [c1, c2, c3, c4, c5]
def trees_pixel(rc_list, matrix):
t_row = rc_list[0]
t_col = rc_list[1]
tree = matrix[t_row, t_col]
for i in range(1, 6, 1):
print "C",i,"=",tree
return tree
for i in trees_list:
trees_pixel(i, site)
Site is a np.array of 400x370 row/columns, that I need to read the values from. C1...C5 are the locations (row/column) from the 'site' array.
My code prints the following:
C 1 = 8.266602
C 2 = 8.266602
C 3 = 8.266602
C 4 = 8.266602
C 5 = 8.266602
C 1 = 17.89282
C 2 = 17.89282
C 3 = 17.89282
C 4 = 17.89282
C 5 = 17.89282
C 1 = 18.31433
C 2 = 18.31433
C 3 = 18.31433
C 4 = 18.31433
C 5 = 18.31433
etc...
But what I expected was:
C 1 = 8.266602
C 2 = 17.89282
C 3 = 18.31433
C 4 = 20.47229
C 5 = 13.5907
How can I do this, so I will avoid the repeating pattern? Thanks!
You're iterating twice, once inside trees_pixel and once outside of it. If I understand what you mean, you want something that looks like the following:
import numpy as np
site = np.random.random((400, 370)) # Used in place of your data
c1 = np.array([148, 108])
c2 = np.array([181, 147])
c3 = np.array([173, 153])
c4 = np.array([98, 221])
c5 = np.array([43, 153])
trees_list = [c1, c2, c3, c4, c5]
def trees_pixel(rc_list, listIdx, matrix):
t_row = rc_list[0]
t_col = rc_list[1]
tree = matrix[t_row, t_col]
print "C",listIdx,"=",tree
return tree
for i in xrange(len(trees_list)):
trees_pixel(trees_list[i], i+1, site)
C 1 = 0.820317259854
C 2 = 0.960883528796
C 3 = 0.363985436225
C 4 = 0.189575015844
C 5 = 0.667578060856

Categories

Resources