如何根据具体的输入处理不一致的浆液?
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)))
您可以为违反目标添加惩罚。这个想法是引入两个新的决策变量,比如 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
然后将 objective 函数更改为
problem += c_under * under + c_over * over
其中 c_under
是低于目标的每单位罚分,c_over
是超过目标的罚分。 (这些是参数。)如果你想对 over/under 施加硬约束,你可以添加新的约束:
problem += under <= max_under
problem += over <= max_over
其中 max_under
和 max_over
是最大允许偏差(同样是参数)。
注意事项:您的模型有点奇怪,因为它实际上没有 objective 函数。通常在饮食问题中你想要最小化成本或最大化卡路里或类似的东西,并且通常在线性规划中你想要最小化或最大化某些东西。在您的模型中,您只有约束。没错,有些东西看起来像 objective 函数 --
problem += gramsOfMeat*1.29 + gramsOfPasta*3.655 + gramsOfOil*9 - target_calories
-- 但由于您已将其限制为等于 0,因此它实际上没有任何作用。没有 objective 函数当然没有 不正确 ,但这很不寻常,我想提一下,以防这不是你想要的。
我已经设置了一个小脚本,描述了纸浆中的饮食优化解决方案。特定的整数并不真正相关,它们只是食物中的宏。奇怪的是,当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)))
您可以为违反目标添加惩罚。这个想法是引入两个新的决策变量,比如 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
然后将 objective 函数更改为
problem += c_under * under + c_over * over
其中 c_under
是低于目标的每单位罚分,c_over
是超过目标的罚分。 (这些是参数。)如果你想对 over/under 施加硬约束,你可以添加新的约束:
problem += under <= max_under
problem += over <= max_over
其中 max_under
和 max_over
是最大允许偏差(同样是参数)。
注意事项:您的模型有点奇怪,因为它实际上没有 objective 函数。通常在饮食问题中你想要最小化成本或最大化卡路里或类似的东西,并且通常在线性规划中你想要最小化或最大化某些东西。在您的模型中,您只有约束。没错,有些东西看起来像 objective 函数 --
problem += gramsOfMeat*1.29 + gramsOfPasta*3.655 + gramsOfOil*9 - target_calories
-- 但由于您已将其限制为等于 0,因此它实际上没有任何作用。没有 objective 函数当然没有 不正确 ,但这很不寻常,我想提一下,以防这不是你想要的。