00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "model.h"
00022
00023 using namespace Udine;
00024
00025
00026
00027 void Model::generateHardConstraints() {
00028
00029 Instance &i = instance;
00030 Neighbourhood &def = definition;
00031 int p, r, c;
00032 int u, ui;
00033 int f;
00034
00035
00036 for (c = 0; c < i.getCourseCount(); c++) {
00037 IloExpr sum(env);
00038 for (p = 0; p < i.getPeriodCount(); p++)
00039 for (r = 0; r < i.getRoomCount(def.type); r++)
00040 sum += vars.x[p][r][c];
00041 constraints.add(sum == i.getCourse(c).lectures);
00042 sum.end();
00043 }
00044
00045
00046 for (p = 0; p < i.getPeriodCount(); p++) {
00047 IloExpr sum(env);
00048 for (c = 0; c < i.getCourseCount(); c++)
00049 for (r = 0; r < i.getRoomCount(def.type); r++)
00050 sum += vars.x[p][r][c];
00051 constraints.add(sum <= i.getRoomTotalMultiplicity(def.type));
00052 sum.end();
00053 }
00054
00055
00056 for (p = 0; p < i.getPeriodCount(); p++)
00057 for (r = 0; r < i.getRoomCount(def.type); r++) {
00058 IloExpr sum(env);
00059 for (c = 0; c < i.getCourseCount(); c++)
00060 sum += vars.x[p][r][c];
00061 constraints.add(sum <= i.getRoomMultiplicity(def.type, r));
00062 sum.end();
00063 }
00064
00065
00066 for (p = 0; p < i.getPeriodCount(); p++)
00067 for (u = 0; u < i.getCurriculumCount(); u++)
00068 if (config.getParam(UseSpecialOrderedSets)) {
00069 IloNumVarArray sum(env);
00070 for (ui = 0; ui < i.getCurriculum(u).courseIds.size(); ui++) {
00071 c = i.getCurriculum(u).courseIds.at(ui);
00072 for (r = 0; r < i.getRoomCount(def.type); r++)
00073 sum.add(vars.x[p][r][c]);
00074 }
00075 model.add(IloSOS1(env, sum));
00076 sum.end();
00077 } else {
00078 IloExpr sum(env);
00079 for (ui = 0; ui < i.getCurriculum(u).courseIds.size(); ui++) {
00080 c = i.getCurriculum(u).courseIds.at(ui);
00081 for (r = 0; r < i.getRoomCount(def.type); r++)
00082 sum += vars.x[p][r][c];
00083 }
00084 constraints.add(sum <= 1);
00085 sum.end();
00086 }
00087
00088
00089 for (f = 0; f < i.getRestrictionCount(); f++)
00090 for (r = 0; r < i.getRoomCount(def.type); r++)
00091 constraints.add(vars.x[i.getRestriction(f).period][r][i.getRestriction(f).courseId] == 0);
00092 }
00093
00094
00095
00096 void Model::generateMinCourseDays() {
00097
00098 Instance &i = instance;
00099 Neighbourhood &def = definition;
00100 int p, d, r, c;
00101
00102 if (def.type == Surface || (def.type == Monolithic && !config.getParam(UseAdditionalVariables))) {
00103
00104
00105 for (c = 0; c < i.getCourseCount(); c++)
00106 for (d = 0; d < i.getDayCount(); d++)
00107 for (p = d * i.getPeriodsPerDayCount(); p < (d + 1) * i.getPeriodsPerDayCount(); p++) {
00108 IloExpr sum(env);
00109 for (r = 0; r < i.getRoomCount(def.type); r++)
00110 sum += vars.x[p][r][c];
00111 constraints.add(sum - vars.courseDays[c][d] <= 0);
00112 }
00113
00114 if (!config.getParam(UsePreprocessingFriendlyFormulation))
00115 for (c = 0; c < i.getCourseCount(); c++)
00116 for (d = 0; d < i.getDayCount(); d++) {
00117 IloExpr sum(env);
00118 for (p = d * i.getPeriodsPerDayCount(); p < (d + 1) * i.getPeriodsPerDayCount(); p++)
00119 for (r = 0; r < i.getRoomCount(def.type); r++)
00120 sum += vars.x[p][r][c];
00121 constraints.add(sum - vars.courseDays[c][d] >= 0);
00122 sum.end();
00123 }
00124
00125
00126 if (config.getParam(UseStaticImpliedBounds))
00127 for (c = 0; c < i.getCourseCount(); c++)
00128 for (d = 0; d < i.getDayCount(); d++) {
00129 IloExpr sum(env);
00130 for (p = d * i.getPeriodsPerDayCount(); p < (d + 1) * i.getPeriodsPerDayCount(); p++)
00131 for (r = 0; r < i.getRoomCount(def.type); r++)
00132 sum += vars.x[p][r][c];
00133 constraints.add(sum + i.getCourse(c).minWorkingDays - i.getCourse(c).lectures - vars.courseMinDayViolations[c] <= 1);
00134 sum.end();
00135 }
00136
00137 }
00138
00139 if (def.type == Monolithic && config.getParam(UseAdditionalVariables)) {
00140
00141
00142 for (c = 0; c < i.getCourseCount(); c++)
00143 for (d = 0; d < i.getDayCount(); d++)
00144 for (p = d * i.getPeriodsPerDayCount(); p < (d + 1) * i.getPeriodsPerDayCount(); p++)
00145 constraints.add(vars.coursePeriods[c][p] - vars.courseDays[c][d] <= 0);
00146 if (!config.getParam(UsePreprocessingFriendlyFormulation))
00147 for (c = 0; c < i.getCourseCount(); c++)
00148 for (d = 0; d < i.getDayCount(); d++) {
00149 IloExpr sum(env);
00150 for (p = d * i.getPeriodsPerDayCount(); p < (d + 1) * i.getPeriodsPerDayCount(); p++)
00151 sum += vars.coursePeriods[c][p];
00152 constraints.add(sum - vars.courseDays[c][d] >= 0);
00153 sum.end();
00154 }
00155
00156
00157 if (config.getParam(UseStaticImpliedBounds))
00158 for (c = 0; c < i.getCourseCount(); c++)
00159 for (d = 0; d < i.getDayCount(); d++) {
00160 IloExpr sum(env);
00161 for (p = d * i.getPeriodsPerDayCount(); p < (d + 1) * i.getPeriodsPerDayCount(); p++)
00162 sum += vars.coursePeriods[c][p];
00163 constraints.add(sum + i.getCourse(c).minWorkingDays - i.getCourse(c).lectures - vars.courseMinDayViolations[c] <= 1);
00164 sum.end();
00165 }
00166 }
00167
00168
00169 for (c = 0; c < i.getCourseCount(); c++) {
00170 IloExpr sum(env);
00171 for (d = 0; d < i.getDayCount(); d++)
00172 sum += vars.courseDays[c][d];
00173 constraints.add(sum + vars.courseMinDayViolations[c] - i.getCourse(c).minWorkingDays >= 0);
00174 sum.end();
00175 }
00176
00177
00178 if (config.getParam(UseStaticImpliedBounds))
00179 for (c = 0; c < i.getCourseCount(); c++) {
00180 IloExpr sum(env);
00181 for (d = 0; d < i.getDayCount(); d++)
00182 sum += vars.courseDays[c][d];
00183 constraints.add(sum >= 1);
00184 sum.end();
00185 }
00186
00187
00188 if (config.getParam(UseStaticImpliedBounds))
00189 for (c = 0; c < i.getCourseCount(); c++)
00190 constraints.add(vars.courseMinDayViolations[c] <= i.getCourse(c).minWorkingDays - 1);
00191
00192 }
00193
00194
00195 void Model::generateCompactness() {
00196
00197 Instance &i = instance;
00198 Neighbourhood &def = definition;
00199 int p, d, r, c;
00200 int u, ui;
00201
00202
00203
00204 for (u = 0; u < i.getProperCurriculumCount(); u++)
00205 for (d = 0; d < i.getDayCount(); d++) {
00206 IloExpr sumMorning(env);
00207 IloExpr sumEvening(env);
00208 for (ui = 0; ui < i.getCurriculum(u).courseIds.size(); ui++) {
00209 c = i.getCurriculum(u).courseIds.at(ui);
00210 p = d * i.getPeriodsPerDayCount();
00211 if (def.type != Surface && config.getParam(UseAdditionalVariables))
00212 sumMorning += vars.coursePeriods[c][p] - vars.coursePeriods[c][p + 1];
00213 else for (r = 0; r < i.getRoomCount(def.type); r++)
00214 sumMorning += vars.x[p][r][c] - vars.x[p + 1][r][c];
00215 p = (d + 1) * i.getPeriodsPerDayCount() - 1;
00216 if (def.type != Surface && config.getParam(UseAdditionalVariables))
00217 sumEvening += vars.coursePeriods[c][p] - vars.coursePeriods[c][p - 1];
00218 else for (r = 0; r < i.getRoomCount(def.type); r++)
00219 sumEvening += vars.x[p][r][c] - vars.x[p - 1][r][c];
00220 }
00221 constraints.add(sumMorning - vars.singletonChecks[u][d][0] <= 0);
00222 if ((def.type == Surface && config.getParam(UseHeuristicCompactnessAtSurface))
00223 || (def.type == FixDay && config.getParam(UseHeuristicCompactnessInDayDives)))
00224 constraints.add(sumEvening - vars.singletonChecks[u][d][0] <= 0);
00225 else
00226 constraints.add(sumEvening - vars.singletonChecks[u][d][1] <= 0);
00227 sumMorning.end();
00228 sumEvening.end();
00229 }
00230
00231 for (u = 0; u < i.getProperCurriculumCount(); u++)
00232 for (d = 0; d < i.getDayCount(); d++)
00233 for (p = d * i.getPeriodsPerDayCount() + 1;
00234 p < (d + 1) * i.getPeriodsPerDayCount() - 1; p++) {
00235 IloExpr sumInbetween(env);
00236 for (ui = 0; ui < i.getCurriculum(u).courseIds.size(); ui++) {
00237 c = i.getCurriculum(u).courseIds.at(ui);
00238 if (def.type != Surface && config.getParam(UseAdditionalVariables))
00239 sumInbetween += vars.coursePeriods[c][p] - vars.coursePeriods[c][p + 1] - vars.coursePeriods[c][p - 1];
00240 else for (r = 0; r < i.getRoomCount(def.type); r++)
00241 sumInbetween += vars.x[p][r][c] - vars.x[p + 1][r][c] - vars.x[p - 1][r][c];
00242 }
00243 int s = p - d * i.getPeriodsPerDayCount() + 1;
00244 if ((def.type == Surface && config.getParam(UseHeuristicCompactnessAtSurface))
00245 || (def.type == FixDay && config.getParam(UseHeuristicCompactnessInDayDives)))
00246 constraints.add(sumInbetween - vars.singletonChecks[u][d][0] <= 0);
00247 else
00248 constraints.add(sumInbetween - vars.singletonChecks[u][d][s] <= 0);
00249 sumInbetween.end();
00250 }
00251 }
00252
00253
00254 void Model::generateRoomStability() {
00255
00256 Instance &i = instance;
00257 Neighbourhood &def = definition;
00258 int p, r, c;
00259
00260
00261
00262 for (c = 0; c < i.getCourseCount(); c++)
00263 for (r = 0; r < i.getRoomCount(def.type); r++)
00264 for (p = 0; p < i.getPeriodCount(); p++)
00265 constraints.add(vars.courseRooms[c][r] - vars.x[p][r][c] >= 0);
00266 if (!config.getParam(UsePreprocessingFriendlyFormulation))
00267 for (c = 0; c < i.getCourseCount(); c++)
00268 for (r = 0; r < i.getRoomCount(def.type); r++) {
00269 IloExpr sum(env);
00270 for (p = 0; p < i.getPeriodCount(); p++)
00271 sum += vars.x[p][r][c];
00272
00273 constraints.add(sum - vars.courseRooms[c][r] >= 0);
00274 sum.end();
00275 }
00276
00277 if (config.getParam(Udine::UseStaticImpliedBounds)) {
00278 for (c = 0; c < i.getCourseCount(); c++) {
00279 IloExpr sum(env);
00280 for (r = 0; r < i.getRoomCount(def.type); r++)
00281 sum += vars.courseRooms[c][r];
00282 constraints.add(sum >= 1);
00283 sum.end();
00284 }
00285 }
00286
00287 if (config.getParam(UseZeroRoomStability)) {
00288 for (c = 0; c < i.getCourseCount(); c++)
00289 for (r = 0; r < i.getRoomCount(def.type); r++) {
00290 IloExpr sum(env);
00291 for (p = 0; p < i.getPeriodCount(); p++)
00292 sum += vars.x[p][r][c];
00293 sum -= i.getCourse(c).lectures * vars.courseRooms[c][r];
00294 constraints.add(sum == 0);
00295 sum.end();
00296 }
00297 for (c = 0; c < i.getCourseCount(); c++) {
00298 IloExpr sum(env);
00299 for (r = 0; r < i.getRoomCount(def.type); r++)
00300 sum += vars.courseRooms[c][r];
00301 constraints.add(sum == 1);
00302 sum.end();
00303 }
00304 }
00305 }
00306
00307
00308 void Model::generateCoursePeriods() {
00309
00310 Instance &i = instance;
00311 Neighbourhood &def = definition;
00312 int c, p, r;
00313 int u, ui;
00314
00315
00316 for (c = 0; c < i.getCourseCount(); c++) {
00317 IloExpr sum(env);
00318 for (p = 0; p < i.getPeriodCount(); p++)
00319 sum += vars.coursePeriods[c][p];
00320 constraints.add(sum == i.getCourse(c).lectures);
00321 sum.end();
00322 }
00323
00324
00325 for (p = 0; p < i.getPeriodCount(); p++)
00326 for (c = 0; c < i.getCourseCount(); c++) {
00327 IloExpr sum(env);
00328 for (r = 0; r < i.getRoomCount(def.type); r++)
00329 sum += vars.x[p][r][c];
00330 constraints.add(vars.coursePeriods[c][p] - sum == 0);
00331 constraints.add(i.getCourse(c).lectures * vars.coursePeriods[c][p] - sum >= 0);
00332 sum.end();
00333 }
00334
00335
00336 for (p = 0; p < i.getPeriodCount(); p++) {
00337 IloExpr sum(env);
00338 for (c = 0; c < i.getCourseCount(); c++)
00339 sum += vars.coursePeriods[c][p];
00340 constraints.add(sum <= i.getRoomTotalMultiplicity(def.type));
00341 sum.end();
00342 }
00343
00344
00345 for (p = 0; p < i.getPeriodCount(); p++)
00346 for (u = 0; u < i.getCurriculumCount(); u++) {
00347 IloExpr sum(env);
00348 for (ui = 0; ui < i.getCurriculum(u).courseIds.size(); ui++) {
00349 IloInt c = i.getCurriculum(u).courseIds.at(ui);
00350 sum += vars.coursePeriods[c][p];
00351 }
00352 constraints.add(sum <= 1);
00353 sum.end();
00354 }
00355
00356
00357 if (config.getParam(UseSpecialOrderedSets)) {
00358 IloNumVarArray sum(env);
00359 for (ui = 0; ui < i.getCurriculum(u).courseIds.size(); ui++) {
00360 c = i.getCurriculum(u).courseIds.at(ui);
00361 sum.add(vars.coursePeriods[i.getCurriculum(u).courseIds.at(ui)][p]);
00362 }
00363 model.add(IloSOS1(env, sum));
00364 sum.end();
00365 }
00366
00367
00368 int clique, ci;
00369 if (config.getParam(UseStaticCliqueCutsInDives))
00370 for (p = 0; p < i.getPeriodCount(); p++)
00371 for (clique = 0; clique < conflictGraph.cliques.size(); clique++)
00372 if (config.getParam(UseSpecialOrderedSets)) {
00373 IloNumVarArray sum(env);
00374 for(ci = 0; ci < conflictGraph.cliques.at(clique).size(); ci++)
00375 sum.add(vars.coursePeriods[conflictGraph.cliques[clique][ci]][p]);
00376 model.add(IloSOS1(env, sum));
00377 } else {
00378 IloExpr sum(env);
00379 for(ci = 0; ci < conflictGraph.cliques.at(clique).size(); ci++)
00380 sum += vars.coursePeriods[conflictGraph.cliques[clique][ci]][p];
00381 constraints.add(sum <= 1);
00382 }
00383 }
00384
00385
00386 void Model::generateNeighbourhood() {
00387
00388 Instance &i = instance;
00389 Neighbourhood &def = definition;
00390 int p, r;
00391
00392
00393 std::vector<CoursePeriodPair>::iterator itFixPeriod;
00394 for (itFixPeriod = def.fixPeriod.begin(); itFixPeriod != def.fixPeriod.end(); itFixPeriod++) {
00395 IloExpr sum(env);
00396 for (r = 0; r < i.getRoomCount(def.type); r++)
00397 sum += vars.x[itFixPeriod->period][r][itFixPeriod->course];
00398 constraints.add(sum == 1);
00399 if (def.type != Surface && config.getParam(UseAdditionalVariables))
00400 constraints.add(vars.coursePeriods[itFixPeriod->course][itFixPeriod->period] == 1);
00401 sum.end();
00402 }
00403
00404
00405 std::vector<CourseDayNumberTriple>::iterator itFixDay;
00406 for (itFixDay = def.fixDay.begin(); itFixDay != def.fixDay.end(); itFixDay++) {
00407 IloExpr sumXes(env);
00408 for (p = itFixDay->day * i.getPeriodsPerDayCount(); p < (itFixDay->day + 1) * i.getPeriodsPerDayCount(); p++)
00409 for (r = 0; r < i.getRoomCount(def.type); r++)
00410 sumXes += vars.x[p][r][itFixDay->course];
00411 constraints.add(sumXes == itFixDay->events);
00412 sumXes.end();
00413 }
00414
00415
00416 if (def.type != Surface && config.getParam(UseAdditionalVariables))
00417 for (itFixDay = def.fixDay.begin(); itFixDay != def.fixDay.end(); itFixDay++) {
00418 IloExpr sumPeriods(env);
00419 for (p = itFixDay->day * i.getPeriodsPerDayCount();
00420 p < (itFixDay->day + 1) * i.getPeriodsPerDayCount(); p++)
00421 sumPeriods += vars.coursePeriods[itFixDay->course][p];
00422 constraints.add(sumPeriods == itFixDay->events);
00423 sumPeriods.end();
00424 }
00425
00426
00427 std::vector<CoursePeriodPair>::iterator it3;
00428 for (it3 = def.preprocessAway.begin(); it3 != def.preprocessAway.end(); it3++) {
00429 for (r = 0; r < i.getRoomCount(def.type); r++)
00430 constraints.add(vars.x[(*it3).period][r][(*it3).course] == 0);
00431 if (def.type != Surface && config.getParam(UseAdditionalVariables))
00432 constraints.add(vars.coursePeriods[(*it3).course][(*it3).period] == 0);
00433 }
00434 }
00435
00436
00437 void Model::generateObjectiveComponents() {
00438
00439 Instance &i = instance;
00440 Neighbourhood &def = definition;
00441 int p, d, r, c, u;
00442
00443 if (def.type == Monolithic || def.type == Surface) {
00444 IloExpr sumPeriodSpread(env);
00445 for (c = 0; c < i.getCourseCount(); c++)
00446 sumPeriodSpread += config.getWeights(def.type).wMinDays * vars.courseMinDayViolations[c];
00447 constraints.add(sumPeriodSpread - vars.penaltyPeriodSpread == 0);
00448 constraints.add(vars.penaltyPeriodSpread >= 0);
00449 obj += vars.penaltyPeriodSpread;
00450 }
00451
00452 if (def.type != FixPeriod) {
00453 int s;
00454 IloExpr sumPeriodSingletons(env);
00455 for (u = 0; u < i.getProperCurriculumCount(); u++)
00456 for (d = 0; d < i.getDayCount(); d++)
00457 if ((def.type == Surface && config.getParam(UseHeuristicCompactnessAtSurface))
00458 || (def.type == FixDay && config.getParam(UseHeuristicCompactnessInDayDives)))
00459 sumPeriodSingletons += config.getWeights(def.type).wCompactness * vars.singletonChecks[u][d][0];
00460 else for (s = 0; s < i.getCheckCount(); s++)
00461 sumPeriodSingletons += config.getWeights(def.type).wCompactness * vars.singletonChecks[u][d][s];
00462 constraints.add(sumPeriodSingletons - vars.penaltyPeriodSingletons == 0);
00463 constraints.add(vars.penaltyPeriodSingletons >= 0);
00464 obj += vars.penaltyPeriodSingletons;
00465 }
00466
00467
00468 IloExpr sumRoomCapacity(env);
00469 for (r = 0; r < i.getRoomCount(def.type); r++)
00470 for (c = 0; c < i.getCourseCount(); c++)
00471 if (i.getCourse(c).students > i.getRoomPerEventCapacity(def.type, r))
00472 for (p = 0; p < i.getPeriodCount(); p++)
00473 sumRoomCapacity += config.getWeights(def.type).wRoomCapacity *
00474 vars.x[p][r][c] * (i.getCourse(c).students - i.getRoomPerEventCapacity(def.type, r));
00475 constraints.add(sumRoomCapacity - vars.penaltyRoomCapacity == 0);
00476 constraints.add(vars.penaltyRoomCapacity >= 0);
00477 obj += vars.penaltyRoomCapacity;
00478
00479 IloExpr sumRoomStability(env);
00480
00481 if (!config.getParam(UseZeroRoomStability)) {
00482 for (c = 0; c < i.getCourseCount(); c++)
00483 for (r = 0; r < i.getRoomCount(def.type); r++)
00484 sumRoomStability += config.getWeights(def.type).wRoomStability * vars.courseRooms[c][r];
00485 sumRoomStability -= config.getWeights(def.type).wRoomStability * i.getCourseCount();
00486 constraints.add(sumRoomStability - vars.penaltyRoomStability == 0);
00487 constraints.add(vars.penaltyRoomStability >= 0);
00488 obj += vars.penaltyRoomStability;
00489 }
00490
00491 }
00492
00493
00494 void Model::generateObjective() {
00495
00496 Instance &i = instance;
00497 Neighbourhood &def = definition;
00498 int p, d, r, c, u;
00499
00500
00501 if (def.type == FixPeriod || def.type == FixDay) {
00502 obj += config.getWeights(def.type).wMinDays * def.penaltyMinCourseDays;
00503 } else {
00504 for (c = 0; c < i.getCourseCount(); c++)
00505 obj += config.getWeights(def.type).wMinDays
00506 * vars.courseMinDayViolations[c];
00507 }
00508
00509
00510 if (def.type == FixPeriod) {
00511 obj += config.getWeights(def.type).wCompactness * def.penaltyCompactness;
00512 } else {
00513 int s;
00514 for (u = 0; u < i.getProperCurriculumCount(); u++)
00515 for (d = 0; d < i.getDayCount(); d++)
00516 if ((def.type == Surface && config.getParam(UseHeuristicCompactnessAtSurface))
00517 || (def.type == FixDay && config.getParam(UseHeuristicCompactnessInDayDives)))
00518 obj += config.getWeights(def.type).wCompactness * vars.singletonChecks[u][d][0];
00519 else for (s = 0; s < i.getCheckCount(); s++)
00520 obj += config.getWeights(def.type).wCompactness * vars.singletonChecks[u][d][s];
00521 }
00522
00523
00524 for (r = 0; r < i.getRoomCount(def.type); r++)
00525 for (c = 0; c < i.getCourseCount(); c++)
00526 if (i.getCourse(c).students > i.getRoomPerEventCapacity(def.type, r))
00527 for (p = 0; p < i.getPeriodCount(); p++)
00528 obj += config.getWeights(def.type).wRoomCapacity *
00529 vars.x[p][r][c] * (i.getCourse(c).students - i.getRoomPerEventCapacity(def.type, r));
00530
00531
00532 if (!config.getParam(UseZeroRoomStability)) {
00533 for (c = 0; c < i.getCourseCount(); c++)
00534 for (r = 0; r < i.getRoomCount(def.type); r++)
00535 obj += config.getWeights(def.type).wRoomStability * vars.courseRooms[c][r];
00536 obj -= config.getWeights(def.type).wRoomStability * i.getCourseCount();
00537 }
00538
00539 }