GEDLIB  1.0
lsap_solver.ipp
Go to the documentation of this file.
1 /***************************************************************************
2 * *
3 * Copyright (C) 2018 by David B. Blumenthal *
4 * *
5 * This file is part of GEDLIB. *
6 * *
7 * GEDLIB is free software: you can redistribute it and/or modify it *
8 * under the terms of the GNU Lesser General Public License as published *
9 * by the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * GEDLIB is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU Lesser General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with GEDLIB. If not, see <http://www.gnu.org/licenses/>. *
19 * *
20 ***************************************************************************/
21 
27 #ifndef SRC_UTIL_LSAP_SOLVER_IPP_
28 #define SRC_UTIL_LSAP_SOLVER_IPP_
29 
30 namespace ged {
31 
33 LSAPSolver(const DMatrix * cost_matrix) :
34 cost_matrix_{cost_matrix},
35 greedy_method_{BASIC},
36 solve_optimally_{true},
37 minimal_cost_{0.0},
38 row_to_col_assignments_(),
39 col_to_row_assignments_(),
40 dual_var_rows_(num_rows()),
41 dual_var_cols_(num_cols()) {}
42 
45 cost_matrix_{nullptr},
46 greedy_method_{BASIC},
47 solve_optimally_{true},
48 minimal_cost_{0.0},
49 row_to_col_assignments_(),
50 col_to_row_assignments_(),
51 dual_var_rows_(),
52 dual_var_cols_() {}
53 
54 void
57  cost_matrix_ = cost_matrix;
59 }
60 
61 void
63 set_greedy_method(const GreedyMethod & greedy_method) {
64  solve_optimally_ = false;
65  greedy_method_ = greedy_method;
66 }
67 
68 void
71  solve_optimally_ = true;
72 }
73 
74 void
77  minimal_cost_ = 0.0;
78  row_to_col_assignments_.clear();
79  col_to_row_assignments_.clear();
80  row_to_col_assignments_.push_back(std::vector<std::size_t>(num_rows()));
81  col_to_row_assignments_.push_back(std::vector<std::size_t>(num_cols()));
82  dual_var_rows_ = std::vector<double>(num_rows());
83  dual_var_cols_ = std::vector<double>(num_cols());
84 }
85 
86 void
90  if (solve_optimally_) {
91  lsape::hungarianLSAP(cost_matrix_->data(), num_rows(), num_cols(), row_to_col_assignments_.at(0).data(), dual_var_rows_.data(), dual_var_cols_.data(), col_to_row_assignments_.at(0).data());
92  compute_cost_from_dual_vars_();
93  if (num_solutions > 1) {
94  std::list<std::size_t *> further_row_to_col_assignments;
95  lsape::lsapSolutions(cost_matrix_->data(), num_rows(), num_cols(), num_solutions, row_to_col_assignments_.at(0).data(), dual_var_rows_.data(), dual_var_cols_.data(),
96  further_row_to_col_assignments);
97  row_to_col_assignments_.clear();
98  col_to_row_assignments_.clear();
99  for (auto row_to_col_assignment = further_row_to_col_assignments.begin(); row_to_col_assignment != further_row_to_col_assignments.end(); row_to_col_assignment++) {
100  row_to_col_assignments_.push_back(std::vector<std::size_t>(*row_to_col_assignment, *row_to_col_assignment + num_rows()));
101  col_to_row_assignments_.push_back(construct_col_to_row_asignment_(row_to_col_assignments_.back()));
102  delete *row_to_col_assignment;
103  }
104  }
105  }
106  else {
107  minimal_cost_ = lsape::greedyLSAP(cost_matrix_->data(), num_rows(), num_cols(), row_to_col_assignments_.at(0).data(), col_to_row_assignments_.at(0).data(), greedy_method_);
108  }
109 }
110 
111 double
113 minimal_cost() const {
114  return minimal_cost_;
115 }
116 
117 std::size_t
119 get_assigned_col(std::size_t row, std::size_t solution_id) const {
120  return row_to_col_assignments_.at(solution_id).at(row);
121 }
122 
123 std::size_t
125 get_assigned_row(std::size_t col, std::size_t solution_id) const {
126  return col_to_row_assignments_.at(solution_id).at(col);
127 }
128 
129 double
131 get_slack(std::size_t row, std::size_t col) const {
132  return cost_matrix_->operator()(row, col) - (dual_var_rows_.at(row) + dual_var_cols_.at(col));
133 }
134 
135 double
137 get_dual_var_row(std::size_t row) const {
138  return dual_var_rows_.at(row);
139 }
140 
141 double
143 get_dual_var_col(std::size_t col) const {
144  return dual_var_cols_.at(col);
145 }
146 
147 const std::vector<std::size_t> &
149 row_to_col_assignment(std::size_t solution_id) const {
150  return row_to_col_assignments_.at(solution_id);
151 }
152 
153 const std::vector<std::size_t> &
155 col_to_row_assignment(std::size_t solution_id) const {
156  return col_to_row_assignments_.at(solution_id);
157 }
158 
159 const DMatrix *
161 cost_matrix() const {
162  return cost_matrix_;
163 }
164 
165 std::size_t
167 num_rows() const {
168  return cost_matrix_->num_rows();
169 }
170 
171 std::size_t
173 num_cols() const {
174  return cost_matrix_->num_cols();
175 }
176 
177 std::size_t
179 num_solutions() const {
180  return row_to_col_assignments_.size();
181 }
182 
183 std::vector<std::size_t>
184 LSAPSolver ::
185 construct_col_to_row_asignment_(const std::vector<std::size_t> row_to_col_assignment) const {
186  std::vector<std::size_t> col_to_row_assignment(num_cols(), num_rows());
187  for (std::size_t row{}; row < num_rows(); row++) {
188  if (row_to_col_assignment.at(row) < num_cols()) {
189  col_to_row_assignment[row_to_col_assignment.at(row)] = row;
190  }
191  }
192  return col_to_row_assignment;
193 }
194 
195 void
196 LSAPSolver ::
197 compute_cost_from_assignments_() {
198  minimal_cost_ = 0.0;
199  for (std::size_t row{}; row < num_rows(); row++) {
200  minimal_cost_ += cost_matrix_->operator()(row, row_to_col_assignments_.at(0).at(row));
201  }
202  for (std::size_t col{}; col < num_cols(); col++) {
203  if (col_to_row_assignments_.at(0).at(col) == num_rows()) {
204  minimal_cost_ += cost_matrix_->operator()(num_rows(), col);
205  }
206  }
207 }
208 
209 void
210 LSAPSolver ::
211 compute_cost_from_dual_vars_() {
212  minimal_cost_ = 0.0;
213  for (auto dual_var = dual_var_rows_.begin(); dual_var != dual_var_rows_.end(); dual_var++) {
214  minimal_cost_ += *dual_var;
215  }
216  for (auto dual_var = dual_var_cols_.begin(); dual_var != dual_var_cols_.end(); dual_var++) {
217  minimal_cost_ += *dual_var;
218  }
219 }
220 
221 }
222 
223 #endif /* SRC_UTIL_LSAP_SOLVER_IPP_ */
std::size_t num_rows() const
Returns the number of rows of the LSAP problem instance.
GreedyMethod
Selects a greedy method.
Definition: lsap_solver.hpp:50
void set_greedy_method(const GreedyMethod &greedy_method)
Makes the solver use a greedy method.
Definition: lsap_solver.ipp:63
double minimal_cost() const
Returns the cost of the computed solutions.
void clear_solution()
Clears a previously computed solution.
Definition: lsap_solver.ipp:76
std::size_t num_cols() const
Returns the number of columns.
Definition: matrix.ipp:110
void solve(int num_solutions=1)
Solves the LSAP problem instance.
Definition: lsap_solver.ipp:88
const std::vector< std::size_t > & col_to_row_assignment(std::size_t solution_id=0) const
Returns the assignment from columns to rows.
void set_hungarian_algorithm()
Makes the solver use the Hungarian algorithm for optimal solving.
Definition: lsap_solver.ipp:70
double get_dual_var_row(std::size_t row) const
Returns the dual variable of a row.
const DMatrix * cost_matrix() const
Returns the LSAP problem instance.
Global namespace for GEDLIB.
std::size_t get_assigned_col(std::size_t row, std::size_t solution_id=0) const
Returns the assigned column.
void set_problem(const DMatrix *cost_matrix)
Sets the LSAP problem instance.
Definition: lsap_solver.ipp:56
LSAPSolver()
Constructs empty solver.
Definition: lsap_solver.ipp:44
double get_dual_var_col(std::size_t col) const
Returns the dual variable of a column.
std::size_t num_cols() const
Returns the number of columns of the LSAP problem instance.
ScalarT * data()
Provides access to internal data.
Definition: matrix.ipp:71
See https://doi.org/10.1007/978-3-319-18224-7_1.
Definition: lsap_solver.hpp:51
std::size_t num_solutions() const
Returns the number of solutions.
double get_slack(std::size_t row, std::size_t col) const
Returns the slack of a cell.
std::size_t get_assigned_row(std::size_t col, std::size_t solution_id=0) const
Returns the assigned row.
std::size_t num_rows() const
Returns the number of rows.
Definition: matrix.ipp:85
const std::vector< std::size_t > & row_to_col_assignment(std::size_t solution_id=0) const
Returns the assignment from rows to columns.