我的 pyomo 模型没有正确的结果

问题描述 投票:0回答:1

任务: 拉里·爱迪生是巴克利学院计算机中心的主任。他现在需要安排该中心的人员配备。营业时间为上午 8 点至午夜。拉里(Larry)监控了一天中不同时间该中心的使用情况,并确定需要以下数量的计算机顾问: 一天中的轮班时间 顾问的最低人数 A 上午 8 点 - 中午 4 点 B 中午 - 下午 4 点 8 C 下午 4 点 - 晚上 8 点 10 D 晚上 8 点 - 午夜 6 点

可以聘请两种类型的计算机顾问:全职和兼职。全职顾问按以下任一班次连续工作 8 小时:上午(上午 8 点至下午 4 点)、下午(中午至晚上 8 点)和晚上(下午 4 点至午夜)。全职顾问的工资为每小时 40 欧元。可以聘请兼职顾问从事上表中列出的四个轮班中的任何一个工作。兼职顾问的工资为每小时 30 欧元。额外的要求是,在每个时间段内,每个兼职顾问在值班时必须至少有两名全职顾问在值。

Larry 希望确定每个班次应有多少全职工人和多少兼职工人,以便以尽可能低的成本满足上述要求。使用索引变量制定线性规划模型,并使用 Pyomo 对其进行求解。确保解决方案只能采用整数值,因为不可能仅雇用工人进行轮班的一部分。

编写一个函数:

名为 model_larry_edison,无参数 返回 pyomo 模型 该模型应具有: 其中一个目标就是工资,即尽量减少必须支付的工资数额。 两个变量: full_time 具有三个索引,每个全职轮班一个,指示该轮班期间有多少全职工人在值班。 part_time 有四个索引,每个兼职轮班一个,表示该轮班期间有多少兼职工人在值班。 八个约束 四个(A_total、B_total、C_total、D_total)确保每个 4 小时轮班所需的顾问数量得到满足。 四个(A_ratio、B_ratio、C_ratio、D_ratio)确保在每个 4 小时轮班中,全职顾问的数量至少是兼职顾问数量的两倍。

def model_larry_edison():

  salary_df_ft = pd.DataFrame()
  salary_df_ft.at["FT1", "Salary"] = 40
  salary_df_ft.at["FT2", "Salary"] = 40
  salary_df_ft.at["FT3", "Salary"] = 40

  salary_df_pt = pd.DataFrame()
  salary_df_pt.at["PT1", "Salary"] = 30
  salary_df_pt.at["PT2", "Salary"] = 30
  salary_df_pt.at["PT3", "Salary"] = 30
  salary_df_pt.at["PT4", "Salary"] = 30

  salary_ft = salary_df_ft.astype(int)
  salary_pt = salary_df_pt.astype(int)

  model = pyo.ConcreteModel('ProductionPlan')

  model.salary_ft = pyo.Set(initialize = salary_ft.index)
  model.salary_pt = pyo.Set(initialize = salary_pt.index)

  model.full_time = pyo.Var(model.salary_ft, bounds=(0,None))
  model.part_time = pyo.Var(model.salary_pt, bounds=(0,None))

  model.wage = pyo.Objective(expr = 320*(model.full_time["FT1"]+model.full_time["FT2"]+model.full_time["FT3"]) + 120*(model.part_time["PT1"]+model.part_time["PT2"]+model.part_time["PT3"]+model.part_time["PT4"]), sense=pyo.minimize)

  model.A_total = pyo.Constraint(expr = (model.full_time["FT1"] + model.part_time["PT1"]) >= 4)
  model.B_total = pyo.Constraint(expr = (model.full_time["FT1"] + model.full_time["FT2"] + model.part_time["PT2"]) >= 8)
  model.C_total = pyo.Constraint(expr = (model.full_time["FT2"] + model.full_time["FT3"] + model.part_time["PT3"]) >= 10)
  model.D_total = pyo.Constraint(expr = (model.full_time["FT3"] + model.part_time["PT4"]) >= 6)
  model.A_ratio = pyo.Constraint(expr = model.full_time["FT1"] >= 2*model.part_time["PT1"])
  model.B_ratio = pyo.Constraint(expr = (model.full_time["FT1"] + model.full_time["FT2"]) >= 2*model.part_time["PT2"])
  model.C_ratio = pyo.Constraint(expr = (model.full_time["FT2"] + model.full_time["FT3"]) >= 2*model.part_time["PT3"])
  model.D_ratio = pyo.Constraint(expr = model.full_time["FT3"] >= 2*model.part_time["PT4"])

  return model
model = model_larry_edison()
results = pyo.SolverFactory('cbc').solve(model)
print(model.wage())

预期结果是 4160,但是我得到 4106.6666666

python pandas model pyomo linear-optimization
1个回答
0
投票

您走在正确的道路上。

你应该问自己:“我如何获得目标的分数值......?

答案是你没有将变量限制为整数!

尝试将变量声明更改为:

  model.full_time = pyo.Var(model.salary_ft, domain=pyo.NonNegativeIntegers) #bounds=(0,None))
  model.part_time = pyo.Var(model.salary_pt, domain=pyo.NonNegativeIntegers) #bounds=(0,None))

另外(以及在执行此操作之前/之后):养成打印模型(带变量)和答案(插入值)的习惯。它对于故障排除非常有价值:

model.pprint()   # the model
model.display()  # the model with the values plugged in
© www.soinside.com 2019 - 2024. All rights reserved.