为什么我会遇到 ILOG CP Optimizer 的段错误

Why am I getting a seg fault with ILOG CP Optimizer

我是约束编程的新手,我正在尝试使用 ILOG CP 优化器将我的第一个问题建模为约束程序。我已经安装了 ILOG Optimization Suite 20.1 并成功编译并 运行 许多包含的示例文件。

我想做的是在 2 个单元上安排 5 个任务。每个任务都有一个发布时间和一个截止时间。此外,在每个单元上,每个任务都有处理时间和处理成本。

以下是我的代码。

#include <ilcp/cp.h>
#include <iostream>

using namespace std;

int main(int argc, const char * argv[]) 
{
    IloEnv env;
    try 
    {
        IloModel model(env);
        IloInt numUnits = 2;
        IloInt numTasks = 5;
        IloIntervalVarArray dummyTasks(env, numTasks);
        IloInt taskReleaseTimes[] = {0, 21, 15, 37, 3};
        IloInt taskDueTimes[] = {200, 190, 172, 194, 161};
        IloArray<IloBoolArray> unitTaskAssignment(env, numUnits);
        unitTaskAssignment[0] = IloBoolArray(env, numTasks, IloTrue, IloTrue, IloFalse, IloTrue, IloTrue);
        unitTaskAssignment[1] = IloBoolArray(env, numTasks, IloTrue, IloFalse, IloTrue, IloFalse, IloTrue);
        IloArray<IloIntArray> unitTaskTimes(env, numUnits);
        IloArray<IloNumArray> unitTaskCosts(env, numUnits);
        IloIntArray minTaskTimes(env, numTasks);
        IloIntArray maxTaskTimes(env, numTasks);
        IloNumExpr totalCost(env);
        unitTaskTimes[0] = IloIntArray(env, numTasks, 51, 67, 0, 24, 76);
        unitTaskTimes[1] = IloIntArray(env, numTasks, 32, 0, 49, 0, 102);
        unitTaskCosts[0] = IloNumArray(env, numTasks, 3.1, 3.7, 0.0, 3.4, 3.6);
        unitTaskCosts[1] = IloNumArray(env, numTasks, 3.2, 0.0, 3.9, 0.0, 3.2);
        IloArray<IloIntervalVarArray> taskUnits(env, numTasks);
        IloArray<IloIntervalVarArray> unitTasks(env, numUnits);
        
        for(IloInt i = 0; i < numTasks; i++)
        {
            IloInt minTaskTime = unitTaskTimes[0][i];
            IloInt maxTaskTime = unitTaskTimes[0][i];
            for(IloInt j = 1; j < numUnits; j++)
            {
                if(unitTaskTimes[j][i] < minTaskTime) minTaskTime = unitTaskTimes[j][i];
                if(unitTaskTimes[j][i] > maxTaskTime) maxTaskTime = unitTaskTimes[j][i];
            }
            minTaskTimes[i] = minTaskTime;
            maxTaskTimes[i] = maxTaskTime;
/*            cout << "Minimum task time for task " << i << ": " << minTaskTimes[i] << endl;*/
/*            cout << "Maximum task time for task " << i << ": " << maxTaskTimes[i] << endl;*/
        }
        
        char name[128];
        for(IloInt i = 0; i < numTasks; i++)
        {
            taskUnits[i] = IloIntervalVarArray(env, numUnits);
            sprintf(name, "dummyTask_%ld", i);
            dummyTasks[i] = IloIntervalVar(env, minTaskTimes[i], maxTaskTimes[i]);
            dummyTasks[i].setStartMin(taskReleaseTimes[i]);
            dummyTasks[i].setEndMax(taskDueTimes[i]);
            for(IloInt j = 0; j < numUnits; j++)
            {
                sprintf(name, "task%ld_in_unit%ld", j, i);
                taskUnits[i][j] = IloIntervalVar(env, unitTaskTimes[j][i], name);
                taskUnits[i][j].setOptional();
                taskUnits[i][j].setStartMin(taskReleaseTimes[i]);
                taskUnits[i][j].setEndMax(taskDueTimes[i]);
                if(!unitTaskAssignment[j][i]) taskUnits[i][j].setAbsent();
                totalCost += unitTaskCosts[j][i]*IloPresenceOf(env, taskUnits[i][j]);
            }
            model.add(IloAlternative(env, dummyTasks[i], taskUnits[i]));
        }
        
        for(IloInt j = 0; j < numUnits; j++)
        {
            unitTasks[j] = IloIntervalVarArray(env, numTasks);
            for(IloInt i = 1; i < numTasks; i++)
            {
                unitTasks[j][i] = taskUnits[i][j];
            }
            model.add(IloNoOverlap(env, unitTasks[j]));
        }
        
        model.add(IloMinimize(env, totalCost));
        
        IloCP cp(model);
        
        cp.setParameter(IloCP::TimeLimit, 20);
        if (cp.solve()) 
        {
            cout << "There's a solution." << endl;
        } 
        else 
        {
            cp.out() << "No solution found. " << std::endl;
        }
    }
    catch (IloException & ex) 
    {
        env.out() << "Caught " << ex << std::endl;
    }
    env.end();
    return 0;
}

也许可以应用更好的逻辑,我很乐意就如何更好地建模问题提出建议,但这真的不是问题所在。

问题是,如果我注释掉这一行

model.add(IloNoOverlap(env, unitTasks[j]));

一切都可以编译并且 运行 很好,但是如果我保留它,程序会编译,但在执行时会出现段错误。为什么?

以下是 valgrind 输出,如果有帮助的话:

==361075== Memcheck, a memory error detector
==361075== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==361075== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==361075== Command: ./CP_test
==361075== 
 ! --------------------------------------------------- CP Optimizer 20.1.0.0 --
 ! Minimization problem - 15 variables, 5 constraints
 ! TimeLimit            = 20
 ! Initial process time : 1.00s (0.99s extraction + 0.02s propagation)
 !  . Log search space  : 18.3 (before), 18.3 (after)
 !  . Memory usage      : 335.4 kB (before), 335.4 kB (after)
 ! Using parallel search with 8 workers.
 ! ----------------------------------------------------------------------------
 !          Best Branches  Non-fixed    W       Branch decision
                        0         15                 -
 + New bound is 17.30000
^C==361075== 
==361075== Process terminating with default action of signal 2 (SIGINT)
==361075==    at 0x4882A9A: futex_wait (futex-internal.h:141)
==361075==    by 0x4882A9A: futex_wait_simple (futex-internal.h:172)
==361075==    by 0x4882A9A: pthread_barrier_wait (pthread_barrier_wait.c:184)
==361075==    by 0xCEFA06: IlcParallel::SynchronizedMaster::workerSynchronize(IlcParallel::ThreadWorker*) (in /home/nate/Dropbox/Princeton/Maravelias/DCA_Branch_and_Cut/cplex_implementation/CP_optimizer_test_instance/CP_test)
==361075==    by 0x66F224: IlcParallelEngineI::SynchronizedMaster::workerSynchronize(IlcParallel::ThreadWorker*) (in /home/nate/Dropbox/Princeton/Maravelias/DCA_Branch_and_Cut/cplex_implementation/CP_optimizer_test_instance/CP_test)
==361075==    by 0xCF3B60: IlcParallel::SynchronizedMaster::ThreadIO::workerWaitInput() (in /home/nate/Dropbox/Princeton/Maravelias/DCA_Branch_and_Cut/cplex_implementation/CP_optimizer_test_instance/CP_test)
==361075==    by 0xCF4182: IlcParallel::ThreadWorker::startup() (in /home/nate/Dropbox/Princeton/Maravelias/DCA_Branch_and_Cut/cplex_implementation/CP_optimizer_test_instance/CP_test)
==361075==    by 0xCF5929: IlcThread::CallStartup(void*) (in /home/nate/Dropbox/Princeton/Maravelias/DCA_Branch_and_Cut/cplex_implementation/CP_optimizer_test_instance/CP_test)
==361075==    by 0x487A608: start_thread (pthread_create.c:477)
==361075==    by 0x4D0A292: clone (clone.S:95)
==361075== 
==361075== HEAP SUMMARY:
==361075==     in use at exit: 1,161,688 bytes in 353 blocks
==361075==   total heap usage: 942 allocs, 589 frees, 2,260,411 bytes allocated
==361075== 
==361075== LEAK SUMMARY:
==361075==    definitely lost: 19,728 bytes in 1 blocks
==361075==    indirectly lost: 9,752 bytes in 13 blocks
==361075==      possibly lost: 2,304 bytes in 8 blocks
==361075==    still reachable: 1,129,904 bytes in 331 blocks
==361075==                       of which reachable via heuristic:
==361075==                         stdstring          : 35 bytes in 1 blocks
==361075==         suppressed: 0 bytes in 0 blocks
==361075== Rerun with --leak-check=full to see details of leaked memory
==361075== 
==361075== For lists of detected and suppressed errors, rerun with: -s
==361075== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

如有任何建议,我们将不胜感激。请注意,我曾尝试 post 访问 IBM 论坛,但由于某种原因显然我没有权限。

你有一个分段错误,因为 unitTasks[j][0] 是空指针,因为你的数组初始化循环从 1 开始。 此外,您应该尝试在调试模式下编译(没有 -DNDEBUG),因此当使用空句柄时您会遇到断言失败。