TCPSPSuite
ebilp.hpp
1 //
2 // Created by lukas on 10.07.18.
3 //
4 
5 #ifndef TCPSPSUITE_EBILP_HPP
6 #define TCPSPSUITE_EBILP_HPP
7 
8 #include "../manager/solvers.hpp" // for get_free_N
9 #include "../util/log.hpp" // for Log
10 #include "generated_config.hpp" // for GUROBI_FOUND
11 #include "ilp.hpp" // for ILPBase
12 
13 #include <string> // for string
14 #include <vector> // for vector
15 class AdditionalResultStorage;
16 class Instance;
17 class SolverConfig;
18 namespace solvers {
19 template <unsigned int>
20 struct registry_hook;
21 }
22 
23 #if defined(GUROBI_FOUND)
24 #include "../contrib/ilpabstraction/src/ilpa_gurobi.hpp"
25 #endif
26 
27 #if defined(CPLEX_FOUND)
28 #include "../contrib/ilpabstraction/src/ilpa_cplex.hpp"
29 #endif
30 
31 template <class SolverT>
32 class EBILP : public ILPBase<SolverT> {
33 public:
34  EBILP(const Instance & instance, AdditionalResultStorage & additional,
35  const SolverConfig & sconf);
36 
37  void run();
38  static std::string get_id();
39 
40 private:
41  Log l;
42 
43  using Base = ILPBase<SolverT>;
44  using MIPSolver = typename Base::MIPSolver;
45  using Model = typename Base::Model;
46  using Variable = typename Base::Variable;
47  using Expression = typename Base::Expression;
48  using VarType = typename Base::VarType;
49  using ParamType = typename Base::ParamType;
50  using ModelStatus = typename Base::ModelStatus;
51  using Constraint = typename Base::Constraint;
52 
53  /*
54  * Job-Start <=> Event Mapping
55  *
56  * job_start_events[j][a] becomes 1 if and only if job j starts at event
57  * skip_numbers[j].first + a.
58  */
59  std::vector<std::vector<Variable>> job_start_events;
60 
61  /*
62  * Job-End <=> Event Mapping
63  *
64  * job_end_events[j][a] becomes 1 if and only if job j ends at event
65  * skip_numbers[j].first + a.
66  */
67  std::vector<std::vector<Variable>> job_end_events;
68 
69  /*
70  * event_times[a] is the point in time at which event a happens
71  */
72  std::vector<Variable> event_times;
73 
74  /*
75  * end_points[jid] is the time when job jid finishes
76  * TODO a variable should not be necessary here
77  */
78  // std::vector<Variable> end_points;
79 
80  /*
81  * usages_after_event[rid][a] contains the amount of resource <rid> used after
82  * event <a>
83  */
84  // std::vector<std::vector<Variable>> usages_after_event;
85 
86  /*
87  * event_usages[rid][a] holds the amount of resource <rid> used after event
88  * <a>
89  */
90  std::vector<std::vector<Expression>> event_usages;
91 
92  /*
93  * Skip numbers specify how many of the first and last events
94  * can be skipped for each job, saving us job_start_events and job_end_events
95  * variables (and constraints).
96  *
97  * The number of jobs that *must* be finished before j (times 2) is the
98  * number of events to skip in the beginning, the number of jobs that must
99  * start after j finishes is the number of events to skip in the end.
100  */
101  std::vector<std::pair<size_t, size_t>> skip_numbers;
102  std::vector<size_t> event_counts;
103 
104  unsigned int max_deadline;
105 
106  /* True if we use (and set) the start points in the base ILP
107  */
108  bool start_point_mode;
109 
110  /* Set to true if we use a sum trick to enforce "end after start"
111  * for every job. */
112  bool enforce_end_after_start_via_sum;
113 
114  void compute_skip_numbers() noexcept;
115 
116  void prepare_variables();
117 
118  /* For now: every job's duration variable is set fixed to its duration */
119  void prepare_duration_constraint();
120 
121  /* Enforce event ordering. TODO is this necessary? */
122  void prepare_event_constraints();
123 
124  /* Make sure every event is used once, and every job has exactly one start and
125  * end */
126  void prepare_job_event_constraints();
127 
128  /* Links events and job durations */
129  void prepare_time_constraints();
130 
131  /* Set start_points variables in base ILP */
132  void prepare_start_points_constraints();
133 
134  /* Prepare realease / deadline constraints (if start points are not used) */
135  void prepare_release_deadline_constraints();
136 
137  /* Prepare dependency constraints (if start points are not used) */
138  void prepare_dependency_constraints();
139 
140  /* Create event_usages expressions */
141  void prepare_usage_expressions();
142 
143  void prepare();
144 
145  /* Only necessary if start points are not used */
146  void create_solution();
147 };
148 
149 // Register the solver
150 namespace solvers {
151 #if defined(GUROBI_FOUND)
152 template <>
153 struct registry_hook<
154  solvers::get_free_N<EBILP<ilpabstraction::GurobiInterface>>()>
155 {
156  constexpr static unsigned int my_N =
157  solvers::get_free_N<EBILP<ilpabstraction::GurobiInterface>>();
158 
159  auto
160  operator()()
161  {
162  return solvers::register_class<EBILP<ilpabstraction::GurobiInterface>,
163  my_N>{}();
164  }
165 };
166 #endif
167 
168 #if defined(CPLEX_FOUND)
169 template <>
170 struct registry_hook<
171  solvers::get_free_N<EBILP<ilpabstraction::CPLEXInterface>>()>
172 {
173  constexpr static unsigned int my_N =
174  solvers::get_free_N<EBILP<ilpabstraction::CPLEXInterface>>();
175 
176  auto
177  operator()()
178  {
179  return solvers::register_class<EBILP<ilpabstraction::CPLEXInterface>,
180  my_N>{}();
181  }
182 };
183 #endif
184 } // namespace solvers
185 
186 #endif // TCPSPSUITE_EBILP_HPP
Instance
a TCPSP instance
Definition: instance.hpp:24