JS lp-solver技术问题:如何确保所有产品至少被使用一次?
问题描述
我给饮食APP编写了线性规划代码,目标是在满足用户所需卡路里的前提下最小化产品成本。目前代码可正常运行,但结果只会选择单个最优产品来达标并压缩成本。我希望让所有产品都至少被使用一次(同时不超过用户卡路里需求),尝试添加约束后问题仍未解决,结果依旧不变,求解决方案建议。注:代码中的response是从.php文件获取的产品信息数组。
原代码
// Set up the model const model = { optimize: "price", opType: "min", constraints: { "calories": { "equal": userCalories } }, variables: {} }; console.log(response); // Set up the variables and the constraints in the model for (var i = 0; i < response.length; i++) { var name = response[i]['name']; //var price = parseFloat(response[i]['price'].replace(',', '.')); // Convert the price to a number model.variables[name] = { "price": parseFloat(response[i]['price'].replace(',', '.')), "calories": response[i]['calories'] }; } for (var i = 0; i < response.length; i++) { var name = response[i]['name']; model.constraints[name] = {}; model.constraints[name][name] = 1; } model.constraints["use_all"] = {}; for (var i = 0; i < response.length; i++) { var name = response[i]['name']; model.constraints["use_all"][name] = 1; } // Solve the linear program const result = solver.Solve(model); console.log(result);
运行结果

问题分析
你添加的约束未生效,核心原因:
- 单独给每个产品创建的约束仅设置了变量系数,但未指定约束的边界(如最小取值),相当于没有实际限制。
use_all约束仅定义了变量的系数,未明确约束的目标(比如总和需要满足的条件),对求解无影响。- 原代码中卡路里约束设为
equal(必须刚好等于用户需求),如果所有产品各用一份的总卡路里与用户需求不匹配,会导致问题无解,solver会退回到原最优解(选单个产品)。
解决方案
修改约束部分代码,确保每个产品至少被使用一次,并调整卡路里约束逻辑:
// Set up the model const model = { optimize: "price", opType: "min", constraints: { // 调整卡路里约束:根据需求选择对应规则 "calories": { "min": userCalories, // 至少满足用户卡路里需求 "max": userCalories // 若要求不超过需求则保留,允许浮动可删除 } }, variables: {} }; console.log(response); // 设置变量 for (var i = 0; i < response.length; i++) { var name = response[i]['name']; model.variables[name] = { "price": parseFloat(response[i]['price'].replace(',', '.')), "calories": response[i]['calories'] }; } // 给每个产品添加「至少使用1份」的约束 for (var i = 0; i < response.length; i++) { var name = response[i]['name']; model.constraints[`min_${name}`] = { min: 1, // 明确要求变量取值至少为1 [name]: 1 }; } // 求解线性规划 const result = solver.Solve(model); console.log(result);
关键调整说明:
- 单个产品的最小用量约束:给每个产品添加
min:1的约束,强制变量取值≥1,确保所有产品都被使用。 - 卡路里约束调整:
- 若只需满足用户的卡路里需求(至少达到),保留
min: userCalories即可; - 若要求不超过卡路里需求,改为
max: userCalories; - 若必须刚好等于,需确保所有产品各用一份的总卡路里可通过调整用量凑到
userCalories,否则问题无解,建议改为浮动约束(min或max)。
- 若只需满足用户的卡路里需求(至少达到),保留
- 约束命名规范:用
min_${name}命名每个产品的约束,避免变量名与约束名冲突(原代码中用产品名作为约束名可能引发潜在问题)。
额外注意:
如果你的场景中产品用量必须是整数(比如不能买0.5份),需要确认使用的solver是否支持整数线性规划(ILP),若支持需给变量添加整数类型的设置。
内容的提问来源于stack exchange,提问作者Muffin
相关产品推荐
相关产品推荐

