Как исправить ошибки при использовании opl.end () в главном цикле управления потоком - PullRequest
1 голос
/ 26 мая 2019

Я запускаю десятки тысяч тестов, используя цикл внутри блока управления потоком main.Каждый запуск цикла порождает новую модель OPL, используя назначенный файл данных .dat и файл модели .mod (который отделен от файла .mod участника программы пакетной обработки, который содержит только блок управления потоком main).

Поскольку при каждом запуске цикла создается новая модель, использование памяти строится и накапливается до тех пор, пока не произойдет сбой среды IDE, когда я не использую операторы .end() для закрытия всех структур данных, созданных для каждого теста.Хотя большинство структур данных закрываются очень хорошо, я обнаружил, что opl.end(); приводит к сбою тестера.

Как мне закрыть модели OPL без сбоя тестера?

Я пробовал и приложение oplide, и интерфейс командной строки oplrun, как в macOS, так и в Windows (хотя в конце мне нужно было запустить тесты в 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() line):

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 не отвечает, необходимо повторно запустить конфигурацию запуска.

1 Ответ

1 голос
/ 28 мая 2019

Мы разобрались с этим по электронной почте.Причиной сбоя является ошибка в 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});

. Хитрость заключается в том, что все сгенерированные наборы являются синглетонами, поскольку идентификаторы уникальны.Затем мы используем функцию first () , чтобы извлечь первый элемент из наборов-одиночек, чтобы получить простые кортежи.

...