我有一个技能水平和工资的列表,并试图选择最佳的2个选择,以最大限度地提高技能,同时保持在总工资。使用scipy.optimize.minimize
,我可以通过以下代码获得最佳选择:
import numpy as np
from scipy.optimize import minimize
# Define the individuals' skill levels and salaries
skill_levels = np.array([7, 13, 5, 1, 11])
salaries = np.array([15, 8, 9, 12, 10])
# Objective function for maximizing total skill level
def objective(selection):
return -np.sum(skill_levels * selection)
# Total salary constraint (no more than $20)
def salary_constraint(selection):
return 20 - np.sum(salaries * selection)
# Number of players selected constraint (select exactly 2 players)
def num_selection_constraint(selection):
return np.sum(selection) - 2
# Bounds are either 1 or 0 (selected or not-selected)
bounds = [(0, 1)] * len(skill_levels)
# Set the constraints based on the above functions
constraints = [
{'type': 'ineq', 'fun': salary_constraint},
{'type': 'eq', 'fun': num_selection_constraint}
]
# Start by guessing the first 2 people
x0 = np.zeros(len(skill_levels))
x0[:2] = 1
# Plug into minimize function
result = minimize(objective, x0, method='SLSQP', bounds=bounds, constraints=constraints)
# Retrieve the optimal solution
optimal_selection = result.x
selected_indices = np.where(optimal_selection > 0.5)[0]
selected_indices
"""Returns
array([1, 4])
"""
字符串
我现在正在寻找下一个 n 最好的独特选择。
- 我尝试过跟踪之前的每个选择并将其添加到约束中,但这会成倍地增加运行时间,并且无法按预期工作:
def repeat_selection_constraint(selection, iter):
return 5 - selection * prev_selection[iter]
# Initialize previous selection
prev_selection = np.zeros((num_selections, len(skill_levels)))
for i in range(num_selections):
# Define the constraints
constraints = [
{'type': 'ineq', 'fun': salary_constraint},
{'type': 'eq', 'fun': num_selection_constraint},
*[{'type': 'ineq', 'fun': lambda x: repeat_selection_constraint(x, lup)} for lup in range(i+1)]
]
型
- 我还考虑过使用
itertools.combinations
检索所有组合,并对每个组合运行scipy.optimize.minimize
,但这也是时间限制。
**注意:**我的实际用例比这个示例大得多;因此,我对这个问题的一个优雅的解决方案很感兴趣,它可以合理地扩展到10^3人。
1条答案
按热度按时间68bkxrlz1#
一个单一的线性规划是做不到的,因为你需要多个解决方案。
如果你的参与者变量少于(比如)30个,你可以做迭代LP,你把每个参与者的二进制赋值放在一个2幂的点积中,以产生一个规范顺序数字,逐步缩小规范顺序约束,以搜索更多的顺序答案。然而,对于高变量计数,这将遇到精度问题并停止工作。
这里是仍然使用迭代LP的解决方案。我最初猜测内部解搜索可以使用常用的丢番图求解器,但它不能,因为变量是有界的(二进制)。相反,我展示了一种方法,其中内部增量是二分搜索。请彻底测试这个,因为我没有。
字符串
与原始数据一起输出
型
使用this输出的代码中显示的较大数组来测试
型
n=20个记录。我没有非常小心的微优化,特别是围绕重复的东西,以便可以得到更快。
混音
对于1,000个玩家或更少的玩家来说,经历所有平分搜索对等麻烦没有多大意义。更改设计,使工资和技能矩阵保持为广播总和(对于旁边的1000个元素,每个仍然只占用4 MB的数量级)。并为LP添加第二个循环级别,以便它自然地优化技能第一,工资第二。这种方法要求技能和天赋都有独立的步骤。