16 #ifndef PAAL_GENERALISED_ASSIGNMENT_HPP
17 #define PAAL_GENERALISED_ASSIGNMENT_HPP
23 #include <boost/range/adaptor/indexed.hpp>
36 template <
typename Problem,
typename LP>
38 auto &&machine_rows = problem.get_machine_rows();
39 if (machine_rows.find(row) == machine_rows.end()) {
43 return row_deg <= 1 || (row_deg == 2 && problem.get_compare().ge(
55 template <
typename Problem,
typename GetSolution>
56 void operator()(Problem &problem,
const GetSolution &solution) {
57 auto jbegin = std::begin(problem.get_jobs());
58 auto mbegin = std::begin(problem.get_machines());
59 auto &col_idx = problem.get_col_idx();
60 auto job_to_machine = problem.get_job_to_machines();
62 for (
auto idx :
irange(col_idx.size())) {
63 if (problem.get_compare().e(solution(col_idx[idx]), 1)) {
65 std::make_pair(*(jbegin + problem.get_j_idx(idx)),
66 *(mbegin + problem.get_m_idx(idx)));
82 template <
typename Problem,
typename LP>
85 lp.set_optimization_type(lp::MINIMIZE);
87 add_variables(problem, lp);
88 add_constraints_for_jobs(problem, lp);
89 add_constraints_for_machines(problem, lp);
98 template <
typename Problem,
typename LP>
99 void add_variables(Problem &problem,
LP &lp) {
100 auto &col_idx = problem.get_col_idx();
101 col_idx.reserve(problem.get_machines_cnt() * problem.get_jobs_cnt());
102 for (
auto &&j : problem.get_jobs()) {
103 for (
auto &&m : problem.get_machines()) {
104 if (problem.get_proceeding_time()(j, m) <=
105 problem.get_machine_available_time()(m)) {
106 col_idx.push_back(lp.
add_column(problem.get_cost()(j, m)));
109 lp.
add_column(problem.get_cost()(j, m), 0, 0));
116 template <
typename Problem,
typename LP>
117 void add_constraints_for_jobs(Problem &problem,
LP &lp) {
118 auto &col_idx = problem.get_col_idx();
119 for (
auto j_idx :
irange(problem.get_jobs_cnt())) {
120 lp::linear_expression expr;
121 for (
auto m_idx :
irange(problem.get_machines_cnt())) {
122 expr += col_idx[problem.idx(j_idx, m_idx)];
124 lp.
add_row(std::move(expr) == 1.0);
129 template <
typename Problem,
typename LP>
130 void add_constraints_for_machines(Problem &problem,
LP &lp) {
131 auto &col_idx = problem.get_col_idx();
132 for (
auto m : problem.get_machines() | boost::adaptors::indexed()) {
133 auto T = problem.get_machine_available_time()(m.value());
134 lp::linear_expression expr;
136 for (
auto j : problem.get_jobs() | boost::adaptors::indexed()) {
137 auto t = problem.get_proceeding_time()(j.value(), m.value());
138 auto x = col_idx[problem.idx(j.index(), m.index())];
141 auto row = lp.
add_row(std::move(expr) <= T);
142 problem.get_machine_rows().insert(row);
147 template <
typename Init = ga_init,
148 typename RoundCondition = default_round_condition,
149 typename RelaxContition = ga_relax_condition,
150 typename SetSolution = ga_set_solution>
151 using ga_ir_components =
152 IRcomponents<Init, RoundCondition, RelaxContition, SetSolution>;
167 template <
typename MachineIter,
typename JobIter,
typename Cost,
168 typename ProceedingTime,
typename MachineAvailableTime,
169 typename JobsToMachinesOutputIterator>
172 using Job =
typename std::iterator_traits<JobIter>::value_type;
173 using Machine =
typename std::iterator_traits<MachineIter>::value_type;
176 using MachineRows = std::unordered_set<lp::row_id>;
177 using ColIdx = std::vector<lp::col_id>;
179 using ErrorMessage = boost::optional<std::string>;
185 JobIter jend,
const Cost &c,
const ProceedingTime &t,
186 const MachineAvailableTime &T,
187 JobsToMachinesOutputIterator job_to_machines)
188 : m_m_cnt(std::distance(mbegin, mend)),
189 m_j_cnt(std::distance(jbegin, jend)), m_jbegin(jbegin), m_jend(jend),
190 m_mbegin(mbegin), m_mend(mend), m_c(c), m_t(t), m_T(T),
191 m_job_to_machine(job_to_machines) {}
197 return ErrorMessage{};
203 std::size_t
idx(std::size_t j_idx, std::size_t m_idx) {
return j_idx * m_m_cnt + m_idx; }
241 return boost::make_iterator_range(m_mbegin, m_mend);
248 return boost::make_iterator_range(m_jbegin, m_jend);
260 return m_job_to_machine;
283 const std::size_t m_m_cnt;
284 const std::size_t m_j_cnt;
287 MachineIter m_mbegin;
290 const ProceedingTime &m_t;
291 const MachineAvailableTime &m_T;
292 JobsToMachinesOutputIterator m_job_to_machine;
293 const Compare m_compare;
295 MachineRows m_machine_rows;
318 template <
typename MachineIter,
typename JobIter,
typename Cost,
319 typename ProceedingTime,
typename MachineAvailableTime,
320 typename JobsToMachinesOutputIterator>
321 generalised_assignment<MachineIter, JobIter, Cost, ProceedingTime,
322 MachineAvailableTime, JobsToMachinesOutputIterator>
324 JobIter jbegin, JobIter jend,
const Cost &c,
325 const ProceedingTime &t,
326 const MachineAvailableTime &T,
327 JobsToMachinesOutputIterator jobs_to_machines) {
329 MachineIter, JobIter, Cost, ProceedingTime, MachineAvailableTime,
330 JobsToMachinesOutputIterator>(mbegin, mend, jbegin, jend, c, t, T,
358 template <
typename MachineIter,
typename JobIter,
typename Cost,
359 typename ProceedingTime,
typename MachineAvailableTime,
360 typename JobsToMachinesOutputIterator,
361 typename Components = ga_ir_components<>,
362 typename Visitor = trivial_visitor>
364 MachineIter mbegin, MachineIter mend, JobIter jbegin, JobIter jend,
365 const Cost &c,
const ProceedingTime &t,
const MachineAvailableTime &T,
366 JobsToMachinesOutputIterator jobs_to_machines,
367 Components
components = Components(), Visitor visitor = Visitor()) {
369 c, t, T, jobs_to_machines);
377 #endif // PAAL_GENERALISED_ASSIGNMENT_HPP
std::size_t idx(std::size_t j_idx, std::size_t m_idx)
std::size_t get_jobs_cnt() const
The common LP solvers base class. Responsible for:
col_id add_column(double cost_coef=0, double lb=0., double ub=lp_traits::PLUS_INF, const std::string &name="")
std::size_t get_j_idx(std::size_t idx)
ErrorMessage check_input_validity()
double get_row_sum(row_id row) const
std::size_t get_machines_cnt() const
The class for solving the Generalised Assignment problem using Iterative Rounding.
std::size_t get_m_idx(std::size_t idx)
IRResult generalised_assignment_iterative_rounding(MachineIter mbegin, MachineIter mend, JobIter jbegin, JobIter jend, const Cost &c, const ProceedingTime &t, const MachineAvailableTime &T, JobsToMachinesOutputIterator jobs_to_machines, Components components=Components(), Visitor visitor=Visitor())
Solves the Generalised Assignment problem using Iterative Rounding.
void set_lp_name(const std::string problem_name)
bool operator()(Problem &problem, const LP &lp, lp::row_id row)
MachineRows & get_machine_rows()
boost::iterator_range< JobIter > get_jobs()
auto irange(T begin, T end)
irange
generalised_assignment(MachineIter mbegin, MachineIter mend, JobIter jbegin, JobIter jend, const Cost &c, const ProceedingTime &t, const MachineAvailableTime &T, JobsToMachinesOutputIterator job_to_machines)
boost::iterator_range< MachineIter > get_machines()
JobsToMachinesOutputIterator get_job_to_machines()
int get_row_degree(row_id row) const
void operator()(Problem &problem, const GetSolution &solution)
void operator()(Problem &problem, LP &lp)
const ProceedingTime & get_proceeding_time()
row_id add_row(const double_bounded_expression &constraint=double_bounded_expression{}, const std::string &name="")
const Cost & get_cost() const
const MachineAvailableTime & get_machine_available_time()
std::pair< lp::problem_type, IRSolutionCost > IRResult
IRResult solve_iterative_rounding(Problem &problem, IRcomponents components, Visitor visitor=Visitor())
Solves an Iterative Rounding problem.
generalised_assignment< MachineIter, JobIter, Cost, ProceedingTime, MachineAvailableTime, JobsToMachinesOutputIterator > make_generalised_assignment(MachineIter mbegin, MachineIter mend, JobIter jbegin, JobIter jend, const Cost &c, const ProceedingTime &t, const MachineAvailableTime &T, JobsToMachinesOutputIterator jobs_to_machines)
Creates a generalised_assignment object.