GEDLIB  1.0
branch.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_METHODS_BRANCH_IPP_
28 #define SRC_METHODS_BRANCH_IPP_
29 
30 namespace ged {
31 
32 // === Definitions of destructor and constructor. ===
33 template<class UserNodeLabel, class UserEdgeLabel>
34 Branch<UserNodeLabel, UserEdgeLabel>::
35 ~Branch() {}
36 
37 template<class UserNodeLabel, class UserEdgeLabel>
38 Branch<UserNodeLabel, UserEdgeLabel>::
39 Branch(const GEDData<UserNodeLabel, UserEdgeLabel> & ged_data) :
40 LSAPEBasedMethod<UserNodeLabel, UserEdgeLabel>(ged_data) {}
41 
42 // === Definitions of member functions inherited from LSAPEBasedMethod. ===
43 template<class UserNodeLabel, class UserEdgeLabel>
44 void
46 lsape_populate_instance_(const GEDGraph & g, const GEDGraph & h, DMatrix & master_problem) {
47 
48 #ifdef _OPENMP
49  omp_set_num_threads(this->num_threads_ - 1);
50 #pragma omp parallel for if(this->num_threads_ > 1)
51 #endif
52  for (std::size_t row_in_master = 0; row_in_master < master_problem.num_rows(); row_in_master++) {
53  for (std::size_t col_in_master = 0; col_in_master < master_problem.num_cols(); col_in_master++) {
54  if ((row_in_master < g.num_nodes()) and (col_in_master < h.num_nodes())) {
55  master_problem(row_in_master, col_in_master) = compute_substitution_cost_(g, h, row_in_master, col_in_master);
56  }
57  else if (row_in_master < g.num_nodes()) {
58  master_problem(row_in_master, h.num_nodes()) = compute_deletion_cost_(g, row_in_master);
59  }
60  else if (col_in_master < h.num_nodes()) {
61  master_problem(g.num_nodes(), col_in_master) = compute_insertion_cost_(h, col_in_master);
62  }
63  }
64  }
65 }
66 
67 // === Definitions of private helper member functions. ===
68 template<class UserNodeLabel, class UserEdgeLabel>
69 double
72  // Collect node substitution costs.
73  double cost{this->ged_data_.node_cost(g.get_node_label(i), h.get_node_label(k))};
74 
75  // Initialize subproblem.
76  DMatrix subproblem(g.degree(i) + 1, h.degree(k) + 1);
77 
78  // Collect edge deletion costs.
79  std::size_t j{0};
80  for (auto ij = g.incident_edges(i).first; ij != g.incident_edges(i).second; ij++, j++) {
81  subproblem(j, h.degree(k)) = this->ged_data_.edge_cost(g.get_edge_label(*ij), ged::dummy_label()) / 2.0;
82  }
83 
84  // Collect edge insertion costs.
85  std::size_t l{0};
86  for (auto kl = h.incident_edges(k).first; kl != h.incident_edges(k).second; kl++, l++) {
87  subproblem(g.degree(i), l) = this->ged_data_.edge_cost(ged::dummy_label(), h.get_edge_label(*kl)) / 2.0;
88  }
89  j = 0;
90 
91  // Collect edge relabelling costs.
92  for (auto ij = g.incident_edges(i).first; ij != g.incident_edges(i).second; ij++, j++) {
93  l = 0;
94  for (auto kl = h.incident_edges(k).first; kl != h.incident_edges(k).second; kl++, l++) {
95  subproblem(j, l) = this->ged_data_.edge_cost(g.get_edge_label(*ij), h.get_edge_label(*kl)) / 2.0;
96  }
97  }
98 
99  // Solve subproblem.
100  LSAPESolver subproblem_solver(&subproblem);
101  subproblem_solver.set_model(this->lsape_model_);
102  subproblem_solver.solve();
103 
104  // Update and return overall substitution cost.
105  cost += subproblem_solver.minimal_cost();
106  return cost;
107 }
108 
109 template<class UserNodeLabel, class UserEdgeLabel>
110 double
113  // Collect node deletion cost.
114  double cost{this->ged_data_.node_cost(g.get_node_label(i), ged::dummy_label())};
115 
116  // Collect edge deletion costs.
117  auto incident_edges_i = g.incident_edges(i);
118  for (auto ij = incident_edges_i.first; ij != incident_edges_i.second; ij++) {
119  cost += this->ged_data_.edge_cost(g.get_edge_label(*ij), ged::dummy_label()) / 2.0;
120  }
121 
122  // Return overall deletion cost.
123  return cost;
124 }
125 
126 template<class UserNodeLabel, class UserEdgeLabel>
127 double
130  // Collect node insertion cost.
131  double cost{this->ged_data_.node_cost(ged::dummy_label(), h.get_node_label(k))};
132 
133  // Collect edge insertion costs.
134  auto incident_edges_k = h.incident_edges(k);
135  for (auto kl = incident_edges_k.first; kl != incident_edges_k.second; kl++) {
136  cost += this->ged_data_.edge_cost(ged::dummy_label(), h.get_edge_label(*kl)) / 2.0;
137  }
138 
139  // Return overall insertion cost.
140  return cost;
141 }
142 
143 }
144 
145 #endif /* SRC_METHODS_BRANCH_IPP_ */
void set_model(const Model &model)
Makes the solver use a specific model for optimal solving.
Computes lower and upper bounds for general edit costs.
Definition: branch.hpp:42
std::size_t num_nodes() const
Returns the number of nodes.
Definition: ged_graph.ipp:211
std::size_t num_threads_
The number of threads to be used.
This class solves LSAPE instances by calling the library lsape available at https://bougleux.users.greyc.fr/lsape/.
const GEDData< UserNodeLabel, UserEdgeLabel > & ged_data_
The data on which the method is run.
Definition: ged_method.hpp:124
void solve(int num_solutions=1)
Solves the LSAPE problem instance.
std::size_t degree(NodeID node) const
Returns node degree.
Definition: ged_graph.ipp:162
std::size_t num_cols() const
Returns the number of columns.
Definition: matrix.ipp:110
LabelID get_node_label(NodeID node) const
Returns the label of a given node.
Definition: ged_graph.ipp:126
LSAPESolver::Model lsape_model_
Specifies model for optimal LSAPE solver.
LabelID get_edge_label(EdgeID edge) const
Returns the label of a given edge.
Definition: ged_graph.ipp:135
std::pair< incident_edge_iterator, incident_edge_iterator > incident_edges(NodeID node) const
Provides access to all incident edges of a node.
Definition: ged_graph.ipp:150
double minimal_cost() const
Returns the cost of the computed solutions.
The normalized input graphs used by GEDLIB. All labels are integers.
Definition: ged_graph.hpp:104
constexpr LabelID dummy_label()
Returns a dummy label.
Global namespace for GEDLIB.
virtual void lsape_populate_instance_(const GEDGraph &g, const GEDGraph &h, DMatrix &master_problem) final
Populates the LSAPE instance.
Definition: branch.ipp:46
std::size_t NodeID
Internally used vertex ID type.
Definition: ged_graph.hpp:108
std::size_t num_rows() const
Returns the number of rows.
Definition: matrix.ipp:85