约束线性优化设置
Constrained Linear Optimization Setup
我正在为以下设置而苦苦挣扎。
我的数据如下:
Group ID Wt Coeff Coeff*Wt
------ --- ------ ------- -------
Group1 A 10.00% 1.00000 0.100
Group1 B 10.00% 1.00000 0.100
Group1 C 10.00% 3.00005 0.300
Group2 D 10.00% 1.00000 0.100
Group2 E 10.00% 1.00000 0.100
Group2 F 10.00% 1.00000 0.100
Group2 G 10.00% 7.80016 0.780
Group3 H 10.00% 7.80485 0.780
Group3 I 10.00% 1.00000 0.100
Group3 J 10.00% 0.39529 0.040
Objective function: Fmin = mimimize(sum of weights * coeff)
我需要实施以下约束:
Sum of Weights*Coeff of Group1 = 20% of total minimized fmin
Sum of Weights*Coeff of Group1 = 45% of total minimized fmin
Sum of Weights*Coeff of Group1 = 35% of total minimized fmin
以及以下边界条件:
Weights <=10% and Weights > 0.30%
和
Sum of weights = 100%
我正在尝试使用以下代码完成此操作。
我不知道为什么这不起作用:
from scipy.optimize import linprog
c = [ 1.0000 ,1.0000 ,3.0001 ,1.0000 ,1.0000 ,1.0000 ,7.8002 ,7.8049 ,1.0000 ,0.3953 ]
groupPerID = ['Group1','Group1','Group1','Group2','Group2','Group2','Group2','Group3','Group3','Group3']
groupList = ['Group1','Group2','Group3']
groupUpperBound = [0.20,0.45,0.40]
A_eq_list = []
A_eq_list.append([1]*len(c))
b_eq_list = [1]
for idx,currentGroup in enumerate(groupList):
matches = [i for i in range(len(groupPerID)) if groupPerID[i] == currentGroup]
currentGroupUB = groupUpperBound[idx]
x_list = [float(-1*currentGroupUB*coeff) for coeff in c]
for idx in matches:
x_list[idx] = float((1-currentGroupUB)*c[idx])
A_eq_list.append(x_list)
b_eq_list.extend([0]*len(groupUpperBound))
res = linprog(c, A_eq=A_eq_list, b_eq=b_eq_list,bounds =(0.003,0.1),options={'tol':0.05})
print(res)
有人可以指出我犯了什么错误吗?
所以我在我的 scipy
包装器 symfit
中实现了它,它负责处理所有样板代码。它现在可以工作了,除了我还没有实现你对权重的限制。但是,我认为您的问题中所述是错误的,因为满足所有权重总和应为 1 的约束的唯一方法是将它们全部设置为 0.1 的上限。除此之外,这是我的尝试:
from symfit import parameters, Minimize, Variable, Eq
import numpy as np
# Make 10 weight parameters w_i to optimize
weights = parameters(','.join('w_{}'.format(i) for i in range(1, 11)))
c = np.array([1.0000, 1.0000, 3.0001, 1.0000, 1.0000, 1.0000, 7.8002, 7.8049, 1.0000, 0.3953])
f = Variable()
for w_i in weights:
w_i.min = 0.003
w_i.max = 1.0
w_i.value = 0.1
sum_of_group_1 = sum(c_i * w_i for c_i, w_i in zip(c, weights)[0:3])
sum_of_group_2 = sum(c_i * w_i for c_i, w_i in zip(c, weights)[3:7])
sum_of_group_3 = sum(c_i * w_i for c_i, w_i in zip(c, weights)[7:10])
# Function to minimize
model = {f: sum_of_group_1 + sum_of_group_2 + sum_of_group_3}
constraints = [
Eq(0.20 * sum_of_group_1, 0.45 * sum_of_group_2),
Eq(0.20 * sum_of_group_1, 0.35 * sum_of_group_3),
Eq(sum(weights), 1)
]
fit = Minimize(model, constraints=constraints)
fit.eval_jacobian = None # Workaround needed because f is just a scalar, not an array
fit_result = fit.execute()
print(fit_result)
print(sum(fit_result.value(w) for w in weights)) # >>> 1.0
您可以在文档中阅读更多内容 here。
我正在为以下设置而苦苦挣扎。
我的数据如下:
Group ID Wt Coeff Coeff*Wt
------ --- ------ ------- -------
Group1 A 10.00% 1.00000 0.100
Group1 B 10.00% 1.00000 0.100
Group1 C 10.00% 3.00005 0.300
Group2 D 10.00% 1.00000 0.100
Group2 E 10.00% 1.00000 0.100
Group2 F 10.00% 1.00000 0.100
Group2 G 10.00% 7.80016 0.780
Group3 H 10.00% 7.80485 0.780
Group3 I 10.00% 1.00000 0.100
Group3 J 10.00% 0.39529 0.040
Objective function: Fmin = mimimize(sum of weights * coeff)
我需要实施以下约束:
Sum of Weights*Coeff of Group1 = 20% of total minimized fmin
Sum of Weights*Coeff of Group1 = 45% of total minimized fmin
Sum of Weights*Coeff of Group1 = 35% of total minimized fmin
以及以下边界条件:
Weights <=10% and Weights > 0.30%
和
Sum of weights = 100%
我正在尝试使用以下代码完成此操作。
我不知道为什么这不起作用:
from scipy.optimize import linprog
c = [ 1.0000 ,1.0000 ,3.0001 ,1.0000 ,1.0000 ,1.0000 ,7.8002 ,7.8049 ,1.0000 ,0.3953 ]
groupPerID = ['Group1','Group1','Group1','Group2','Group2','Group2','Group2','Group3','Group3','Group3']
groupList = ['Group1','Group2','Group3']
groupUpperBound = [0.20,0.45,0.40]
A_eq_list = []
A_eq_list.append([1]*len(c))
b_eq_list = [1]
for idx,currentGroup in enumerate(groupList):
matches = [i for i in range(len(groupPerID)) if groupPerID[i] == currentGroup]
currentGroupUB = groupUpperBound[idx]
x_list = [float(-1*currentGroupUB*coeff) for coeff in c]
for idx in matches:
x_list[idx] = float((1-currentGroupUB)*c[idx])
A_eq_list.append(x_list)
b_eq_list.extend([0]*len(groupUpperBound))
res = linprog(c, A_eq=A_eq_list, b_eq=b_eq_list,bounds =(0.003,0.1),options={'tol':0.05})
print(res)
有人可以指出我犯了什么错误吗?
所以我在我的 scipy
包装器 symfit
中实现了它,它负责处理所有样板代码。它现在可以工作了,除了我还没有实现你对权重的限制。但是,我认为您的问题中所述是错误的,因为满足所有权重总和应为 1 的约束的唯一方法是将它们全部设置为 0.1 的上限。除此之外,这是我的尝试:
from symfit import parameters, Minimize, Variable, Eq
import numpy as np
# Make 10 weight parameters w_i to optimize
weights = parameters(','.join('w_{}'.format(i) for i in range(1, 11)))
c = np.array([1.0000, 1.0000, 3.0001, 1.0000, 1.0000, 1.0000, 7.8002, 7.8049, 1.0000, 0.3953])
f = Variable()
for w_i in weights:
w_i.min = 0.003
w_i.max = 1.0
w_i.value = 0.1
sum_of_group_1 = sum(c_i * w_i for c_i, w_i in zip(c, weights)[0:3])
sum_of_group_2 = sum(c_i * w_i for c_i, w_i in zip(c, weights)[3:7])
sum_of_group_3 = sum(c_i * w_i for c_i, w_i in zip(c, weights)[7:10])
# Function to minimize
model = {f: sum_of_group_1 + sum_of_group_2 + sum_of_group_3}
constraints = [
Eq(0.20 * sum_of_group_1, 0.45 * sum_of_group_2),
Eq(0.20 * sum_of_group_1, 0.35 * sum_of_group_3),
Eq(sum(weights), 1)
]
fit = Minimize(model, constraints=constraints)
fit.eval_jacobian = None # Workaround needed because f is just a scalar, not an array
fit_result = fit.execute()
print(fit_result)
print(sum(fit_result.value(w) for w in weights)) # >>> 1.0
您可以在文档中阅读更多内容 here。