【问题标题】:Modelling constraints in Choco solverChoco求解器中的建模约束
【发布时间】:2018-08-22 10:20:17
【问题描述】:

我正在使用 choco solver 来解决一些任务调度问题。

我有几个作业和可能的插槽(可以执行作业)。 有一些限制,例如:

  • 每个插槽只能有一个作业 (C.1)
  • 作业需要一定的时间t,并且槽有可用的持续时间d。 作业必须适合可用的持续时间:t<=d (C.2)

所以,基本上用一些基本/伪类来表达:

class Job {
    int id;
    int time;
}

class Slot {
    int id;
    int duration;
}

目前,我可以为每个作业分配一个插槽,假设作业的 id 和插槽是连续编号的

int jobCount = 5;  // 5 jobs with ids from 0 to 4
int slotCount= 20; // 20 jobs with ids from 0 to 19
Model model = new Model("Example");
IntVar[] jobs = model.intVarArray("Job", jobCount, 0, slotCount, false);
// all jobs must have different slots (C.1)
model.allDifferent(jobs).post();

// solving - details omitted, because I think it is not relevant...
Solution solution = model.getSolver().findSolution();
// assign the jobs to the slots like (pseudo-code): 
// foreach i in jobs.length do 
//     job = getJobForId(i);
//     getSlotForId(jobs[i]).setJob(job);

这按预期工作。但现在我也想对其他约束进行建模。但我坚持如何将工作/时段与时间/持续时间结合起来,因为时间和持续时间是一个因变量。

第一步,我为时间和持续时间建模了两个额外的变量:

int[] slotDurations = {10, 20, 10, 40, ..., 20} // 20 durations (d)
IntVar[] durations = model.intVarArray("Time", slotCount, slotDurations);

int[] jobTimes = {5, 16, 30, 2, 17} // 5 times (t)
IntVar[] times = model.intVarArray("Time", jobCount , jobTimes);

现在,我需要表达时间应该适合持续时间的约束(C.2)。

是否可以定义这样的约束(无效/有效的伪代码):

for(int i=0;i<jobCount;i++){
    times[i].le(durations[jobs[i]]).post();
}

还是模型完全错误?!

也许有人有解决方案或想法?!

【问题讨论】:

    标签: java constraint-programming choco


    【解决方案1】:

    如果你说每个槽只能有一个作业,那么很自然地选择slot作为你的IntVarArray,如下所示:

     IntVar[] slots = model.intVarArray("Slot", slotCount, 0, jobCount, false);
     int[] jobTimes = {0, 5, 16, 30, 2, 17};  //6(!) items; see explanation below.
     int[] slotDurations = {10, 20, 10, 40, ..., 20}; //20 items
    

    这里,slots 指向jobTime 中的项目。如果您的插槽比工作多,请注意allDifferent 约束:您最终将没有解决方案。在这种情况下,请使用修改后的约束,例如 allDifferentExcept0,以便求解器可以选择有效项目。然后,jobTimes[0] 必须是满足所有槽的条目(例如,0)。

    那你就很亲近了。你需要做的就是引入一个中间变量IntVar,比如shadowTime,它代表slots给出的顺序中的时间,像这样:

    IntVar[] shadowTime = model.intVarArray("shadowTime", slotDurations.length, 0, jobTimes.length, false); //has the jobTimes in the order indicated by slots.
    for(int i=0;i<slotCount;i++){
        model.element(shadowTime[i], jobTimes, slots[i]).post();
        //this is similar to what you wanted to achieve with 'durations[jobs[i]]' in your code
    }
    

    然后你可以在同一个循环中添加约束C.2:

    //within in the above loop:
    {    
        ...
        model.arithm(shadowTime[i], "<", slotDurations[i]).post();
    }
    

    然后您可以按照手册 (while (solver.solver(){...}) 中的说明列举所有解决方案。

    【讨论】:

    • model.element 帮助了我!可能有数百个插槽,但只有几个工作,所以我或多或少只是添加了shadow 以及与您的第二部分类似的约束。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多