基于CPLEX的双工厂多配送点5需求场景生产计划模型问题咨询
多场景生产计划模型的CPLEX实现方案
问题说明
现有双工厂向5个配送点供货的生产计划模型,需基于历史需求生成5种需求场景(乘数为0.8、0.9、1.0、1.1、1.2),但原代码仅支持单一预测系数,且之前尝试主函数迭代时无法获取决策变量x的取值。
解决方案
以下提供两种可行的实现方式:
方式1:主函数迭代求解多场景
通过OPL主函数循环遍历所有预测乘数,每次更新ForecastMultiplier后求解模型,并将每个场景的决策变量值和目标函数值输出保存。
修改后的完整代码:
// Data range ProductionRegionID = 1..2; range SalesRegionID = 1..5; // 定义所有预测乘数场景 float multiplers[1..5] = [0.8, 0.9, 1.0, 1.1, 1.2]; // 工厂最大产能 int cap[ProductionRegionID] = ... ; // 工厂生产成本费率 float cost[ProductionRegionID] = ... ; // 工厂到配送点的运输成本 float Trans[ProductionRegionID][SalesRegionID] = ... ; // 各配送点历史需求 int HistOrder[SalesRegionID] = ... ; // 预测乘数(主函数中动态赋值) float ForecastMultiplier; // 决策变量:工厂p向配送点s的配送量 dvar int+ x[ProductionRegionID][SalesRegionID]; // 目标函数:最小化总生产成本+总运输成本 minimize sum (p in ProductionRegionID, s in SalesRegionID) (cost[p]*x[p][s] + Trans[p][s]*x[p][s]); // 约束条件 subject to { // 每个配送点的需求满足约束 forall(s in SalesRegionID) sum (p in ProductionRegionID) x[p][s] >= ForecastMultiplier*HistOrder[s]; // 每个工厂的产能约束 forall(p in ProductionRegionID) sum (s in SalesRegionID) x[p][s] <= cap[p]; } // 主函数:迭代所有场景并输出结果 main { var source = thisOplModel; var cplex = new IloCplex(); var data = source.dataElements; // 遍历每个预测乘数场景 for(var m in data.multiplers) { writeln("=== 处理预测乘数为 ", m, " 的场景 ==="); source.ForecastMultiplier = m; // 加载模型并求解 var cplexModel = cplex.copyModel(source); if(cplex.solve()) { // 输出当前场景的目标总成本 writeln("目标总成本: ", cplex.getObjValue()); // 获取并输出决策变量x的取值矩阵 writeln("配送量矩阵x:"); for(var p in data.ProductionRegionID) { var rowContent = ""; for(var s in data.SalesRegionID) { rowContent += cplex.getValue(source.x[p][s]) + "\t"; } writeln(rowContent); } } else { writeln("场景乘数", m, "求解失败"); } cplexModel.end(); } cplex.end(); }
关键说明:
- 通过
cplex.getValue(source.x[p][s])可直接获取决策变量x在当前场景下的取值,解决之前无法读取矩阵变量值的问题 - 每次迭代后调用
cplexModel.end()释放资源,避免内存溢出
方式2:一次性建模所有场景
将场景作为额外维度加入模型,一次性求解所有场景的最优解,适合场景数量较少的情况(如本次的5个场景)。
修改后的代码示例:
// Data range ProductionRegionID = 1..2; range SalesRegionID = 1..5; // 场景索引 range ScenarioID = 1..5; // 各场景对应的预测乘数 float multiplers[ScenarioID] = [0.8, 0.9, 1.0, 1.1, 1.2]; // 工厂最大产能 int cap[ProductionRegionID] = ... ; // 工厂生产成本费率 float cost[ProductionRegionID] = ... ; // 工厂到配送点的运输成本 float Trans[ProductionRegionID][SalesRegionID] = ... ; // 各配送点历史需求 int HistOrder[SalesRegionID] = ... ; // 决策变量:新增场景维度,sc场景下工厂p向配送点s的配送量 dvar int+ x[ScenarioID][ProductionRegionID][SalesRegionID]; // 目标函数:最小化所有场景的总成本之和(可按需调整为加权和或其他形式) minimize sum (sc in ScenarioID, p in ProductionRegionID, s in SalesRegionID) (cost[p]*x[sc][p][s] + Trans[p][s]*x[sc][p][s]); // 约束条件 subject to { // 每个场景下的配送点需求满足约束 forall(sc in ScenarioID, s in SalesRegionID) sum (p in ProductionRegionID) x[sc][p][s] >= multiplers[sc]*HistOrder[s]; // 每个场景下的工厂产能约束 forall(sc in ScenarioID, p in ProductionRegionID) sum (s in SalesRegionID) x[sc][p][s] <= cap[p]; }
关键说明:
- 变量
x新增场景维度ScenarioID,每个场景对应一组独立的配送决策 - 求解后可直接通过
x[sc][p][s]获取第sc个场景下工厂p向配送点s的配送量 - 若无需同时优化所有场景的总成本,方式1的迭代求解会更灵活
内容的提问来源于stack exchange,提问作者Anduliska
相关产品推荐
相关产品推荐

