You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在CPLEX循环中迭代扩展集合N并保留迭代方案的技术求助

逐步扩展集合N的CPLEX迭代实现方案

核心思路

通过OPL主脚本循环迭代,每次生成集合N的递增子集(从{"a"}开始,逐步添加后续元素),复用恒定数据,并用前一次迭代的解作为初始暖启动,最后保存每次迭代的方案。

实现步骤与代码示例

1. 定义恒定数据与有序集合

首先在模型文件中定义所有恒定数据,并将原始集合N转换为有序数组,确保子集扩展顺序固定:

// 恒定数据(所有迭代保持不变)
{string} N_full = {"a", "b", "c", "d", "e", "f", "g"};
string N_arr[1..card(N_full)] = asSequence(N_full); // 转换为有序数组,保证子集顺序
{string} M = {"aa","bb","cc","dd","ee"};
range nods = 0..10;
tuple edge{int o;int d;float C;float D;};
{edge} edges = ...; // 填入你的边数据
int Tr = ...;
int cd = ...;
// 其他恒定数据...

// 可迭代更新的集合N(初始占位,将在主脚本中修改)
{string} N = {};

// 变量定义(依赖当前迭代的N)
dvar boolean x[M][N];
dvar boolean y[M,edges];
dvar boolean w[M,N,edges];
dvar float+ T[M][nods];

// 目标函数与约束条件(根据你的问题定义)
minimize ...; // 或 maximize
subject to {
   // 你的约束逻辑...
}

2. 主脚本实现迭代逻辑

在OPL主脚本中编写循环,生成递增子集、加载模型、暖启动求解并保存方案:

main {
   var source = thisOplModel;
   var cplex = new IloCplex();
   var prevSolData = {}; // 存储前一次迭代的解数据

   // 迭代1到7(对应N的7个元素逐步扩展)
   for (var k=1; k<=source.N_full.size; k++) {
      // 生成当前迭代的N子集:前k个元素
      var current_N = new IloOplSet();
      for (var i=1; i<=k; i++) {
         current_N.add(source.N_arr[i]);
      }
      source.N = current_N; // 更新模型的N集合

      // 初始化当前迭代的模型
      var currentModel = new IloOplModel(source, cplex);
      currentModel.generate();

      // 暖启动:使用前一次迭代的解作为初始值
      if (k > 1) {
         for (var m in source.M) {
            // 更新x变量
            for (var n in current_N) {
               if (prevSolData.x && prevSolData.x[m] && prevSolData.x[m][n] !== undefined) {
                  currentModel.x[m][n].LB = prevSolData.x[m][n];
                  currentModel.x[m][n].UB = prevSolData.x[m][n];
               }
            }
            // 更新y变量(恒定,直接复用)
            for (var e in source.edges) {
               if (prevSolData.y[m] && prevSolData.y[m][e] !== undefined) {
                  currentModel.y[m][e].LB = prevSolData.y[m][e];
                  currentModel.y[m][e].UB = prevSolData.y[m][e];
               }
            }
            // 更新w变量
            for (var n in current_N) {
               for (var e in source.edges) {
                  if (prevSolData.w[m] && prevSolData.w[m][n] && prevSolData.w[m][n][e] !== undefined) {
                     currentModel.w[m][n][e].LB = prevSolData.w[m][n][e];
                     currentModel.w[m][n][e].UB = prevSolData.w[m][n][e];
                  }
               }
            }
            // 更新T变量(恒定,直接复用)
            for (var nd in source.nods) {
               if (prevSolData.T[m] && prevSolData.T[m][nd] !== undefined) {
                  currentModel.T[m][nd].LB = prevSolData.T[m][nd];
                  currentModel.T[m][nd].UB = prevSolData.T[m][nd];
               }
            }
         }
      }

      // 求解当前模型
      if (cplex.solve()) {
         writeln("=== 迭代", k, "完成 ===");
         writeln("目标值: ", cplex.getObjValue());

         // 保存当前解数据,供下一次迭代暖启动使用
         prevSolData = {
            x: {}, y: {}, w: {}, T: {}
         };
         for (var m in source.M) {
            prevSolData.x[m] = {};
            for (var n in current_N) {
               prevSolData.x[m][n] = currentModel.x[m][n].solutionValue;
            }
            prevSolData.y[m] = {};
            for (var e in source.edges) {
               prevSolData.y[m][e] = currentModel.y[m][e].solutionValue;
            }
            prevSolData.w[m] = {};
            for (var n in current_N) {
               prevSolData.w[m][n] = {};
               for (var e in source.edges) {
                  prevSolData.w[m][n][e] = currentModel.w[m][n][e].solutionValue;
               }
            }
            prevSolData.T[m] = {};
            for (var nd in source.nods) {
               prevSolData.T[m][nd] = currentModel.T[m][nd].solutionValue;
            }
         }

         // 将当前解写入文件(可选,用于后续分析)
         var solFile = new IloOplOutputFile("iteration_" + k + "_solution.dat");
         solFile.writeln("// 迭代", k, "解数据");
         solFile.writeln("Current N subset: ", current_N);
         solFile.writeln("Objective value: ", cplex.getObjValue());
         solFile.writeln("// x变量值");
         for (var m in source.M) {
            for (var n in current_N) {
               solFile.writeln("x[\"", m, "\"][\"", n, "\"] = ", prevSolData.x[m][n], ";");
            }
         }
         // 可继续写入y、w、T变量值...
         solFile.close();
      } else {
         writeln("迭代", k, "求解失败,终止循环");
         break;
      }

      // 清理当前模型资源
      currentModel.end();
   }

   // 释放CPLEX资源
   cplex.end();
}

关键说明

  • 有序子集生成:通过asSequence将无序集合N转换为有序数组,确保每次迭代按a→b→c...的顺序扩展子集。
  • 暖启动优化:将前一次迭代的解赋值给当前模型变量的上下界,让CPLEX从已有解开始搜索,大幅提升求解速度。
  • 解保存:通过字典存储每次迭代的变量值,既用于下一次暖启动,也可写入文件留存。

内容的提问来源于stack exchange,提问作者yalan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 20:15:38