1

main我正在使用流控制块内的循环批量运行数以万计的测试。.dat循环的每次运行都会使用指定的数据文件和模型文件(与仅包含流控制块.mod的批处理运行程序文件分开)生成一个新的 OPL 模型。.modmain

.end()因为循环的每次运行都会创建一个新模型,所以当我不使用语句来关闭为每个测试创建的所有数据结构时,内存使用量会不断增加,直到最终导致 IDE 崩溃。虽然大多数数据结构都可以正常关闭,但我发现这opl.end();会使测试仪崩溃。

如何关闭 OPL 模型而不使测试仪崩溃?

我已经oplrun在 macOS 和 Windows 上尝试了 oplide 应用程序和命令行界面(尽管我最终需要在 Windows 上运行测试)。我正在使用 CPLEX Optimization Studio 12.9。

我使用以下方法创建对象:

// Create new model
var source = new IloOplModelSource("model-file.mod");
var def = new IloOplModelDefinition(source);
var cp = new IloCP();
var opl = new IloOplModel(def,cp);

// Set next test case as data source
var testCasePath = thisOplModel.TestCaseFilenames[testNumber];
var data = new IloOplDataSource(testCasePath);
opl.addDataSource(data);

// Generate model
opl.generate();

当我完成后,我尝试使用以下方法关闭它们:

data.end();
opl.end(); // Causes it to crash
cp.end();
def.end();
source.end();

编辑以添加更多具体信息: 我正在使用我自己的模型运行 RCPSP 调度问题,该模型是内置示例的修改版本。

这是我正在使用的代码的精简版本。我创建了一个只包含这个批处理运行.mod程序文件的运行配置,模型文件和它引用的数据文件存储在其他地方:

using CP;

// Import test case filename data
int NumberOfFiles = 3;
range FileIDs = 0..NumberOfFiles-1;
string TestCaseFilenames[FileIDs] = ["TestCase-01.dat", "TestCase-02.dat", "TestCase-03.dat"];

main {
  var testCaseDirectory = "~/Desktop/TestCases/";

  // Solve each test case in the list
  for (var testNumber = 0; testNumber < thisOplModel.NumberOfFiles; testNumber++) {
    // Create new model
    var source = new IloOplModelSource("RCPSP.mod");
    var def = new IloOplModelDefinition(source);
    var cp = new IloCP();
    var opl = new IloOplModel(def,cp);

    // Set CP parameters
    cp.param.TimeLimit = 5; // Number is in seconds
    cp.param.Workers = 4; // Number of computer cores used
    cp.param.TimeMode = "ElapsedTime"; // How to report time 
    cp.param.LogVerbosity = "Quiet"; // How much to write to the engine log

    // Set next test case as data source
    var testCaseFilename = thisOplModel.TestCaseFilenames[testNumber];
    var testCasePath = testCaseDirectory + testCaseFilename;
    var data = new IloOplDataSource(testCasePath);
    opl.addDataSource(data);

    // Generate model
    opl.generate();

    // Report test case name to script log for progress visibility
    writeln(testNumber+1 + ") Solving " + opl.TestCaseFilename + "...");

    // Solve model
    if (cp.solve()) { // Successfully found solution
      // Run solution validation code in model file's post-processing execute statement
        // If a solution is invalid, the entire bath runner will fail with an error at that test and line
      opl.postProcess();

      // Report some solve-dependent results to oplide log for visibility
      writeln(" - UB = " + cp.getObjValue() + ", LB = " + cp.getObjBound()); // Makespan
    } else { // Failed to find solution
      // Report no solution to oplide log for visibility
      writeln(" - No solution found.")
      writeln(" - Lower Bound = " + cp.getObjBound());
    }

    // Report some results to script log for visibility
    writeln(" - Status = " + cp.status); // Solver status
    writeln(" - Solve Time = " + cp.info.SolveTime + " sec"); // Time spent solving

    // End processes to prevent memory leaks
    data.end();
    opl.end(); // Causes it to crash
    cp.end();
    def.end();
    source.end();
  }

  // Confirm to user that tests are complete
  writeln();
  writeln("All done!");
}

这是输出应该是什么(通过注释掉该opl.end()行产生):

1) Solving TestCase-01.dat...
 - UB = 48, LB = 48
 - Status = 2
 - Solve Time = 1.299999952 sec
2) Solving TestCase-02.dat...
 - UB = 65, LB = 36
 - Status = 1
 - Solve Time = 5.019999981 sec
3) Solving TestCase-03.dat...
 - No solution found.
 - LB = 1
 - Status = 0
 - Solve Time = 5.010000229 sec

All done!

相反,它只记录以下输出:

1) Solving TestCase-01.dat...
 - UB = 48, LB = 48
 - Status = 2
 - Solve Time = 1.299999952 sec

然后弹出一个带有此错误消息的窗口:

Oplrun 进程没有响应,您必须重新启动运行配置。

4

1 回答 1

1

我们通过电子邮件对此进行了整理。崩溃的原因是 OPL 中的一个错误。代码的问题部分是这样的:

tuple T {
  key int id;
  int intArray[0..0];
}

{T} tuples = ...;

T tupleById[1..1];
execute {
  for (var t in tuples)
    tupleById[t.id] = t;
}

问题是在脚本中分配包含数组或集合成员的元组。这会触发 OPL 中的错误,然后最终导致崩溃。tupleById一种解决方法是在不编写脚本的情况下通过以下方式进行初始化

T tupleById[id in 1..1] = first({ t | t in tuples : t.id == id});

这里的诀窍是所有生成的集合都是单例的,因为 id 是唯一的。然后我们使用first()函数从单例集中提取第一个元素以获得普通元组。

于 2019-05-28T11:44:22.137 回答