python中的分配包装器

python中的分配包装器,python,pandas,linear-programming,Python,Pandas,Linear Programming,我是python新手,有简单LP问题的输出 在这个问题上,几个部分组成一个房子,几个部分组成一个社会。交付时有房屋和社会层面的目标。如果在任何级别均未达到交付要求,则将不良零件更换为交付50个单元的零件(更换=Y) 解决方案已优化,但我们没有替换的能力。 所以,我想优先考虑更换 我有能力做3次更换,解决方案是7次更换 我们是否可以根据优先级对解决方案进行后处理以获得3个替换 给定值=3个最大替换值 优先级=S3(社会3),H2,H1,S2 我的输出将是U、R和A的替换,而另一个保持不变?可以用

我是python新手,有简单LP问题的输出

在这个问题上,几个部分组成一个房子,几个部分组成一个社会。交付时有房屋和社会层面的目标。如果在任何级别均未达到交付要求,则将不良零件更换为交付50个单元的零件(更换=Y)

解决方案已优化,但我们没有替换的能力。 所以,我想优先考虑更换

我有能力做3次更换,解决方案是7次更换

我们是否可以根据优先级对解决方案进行后处理以获得3个替换

给定值=3个最大替换值 优先级=S3(社会3),H2,H1,S2

我的输出将是U、R和A的替换,而另一个保持不变?可以用python来做吗?或者这不能在python中完成(在这种情况下,我可以使用excel宏)

编辑

Raw data:
data = [
    {'Part': 'A', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 10, 'Replaced': 'Y'},
    {'Part': 'B', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 30, 'Replaced': ''},
    {'Part': 'C', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 40, 'Replaced': ''},
    {'Part': 'D', 'House': 'H1', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
    {'Part': 'E', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
    {'Part': 'F', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
    {'Part': 'G', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},
    {'Part': 'H', 'House': 'H2', 'Society': 'S1', 'Present_Delivery': 50, 'Replaced': ''},

    {'Part': 'I', 'House': 'H3', 'Society': 'S2', 'Present_Delivery': 30, 'Replaced': 'Y'},
    {'Part': 'J', 'House': 'H3', 'Society': 'S2', 'Present_Delivery': 40, 'Replaced': ''},
    {'Part': 'K', 'House': 'H3', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},
    {'Part': 'L', 'House': 'H4', 'Society': 'S2', 'Present_Delivery': 30, 'Replaced': 'Y'},
    {'Part': 'M', 'House': 'H4', 'Society': 'S2', 'Present_Delivery': 30, 'Replaced': 'Y'},
    {'Part': 'N', 'House': 'H4', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},
    {'Part': 'O', 'House': 'H5', 'Society': 'S2', 'Present_Delivery': 20, 'Replaced': 'Y'},
    {'Part': 'P', 'House': 'H5', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},
    {'Part': 'Q', 'House': 'H5', 'Society': 'S2', 'Present_Delivery': 50, 'Replaced': ''},

    {'Part': 'R', 'House': 'H6', 'Society': 'S3', 'Present_Delivery': 20, 'Replaced': 'Y'},
    {'Part': 'S', 'House': 'H6', 'Society': 'S3', 'Present_Delivery': 40, 'Replaced': ''},
    {'Part': 'T', 'House': 'H6', 'Society': 'S3', 'Present_Delivery': 50, 'Replaced': ''},
    {'Part': 'U', 'House': 'H7', 'Society': 'S3', 'Present_Delivery': 15, 'Replaced': 'Y'},
    {'Part': 'V', 'House': 'H7', 'Society': 'S3', 'Present_Delivery': 40, 'Replaced': ''},
    {'Part': 'W', 'House': 'H7', 'Society': 'S3', 'Present_Delivery': 50, 'Replaced': ''},

]

house_targets = {'H1': 140,
                 'H2': 160,
                 'H3': 120,
                 'H4': 110,
                 'H5': 120,
                 'H6': 115,
                 'H7': 105,

                 }

society_targets = {'S1': 330,
                   'S2': 500,
                   'S3': 250}
df = pd.DataFrame(data)
    for house, target in house_targets.items():
        df.loc[df['House'] == house, 'House_Target'] = target
    for society, target in society_targets.items():
        df.loc[df['Society'] == society, 'Society_Target'] = target
    replacement_value = 50
    df.loc[df['Replaced'] == 'Y', 'replacement_value'] = replacement_value - df['Present_Delivery']
    df['replacement_value'].fillna(0, inplace=True)

事实上,解决方案是直截了当的。您只需要按照给定的优先级对正确的列进行切片并对其进行排序。大部分代码只是包装器的锅炉板

包装纸
将熊猫作为pd导入
类替换约束:
定义初始化(self,df:pd.DataFrame,*,max_replacements:int,priority:list):
断言isinstance(df,pd.DataFrame)
self.df=df
self.max\u replacements=max\u replacements
self.priority=优先级
self.result=pd.DataFrame()
@静力学方法
def解析优先级(优先级):
“”“将优先级字符串映射到列”“”
col_map={'H':'House',
'S':'Society'}
返回col_映射[prio_str[0]]
def计算(自我):
“”“根据优先级对数据帧的切片进行排序并附加到self.result”“”
对于具有自优先权的prio:
col=自解析优先级(prio)
掩码=(self.df['Replaced']='Y')&(self.df[col]==prio)
结果\u tmp=self.df[mask]。排序\u值('replacement\u value',升序=False)
self.result=pd.concat([self.result,result\u tmp])
self.result=self.result.iloc[:self.max\u replacements]
给定一个数据帧
df
(见下文),您可以将包装器用作:

wrapper=ReplacementConstraint(df,max_replacements=3,优先级=['S3'、'H2'、'H1'、'S2']))
wrapper.calculate()
打印(wrapper.result)
解决方案如下所示:

   Part House Society  ...  House_Target Society_Target  replacement_value
20    U    H7      S3  ...         105.0          250.0               35.0
17    R    H6      S3  ...         115.0          250.0               30.0
0     A    H1      S1  ...         140.0          330.0               40.0

原始数据 数据帧数据的键入占用了我大部分时间。请考虑下一次发布文本而不是图片。我在这里发布它,这样如果其他人想发布另一个解决方案,她就不需要再次键入它。此外,通过发布数据帧,我的解决方案是


可能的改进
  • 包装器不检查目标值。我认为这与第一次优化无关
  • 结果数据帧不会更正传递的值。这没什么大不了的。我只是想提供一个简单的例子。您可以根据需要改进包装器

这可以通过使用
join
combine\u first
sort
来实现:

priority = ["S3", "H2", "H1", "S2"]
priority = pd.Series(range(len(priority)), index=priority, name="priority")

df["priority"] = df.join(priority, on="Society").priority.combine_first(df.join(priority, on="House").priority)

result = df[df.replacement_value > 0] .sort_values("priority").head(3)
print(result)
结果:

   Part House Society  Present_Delivery Replaced  House_Target  Society_Target  replacement_value  priority
17    R    H6      S3                20        Y         115.0           250.0               30.0       0.0
20    U    H7      S3                15        Y         105.0           250.0               35.0       0.0
0     A    H1      S1                10        Y         140.0           330.0               40.0       2.0

我会将容量限制直接添加到LP/MIP问题中,而不是在事后试图捏造。这意味着模型没有反映问题,或者你对问题的理解不够详细。你可能会说……问题是一些约束条件不满足于容量约束条件,因此,选择或回避(正如你所说的)下游是很重要的……如何解决可能的改进
   Part House Society  Present_Delivery Replaced  House_Target  Society_Target  replacement_value  priority
17    R    H6      S3                20        Y         115.0           250.0               30.0       0.0
20    U    H7      S3                15        Y         105.0           250.0               35.0       0.0
0     A    H1      S1                10        Y         140.0           330.0               40.0       2.0