I would like to minimize an objective function which I calculate based on variables A, B1, B2, B3, B4 coming from 4 Centers.
My (simplified) dataset looks like follows:
Center1 Center2 Center3 Center4
A 10.0000 10.0000 10.0000 10.0000
B1 0.8415 0.9547 0.9460 0.9512
B2 0.9895 0.9443 0.9042 0.9634
B3 0.9460 0.9443 0.8101 0.9199
B4 0.9878 0.8362 0.9233 0.7909
I know how to find the vector of weights x that minimizes this objective function simply using scipy.optimize.linprog
import numpy as np
from scipy.optimize import linprog
from numpy.linalg import multi_dot as dot
import pandas as pd
# minimise the costs across A and B variables in the 4 centres.
df = pd.DataFrame(np.array([[10, 10, 10, 10],
[0.8415, 0.9547, 0.9460, 0.9512],
[0.9895, 0.9443, 0.9042, 0.9634],
[0.9460, 0.9443, 0.8101, 0.9199],
[0.9878, 0.8362, 0.9233, 0.7909]]),
columns=['Center1', 'Center2', 'Center3', 'Center4'],
index=['A', 'B1', 'B2', 'B3', 'B4'])
# to reduce df (2-D array) to a 1-D array
lamb = np.array([0.1, 1, 1, 1, 1])
bounds = list(zip([-3, -3, -3, -3], [3, 3, 3, 3]))
A= None
b=None
c = dot([lamb,df.values]).squeeze()
res3 = linprog(c=c, A_ub=A, b_ub=b, bounds=bounds,
options={"disp": True})
# Solution vector of weights x
x = res3.x
My question is, I want to penalize the max difference between B1.x, B2.x, B3.x, B4.x. In other words, at the end of the optimization, I want the solution set x that results in the least absolute deviations in set B1.x, B2.x, B3.x, B4.x.
>>df.loc[['B1', 'B2', 'B3', 'B4'],:].dot(x)
Out[24]:
B1 -11.0802
B2 -11.4042
B3 -10.8609
B4 -10.6146
dtype: float64
I can calculate the pairwise differences between all pairs of Bi,Bj as follows, since I want the maximum differences for each pair I look at both Bi-Bj and Bj-Bi.
# pairwise differences
constraints = {'b1_b2' : df.loc['B1']-df.loc['B2'],
'b1_b3' : df.loc['B1']-df.loc['B3'],
'b1_b4' : df.loc['B1']-df.loc['B4'],
'b2_b3' : df.loc['B2']-df.loc['B3'],
'b2_b4' : df.loc['B2']-df.loc['B4'],
'b3_b4' : df.loc['B3']-df.loc['B4']}
const_df = pd.DataFrame(constraints)
A = pd.concat([const_df, -1*const_df], axis=1).T
b = np.array([1]*12) # the 1's here are arbitrary place holders.
res4 = linprog(c=c, A_ub=A, b_ub=b, bounds=bounds,
options={"disp": True})
The code above runs but I do not quite get how to include slack variables that penalise the max() of these pairwise differences in A, which are currently just in Ax<=b constraint form. I am aware Linear Programming can be used to solve the absolute deviation problem. I would appreciate greatly if anyone can provide some direction / simple code.
(B1-B2), (B1-B3),...and including slack variables and a maximum deviation variable. So solving this while remaining within LP. I just do not know how to formulate it exactly.B1.x, B2.x, B3.x, B4.x.