You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Pandas DataFrame集成到PuLP/Pyomo中作为约束实现成本最小化分配

解决Pandas DataFrame约束集成到PuLP的成本分配问题

我来帮你搞定这个把Pandas数据转化为PuLP约束的问题!你的核心需求是根据零件和系统的属性规则,批量生成禁止分配的约束,咱们用Pandas的批量处理能力来实现,比嵌套循环更高效好维护。

第一步:批量标记合法的零件-系统分配对

首先,我们把零件表和系统表做笛卡尔积,这样能一次性处理所有可能的分配组合,然后给每个组合标记是否符合规则:

import pandas as pd
import pulp

# 你的原始数据
data_part = [
    {'Part': 'A', 'Units': 20, 'Engine': True, 'TurboCharger': True, 'Restricted': True},
    {'Part': 'B', 'Units': 15, 'Engine': False, 'TurboCharger': True, 'Restricted': False},
    {'Part': 'C', 'Units': 15, 'Engine': False, 'TurboCharger': True, 'Restricted': False},
    {'Part': 'D', 'Units': 40, 'Engine': False, 'TurboCharger': True, 'Restricted': False},
    {'Part': 'E', 'Units': 25, 'Engine': True, 'TurboCharger': True, 'Restricted': False},
    {'Part': 'F', 'Units': 20, 'Engine': True, 'TurboCharger': False, 'Restricted': True},
]
df_part = pd.DataFrame(data_part)

data_system = [
    {'System': 'Rapidx', 'Type': 'Engine Super', 'Condition': 'Restricted'},
    {'System': 'Assex', 'Type': 'Engine', 'Condition': ''},
    {'System': 'Dulingo', 'Type': 'TurboCharger', 'Condition': ''},
    {'System': 'Das', 'Type': 'TurboCharger', 'Condition': ''},
]
df_system = pd.DataFrame(data_system)

# 创建所有零件-系统的组合(笛卡尔积)
cross_df = df_part.assign(temp_key=1).merge(df_system.assign(temp_key=1), on='temp_key').drop('temp_key', axis=1)

# 定义类型匹配规则:系统类型对应零件的布尔字段
def check_type_match(row):
    sys_type = row['Type']
    if sys_type == 'Engine':
        return row['Engine']
    elif sys_type == 'TurboCharger':
        return row['TurboCharger']
    elif sys_type == 'Engine Super':
        # 按你的示例,Engine Super要求零件Engine为True,可按需调整为同时要TurboCharger=True
        return row['Engine']
    return False  # 未知类型默认不允许

# 定义约束匹配规则:受限系统只能放受限零件,非受限系统只能放非受限零件
def check_condition_match(row):
    sys_condition = row['Condition']
    part_restricted = row['Restricted']
    if sys_condition == 'Restricted':
        return part_restricted
    else:
        return not part_restricted  # 如果非受限系统允许放受限零件,改成return True即可

# 给每个组合标记是否允许分配
cross_df['type_ok'] = cross_df.apply(check_type_match, axis=1)
cross_df['condition_ok'] = cross_df.apply(check_condition_match, axis=1)
cross_df['is_allowed'] = cross_df['type_ok'] & cross_df['condition_ok']

第二步:生成PuLP约束

接下来,我们把每个系统下不允许分配的零件组合起来,生成你要的约束:

# 初始化PuLP变量(你的原有代码)
allocate = pulp.LpVariable.dicts("allocate", [(p, s) for p in df_part.Part for s in df_system.System], cat='Binary')

# 初始化PuLP问题
allocation_prob = pulp.LpProblem("Minimize_Allocation_Cost", pulp.LpMinimize)

# 按系统分组,生成约束
for system, group in cross_df[~cross_df['is_allowed']].groupby('System'):
    # 收集该系统下所有禁止的分配变量
    forbidden_assignments = [allocate[(row['Part'], system)] for _, row in group.iterrows()]
    # 添加约束:这些变量的和必须<=0(等价于每个变量都为0)
    allocation_prob += pulp.lpSum(forbidden_assignments) <= 0, f"No_Assign_{system}"

# 打印约束看结果(和你期望的输出一致)
for constraint_name, constraint in allocation_prob.constraints.items():
    print(constraint)

运行后的输出

你会得到和你期望完全一致的约束:

allocate_('B',_'Rapidx') + allocate_('C',_'Rapidx') + allocate_('D',_'Rapidx') + allocate_('E',_'Rapidx') <= 0
allocate_('A',_'Assex') + allocate_('B',_'Assex') + allocate_('C',_'Assex') + allocate_('D',_'Assex') + allocate_('F',_'Assex') <= 0
allocate_('A',_'Dulingo') + allocate_('F',_'Dulingo') <= 0
allocate_('A',_'Das') + allocate_('F',_'Das') <= 0

灵活调整规则

如果后续你的匹配规则变了,比如Engine Super需要同时满足Engine和TurboCharger为True,只需要修改check_type_match里的对应分支:

elif sys_type == 'Engine Super':
    return row['Engine'] and row['TurboCharger']

如果非受限系统允许分配受限零件,就把check_condition_match的else分支改成return True就行。

内容的提问来源于stack exchange,提问作者Greg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 17:37:44