在主流控制循环中使用opl.end()时如何解决错误

时间:2019-05-26 19:50:08

标签: cplex opl cp-optimizer

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

由于每次循环运行都会创建一个新模型,因此内存使用量会不断增加,直到我不使用main语句关闭为每个测试创建的所有数据结构时最终导致IDE崩溃为止。虽然大多数数据结构都很好,但我发现.end()使测试仪崩溃了。

如何在不使测试仪崩溃的情况下关闭OPL模型?

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

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

oplrun

使用以下方法尝试关闭它们:

// 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();

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

这是我正在使用的代码的简化版本。我创建了一个运行配置,其中仅包含此批处理运行程序data.end(); opl.end(); // Causes it to crash cp.end(); def.end(); source.end(); 文件,其引用的模型文件和数据文件存储在其他位置:

.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!

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

  

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

1 个答案:

答案 0 :(得分: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;
}

问题在于脚本中包含数组或set成员的元组的分配。这会触发OPL中的错误,最终导致崩溃。一种解决方法是初始化tupleById,而无需通过

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

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