GEDLIB  1.0
lsape_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 LSAPE_SOLVER_IPP
28 #define LSAPE_SOLVER_IPP 1
29 
30 namespace ged {
31 
33 LSAPESolver(const DMatrix * cost_matrix) :
34 cost_matrix_{cost_matrix},
35 model_{ECBP},
36 greedy_method_{BASIC},
37 solve_optimally_{true},
38 minimal_cost_{0.0},
39 row_to_col_assignments_(),
40 col_to_row_assignments_(),
41 dual_var_rows_(total_num_rows()),
42 dual_var_cols_(total_num_cols()) {}
43 
46 cost_matrix_{nullptr},
47 model_{ECBP},
48 greedy_method_{BASIC},
49 solve_optimally_{true},
50 minimal_cost_{0.0},
51 row_to_col_assignments_(),
52 col_to_row_assignments_() {}
53 
54 void
57  cost_matrix_ = cost_matrix;
58 }
59 
60 void
63  minimal_cost_ = 0.0;
64  row_to_col_assignments_.clear();
65  col_to_row_assignments_.clear();
66  row_to_col_assignments_.push_back(std::vector<std::size_t>(num_rows()));
67  col_to_row_assignments_.push_back(std::vector<std::size_t>(num_cols()));
68  dual_var_rows_ = std::vector<double>(total_num_rows());
69  dual_var_cols_ = std::vector<double>(total_num_cols());
70 }
71 
72 void
74 set_model(const Model & model) {
75  solve_optimally_ = true;
76  model_ = model;
77 }
78 
79 void
81 set_greedy_method(const GreedyMethod & greedy_method) {
82  solve_optimally_ = false;
83  greedy_method_ = greedy_method;
84 }
85 
86 void
90  if (solve_optimally_) {
91  lsape::lsapeSolver(cost_matrix_->data(), total_num_rows(), total_num_cols(), row_to_col_assignments_.at(0).data(), col_to_row_assignments_.at(0).data(),
92  dual_var_rows_.data(), dual_var_cols_.data(), static_cast<lsape::LSAPE_MODEL>(model_));
93  compute_cost_from_assignments_();
94  if (num_solutions > 1) {
95  std::list<std::size_t *> further_row_to_col_assignments;
96  lsape::lsapeSolutionsFromOne(cost_matrix_->data(), total_num_rows(),total_num_cols(), num_solutions, row_to_col_assignments_.at(0).data(), col_to_row_assignments_.at(0).data(),
97  dual_var_rows_.data(), dual_var_cols_.data(), further_row_to_col_assignments);
98  row_to_col_assignments_.clear();
99  col_to_row_assignments_.clear();
100  for (auto row_to_col_assignment : further_row_to_col_assignments) {
101  row_to_col_assignments_.push_back(std::vector<std::size_t>(row_to_col_assignment, row_to_col_assignment + num_rows()));
102  col_to_row_assignments_.push_back(construct_col_to_row_asignment_(row_to_col_assignments_.back()));
103  }
104  for (auto && row_to_col_assignment : further_row_to_col_assignments) {
105  delete row_to_col_assignment;
106  }
107  }
108  }
109  else {
110  minimal_cost_ = lsape::lsapeGreedy(cost_matrix_->data(), num_rows(), num_cols(), row_to_col_assignments_.at(0).data(), col_to_row_assignments_.at(0).data(),
111  static_cast<lsape::GREEDY_METHOD>(greedy_method_));
112  }
113 }
114 
115 double
117 minimal_cost() const {
118  return minimal_cost_;
119 }
120 
121 std::size_t
123 get_assigned_col(LabelID row, std::size_t solution_id) const {
124  return row_to_col_assignments_.at(solution_id).at(row);
125 }
126 
127 std::size_t
129 get_assigned_row(LabelID col, std::size_t solution_id) const {
130  return col_to_row_assignments_.at(solution_id).at(col);
131 }
132 
133 const std::vector<std::size_t> &
135 row_to_col_assignment(std::size_t solution_id) const {
136  return row_to_col_assignments_.at(solution_id);
137 }
138 
139 const std::vector<std::size_t> &
141 col_to_row_assignment(std::size_t solution_id) const {
142  return col_to_row_assignments_.at(solution_id);
143 }
144 
145 double
147 get_slack(std::size_t row, std::size_t col) const {
148  return cost_matrix_->operator()(row, col) - (dual_var_rows_.at(row) + dual_var_cols_.at(col));
149 }
150 
151 double
153 get_dual_var_row(std::size_t row) const {
154  return dual_var_rows_.at(row);
155 }
156 
157 double
159 get_dual_var_col(std::size_t col) const {
160  return dual_var_cols_.at(col);
161 }
162 
163 const DMatrix *
165 cost_matrix() const {
166  return cost_matrix_;
167 }
168 
169 std::size_t
171 num_rows() const {
172  return cost_matrix_->num_rows() - 1;
173 }
174 
175 std::size_t
177 num_cols() const {
178  return cost_matrix_->num_cols() - 1;
179 }
180 
181 std::size_t
183 total_num_rows() const {
184  return cost_matrix_->num_rows();
185 }
186 
187 std::size_t
189 total_num_cols() const {
190  return cost_matrix_->num_cols();
191 }
192 
193 std::size_t
195 num_solutions() const {
196  return row_to_col_assignments_.size();
197 }
198 
199 std::vector<std::size_t>
200 LSAPESolver ::
201 construct_col_to_row_asignment_(const std::vector<std::size_t> row_to_col_assignment) const {
202  std::vector<std::size_t> col_to_row_assignment(num_cols(), num_rows());
203  for (std::size_t row{}; row < num_rows(); row++) {
204  if (row_to_col_assignment.at(row) < num_cols()) {
205  col_to_row_assignment[row_to_col_assignment.at(row)] = row;
206  }
207  }
208  return col_to_row_assignment;
209 }
210 
211 void
212 LSAPESolver ::
213 compute_cost_from_assignments_() {
214  minimal_cost_ = 0.0;
215  for (std::size_t row{}; row < num_rows(); row++) {
216  minimal_cost_ += cost_matrix_->operator()(row, row_to_col_assignments_.at(0).at(row));
217  }
218  for (std::size_t col{}; col < num_cols(); col++) {
219  if (col_to_row_assignments_.at(0).at(col) == num_rows()) {
220  minimal_cost_ += cost_matrix_->operator()(num_rows(), col);
221  }
222  }
223 }
224 
225 void
226 LSAPESolver ::
227 compute_cost_from_dual_vars_() {
228  minimal_cost_ = 0.0;
229  for (auto dual_var = dual_var_rows_.begin(); dual_var != dual_var_rows_.end(); dual_var++) {
230  minimal_cost_ += *dual_var;
231  }
232  for (auto dual_var = dual_var_cols_.begin(); dual_var != dual_var_cols_.end(); dual_var++) {
233  minimal_cost_ += *dual_var;
234  }
235 }
236 
237 }
238 
239 
240 #endif
void set_model(const Model &model)
Makes the solver use a specific model for optimal solving.
double get_dual_var_col(std::size_t col) const
Returns the dual variable of a column.
std::size_t total_num_rows() const
Returns the total number of rows of the LSAPE problem instance.
std::size_t num_cols() const
Returns the number of real columns of the LSAPE problem instance, i.e, the number of columns of the i...
LSAPESolver()
Constructs empty solver.
GreedyMethod
Selects a greedy method.
void solve(int num_solutions=1)
Solves the LSAPE problem instance.
std::size_t num_cols() const
Returns the number of columns.
Definition: matrix.ipp:110
std::size_t LabelID
Internally used type of node and edge labels.
double get_dual_var_row(std::size_t row) const
Returns the dual variable of a row.
double get_slack(std::size_t row, std::size_t col) const
Returns the slack of a cell.
void clear_solution()
Clears a previously computed solution.
const DMatrix * cost_matrix() const
Returns the LSAPE problem instance.
Adaption of Hungarian Algorithm to LSAPE.
const std::vector< std::size_t > & col_to_row_assignment(std::size_t solution_id=0) const
Returns the assignment from columns to rows.
double minimal_cost() const
Returns the cost of the computed solutions.
std::size_t get_assigned_row(std::size_t col, std::size_t solution_id=0) const
Returns the assigned row.
std::size_t total_num_cols() const
Returns the total number of columns of the LSAPE problem instance.
const std::vector< std::size_t > & row_to_col_assignment(std::size_t solution_id=0) const
Returns the assignment from rows to columns.
std::size_t num_rows() const
Returns the number of real rows of the LSAPE problem instance, i.e, the number of rows of the interna...
std::size_t get_assigned_col(std::size_t row, std::size_t solution_id=0) const
Returns the assigned column.
Global namespace for GEDLIB.
ScalarT * data()
Provides access to internal data.
Definition: matrix.ipp:71
void set_problem(const DMatrix *cost_matrix)
Sets the LSAPE problem instance.
std::size_t num_solutions() const
Returns the number of solutions.
Model
Selects a model for solving LSAPE with the Hungarian algorithm.
See https://doi.org/10.1007/978-3-319-18224-7_1.
void set_greedy_method(const GreedyMethod &greedy_method)
Makes the solver use a greedy method.
std::size_t num_rows() const
Returns the number of rows.
Definition: matrix.ipp:85