使用 scipy.optimize.linprog 的权重中间范围(单纯形算法)
Weight Middle Range for use of scipy.optimize.linprog (Simplex algorithm)
基本问题给出这些约束(这是一个简单的例子,我的用例遵循相同的格式但可以引入更多变量):
x + y = C1
C2 <= x <= C3
C4 <= y <= C5
(其中CX为常量,x、y为变量),求解。
使用 scipy.optimize.linprog
非常简单。我能够得到技术上正确的结果。
例子。使用这些特定约束:
x + y = 50
5 <= x <= 65
10 <= y <= 40
我们得到:
>>> res = scipy.optimize.linprog([1,1], bounds=([5, 65], [10, 40]), A_eq=[[1,1]], b_eq=[50] )
>>> res.x
array([ 40., 10.])
这在技术上是正确的。请注意,第二个变量处于最小值。但是由于商业原因,我们更喜欢 "fair" 如果可能的话每个变量都超过它的最小值,更多的是(但不一定相同):
array([ 25., 25.])
所以我一直在考虑加权中点。我如何使用此 scipy.optimize.linprog
api(或其他一些 scipy 优化 api)来修改正在最小化的函数,以便它将更高的优先级赋予更接近中点的值每个变量范围?
请将此答案作为草稿查看,以了解如何解决此类问题。这当然不是最好的方法,当然也不是解决此类问题的最有效算法。
这里的问题是,您可能无法将您的想法表达为平滑的线性目标函数。您需要某种距离测量,在平滑函数的情况下可能必须至少是二次的。
以下代码添加 x
向量范数的 L2
作为惩罚。这在这种情况下有所帮助,因为 L2 范数在其组件中是二次的,因此更喜欢所有组件都同样小,而不是一大一小。
from scipy.optimize import fmin_slsqp
# equality constraints as h(x) = 0
def h(x):
return x[0] + x[1] - 50
# inequality constraints as g(x) >= 0
def g(x):
return [
x[0] - 5,
-x[0] + 65,
x[1] - 10,
-x[1] + 40,
]
# target functions
f1 = lambda x: x[0] + x[1]
f2 = lambda x: x[0] + x[1] + sum(x**2)
结果:
x = fmin_slsqp(f1, (5,45), f_eqcons=h, f_ieqcons=g)
print(x)
输出:
Optimization terminated successfully. (Exit mode 0)
Current function value: 50.0
Iterations: 1
Function evaluations: 5
Gradient evaluations: 1
[ 10. 40.]
以及惩罚版本:
x = fmin_slsqp(f2, (5,45), f_eqcons=h, f_ieqcons=g)
print(x)
打印
Optimization terminated successfully. (Exit mode 0)
Current function value: 1300.0
Iterations: 3
Function evaluations: 12
Gradient evaluations: 3
[ 25. 25.]
基本问题给出这些约束(这是一个简单的例子,我的用例遵循相同的格式但可以引入更多变量):
x + y = C1
C2 <= x <= C3
C4 <= y <= C5
(其中CX为常量,x、y为变量),求解。
使用 scipy.optimize.linprog
非常简单。我能够得到技术上正确的结果。
例子。使用这些特定约束:
x + y = 50
5 <= x <= 65
10 <= y <= 40
我们得到:
>>> res = scipy.optimize.linprog([1,1], bounds=([5, 65], [10, 40]), A_eq=[[1,1]], b_eq=[50] )
>>> res.x
array([ 40., 10.])
这在技术上是正确的。请注意,第二个变量处于最小值。但是由于商业原因,我们更喜欢 "fair" 如果可能的话每个变量都超过它的最小值,更多的是(但不一定相同):
array([ 25., 25.])
所以我一直在考虑加权中点。我如何使用此 scipy.optimize.linprog
api(或其他一些 scipy 优化 api)来修改正在最小化的函数,以便它将更高的优先级赋予更接近中点的值每个变量范围?
请将此答案作为草稿查看,以了解如何解决此类问题。这当然不是最好的方法,当然也不是解决此类问题的最有效算法。
这里的问题是,您可能无法将您的想法表达为平滑的线性目标函数。您需要某种距离测量,在平滑函数的情况下可能必须至少是二次的。
以下代码添加 x
向量范数的 L2
作为惩罚。这在这种情况下有所帮助,因为 L2 范数在其组件中是二次的,因此更喜欢所有组件都同样小,而不是一大一小。
from scipy.optimize import fmin_slsqp
# equality constraints as h(x) = 0
def h(x):
return x[0] + x[1] - 50
# inequality constraints as g(x) >= 0
def g(x):
return [
x[0] - 5,
-x[0] + 65,
x[1] - 10,
-x[1] + 40,
]
# target functions
f1 = lambda x: x[0] + x[1]
f2 = lambda x: x[0] + x[1] + sum(x**2)
结果:
x = fmin_slsqp(f1, (5,45), f_eqcons=h, f_ieqcons=g)
print(x)
输出:
Optimization terminated successfully. (Exit mode 0)
Current function value: 50.0
Iterations: 1
Function evaluations: 5
Gradient evaluations: 1
[ 10. 40.]
以及惩罚版本:
x = fmin_slsqp(f2, (5,45), f_eqcons=h, f_ieqcons=g)
print(x)
打印
Optimization terminated successfully. (Exit mode 0)
Current function value: 1300.0
Iterations: 3
Function evaluations: 12
Gradient evaluations: 3
[ 25. 25.]