关于#python#的问题:gurobipy求解篮球球员上场优化

假设有一个30人阵容,对阵容中的球员进行分类,分为五个位置,分别为PG,SG,PF,SF,C,要求每个位置选两个人,分别作为首发和替补。
每个球员有十个能力值分类,分别为篮板、运动、突破、篮下、背身、中投、三分、组织、内防、外防和整体评估。这11个能力值又可组成4个进攻战术倾向和4个防守战术倾向。
定义进攻战术倾向和防守战术倾向:
进攻战术倾向:
主打内线=突破+篮下+背身
外线为主=三分+中投
快攻优先=组织+运动
篮板优先=篮板
防守战术倾向:
主防内线=内防
主防外线=外防
回防优先=运动
篮板优先=篮板
首先,我们会根据经验人为对对手的惯用战术做出假设,然后确定各个战术倾向所对应能力值的权重,这样就可计算每个球员的“该战术下最终能力值”,最后找到“该战术下最终能力值”总和最高的10人阵容最优解。
定义“该战术下最终能力值”:在权重赋予规则下,球员各战术倾向的能力值乘其权重的和。
赋予权重规则:整体评估能力值不算入战术倾向,单独占20%,进攻战术倾向和防守战术倾向各占40%。其中进攻战术倾向和防守战术倾向40%的具体分配方法根据当前的对手情况人为确定,需要作为输入的值,比如主打内线占5%,外线为主占15%,快攻优先占5%,篮板优先占15%,主防内线占5%,主防外线占15%,回防优先占5%篮板优先占15%

最后,从30人中找到一个10人名单,要求首发的球员在该权重和该位置上的能力值最高,替补第二,并输出各个位置首发和替补的人选。

from gurobipy import Model, GRB
import pandas as pd
# 读取数据
data = pd.read_excel('players_data1.xlsx')

# 定义战术变量
data['主打内线'] = data['突破'] + data['篮下'] + data['背身']
data['外线为主'] = data['三分'] + data['中投']
data['快攻优先'] = data['组织'] + data['运动']
data['进攻篮板优先'] = data['篮板']
data['主防内线'] = data['内防']
data['主防外线'] = data['外防']
data['回防优先'] = data['运动']
data['防守篮板优先'] = data['篮板']
def get_weights():
    # 定义权重
    weights = {'综合能力': 0.2}

    # 获取用户输入的权重值
    for ability in ['主打内线', '外线为主', '快攻优先', '进攻篮板优先', '主防内线', '主防外线', '回防优先','防守篮板优先']:
        weight = float(input(f'请输入{ability}的权重:'))
        weights[ability] = weight

    # 检查权重值是否符合规则
    if sum(weights.values()) != 1:
        raise ValueError('权重值之和必须为1')
    if sum(weights[ability] for ability in ['主打内线', '外线为主', '快攻优先', '进攻篮板优先']) != 0.4:
        raise ValueError('主打内线+外线为主+快攻优先+篮板优先的权重之和必须为0.4')
    if sum(weights[ability] for ability in ['主防内线', '主防外线', '回防优先','防守篮板优先']) != 0.4:
        raise ValueError('主防内线+主防外线+回防优先的权重之和必须为0.4')

    return weights

# 获取用户输入的权重值
weights = get_weights()

# 计算每个球员的“该战术下最终能力值”
data['该战术下最终能力值'] = sum(data[ability] * weight for ability, weight in weights.items())


# 计算每个球员的“该战术下最终能力值”
data['该战术下最终能力值'] = sum(data[ability] * weight for ability, weight in weights.items())

# 使用Gurobi求解
m = Model()
vars = m.addVars(data.index, vtype=GRB.BINARY, name='x')
m.setObjective(sum(vars[i] * data.loc[i, '该战术下最终能力值'] for i in data.index), GRB.MAXIMIZE)

# 添加约束条件
m.addConstr(sum(vars[i] for i in data.index) == 10, name='c1')
for position in ['PG', 'SG', 'PF', 'SF', 'C']:[]([]())
    m.addConstr(sum(vars[i] for i in data[data['位置'] == position].index) == 2, name=f'c_{position}')

m.optimize()

# 输出结果
selected_players = data[data.index.isin([int(v.varName[2:-1]) for v in m.getVars() if v.x == 1])]
grouped = selected_players.groupby('位置')['球员']
for position, players in grouped:
    print(f'{position}: {", ".join(players)}')

这是我原本设计的题目和代码,但是我发现代码并没有完全按照我的要求再选人,而且觉得数学模型太简单了,想这样改进:我现在希望进一步完善我解决的问题,我希望将优化的最终目的不只是按该战术下最终能力值选出首发替补,而且要求计算他们的上场时间。现在已知一场比赛有16分钟,首发和替补至少都上场一分钟,且首发的上场时间要大于替补,随着时间的推进,球员的体力将会不断下滑,进而导致该状态下最终能力值下降。还有个问题需要解决,我会在数据中新增一列体力值的数据,都在100左右波动,进而区分不同球员的体力情况,如何体现出不同球员的体力值差异对其上场时间的影响,如何定义体力值对该战术下最终能力值的影响呢?请你帮我确定一个模型,并给出解决这个问题的代码,确定首发和替补的上场时间,使得个位置的首发加替补的出场时间为16分钟,且在该上场时间条件下该战术下最终能力值的和最大。但是发现这个可能需要用到变量之间相乘,gurobi跑不了,请问我该怎么办