如何根据具体的输入处理不一致的浆液?

How to deal with inconsistent pulp solution depending on specific inputs?

我已经设置了一个小脚本,描述了纸浆中的饮食优化解决方案。特定的整数并不真正相关,它们只是食物中的宏。奇怪的是,当protein_ratio、carb_ratio或fat_ratio其中之一为0.1时,那么问题就变得不可行了。对于这些因素的其他组合(总应加起来为 1),问题有解决方案。有什么办法可以放宽 objective 函数,使解决方案的误差范围很小吗?例如,它不会为您提供导致 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)))

您可以为违反目标添加惩罚。这个想法是引入两个新的决策变量,比如 underover,并添加约束

problem += gramsOfMeat*1.29 + gramsOfPasta*3.655 + gramsOfOil*9 - target_calories <= under
problem += target_calories - (gramsOfMeat*1.29 + gramsOfPasta*3.655 + gramsOfOil*9) <= over

然后将 objective 函数更改为

problem += c_under * under + c_over * over

其中 c_under 是低于目标的每单位罚分,c_over 是超过目标的罚分。 (这些是参数。)如果你想对 over/under 施加硬约束,你可以添加新的约束:

problem += under <= max_under
problem += over <= max_over

其中 max_undermax_over 是最大允许偏差(同样是参数)。

注意事项:您的模型有点奇怪,因为它实际上没有 objective 函数。通常在饮食问题中你想要最小化成本或最大化卡路里或类似的东西,并且通常在线性规划中你想要最小化或最大化某些东西。在您的模型中,您只有约束。没错,有些东西看起来像 objective 函数 --

problem += gramsOfMeat*1.29 + gramsOfPasta*3.655 + gramsOfOil*9 - target_calories

-- 但由于您已将其限制为等于 0,因此它实际上没有任何作用。没有 objective 函数当然没有 不正确 ,但这很不寻常,我想提一下,以防这不是你想要的。