我设置了一个小脚本,描述了纸浆中的饮食优化解决方案。特定的整数并不真正相关,它们只是食物中的宏。奇怪的是,当protein_ratio,carb_ratio或fat_ratio之一为0.1时,该问题将变得不可行。对于这些因素的其他组合(总应加1 ),问题已解决。有什么方法可以放宽目标函数,以使解决方案的误差幅度较小?例如,与其给您带来800卡路里的热量的克,不如给您带来810卡路里的能量的克。这仍然可以接受。这是脚本:
from pulp import *
target_calories = 1500
protein_ratio = 0.4 #play around with this - 0.1 breaks it
carb_ratio = 0.4 #play around with this - 0.1 breaks it
fat_ratio = 0.2 #play around with this - 0.1 breaks it
problem = LpProblem("diet", sense = LpMinimize)
gramsOfMeat = LpVariable("gramsOfMeat", lowBound = 1)
gramsOfPasta = LpVariable("gramsOfPasta", lowBound = 1 )
gramsOfOil = LpVariable("gramsOfOil", lowBound = 1)
problem += gramsOfMeat*1.29 + gramsOfPasta*3.655 + gramsOfOil*9 - target_calories
totalprotein = gramsOfMeat*0.21 + gramsOfPasta*0.13 + gramsOfOil*0
totalcarb = gramsOfMeat*0 + gramsOfPasta*0.75 + gramsOfOil*0
totalfat = gramsOfMeat*0.05 + gramsOfPasta*0.015 + gramsOfOil*1
totalmacros = totalprotein + totalcarb + totalfat
problem += totalfat== fat_ratio*totalmacros
problem += totalcarb == carb_ratio*totalmacros
problem += totalprotein == protein_ratio*totalmacros
problem += gramsOfMeat*1.29 + gramsOfPasta*3.655 + gramsOfOil*9 - target_calories == 0
status = problem.solve()
print(status)
#assert status == pulp.LpStatusOptimal
#print(totalmacros)
print("Grams of meat: {}, grams of pasta: {}, grams of oil: {}, error: {}".format(value(gramsOfMeat), value(gramsOfPasta), value(gramsOfOil), value(problem.objective)))
答案 0 :(得分:1)
您可以添加违反目标的罚款。这个想法是引入两个新的决策变量,例如under
和over
,并添加约束条件
problem += gramsOfMeat*1.29 + gramsOfPasta*3.655 + gramsOfOil*9 - target_calories <= under
problem += target_calories - (gramsOfMeat*1.29 + gramsOfPasta*3.655 + gramsOfOil*9) <= over
然后将目标函数更改为类似
problem += c_under * under + c_over * over
其中c_under
是低于目标的罚款,而c_over
是超过目标的罚款。 (这些是参数。)如果要对上方/下方施加硬约束,则可以添加新的约束:
problem += under <= max_under
problem += over <= max_over
其中max_under
和max_over
是最大允许偏差(再次是参数)。
一个注意事项:您的模型有点奇怪,因为它实际上没有目标函数。通常,在饮食问题中,您想最小化成本或使卡路里最大化或类似的东西,并且通常在线性编程中,您要最小化或最大化某些东西。在模型中,只有约束。没错,有些东西看起来像是目标函数-
problem += gramsOfMeat*1.29 + gramsOfPasta*3.655 + gramsOfOil*9 - target_calories
-但由于已将其限制为等于0,因此它实际上没有任何作用。没有目标函数当然没有什么不对劲,但这很不寻常,我想提一提,以防它不是您想要的。