GEDLIB  1.0
branch_compact.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_COMPACT_IPP_
28 #define SRC_METHODS_BRANCH_COMPACT_IPP_
29 
30 namespace ged {
31 
32 // === Definitions of destructors and constructors. ===
33 template<class UserNodeLabel, class UserEdgeLabel>
34 BranchCompact<UserNodeLabel, UserEdgeLabel>::
35 ~BranchCompact() {}
36 
37 template<class UserNodeLabel, class UserEdgeLabel>
38 BranchCompact<UserNodeLabel, UserEdgeLabel>::
39 BranchCompact(const GEDData<UserNodeLabel, UserEdgeLabel> & ged_data) :
40 GEDMethod<UserNodeLabel, UserEdgeLabel>(ged_data),
41 sort_method_{COUNTING},
42 branches_() {}
43 
44 // === Definitions of member functions inherited from GEDMethod. ===
45 template<class UserNodeLabel, class UserEdgeLabel>
46 void
49  for (auto graph = this->ged_data_.begin(); graph != this->ged_data_.end(); graph++) {
50  init_graph_(*graph);
51  }
52 }
53 
54 template<class UserNodeLabel, class UserEdgeLabel>
55 void
57 ged_run_(const GEDGraph & g, const GEDGraph & h, Result & result) {
58  // Initialize the branches.
59  if (not this->initialized_) {
60  init_graph_(g);
61  init_graph_(h);
62  }
63  std::list<Branch_> branches_g(branches_.at(g.id()));
64  std::list<Branch_> branches_h(branches_.at(h.id()));
65  double min_edit_cost{this->ged_data_.min_edit_cost(g, h)};
66  // Delete common branches.
67  auto branch_g = branches_g.begin();
68  auto branch_h = branches_h.begin();
69  while ((branch_g != branches_g.end()) and (branch_h != branches_h.end())) {
70  int comp{branch_g->compare(*branch_h)};
71  if (comp == 0) {
72  branch_g = branches_g.erase(branch_g);
73  branch_h = branches_h.erase(branch_h);
74  }
75  else if (comp == -1) {
76  branch_g++;
77  }
78  else {
79  branch_h++;
80  }
81  }
82  // Compute lower bound from remaining branches.
83  double lower_bound{0.0};
84  branch_g = branches_g.begin();
85  branch_h = branches_h.begin();
86  while ((branch_g != branches_g.end()) and (branch_h != branches_h.end())) {
87  int comp{branch_g->compare(*branch_h)};
88  if (branch_g->node_label == branch_h->node_label) {
89  branch_g = branches_g.erase(branch_g);
90  branch_h = branches_h.erase(branch_h);
91  lower_bound += 0.5 * min_edit_cost;
92  }
93  else if (comp == -1) {
94  branch_g++;
95  }
96  else {
97  branch_h++;
98  }
99  }
100  lower_bound += (static_cast<double>(std::max(branches_g.size(), branches_h.size())) * min_edit_cost);
101  result.set_lower_bound(lower_bound);
102 }
103 
104 template<class UserNodeLabel, class UserEdgeLabel>
105 bool
107 ged_parse_option_(const std::string & option, const std::string & arg) {
108  if (option == "sort-method") {
109  if (arg == "STD") {
110  sort_method_ = STD;
111  }
112  else if (arg == "COUNTING") {
113  sort_method_ = COUNTING;
114  }
115  else {
116  throw ged::Error(std::string("Invalid argument \"") + arg + "\" for option upper-bound. Usage: options = \"[--sort-method STD|COUNTING] [...]\"");
117  }
118  return true;
119  }
120  return false;
121 }
122 
123 template<class UserNodeLabel, class UserEdgeLabel>
124 std::string
127  return "[--sort-method <arg>]";
128 }
129 
130 template<class UserNodeLabel, class UserEdgeLabel>
131 void
134  sort_method_ = COUNTING;
135 }
136 
137 // === Definition of private helper functions. ===
138 template<class UserNodeLabel, class UserEdgeLabel>
139 void
141 init_graph_(const GEDGraph & graph) {
142  SortedUserEdgeLabels_ sorted_edge_labels(graph, sort_method_);
143  std::list<Branch_> branches;
144  for (auto node = graph.nodes().first; node != graph.nodes().second; node++) {
145  branches.emplace_back(graph.get_node_label(*node), sorted_edge_labels.get_incident_labels(*node));
146  }
147  branches.sort();
148  branches_[graph.id()] = branches;
149 }
150 
151 // === Definition of private class SortedUserEdgeLabels_. ===
152 template<class UserNodeLabel, class UserEdgeLabel>
155 SortedUserEdgeLabels_(const GEDGraph & g, SortMethod_ sort_method):
156 sorted_edge_labels_(){
157  for (auto node = g.nodes().first; node != g.nodes().second; node++) {
158  sorted_edge_labels_[*node] = std::vector<LabelID>(0);
159  for (auto edge = g.incident_edges(*node).first; edge != g.incident_edges(*node).second; edge++) {
160  sorted_edge_labels_[*node].push_back(g.get_edge_label(*edge));
161  }
162  switch (sort_method) {
163  case STD:
164  std::sort(sorted_edge_labels_[*node].begin(), sorted_edge_labels_[*node].end());
165  break;
166  default:
167  util::counting_sort(sorted_edge_labels_[*node].begin(), sorted_edge_labels_[*node].end());
168  break;
169  }
170  }
171 }
172 
173 template<class UserNodeLabel, class UserEdgeLabel>
174 const std::vector<LabelID> &
178  return sorted_edge_labels_.at(node);
179 }
180 
181 // === Definition of private class Branch_. ===
182 template<class UserNodeLabel, class UserEdgeLabel>
185 Branch_(LabelID node_label, const std::vector<LabelID> & sorted_edge_labels) :
186 node_label{node_label},
187 sorted_edge_labels(sorted_edge_labels){}
188 
189 template<class UserNodeLabel, class UserEdgeLabel>
192 Branch_(const Branch_ & branch) :
193 node_label{branch.node_label},
194 sorted_edge_labels(branch.sorted_edge_labels){}
195 
196 template<class UserNodeLabel, class UserEdgeLabel>
197 int
200 compare(const Branch_ & rhs) const {
201  if (node_label < rhs.node_label) {
202  return -1;
203  }
204  if (node_label > rhs.node_label) {
205  return 1;
206  }
207  auto label_l = sorted_edge_labels.begin();
208  auto label_r = rhs.sorted_edge_labels.begin();
209  while ((label_l != sorted_edge_labels.end()) and (label_r != rhs.sorted_edge_labels.end())) {
210  if (*label_l == *label_r) {
211  label_l++;
212  label_r++;
213  }
214  else if (*label_l < *label_r){
215  return -1;
216  }
217  else if (*label_l > *label_r){
218  return 1;
219  }
220  }
221  if ((label_l == sorted_edge_labels.end()) and (label_r == rhs.sorted_edge_labels.end())) {
222  return 0;
223  }
224  if (label_l == sorted_edge_labels.end()) {
225  return -1;
226  }
227  return 1;
228 }
229 
230 template<class UserNodeLabel, class UserEdgeLabel>
231 bool
234 operator<(const Branch_ & rhs) const {
235  return compare(rhs) == -1;
236 }
237 
238 template<class UserNodeLabel, class UserEdgeLabel>
239 bool
242 operator>(const Branch_ & rhs) const {
243  return compare(rhs) == 1;
244 }
245 
246 template<class UserNodeLabel, class UserEdgeLabel>
247 bool
250 operator==(const Branch_ & rhs) const {
251  return compare(rhs) == 0;
252 }
253 
254 }
255 
256 #endif /* SRC_METHODS_BRANCH_COMPACT_IPP_ */
const GEDData< UserNodeLabel, UserEdgeLabel > & ged_data_
The data on which the method is run.
Definition: ged_method.hpp:124
void set_lower_bound(double lower_bound)
Sets the lower bound for GED.
Definition: result.ipp:39
A wrapper structure for the result of calls to ged::GEDMethod::run_as_util() and ged::GEDMethod::ged_...
Definition: result.hpp:38
std::size_t LabelID
Internally used type of node and edge labels.
virtual bool ged_parse_option_(const std::string &option, const std::string &arg) final
Parses one option.
void counting_sort(std::vector< LabelID >::iterator first, std::vector< LabelID >::iterator last)
Implementation of counting sort.
Definition: misc.ipp:111
LabelID get_node_label(NodeID node) const
Returns the label of a given node.
Definition: ged_graph.ipp:126
Runtime error class.
Definition: error.hpp:37
LabelID get_edge_label(EdgeID edge) const
Returns the label of a given edge.
Definition: ged_graph.ipp:135
virtual void ged_set_default_options_() final
Sets all options to default values.
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
virtual void ged_run_(const GEDGraph &g, const GEDGraph &h, Result &result) final
Runs the method with options specified by set_options().
bool initialized_
A flag that equals true if init() has been called and false otherwise.
Definition: ged_method.hpp:119
std::pair< node_iterator, node_iterator > nodes() const
Provides access to all nodes in the graph.
Definition: ged_graph.ipp:205
The normalized input graphs used by GEDLIB. All labels are integers.
Definition: ged_graph.hpp:104
Global namespace for GEDLIB.
virtual std::string ged_valid_options_string_() const final
Returns string of all valid options.
virtual void ged_init_() final
Initializes the method.
Computes a lower bound for uniform edit costs.
std::size_t NodeID
Internally used vertex ID type.
Definition: ged_graph.hpp:108
GraphID id() const
Returns the ID of the graph.
Definition: ged_graph.ipp:184