【问题标题】:Running solve multiple timese多次运行求解
【发布时间】:2020-05-05 15:23:26
【问题描述】:

我需要运行 3 次求解。每次求解都需要来自元组的不同列的不同输入。这就是为什么我需要访问 OPL 中的循环变量作为参数,并且需要在每个循环中更改该参数。请建议如何在 ODM OPL 中执行此操作。 (通过在 dat 文件中引入一个 int 并在每个循环中更改其值,我可以在使用物理 .dat 文件运行独立模型时做到这一点,但在通过 ODM 应用程序运行时,这是不可能的)。

【问题讨论】:

    标签: optimization opl


    【解决方案1】:

    您可以使用脚本main() 函数来做到这一点:

    .dat文件:

    param = 0; // This value is actually never used
    

    .mod文件:

    tuple T {
      int round1;
      int round2;
    }
    T t = <1, 2>;
    
    int param = ...;
    
    dvar float x;
    
    minimize x;
    subject to { x >= param; }
    
    main {
      thisOplModel.generate();
      var def = thisOplModel.modelDefinition;
      var data = thisOplModel.dataElements;
      for (var i = 0; i < 2; ++i) {
        if (i == 0)
           data.param = thisOplModel.t.round1;
        else
           data.param = thisOplModel.t.round2;
        var opl = new IloOplModel(def, cplex);
        opl.addDataSource(data);
        opl.generate();
        cplex.solve();
        writeln("Round " + i + ": " + cplex.getObjValue() + ", " + data.param);
        opl.end();
      }
    }
    

    脚本代码会在每次迭代中创建新模型之前修改数据。在 CPLEX 附带的 cutstock_main.mod 示例中,您有类似这样的更详细的代码版本。

    【讨论】:

    • 谢谢丹尼尔,它成功了,达到了我的目的。现在我面临其他问题,我需要访问“opl”模型生成的输出并将其用于 ODM 应用程序来填充表。当我使用 thisOplModel 时,我可以做到,但不能使用“opl”模型。
    • 既然这是一个不同的问题,你能提出一个新问题吗?
    【解决方案2】:

    丹尼尔写的很好。如果您不想拥有不必要的 .dat 文件,您可以编写

    sub.mod

    tuple T {
      int round1;
      int round2;
    }
    T t = <1, 2>;
    
    int param = ...;
    
    dvar float x;
    
    minimize x;
    subject to { x >= param; }
    

    然后在另一个将成为主要模型的模型中:

    tuple T {
      int round1;
      int round2;
    }
    T t = <1, 2>;
    
    main {
      thisOplModel.generate();
      var src = new IloOplModelSource("sub.mod");
      var def=new IloOplModelDefinition(src);
      var data = new IloOplDataElements();;
      for (var i = 0; i < 2; ++i) {
        if (i == 0)
           data.param = thisOplModel.t.round1;
        else
           data.param = thisOplModel.t.round2;
        var opl = new IloOplModel(def, cplex);
        opl.addDataSource(data);
        opl.generate();
        cplex.solve();
        writeln("Round " + i + ": " + cplex.getObjValue() + ", " + data.param);
        opl.end();
      }
    }
    

    这会给

    Round 0: 1, 1
    Round 1: 2, 2
    

    tuple T {
      int round1;
      int round2;
    }
    T t = <1, 2>;
    
    int solutions[0..1];
    
    main {
      thisOplModel.generate();
      var src = new IloOplModelSource("sub.mod");
      var def=new IloOplModelDefinition(src);
      var data = new IloOplDataElements();;
      for (var i = 0; i < 2; ++i) {
        if (i == 0)
           data.param = thisOplModel.t.round1;
        else
           data.param = thisOplModel.t.round2;
        var opl = new IloOplModel(def, cplex);
        opl.addDataSource(data);
        opl.generate();
        cplex.solve();
        writeln("Round " + i + ": " + cplex.getObjValue() + ", " + data.param);
        thisOplModel.solutions[i]=opl.x.solutionValue;
        opl.end();
      }
    
      writeln(thisOplModel.solutions);
    }
    

    解决您关于填充表格的下一个问题

    给了

    Round 0: 1, 1
    Round 1: 2, 2
     [1 2]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-29
      相关资源
      最近更新 更多