我尝试从 Dataframe 中选择一个行子集,以满足某些约束条件,同时最大化目标。这是我目前所拥有的:
import pandas as pd
import numpy as np
from scipy.optimize import minimize
df = pd.DataFrame({'a': np.random.randint(0, 100, size=100),
'b': np.random.randint(0, 100, size=100),
'c': np.random.randint(0, 10, size=100),
'd': np.random.randint(0, 5, size=100)})
# constraint functions
def a_constraint(x0, df):
return 1000 - df[x0].a.sum()
def c_constraint(x0, df):
return 3 - df[x0].c.value_counts().max()
def d_constraint(x0, df):
return 3 - df[(x0) & (df.d == 1)].shape[0]
def n_constraint(x0, df):
return 15 - df[x0].shape[0]
# objective function
def objective(x0, df):
return -df[x0].b.sum()
# initial guess
x0 = np.full((df.shape[0]), True, dtype=bool)
# optimization connstraints as list of dicts
constraints = [{'type': 'ineq', 'fun': a_constraint, 'args': (df,)},
{'type': 'ineq', 'fun': d_constraint, 'args': (df,)},
{'type': 'eq', 'fun': c_constraint, 'args': (df,)},
{'type': 'eq', 'fun': n_constraint, 'args': (df,)},
]
result = minimize(objective, x0=x0, method='SLSQP', args=(df,), constraints=constraints)
然而,我得到了一个KeyError。看起来它把我的布尔数组当作列标签而不是索引掩码。有人能告诉我哪里出错了吗?
为了回应下面hpaulj的评论,回溯为:
KeyError Traceback (most recent call last)
d:\Users\github\fpl\fpl_stackoverflow.py in <module>
38 ]
39
---> 40 result = minimize(objective, x0=x0, method='SLSQP', args=(df,), constraints=constraints)
d:\Users\.conda\envs\test_env\lib\site-packages\scipy\optimize\_minimize.py in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
626 elif meth == 'slsqp':
627 return _minimize_slsqp(fun, x0, args, jac, bounds,
--> 628 constraints, callback=callback,**options)
629 elif meth == 'trust-constr':
630 return _minimize_trustregion_constr(fun, x0, args, jac, hess, hessp,
d:\Users\.conda\envs\test_env\lib\site-packages\scipy\optimize\slsqp.py in _minimize_slsqp(func, x0, args, jac, bounds, constraints, maxiter, ftol, iprint, disp, eps, callback, finite_diff_rel_step,**unknown_options)
327 # meq, mieq: number of equality and inequality constraints
328 meq = sum(map(len, [atleast_1d(c['fun'](x, *c['args']))
--> 329 for c in cons['eq']]))
330 mieq = sum(map(len, [atleast_1d(c['fun'](x, *c['args']))
331 for c in cons['ineq']]))
d:\Users\.conda\envs\test_env\lib\site-packages\scipy\optimize\slsqp.py in <listcomp>(.0)
327 # meq, mieq: number of equality and inequality constraints
328 meq = sum(map(len, [atleast_1d(c['fun'](x, *c['args']))
--> 329 for c in cons['eq']]))
...
-> 1308 raise KeyError(f"None of [{key}] are in the [{axis_name}]")
1309
1310 ax = self.obj._get_axis(axis)
KeyError: "None of [Float64Index([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,\n 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,\n 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,\n 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,\n 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,\n 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,\n 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,\n 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],\n dtype='float64')] are in the [columns]"
该错误在目标函数中的print(x0)
之前抛出。
1条答案
按热度按时间sh7euo9m1#
首先,只有当你能保证
x0
总是整数或布尔值dtype
时,你的公式才有效。因为scipy.optimize.minimize
是针对连续优化问题的,所以它使用浮点数dtype
作为当前迭代x
的底层,所以第一次迭代已经失败了。也就是说,你的约束条件不是连续可微的,因此违反了底层算法的数学假设。简而言之,您尝试使用连续优化问题的求解器来解决离散优化问题。将您的问题公式化为离散优化问题是一种更方便的方法。python-mip中可能的公式化和实现如下所示: