问题描述
ict |constraint1|constraint2|
float(x) | y | z |
我在数据框中有480行,当前按ict
排序。我需要找到11个元素的ict
的最大可能总和,然后检查该集合是否满足条件(例如constraint1
只能等于b
少于5倍)。如果不符合条件,我需要找到11个元素中ict
的下一个最大和。
我目前有一个函数check_ict(list1)
,它检查作为数据帧行索引列表输入的11个元素中的ict
。我还有一个函数check_constraints(list1)
,用于检查同一输入是否满足约束条件。但是,我正在努力寻找如何找到“ ict
s的下一个最大和”。
由于数据已经按ict
进行排序,因此我知道最好的组合是数据帧的第0-10行。下一个最佳组合是第0-9行+第11行。但是之后,事情变得棘手。没有明显的方法可以知道[0,1,2,3,4,5,6,7,8,9,12]
是更大还是[0,10,11]
。而且没有明显的方法知道那之后最大的是什么。
我如何不断寻找下一个最佳组合? 10^21
可能包含480个元素中的11个元素的组合,因此绝对不能使用强行强制。
解决方法
如评论中所述,使用数学优化来解决此问题。如果可能,在约束可以写为线性的条件下,线性优化是数学优化的简单子集。在这种情况下,像pulp
这样的软件包可能会为您提供帮助。
一些示例代码:
import numpy as np
import pandas as pd
import pulp as pl
# Generate some data
np.random.seed(42)
n_rows = 20
constraint1_capacities = {
'a': 3,'b': 20,'c': 5
}
constraint2_capacities = {
'x': 5,'y': 10,'z': 15
}
df = pd.DataFrame({
'ict': np.random.rand(n_rows),'constraint1': np.random.choice(list(constraint1_capacities),n_rows),'constraint2': np.random.choice(list(constraint2_capacities),})
print(df)
# Solve the actual problem
take_best = 11
# Create variables: x_i denotes that the i'th element is included,we create
# one for each row in the dataframe
x = [pl.LpVariable(f"x_{i:02}",cat=pl.LpBinary) for i in range(len(df))]
# Initialise the problem
problem = pl.LpProblem("choices",pl.LpMaximize)
# Define the objective function as the sum of all x_i * ict_i
problem += pl.lpSum(x * df.ict.values)
# Constraints:
# In total,at most `take_best` rows can be taken:
problem += pl.lpSum(x) <= take_best
for key,_max in constraint1_capacities.items():
# x_i * constraint1_i <= _max for every potential key
problem += pl.lpSum(x * (df.constraint1 == key).values) <= _max
for key,_max in constraint2_capacities.items():
# x_i * constraint2_i <= _max for every potential key
problem += pl.lpSum(x * (df.constraint2 == key).values) <= _max
problem.solve()
print(pl.LpStatus[problem.status])
print("Choose rows: ")
for v in problem.variables():
if v.varValue != 0:
print(v)
产生
Optimal
Choose rows:
x_01
x_02
x_03
x_07
x_08
x_09
x_11
x_12
x_16
x_18
x_19