French Flag Version française

Exercise Session 8: Advanced Modeling in Mixed Integer Programming

Reminders

Install or-tools

No need to re-install or-tools if you already did it in the last session: just create another subdirectory td8 next to td7 and td8, and do all your work there:
mkdir td8  # Inside the installed ortools directory
cd td8
wget --no-cache http://fabien.viger.free.fr/oc/td8/test.tar.gz
tar xf test.tar.gz
make ortools_test

Exercise 1: Job assignment

  1. Copy the code files from exercise 2 of last session: job.h, job.cc.
    We now add mutual exclusion constraints.
    For example: "job X, job Y and job Z are mutually exclusive on the same machine (whichever machine it might be)":
    if job Y runs on machine #4, then neither job X nor job Z can run on machine #4 (but they may run on another machine).
    Implement in file job1.cc (you may start by copying job.cc) the function BestJobAssignment1() described in job1.h.
    #ifndef __JOB1_H
    #define __JOB1_H
    
    #include "job.h"
    
    // Like BestJobAssignment(), but we add local exclusivity constraints:
    // For each exclusivity list L in "local_exclusive",
    // any 2 jobs in L may never run on the same machine.
    vector<int> BestJobAssignment1(const vector<Resources>& jobs,
                                   const vector<Resources>& machines,
                                   const vector<vector<int>>& local_exclusive);
    
    #endif  // __JOB1_H
    Test: make job1

    TO SUBMIT: job1.cc (don't change the .h!)

  2. We go back to the initial version, without the local exclusivity constraints, and now we add local dependency constraints.
    For example: "If job X run on a machine, then job Y needs to also run on that same machine".
    NOTE: This question could totally keep the exclusivity constraints: it would be no problem for the MIP model. But it would prevent you from skipping the previous question (if you can't find a way to do it).

    Implement in file job2.cc (you can copy job.cc) the function BestJobAssignment2() described in job2.h.
    #ifndef __JOB2_H
    #define __JOB2_H
    
    #include "job.h"
    
    #include <utility>
    using std::pair;
    
    // Like BestJobAssignment1(), but we add local dependency constraints:
    // for each pair (A, B) in "local_dep", job A depends on job B locally, which
    // means that if job A run on some machine, then job B also runs, and runs on
    // the same machine.
    vector<int> BestJobAssignment2(const vector<Resources>& jobs,
                                   const vector<Resources>& machines,
                                   const vector<pair<int, int>>& local_dep);
    
    #endif  // __JOB2_H
    Test: make job2

    TO SUBMIT: job2.cc (don't change the .h!)

  3. We go back to the base version and now we add global exclusivity constraints.
    For example: "If job X runs (on any machine), then job Y cannot run (even on another machine)".
    Implement in file job3.cc (you can copy job.cc) the function BestJobAssignment3() described in job3.h.
    #ifndef __JOB3_H
    #define __JOB3_H
    
    #include "job.h"
    
    // Like BestJobAssignment1(), mais the exclusivity is global:
    // 2 "exclusive" jobs can't both be run, even on different machines.
    // But each of them can run if the other doesn't.
    vector<int> BestJobAssignment3(const vector<Resources>& jobs,
                                   const vector<Resources>& machines,
                                   const vector<vector<int>>& global_exclusive);
    
    #endif  // __JOB3_H
    Test: make job3

    TO SUBMIT: job3.cc (don't change the .h!)

  4. We go back to the base version and now we add global inter-dependency constraints.
    For example: "job X and job Y need each other, but may run on different machines. So if job X runs, then job Y runs (possibly on a different machine), and vice-versa.
    Implement in file job4.cc (you may copy job.cc) the function BestJobAssignment4() described in job4.h.
    #ifndef __JOB4_H
    #define __JOB4_H
    
    #include "job.h"
    
    #include <utility>
    using std::pair;
    
    // Like BestJobAssignment2(), but dependencies are bidirectionnal and global:
    // each pair (A, B) in "global_dep" implies that job A and B need each other:
    // if one of them runs, the other must run too (not necessarily on the same
    // machine).
    vector<int> BestJobAssignment4(const vector<Resources>& jobs,
                                   const vector<Resources>& machines,
                                   const vector<pair<int, int>>& global_dep);
    
    #endif  // __JOB4_H
    Test: make job4

    TO SUBMIT: job4.cc (don't change the .h!)


Exercise 2: Assignement of Students to Courses

You are tasked with assigning students to courses. Your objective is to avoid generating a really bad course assignment for a student. So we'll focus on the worst total score among all students: this "unluckiest" student shouldn't be too bad. The total score of a student is the sum of scores he gave to each course that he ends up being assigned to. In other words, your objective is to maximize the minimum total score among all students.
Test: make students

TO SUBMIT: students.cc


Exercice 3: Too Big For Mip

  1. Implement in file job0.cc the function BestJobAssignment0() described in job0.h.

    Hints:
    #ifndef __JOB0_H
    #define __JOB0_H
    
    #include "job.h"
    
    // Like the original BestJobAssignment() (without exotic constraints),
    // but this time:
    // 1) Each job yields a given "profit" if it runs, and you want to maximize
    //    the total profit of assigned jobs.
    // 2) You must be able to solve much larger models.
    // 3) You may not spend more than 10 seconds.
    // 4) Which also implies that you don't need to return the optimal
    //    solution: your solution will be scored by its quality, i.e. the
    //    total profit it yields (it will of course need to be a valid
    //    solution).
    vector<int> BestJobAssignment0(const vector<Resources>& jobs,
                                   const vector<double>& profits,
                                   const vector<Resources>& machines);
    
    #endif  // __JOB0_H
    Test: make job0

    TO SUBMIT: job0.cc (don't change the .h!)