我正在使用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进程没有响应,您必须重新启动运行配置。
答案 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()函数从单例集中提取第一个元素以获得简单的元组。