作为一个简单的 Web 开发人员 :) 在使用 SciPy Optimize 最小化功能时,我无法找出更多关注数据科学的问题。给定一组界限和一系列约束,我试图在这种情况下找到 8 种成分的值(谁的总数必须等于 100)。
约束规定了整体常量营养素值的最小值/最大值,例如。必须是至少 40% 的固体,或者必须具有等于 13.0 等的 rs 值(相对甜度)。
我已经为这些成分中的每一种设置了我的约束(我希望是正确的)和一系列界限(其中一些可以在 0 到 100 之间),但其他成分的上限和下限相同,即。固定的?。在提供的答案中,我很困惑,因为我成功运行了优化,但某些成分的值不在设置的范围内。
到目前为止,请参见下面的代码。非常感谢您的帮助!
cream = {
"rs": 0.0,
"se": 0.0,
"solids": 0.454,
"water": 0.0,
"fat": 0.4,
"saturated": 0.4,
"unsaturated": 0.26,
"msnf": 0.14,
"protein": 0.054,
"brix": 0.019,
"acid": 0.0
}
whole_milk = {
"rs": 0.0,
"se": 0.0,
"solids": 0.128,
"water": 0.872,
"fat": 0.037,
"saturated": 0.024,
"unsaturated": 0.013,
"msnf": 0.091,
"protein": 0.035,
"brix": 0.049,
"acid": 0.0
}
sucrose = {
"rs": 1.0,
"se": 1.0,
"solids": 1.0,
"water": 0.0,
"fat": 0.0,
"saturated": 0.0,
"unsaturated": 0.0,
"msnf": 0.0,
"protein": 0.0,
"brix": 1.0,
"acid": 0.0
}
skim_milk_powder = {
"rs": 0.0,
"se": 0.0,
"solids": 0.97,
"water": 0.0,
"fat": 0.07,
"saturated": 0.05,
"unsaturated": 0.02,
"msnf": 0.963,
"protein": 0.38,
"brix": 0.54,
"acid": 0.0
}
buttermilk = {
"rs": 0.0,
"se": 0.0,
"solids": 0.099,
"water": 0.901,
"fat": 0.009,
"saturated": 0.005,
"unsaturated": 0.003,
"msnf": 0.095,
"protein": 0.033,
"brix": 0.048,
"acid": 0.0
}
tapioca_starch = {
"rs": 0.0,
"se": 0.0,
"solids": 0.867,
"water": 0.133,
"fat": 0.0,
"saturated": 0.0,
"unsaturated": 0.0,
"msnf": 0.0,
"protein": 0.0,
"brix": 0.0,
"acid": 0.0
}
salt = {
"rs": 0.0,
"se": 5.9,
"solids": 1.0,
"water": 0.0,
"fat": 0.0,
"saturated": 0.0,
"unsaturated": 0.0,
"msnf": 0.0,
"protein": 0.0,
"brix": 0.0,
"acid": 0.0
}
sugared_egg_yolk = {
"rs": 0.1,
"se": 0.1,
"solids": 0.529,
"water": 0.471,
"fat": 0.239,
"saturated": 0.09,
"unsaturated": 0.143,
"msnf": 0.0,
"protein": 0.143,
"brix": 0.105,
"acid": 0.0
}
import numpy as np
from scipy.optimize import minimize
initial_guess = np.array([12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5])
x0 = np.zeros(8)
fat_value = 15.0
rs_value = 13.0
solids_value = 40.0
msnf_value = 11.0
def optimize_function(x):
return x[0] + x[2] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7]
def total_amount_constraint(x):
return x[0] + x[2] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7] - 100
def total_fat_constraint(x):
return (x[0] * cream["fat"] + \
x[2] * whole_milk["fat"] + \
x[2] * sucrose["fat"] + \
x[3] * skim_milk_powder["fat"] + \
x[4] * buttermilk["fat"] + \
x[5] * tapioca_starch["fat"]+ \
x[6] * salt["fat"] + \
x[7] * sugared_egg_yolk["fat"]) - fat_value
def total_rs_constraint(x):
return (x[0] * cream["rs"] + \
x[2] * whole_milk["rs"] + \
x[2] * sucrose["rs"] + \
x[3] * skim_milk_powder["rs"] + \
x[4] * buttermilk["rs"] + \
x[5] * tapioca_starch["rs"]+ \
x[6] * salt["rs"] + \
x[7] * sugared_egg_yolk["rs"]) - rs_value
def total_solids_constraint(x):
return (x[0] * cream["solids"] + \
x[2] * whole_milk["solids"] + \
x[2] * sucrose["solids"] + \
x[3] * skim_milk_powder["solids"] + \
x[4] * buttermilk["solids"] + \
x[5] * tapioca_starch["solids"]+ \
x[6] * salt["solids"] + \
x[7] * sugared_egg_yolk["solids"]) - solids_value
def total_msnf_constraint(x):
return (x[0] * cream["msnf"] + \
x[2] * whole_milk["msnf"] + \
x[2] * sucrose["msnf"] + \
x[3] * skim_milk_powder["msnf"] + \
x[4] * buttermilk["msnf"] + \
x[5] * tapioca_starch["msnf"]+ \
x[6] * salt["msnf"] + \
x[7] * sugared_egg_yolk["msnf"]) - msnf_value
b = (0.0, 100.0)
salt_bound = (0.1, 0.1)
buttermilk_bound = (9.0, 9.0)
tapioca_starch_bound = (1.0, 1.0)
sugared_egg_yolk_bound = (7.77, 7.77)
bnds = (b, b, b, b, buttermilk_bound, tapioca_starch_bound, salt_bound, sugared_egg_yolk_bound)
cons = [
{'type': 'eq', 'fun': total_amount_constraint},
{'type': 'eq', 'fun': total_fat_constraint},
{'type': 'ineq', 'fun': total_solids_constraint},
{'type': 'eq', 'fun': total_rs_constraint},
{'type': 'eq', 'fun': total_msnf_constraint},
]
options = {
'maxiter': 1000
}
response = minimize(optimize_function, initial_guess, method="trust-constr", tol=1e-10, constraints = cons, bounds = bnds, options = options)
print(response)```
The solution set given is the following:
```x: array([29.12370093, 37.03694111, 12.45159589, 3.03213572, 8.99735476,
1.2025148 , 0.33409969, 7.82503797])```
Given that I set the bounds of 9, 1, 0.1 and 7.77 for the last 4 entries in this solution set, I would expect the last 4 values in the above array to be equal to that fixed bound value.
[1]: https://i.stack.imgur.com/MDDa4.png
[2]: https://i.stack.imgur.com/7aMgy.png