你如何在Python中解决这个优化问题?

时间:2016-06-27 13:57:21

标签: python-2.7 optimization linear

我是Python的新手,希望使用SciPy解决以下问题,但不知道哪种方法是最好的方法。我已经看过这个论坛,找不到类似我遇到的问题。

我有以下销售数据: Sales Data 2016

此数据总结了不同地点的各种销售人员的表现,目的是根据销售数据分配奖金分配(x1-x8),但有以下限制:

奖金分配总和CMakeLists.txt

最高奖金分配(x1 to x8) = 100%

按地点<=10% of total分配的最高额外奖金。

非常感谢。感谢。

1 个答案:

答案 0 :(得分:0)

如果您需要使用优化方法,可以使用scipy.minimize,特别是'SLSQP'方法。这是一种受约束的,基于梯度的最小化算法。

请注意,scipy.minimise只是scipy.fmin_slsqp方法的包装。

问题定义

优化的第一步是确定设计变量目标函数约束。虽然你的约束条件很明确,但其他两个不太明显。

您尚未指定目标函数的方向。我认为这是为了最大化所有员工分配的奖金百分比。

对于设计变量,您有8名员工,并且能够为每个人分配单独的x奖金。虽然您可以使用8个设计变量,但您声明这些应该与每个员工达到的销售数量相关,因此使用单个设计变量可能更有意义,该变量用作销售数量的乘数:

# Design variable
x = 1

# Sales info
sales_list = [10, 2, 4, 15, 8, 7, 12, 1]

# Calculate x1 - x8
for index, entry in enumerate(sales_list):
    print 'x' + str(index) + ': ' + str(entry * x)

目标函数

Scipy.minimize需要一个最小化的函数。在您的情况下,仅使用一个设计变量,整体目标函数将在满足约束条件的同时最大化x0。要将最大化切换为最小化问题,您可以return -result

它还需要你的目标函数的梯度,它也必须被公式化以给出-result的渐变。

约束

您现在需要构造表示约束的函数。约束被输入为表示每个约束的字典元组。字典以下列形式构建:

{'type': 'ineq', 'fun': const_func, 'jac': const_func_grad, 'args': (m, n, ..)}

来自scipy文档:

  

等式约束意味着约束函数结果为零,而不等式意味着它是非负的。

因此,对于您的所有情况,您都希望使用&#39; ineq&#39;并设置函数,然后在满足时返回值> = 0.0。您的位置fun功能及其jac功能如下所示:

def loc_a_const(x):
    return 25 - (x * sales_list[0] + x * sales_list[5])

def loc_a_grad(x):
    return - sales_list[0] - sales_list[5]

请注意,loc_a_grad并未使用x,但SLSQP方法会尝试将相同数量的args传递给两个函数。

旁注

在没有优化方法的情况下写出问题很简单,而是有一个初始猜测,并为每个约束返回true。我发现唯一有效的非零整数值是x = 1。如果您需要解决方案而不是工具,可以使用反复试验找到几个小数位的解决方案。

工作示例

import scipy.optimize as opt

sales_list = [10, 2, 4, 15, 8, 7, 12, 1]

# Function and gradient
def func(x):
    return - x

def func_prime(x):
    return - 1

# Constraints
def loc_a_const(x):
    return 25 - (x * sales_list[0] + x * sales_list[5])

def loc_a_const_grad(x):
    return - sales_list[0] - sales_list[5]

def loc_b_const(x):
    return 25 - (x * sales_list[1] + x * sales_list[2] + x * sales_list[6])

def loc_b_const_grad(x):
    return - sales_list[1] - sales_list[2] - sales_list[6]

def loc_c_const(x):
    return 25 - (x * sales_list[3] + x * sales_list[4] + x * sales_list[7])

def loc_c_const_grad(x):
    return - sales_list[3] - sales_list[4] - sales_list[7]

loc_a_dict = {'type': 'ineq', 'fun': loc_a_const, 'jac': loc_a_const_grad}
loc_b_dict = {'type': 'ineq', 'fun': loc_b_const, 'jac': loc_b_const_grad}
loc_c_dict = {'type': 'ineq', 'fun': loc_c_const, 'jac': loc_c_const_grad}

# Initial guess
x0 = 1

results = opt.minimize(
            fun=func,
            x0=x0,
            method='SLSQP',
            jac=func_prime,
            constraints=(loc_a_dict, loc_b_dict, loc_c_dict))

print results