GEDLIB  1.0
ged_method.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_GED_METHOD_IPP_
28 #define SRC_METHODS_GED_METHOD_IPP_
29 
30 namespace ged {
31 
32 // === Definitions of destructors and constructors. ===
33 template<class UserNodeLabel, class UserEdgeLabel>
36 
37 template<class UserNodeLabel, class UserEdgeLabel>
40 initialized_{false},
41 ged_data_(ged_data),
42 options_(),
43 lower_bound_(0.0),
44 upper_bound_(std::numeric_limits<double>::infinity()),
45 node_map_(0, 0),
46 runtime_(),
47 init_time_(){}
48 
49 // Definitions of public member functions.
50 template<class UserNodeLabel, class UserEdgeLabel>
51 Seconds
53 get_runtime() const {
54  return runtime_;
55 }
56 
57 template<class UserNodeLabel, class UserEdgeLabel>
58 Seconds
60 get_init_time() const {
61  return init_time_;
62 }
63 
64 template<class UserNodeLabel, class UserEdgeLabel>
65 const NodeMap &
67 get_node_map() const {
68  return node_map_;
69 }
70 
71 template<class UserNodeLabel, class UserEdgeLabel>
72 double
74 get_lower_bound() const {
75  return lower_bound_;
76 }
77 
78 template<class UserNodeLabel, class UserEdgeLabel>
79 void
81 init() {
82  auto start = std::chrono::high_resolution_clock::now();
83  ged_init_();
84  auto end = std::chrono::high_resolution_clock::now();
85  init_time_ = end - start;
86  initialized_ = true;
87 }
88 
89 template<class UserNodeLabel, class UserEdgeLabel>
90 double
92 get_upper_bound() const {
93  return upper_bound_;
94 }
95 
96 template<class UserNodeLabel, class UserEdgeLabel>
97 void
99 set_options(const std::string & options) {
100  read_options_from_string_(options);
102  for (auto option_arg : options_) {
103  if (not ged_parse_option_(option_arg.first, option_arg.second)) {
104  throw Error("Invalid option \"" + option_arg.first + "\". Usage: options = \"" + ged_valid_options_string_() + "\".");
105  }
106  }
107  initialized_ = false;
108 }
109 
110 template<class UserNodeLabel, class UserEdgeLabel>
111 void
114  Result result;
115  auto start = std::chrono::high_resolution_clock::now();
116  run_as_util(ged_data_.graph(g_id), ged_data_.graph(h_id), result);
117  auto end = std::chrono::high_resolution_clock::now();
118  lower_bound_ = result.lower_bound();
119  upper_bound_ = result.upper_bound();
120  if (result.num_node_maps() > 0) {
121  node_map_ = result.node_map(0);
122  }
123  runtime_ = end - start;
124 }
125 
126 template<class UserNodeLabel, class UserEdgeLabel>
127 void
129 run_as_util(const GEDGraph & g, const GEDGraph & h, Result & result) {
130 
131  // Compute optimal solution and return if at least one of the two graphs is empty.
132  if ((g.num_nodes() == 0) or (h.num_nodes() == 0)) {
133  std::size_t index_node_map{result.add_node_map(g.num_nodes(), h.num_nodes())};
134  for (auto node = g.nodes().first; node != g.nodes().second; node++) {
135  result.node_map(index_node_map).add_assignment(*node, GEDGraph::dummy_node());
136  }
137  for (auto node = h.nodes().first; node != h.nodes().second; node++) {
138  result.node_map(index_node_map).add_assignment(GEDGraph::dummy_node(), *node);
139  }
140  ged_data_.compute_induced_cost(g, h, result.node_map(index_node_map));
141  result.set_lower_bound(result.upper_bound());
142  return;
143  }
144 
145  // Run the method.
146  ged_run_(g, h, result);
147 }
148 
149 // === Definitions of private helper member functions. ===
150 template<class UserNodeLabel, class UserEdgeLabel>
151 void
153 read_options_from_string_(const std::string & options) {
154  if (options == "") return;
155  options_.clear();
156  std::vector<std::string> words;
157  tokenize_(options, words);
158  std::string option_name;
159  bool expect_option_name{true};
160  for (auto word : words) {
161  if (expect_option_name) {
162  if (is_option_name_(word)) {
163  option_name = word;
164  if (options_.find(option_name) != options_.end()) {
165  throw Error("Multiple specification of option \"" + option_name + "\".");
166  }
167  options_[option_name] = "";
168  }
169  else {
170  throw Error("Invalid options \"" + options + "\". Usage: options = \"[--<option> <arg>] [...]\"");
171  }
172  }
173  else {
174  if (is_option_name_(word)) {
175  throw Error("Invalid options \"" + options + "\". Usage: options = \"[--<option> <arg>] [...]\"");
176  }
177  else {
178  options_[option_name] = word;
179  }
180  }
181  expect_option_name = not expect_option_name;
182  }
183 }
184 
185 template<class UserNodeLabel, class UserEdgeLabel>
186 void
188 tokenize_(const std::string & options, std::vector<std::string> & words) const {
189  bool outside_quotes{true};
190  std::size_t word_length{0};
191  std::size_t pos_word_start{0};
192  for (std::size_t pos{0}; pos < options.size(); pos++) {
193  if (options.at(pos) == '\'') {
194  if (not outside_quotes and pos < options.size() - 1) {
195  if (options.at(pos + 1) != ' ') {
196  throw Error("Options string contains closing single quote which is followed by a char different from ' '.");
197  }
198  }
199  word_length++;
200  outside_quotes = not outside_quotes;
201  }
202  else if (outside_quotes and options.at(pos) == ' ') {
203  if (word_length > 0) {
204  words.push_back(options.substr(pos_word_start, word_length));
205  }
206  pos_word_start = pos + 1;
207  word_length = 0;
208  }
209  else {
210  word_length++;
211  }
212  }
213  if (not outside_quotes) {
214  throw Error("Options string contains unbalanced single quotes.");
215  }
216  if (word_length > 0) {
217  words.push_back(options.substr(pos_word_start, word_length));
218  }
219 }
220 
221 template<class UserNodeLabel, class UserEdgeLabel>
222 bool
224 is_option_name_(std::string & word) const {
225  if (word.at(0) == '\'') {
226  word = word.substr(1, word.size() - 2);
227  return false;
228  }
229  if (word.size() < 3) {
230  return false;
231  }
232  if ((word.at(0) == '-') and (word.at(1) == '-') and (word.at(2) != '-')) {
233  word = word.substr(2);
234  return true;
235  }
236  return false;
237 }
238 
239 // === Default definitions of private virtual member functions to be overridden by derived classes. ===
240 template<class UserNodeLabel, class UserEdgeLabel>
241 void
244 
245 template<class UserNodeLabel, class UserEdgeLabel>
246 void
248 ged_run_(const GEDGraph & g, const GEDGraph & h, Result & result) {}
249 
250 template<class UserNodeLabel, class UserEdgeLabel>
251 bool
253 ged_parse_option_(const std::string & option, const std::string & arg) {
254  return false;
255 }
256 
257 template<class UserNodeLabel, class UserEdgeLabel>
258 std::string
261  return "";
262 }
263 
264 template<class UserNodeLabel, class UserEdgeLabel>
265 void
268 
269 }
270 
271 #endif /* SRC_METHODS_GED_METHOD_IPP_ */
std::size_t num_nodes() const
Returns the number of nodes.
Definition: ged_graph.ipp:211
Contains the standardized input data along with basic functionality.
Definition: ged_data.hpp:55
double upper_bound() const
Returns the upper bound for GED.
Definition: result.ipp:51
GEDMethod(const GEDData< UserNodeLabel, UserEdgeLabel > &ged_data)
Constructor.
Definition: ged_method.ipp:39
A class for node maps.
Definition: node_map.hpp:43
virtual std::string ged_valid_options_string_() const
Returns string of all valid options.
Definition: ged_method.ipp:260
std::vector< GEDGraph >::size_type GraphID
Type of internally used graph IDs.
Definition: ged_graph.hpp:112
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
void run_as_util(const GEDGraph &g, const GEDGraph &h, Result &result)
Runs the method with options specified by set_options().
Definition: ged_method.ipp:129
double lower_bound() const
Returns the lower bound for GED.
Definition: result.ipp:45
std::size_t num_node_maps() const
Returns the number of node maps.
Definition: result.ipp:104
A wrapper structure for the result of calls to ged::GEDMethod::run_as_util() and ged::GEDMethod::ged_...
Definition: result.hpp:38
virtual void ged_set_default_options_()
Sets all options to default values.
Definition: ged_method.ipp:267
Abstract class for the (suboptimal) computation of the graph edit distance.
Definition: ged_method.hpp:40
double get_lower_bound() const
Returns a lower bound.
Definition: ged_method.ipp:74
Seconds get_runtime() const
Returns the runtime.
Definition: ged_method.ipp:53
const NodeMap & get_node_map() const
Returns a graph matching.
Definition: ged_method.ipp:67
std::size_t add_node_map(std::size_t num_nodes_g, std::size_t num_nodes_h)
Adds an empty node map to the result.
Definition: result.ipp:60
std::chrono::duration< double > Seconds
Internally used type for measurements in seconds.
Runtime error class.
Definition: error.hpp:37
static NodeID dummy_node()
Returns a dummy node.
Definition: ged_graph.ipp:56
void run(GEDGraph::GraphID g_id, GEDGraph::GraphID h_id)
Runs the method with options specified by set_options().
Definition: ged_method.ipp:113
double get_upper_bound() const
Returns an upper bound.
Definition: ged_method.ipp:92
void set_options(const std::string &options)
Sets the options of the method.
Definition: ged_method.ipp:99
bool initialized_
A flag that equals true if init() has been called and false otherwise.
Definition: ged_method.hpp:119
virtual bool ged_parse_option_(const std::string &option, const std::string &arg)
Parses one option.
Definition: ged_method.ipp:253
virtual void ged_run_(const GEDGraph &g, const GEDGraph &h, Result &result)
Runs the method with options specified by set_options().
Definition: ged_method.ipp:248
virtual void ged_init_()
Initializes the method.
Definition: ged_method.ipp:243
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
void add_assignment(GEDGraph::NodeID i, GEDGraph::NodeID k)
Add node substitution, insertion, or deletion to the node map.
Definition: node_map.ipp:183
Global namespace for GEDLIB.
Seconds get_init_time() const
Returns the initialization time.
Definition: ged_method.ipp:60
NodeMap & node_map(std::size_t index_node_map)
Provides access to a node map.
Definition: result.ipp:74
void init()
Initializes the method with options specified by set_options().
Definition: ged_method.ipp:81
virtual ~GEDMethod()=0
Pure virtual destructor.
Definition: ged_method.ipp:35