В CPLEX_Studio129 \ opl \ examples \ opl \ sched_jobshopflex у нас есть пример работы с CPO. И CPO - правильный метод для jobhopflex.
Мне часто задают вопрос о том, как написать это как MIP, хотя CPO - это путь.
Один из способов - перечислить время с булевыми переменными решения.
Если вы хотите адаптировать модель CPO к MIP, вы можете написать следующее:
.mod
int nbJobs = ...;
int nbMchs = ...;
range Jobs = 0..nbJobs-1;
range Mchs = 0..nbMchs-1;
// Mchs is used both to index machines and operation position in job
tuple Operation {
int mch; // Machine
int pt; // Processing time
};
Operation Ops[j in Jobs][m in Mchs] = ...;
dvar int+ s[j in Jobs][o in Mchs];
dexpr int e[j in Jobs][o in Mchs]=s[j][o]+Ops[j][o].pt;
minimize max(j in Jobs) e[j][nbMchs-1];
subject to {
forall (m in Mchs,ordered i,j in Jobs, o1 in Mchs,o2 in Mchs:Ops[i][o1].mch == m && Ops[j][o2].mch == m)
(e[i][o1]<=s[j][o2]) || (e[j][o2]<=s[i][o1]);
forall (j in Jobs, o in 0..nbMchs-2)
//endBeforeStart(itvs[j][o], itvs[j][o+1]);
e[j][o]<=s[j][o+1];
}
execute {
for (var j = 0; j <= nbJobs-1; j++) {
for (var o = 0; o <= nbMchs-1; o++) {
write(s[j][o] + " ");
}
writeln("");
}
}
.dat
Params = <20, 10>;
Ops = {
<1,1,0>,
<2,1,1>,
<3,1,2>,
<4,1,3>,
<5,1,4>,
<6,1,5>,
<7,1,6>,
<8,1,7>,
<9,1,8>,
<10,1,9>,
<11,1,10>,
<12,1,11>,
<13,1,12>,
<14,1,13>,
<15,2,0>,
<16,2,1>,
<17,2,2>,
<18,2,3>,
<19,2,4>,
<20,2,5>,
<21,2,6>,
<22,2,7>,
<23,2,8>,
<24,2,9>,
<25,3,0>,
<26,3,1>,
<27,3,2>,
<28,3,3>,
<29,3,4>,
<30,3,5>,
<31,3,6>,
<32,3,7>,
<33,3,8>,
<34,3,9>,
<35,3,10>,
<36,4,0>,
<37,4,1>,
<38,4,2>,
<39,4,3>,
<40,4,4>,
<41,4,5>,
<42,4,6>,
<43,4,7>,
<44,4,8>,
<45,4,9>,
<46,4,10>,
<47,4,11>,
<48,4,12>,
<49,4,13>,
<50,5,0>
};
Modes = {
<1,3,13>,
<1,7,12>,
<2,8,9>,
<2,9,17>,
<3,7,16>,
<3,5,5>,
<4,1,8>,
<5,10,18>,
<5,7,14>,
<6,4,15>,
<6,9,20>,
<7,2,11>,
<8,8,3>,
<9,5,5>,
<9,6,17>,
<10,3,5>,
<11,7,10>,
<12,9,15>,
<12,6,18>,
<13,4,7>,
<13,1,7>,
<14,8,17>,
<15,10,10>,
<16,8,16>,
<16,4,8>,
<17,2,3>,
<18,7,14>,
<19,8,3>,
<20,10,17>,
<20,6,2>,
<21,2,19>,
<22,10,5>,
<23,3,2>,
<23,7,16>,
<24,1,16>,
<25,3,17>,
<25,7,20>,
<26,2,15>,
<27,7,1>,
<28,7,18>,
<28,6,18>,
<29,8,2>,
<30,3,20>,
<30,4,17>,
<31,7,5>,
<32,3,13>,
<33,5,13>,
<34,4,5>,
<35,5,19>,
<36,1,18>,
<36,6,7>,
<37,5,4>,
<37,3,16>,
<38,8,1>,
<39,3,12>,
<40,2,18>,
<41,4,20>,
<42,7,10>,
<42,9,15>,
<43,6,13>,
<44,4,2>,
<44,7,6>,
<45,6,12>,
<46,8,20>,
<46,2,10>,
<47,7,20>,
<47,1,3>,
<48,6,7>,
<49,8,20>,
<50,2,10>
};
Мне пришлось использовать меньший .dat, потому что в противном случае MIP работает слишком медленно. Конечно, MIP и CPO находят одну и ту же цель.
И снова CPO - это путь: https://www.slideshare.net/PhilippeLaborie/introduction-to-cp-optimizer-for-scheduling