27 #ifndef SRC_ENV_GED_ENV_IPP_ 28 #define SRC_ENV_GED_ENV_IPP_ 32 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
38 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
48 original_to_internal_node_ids_(),
49 internal_to_original_node_ids_(),
50 ged_method_{
nullptr} {}
52 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
56 ged_data_.set_edit_costs_(edit_costs, std::vector<double>(edit_cost_constants));
59 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
63 ged_data_.set_edit_costs_(edit_costs);
66 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
69 add_graph(
const std::string & name,
const std::string & graph_class) {
70 for (
auto & graph : ged_data_.graphs_) {
75 new_graph_ids_.push_back(graph_id);
76 ged_data_.graphs_.emplace(ged_data_.graphs_.begin() + graph_id, graph_id);
77 ged_data_.graph_names_.insert(ged_data_.graph_names_.begin() + graph_id, name);
78 ged_data_.graph_classes_.insert(ged_data_.graph_classes_.begin() + graph_id, graph_class);
79 original_to_internal_node_ids_.insert(original_to_internal_node_ids_.begin() + graph_id, std::map<UserNodeID, GEDGraph::NodeID>());
80 internal_to_original_node_ids_.insert(internal_to_original_node_ids_.begin() + graph_id, std::map<GEDGraph::NodeID, UserNodeID>());
81 ged_data_.strings_to_internal_node_ids_.insert(ged_data_.strings_to_internal_node_ids_.begin() + graph_id, std::map<std::string, GEDGraph::NodeID>());
82 ged_data_.internal_node_ids_to_strings_.insert(ged_data_.internal_node_ids_to_strings_.begin() + graph_id, std::map<GEDGraph::NodeID, std::string>());
86 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
90 if (graph_id >= ged_data_.num_graphs_without_shuffled_copies()) {
91 throw Error(
"The graph " +
get_graph_name(graph_id) +
" has not been added to the environment.");
93 ged_data_.graphs_[graph_id].clear();
94 original_to_internal_node_ids_[graph_id].clear();
95 internal_to_original_node_ids_[graph_id].clear();
96 ged_data_.strings_to_internal_node_ids_[graph_id].clear();
97 ged_data_.internal_node_ids_to_strings_[graph_id].clear();
101 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
106 graph_id =
add_graph(graph_name, graph_class);
116 if (exchange_graph.
adj_matrix.at(i).at(j) == 1) {
128 const std::unordered_set<std::string> & irrelevant_node_attributes,
const std::unordered_set<std::string> & irrelevant_edge_attributes,
GEDGraph::GraphID graph_id,
const std::string & graph_class) {
131 boost::property_tree::ptree root;
133 read_xml(filename, root);
135 catch (
const boost::property_tree::xml_parser_error & error) {
136 throw Error(std::string(
"Error reading file ") + filename +
": " + error.message() +
".");
140 if (root.count(
"gxl") == 0) {
141 throw Error(
"The file " + filename +
" has the wrong format: no xml-element <gxl>.");
143 if (root.count(
"gxl") >= 2) {
144 throw Error(
"The file " + filename +
" has the wrong format: more than one xml-element <gxl>.");
146 root = root.get_child(
"gxl");
147 if (root.count(
"graph") == 0) {
148 throw Error(
"The file " + filename +
" has the wrong format: no xml-element <gxl>.<graph>");
150 if (root.count(
"graph") >= 2) {
151 throw Error(
"The file " + filename +
" has the wrong format: more than one xml-element <gxl>.<graph>");
153 root = root.get_child(
"graph");
157 graph_id =
add_graph(filename, graph_class);
165 std::string attr_name;
166 std::string attr_val;
170 for (
const boost::property_tree::ptree::value_type & node_or_edge : root) {
173 if (node_or_edge.first ==
"node") {
176 v_id = node_or_edge.second.get<std::string>(
"<xmlattr>.id");
178 catch (
const boost::property_tree::ptree_bad_path & error) {
179 throw Error(
"The file " + filename +
" has the wrong format: missing xml-attribute \"id\" in element <gxl>.<graph>.<node>.");
185 read_gxl_label_from_ptree_(node_or_edge, irrelevant_node_attributes, filename, label);
191 else if (node_or_edge.first ==
"edge") {
194 from = node_or_edge.second.get<std::string>(
"<xmlattr>.from");
196 catch (
const boost::property_tree::ptree_bad_path & error) {
197 throw Error(
"The file " + filename +
" has the wrong format: missing xml-attribute \"from\" in element <gxl>.<graph>.<edge>.");
200 to = node_or_edge.second.get<std::string>(
"<xmlattr>.to");
202 catch (
const boost::property_tree::ptree_bad_path & error) {
203 throw Error(
"The file " + filename +
" has the wrong format: missing xml-attribute \"to\" in element <gxl>.<graph>.<edge>.");
208 read_gxl_label_from_ptree_(node_or_edge, irrelevant_edge_attributes, filename, label);
210 add_edge(graph_id, from, to, label);
214 else if (node_or_edge.first !=
"<xmlattr>"){
215 throw Error(
"The file " + filename +
" has the wrong format: unexpected element <gxl>.<graph>.<" + node_or_edge.first +
">.");
223 std::vector<GEDGraph::GraphID>
226 const std::unordered_set<std::string> & irrelevant_node_attributes,
const std::unordered_set<std::string> & irrelevant_edge_attributes) {
228 boost::property_tree::ptree root;
230 read_xml(file, root);
232 catch (
const boost::property_tree::xml_parser_error & error) {
233 throw Error(std::string(
"Error reading file ") + file +
": " + error.message() +
".");
236 if (root.count(
"GraphCollection") == 0) {
237 throw Error(
"The file " + file +
" has the wrong format: no xml-element <GraphCollection>.");
239 if (root.count(
"GraphCollection") >= 2) {
240 throw Error(
"The file " + file +
" has the wrong format: more than one xml-element <GraphCollection>.");
242 root = root.get_child(
"GraphCollection");
246 std::vector<GEDGraph::GraphID>
graph_ids;
247 std::string gxl_file(
"");
248 std::string graph_class(
"");
249 for (
const boost::property_tree::ptree::value_type & val : root) {
250 if (val.first ==
"graph") {
252 gxl_file = val.second.get<std::string>(
"<xmlattr>.file");
254 catch (
const boost::property_tree::ptree_bad_path & error) {
255 throw Error(
"The file " + file +
" has the wrong format: missing xml-attribute \"file\" in element <GraphCollection>.<graph>");
257 catch (
const boost::property_tree::ptree_bad_data & error) {
258 throw Error(
"The file " + file +
" has the wrong format: corrupted content in xml-attribute \"file\" of element <GraphCollection>.<graph>");
261 graph_class = val.second.get<std::string>(
"<xmlattr>.class");
263 catch (
const boost::property_tree::ptree_bad_path & error) {
264 throw Error(
"The file " + file +
" has the wrong format: missing xml-attribute \"class\" in element <GraphCollection>.<graph>");
266 catch (
const boost::property_tree::ptree_bad_data & error) {
267 throw Error(
"The file " + file +
" has the wrong format: corrupted content in xml-attribute \"class\" of element <GraphCollection>.<graph>");
269 graph_ids.push_back(
load_gxl_graph(graph_dir + gxl_file, node_type, edge_type, irrelevant_node_attributes, irrelevant_edge_attributes,
ged::undefined(), graph_class));
271 else if (val.first !=
"<xmlattr>") {
272 throw Error(
"The file " + file +
" has the wrong format: unexpected element <GraphCollection>.<" + val.first +
">.");
278 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
281 read_gxl_label_from_ptree_(
const boost::property_tree::ptree::value_type & node_or_edge,
const std::unordered_set<std::string> & irrelevant_attributes,
const std::string & file,
GXLLabel & label) {
282 std::string attr_name, attr_val;
283 std::string info(node_or_edge.first);
285 for (
const boost::property_tree::ptree::value_type & attr : node_or_edge.second) {
287 if (attr.first ==
"attr") {
290 attr_name = attr.second.get<std::string>(
"<xmlattr>.name");
292 catch (
const boost::property_tree::ptree_bad_path & error) {
293 throw Error(
"The file " + file +
" has the wrong format: missing xml-attribute \"name\" in element <gxl>.<graph>.<" + info +
">.<attr>");
295 if (irrelevant_attributes.find(attr_name) != irrelevant_attributes.end()) {
300 for (
const boost::property_tree::ptree::value_type & val : attr.second) {
301 if (val.first !=
"<xmlattr>") {
303 if (++num_attr > 1) {
304 throw Error(
"The file " + file +
" has the wrong format: each element <gxl>.<graph>.<" + info +
">.<attr> has to have exactly one child. Actual number of children: " + std::to_string(num_attr));
307 attr_val = val.second.get<std::string>(
"");
309 catch (
const boost::property_tree::ptree_bad_path & error) {
310 throw Error(
"The file " + file +
" has the wrong format: missing content <gxl>.<graph>.<" + info +
">.<attr>.<[TYPENAME]>.___.");
312 catch (
const boost::property_tree::ptree_bad_data & error) {
313 throw Error(
"The file " + file +
" has the wrong format: corrupted content <gxl>.<graph>.<" + info +
">.<attr>.<[TYPENAME]>.___.");
318 label[attr_name] = attr_val;
321 else if (attr.first !=
"<xmlattr>"){
322 throw Error(
"The file " + file +
" has the wrong format: unexpected element <gxl>.<graph>.<" + info +
">.<" + attr.first +
">.");
327 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
331 std::stringstream ss;
336 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
340 if (graph_id >= ged_data_.num_graphs()) {
341 throw Error(
"The graph " +
get_graph_name(graph_id) +
" with ID " + std::to_string(graph_id) +
" has not been added to the environment. The environment contains " + std::to_string(ged_data_.num_graphs_without_shuffled_copies()) +
" graphs.");
343 if (original_to_internal_node_ids_[graph_id].find(node_id) != original_to_internal_node_ids_[graph_id].end()) {
344 throw Error(
"The node " + to_string_(node_id) +
" has already been added to the graph " + std::to_string(graph_id) +
": " +
get_graph_name(graph_id) +
".");
346 initialized_ =
false;
348 original_to_internal_node_ids_[graph_id][node_id] = internal_node_id;
349 internal_to_original_node_ids_[graph_id][internal_node_id] = node_id;
350 ged_data_.strings_to_internal_node_ids_[graph_id][to_string_(node_id)] = internal_node_id;
351 ged_data_.internal_node_ids_to_strings_[graph_id][internal_node_id] = to_string_(node_id);
352 LabelID label_id{ged_data_.node_label_to_id_(node_label)};
353 ged_data_.graphs_[graph_id].set_label(original_to_internal_node_ids_[graph_id][node_id], label_id);
356 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
359 add_edge(
GEDGraph::GraphID graph_id,
const UserNodeID & from,
const UserNodeID & to,
const UserEdgeLabel & edge_label,
bool ignore_duplicates) {
360 if (graph_id >= ged_data_.num_graphs()) {
361 throw Error(
"The graph " +
get_graph_name(graph_id) +
" with ID " + std::to_string(graph_id) +
" has not been added to the environment. The environment contains " + std::to_string(ged_data_.num_graphs_without_shuffled_copies()) +
" graphs.");
363 if (original_to_internal_node_ids_[graph_id].find(from) == original_to_internal_node_ids_[graph_id].end()) {
364 throw Error(
"The node " + to_string_(from) +
" does not exist in the graph " +
get_graph_name(graph_id) +
".");
366 if (original_to_internal_node_ids_[graph_id].find(to) == original_to_internal_node_ids_[graph_id].end()) {
367 throw Error(
"The node " + to_string_(to) +
" does not exist in the graph " +
get_graph_name(graph_id) +
".");
369 initialized_ =
false;
370 if (ged_data_.graphs_[graph_id].safe_is_edge(original_to_internal_node_ids_[graph_id][from], original_to_internal_node_ids_[graph_id][to])) {
371 if (ignore_duplicates) {
374 throw Error(
"An edge between " + to_string_(from) +
" and " + to_string_(to) +
" has already been added to the graph " +
get_graph_name(graph_id) +
".");
376 GEDGraph::EdgeID edge_id{ged_data_.graphs_[graph_id].add_edge(original_to_internal_node_ids_[graph_id][from], original_to_internal_node_ids_[graph_id][to])};
377 LabelID label_id{ged_data_.edge_label_to_id_(edge_label)};
378 ged_data_.graphs_[graph_id].set_label(edge_id, label_id);
381 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
451 case Options::GEDMethod::F1:
454 case Options::GEDMethod::F2:
457 case Options::GEDMethod::COMPACT_MIP:
460 case Options::GEDMethod::BLP_NO_EDGE_LABELS:
465 ged_method_->set_options(options);
468 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
472 if (g_id >= ged_data_.num_graphs()) {
473 throw Error(
"The graph with ID " + std::to_string(g_id) +
" has not been added to the environment.");
475 if (h_id >= ged_data_.num_graphs()) {
476 throw Error(
"The graph with ID " + std::to_string(h_id) +
" has not been added to the environment.");
478 if (not initialized_) {
479 throw Error(
"The environment is uninitialized. Call init() after adding all graphs to the environment.");
481 if (not ged_method_) {
482 throw Error(
"No method has been set. Call set_method() before calling run().");
485 if (ged_data_.shuffled_graph_copies_available() and (g_id == h_id)) {
486 ged_method_->run(g_id, ged_data_.id_shuffled_graph_copy(h_id));
489 ged_method_->run(g_id, h_id);
491 std::pair<GEDGraph::GraphID, GEDGraph::GraphID> key(g_id, h_id);
492 lower_bounds_[key] = ged_method_->get_lower_bound();
493 upper_bounds_[key] = ged_method_->get_upper_bound();
494 runtimes_[key] = ged_method_->get_runtime();
495 auto it = node_maps_.find(key);
496 if (it == node_maps_.end()) {
497 node_maps_.emplace(key, ged_method_->get_node_map());
500 it->second = ged_method_->get_node_map();
504 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
505 std::pair<GEDGraph::GraphID, GEDGraph::GraphID>
508 return std::make_pair(0, static_cast<GEDGraph::GraphID>(ged_data_.num_graphs_without_shuffled_copies()));
511 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
515 return ged_data_.num_graphs_without_shuffled_copies();
518 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
522 if (not initialized_) {
523 throw Error(
"The environment is uninitialized. Call init() before calling init_method().");
525 if (not ged_method_) {
526 throw Error(
"No method has been set. Call set_method() before calling init_method().");
531 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
535 std::pair<GEDGraph::GraphID, GEDGraph::GraphID> key(g_id, h_id);
536 if (lower_bounds_.find(key) == lower_bounds_.end()) {
537 throw Error(
"Call run(" + std::to_string(g_id) +
"," + std::to_string(h_id) +
") before calling get_lower_bound(" + std::to_string(g_id) +
"," + std::to_string(h_id) +
").");
539 return lower_bounds_.at(key);
542 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
546 std::pair<GEDGraph::GraphID, GEDGraph::GraphID> key(g_id, h_id);
547 if (upper_bounds_.find(key) == upper_bounds_.end()) {
548 throw Error(
"Call run(" + std::to_string(g_id) +
"," + std::to_string(h_id) +
") before calling get_upper_bound(" + std::to_string(g_id) +
"," + std::to_string(h_id) +
").");
550 return upper_bounds_.at(key);
553 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
557 std::pair<GEDGraph::GraphID, GEDGraph::GraphID> key(g_id, h_id);
558 if (node_maps_.find(key) == node_maps_.end()) {
559 throw Error(
"Call run(" + std::to_string(g_id) +
"," + std::to_string(h_id) +
") before calling get_node_map(" + std::to_string(g_id) +
"," + std::to_string(h_id) +
").");
561 return node_maps_.at(key);
564 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
568 std::pair<GEDGraph::GraphID, GEDGraph::GraphID> key(g_id, h_id);
569 if (runtimes_.find(key) == runtimes_.end()) {
570 throw Error(
"Call run(" + std::to_string(g_id) +
"," + std::to_string(h_id) +
") before calling get_runtime(" + std::to_string(g_id) +
"," + std::to_string(h_id) +
").");
572 return runtimes_.at(key).count();
575 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
579 return ged_data_.graph_classes_.at(graph_id);
582 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
586 return ged_data_.graph(graph_id).num_nodes();
589 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
593 std::size_t sum_num_nodes{0};
594 for (std::size_t graph_id{0}; graph_id < ged_data_.num_graphs_without_shuffled_copies(); graph_id++) {
595 sum_num_nodes += ged_data_.graph(graph_id).num_nodes();
597 return static_cast<double>(sum_num_nodes) / static_cast<double>(ged_data_.num_graphs_without_shuffled_copies());
600 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
604 return ged_data_.graph_names_.at(graph_id);
607 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
612 const GEDGraph & graph{ged_data_.graphs_.at(graph_id)};
613 exchange_graph.
id = graph.id();
614 exchange_graph.
num_nodes = graph.num_nodes();
615 exchange_graph.
num_edges = graph.num_edges();
616 exchange_graph.
adj_matrix = std::vector<std::vector<std::size_t>>(exchange_graph.
num_nodes, std::vector<std::size_t>(exchange_graph.
num_nodes, 0));
618 exchange_graph.
original_node_ids.emplace_back(internal_to_original_node_ids_.at(graph_id).at(node_id));
619 exchange_graph.
node_labels.emplace_back(ged_data_.node_labels_.at(graph.get_node_label(node_id) - 1));
621 for (
auto eitr = graph.edges(); eitr.first != eitr.second; eitr.first++) {
623 exchange_graph.
adj_matrix[graph.tail(edge)][graph.head(edge)] = 1;
624 exchange_graph.
adj_matrix[graph.head(edge)][graph.tail(edge)] = 1;
625 exchange_graph.
edge_labels[std::make_pair(graph.tail(edge),graph.head(edge))] = ged_data_.edge_labels_.at(graph.get_edge_label(edge) - 1);
626 exchange_graph.
edge_labels[std::make_pair(graph.head(edge),graph.tail(edge))] = ged_data_.edge_labels_.at(graph.get_edge_label(edge) - 1);
628 return exchange_graph;
631 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
635 return ged_method_->get_init_time().count();
638 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
642 ged_data_.compute_induced_cost(ged_data_.graphs_.at(g_id), ged_data_.graphs_.at(h_id), node_map);
645 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
649 return ged_data_.quasimetric_costs();
652 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
658 if (not ged_data_.edit_costs_) {
659 throw Error(
"No edit costs have been selected. Call set_edit_costs() before calling init().");
668 ged_data_.init_type_ = init_type;
671 if (ged_data_.shuffled_graph_copies_available()) {
672 for (
auto graph_id : new_graph_ids_) {
673 construct_shuffled_graph_copy_(graph_id);
678 for (
auto & graph : ged_data_.graphs_) {
679 if (not graph.initialized()) {
680 graph.setup_adjacency_matrix();
681 ged_data_.max_num_nodes_ = std::max(ged_data_.max_num_nodes_, graph.num_nodes());
682 ged_data_.max_num_edges_ = std::max(ged_data_.max_num_edges_, graph.num_edges());
687 if (ged_data_.eager_init_()) {
688 ged_data_.init_cost_matrices_();
693 new_graph_ids_.clear();
696 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
701 if (copied_graph_id < ged_data_.num_graphs()) {
702 ged_data_.graphs_[copied_graph_id].clear();
703 original_to_internal_node_ids_[copied_graph_id].clear();
704 ged_data_.strings_to_internal_node_ids_[copied_graph_id].clear();
705 internal_to_original_node_ids_[copied_graph_id].clear();
706 ged_data_.internal_node_ids_to_strings_[copied_graph_id].clear();
708 else if (copied_graph_id == ged_data_.num_graphs()) {
709 ged_data_.graphs_.emplace_back(copied_graph_id);
712 original_to_internal_node_ids_.push_back(std::map<UserNodeID, GEDGraph::NodeID>());
713 ged_data_.strings_to_internal_node_ids_.push_back(std::map<std::string, GEDGraph::NodeID>());
714 internal_to_original_node_ids_.push_back(std::map<GEDGraph::NodeID, UserNodeID>());
715 ged_data_.internal_node_ids_to_strings_.push_back(std::map<GEDGraph::NodeID, std::string>());
718 throw Error(
"Unexpected copied graph ID " + std::to_string(copied_graph_id) +
" for graph with ID " + std::to_string(graph_id) +
". Number of graphs in environment: " + std::to_string(ged_data_.num_graphs()) +
".");
720 return copied_graph_id;
723 template<
class UserNodeID,
class UserNodeLabel,
class UserEdgeLabel>
728 const GEDGraph & graph{ged_data_.graph(graph_id)};
729 std::vector<std::pair<UserNodeID, UserNodeLabel>> nodes;
730 for (
auto node = graph.nodes().first; node != graph.nodes().second; node++) {
731 nodes.emplace_back(internal_to_original_node_ids_.at(graph_id).at(*node), ged_data_.id_to_node_label(graph.get_node_label(*node)));
733 std::random_device rng_g;
734 std::mt19937 urng_g(rng_g());
735 std::shuffle(nodes.begin(), nodes.end(), urng_g);
736 for (
const auto & node : nodes) {
737 add_node(copied_graph_id, node.first, node.second);
739 for (
auto edge = graph.edges().first; edge != graph.edges().second; edge++) {
740 add_edge(copied_graph_id, internal_to_original_node_ids_.at(graph_id).at(graph.tail(*edge)), internal_to_original_node_ids_.at(graph_id).at(graph.head(*edge)), ged_data_.id_to_edge_label(graph.get_edge_label(*edge)));
Computes lower and upper bounds for general edit costs.
Computes a lower bound for uniform edit costs.
Computes a lower bound for general edit costs.
GEDGraph::GraphID load_gxl_graph(const std::string &file_name, Options::GXLNodeEdgeType node_type, Options::GXLNodeEdgeType edge_type, const std::unordered_set< std::string > &irrelevant_node_attributes, const std::unordered_set< std::string > &irrelevant_edge_attributes, GEDGraph::GraphID graph_id=ged::undefined(), const std::string &graph_class="")
Load graph given in the GXL file format.
Computes an upper bound for general edit costs.
std::string GXLNodeID
Type of node IDs of graphs given in the .gxl file format.
std::size_t id
Internal ID of the graph.
Mixed integer linear programming formulation of the graph edit distance.
std::size_t num_graphs() const
The number of graphs contained in the environment.
bool quasimetric_costs() const
Checks if the edit costs are quasimetric.
std::pair< GEDGraph::GraphID, GEDGraph::GraphID > graph_ids() const
Provides access to the IDs of the graphs contained in the environment.
std::vector< GEDGraph >::size_type GraphID
Type of internally used graph IDs.
Computes an upper bound for general edit costs.
void init(Options::InitType init_type=Options::InitType::EAGER_WITHOUT_SHUFFLED_COPIES)
Initializes the environment.
ExchangeGraph< UserNodeID, UserNodeLabel, UserEdgeLabel > get_graph(GEDGraph::GraphID graph_id) const
Returns ged::ExchangeGraph representation.
std::vector< std::vector< std::size_t > > adj_matrix
Adjacency matrix.
Uses characteristics of an LSAPE instance for defining feature vectors for node edit operations...
GEDGraph::GraphID load_exchange_graph(const ged::ExchangeGraph< UserNodeID, UserNodeLabel, UserEdgeLabel > &exchange_graph, GEDGraph::GraphID graph_id=ged::undefined(), const std::string &graph_name="", const std::string &graph_class="")
Loads ged::ExchangeGraph into the environment.
std::vector< GEDGraph::GraphID > load_gxl_graphs(const std::string &graph_dir, const std::string &collection_file, Options::GXLNodeEdgeType node_type=Options::GXLNodeEdgeType::LABELED, Options::GXLNodeEdgeType edge_type=Options::GXLNodeEdgeType::LABELED, const std::unordered_set< std::string > &irrelevant_node_attributes=std::unordered_set< std::string >(), const std::unordered_set< std::string > &irrelevant_edge_attributes=std::unordered_set< std::string >())
Loads graphs given in the GXL file format.
Computes lower and upper bounds for uniform edit costs.
Selects ged::AnchorAwareGED.
double get_init_time() const
Returns initialization time.
Simple graph class used for communication with user.
Computes lower and upper bounds for general edit costs.
void set_edit_costs(Options::EditCosts edit_costs, std::initializer_list< double > edit_cost_constants={})
Sets the edit costs to one of the predefined edit costs.
void init_method()
Initializes the method specified by call to set_method().
Computes lower and upper bounds for general edit costs.
GEDMethod
Selects the method.
std::vector< UserNodeLabel > node_labels
The labels of all nodes.
GXLNodeEdgeType
Selects whether nodes or edges of graphs given in GXL file format are labeled or unlabeled.
const std::string & get_graph_class(GEDGraph::GraphID graph_id) const
Returns the graph class.
std::vector< UserNodeID > original_node_ids
The original IDs of all nodes.
Selects ged::BranchTight.
std::size_t LabelID
Internally used type of node and edge labels.
Uses ring structures for defining feature vectors for node edit operations.
Mixed integer linear programming formulation of the graph edit distance.
double get_runtime(GEDGraph::GraphID g_id, GEDGraph::GraphID h_id) const
Returns runtime.
InitType
Selects the initialization type of the environment.
Computes lower and upper bounds for general edit costs.
double get_avg_num_nodes() const
Returns average number of nodes.
Computes lower and upper bounds for general edit costs.
Binary linear programming formulation of the graph edit distance without edge labels.
void add_node(GEDGraph::GraphID graph_id, const UserNodeID &node_id, const UserNodeLabel &node_label)
Adds a labeled node.
void compute_induced_cost(GEDGraph::GraphID g_id, GEDGraph::GraphID h_id, NodeMap &node_map) const
Computes the edit cost between two graphs induced by a node map.
Selects ged::SimulatedAnnealing.
Selects ged::BipartiteML.
std::map< std::string, std::string > GXLLabel
Type of node and edge labels of graphs given in the .gxl file format.
double get_upper_bound(GEDGraph::GraphID g_id, GEDGraph::GraphID h_id) const
Returns upper bound for edit distance between the input graphs.
The normalized input graphs used by GEDLIB. All labels are integers.
std::size_t num_nodes
The number of nodes. Nodes have IDs between 0 and num_nodes - 1.
detail::GedGraphAL::edge_descriptor EdgeID
Internally used edge ID type.
std::size_t num_edges
The number of edges.
std::map< std::pair< std::size_t, std::size_t >, UserEdgeLabel > edge_labels
A hash map with a key-value pair ((internal_tail_id, internal_head_id), label) for each edge...
std::size_t get_num_nodes(GEDGraph::GraphID graph_id) const
Returns the number of nodes.
constexpr std::size_t undefined()
Returns undefined size.
void clear_graph(GEDGraph::GraphID graph_id)
Clears and de-initializes a graph that has previously been added to the environment. Call init() after calling this method.
Computes a lower bound for uniform edit costs.
Computes an upper bound for general edit costs.
void run_method(GEDGraph::GraphID g_id, GEDGraph::GraphID h_id)
Runs the GED method specified by call to set_method() between the graphs with IDs g_id and h_id...
void set_method(Options::GEDMethod method, const std::string &options=std::string(""))
Sets the GEDMethod to be used by run_method().
Global namespace for GEDLIB.
void add_edge(GEDGraph::GraphID graph_id, const UserNodeID &tail, const UserNodeID &head, const UserEdgeLabel &edge_label, bool ignore_duplicates=true)
Adds a labeled edge.
EditCosts
Selects the edit costs.
const NodeMap & get_node_map(GEDGraph::GraphID g_id, GEDGraph::GraphID h_id) const
Returns node map between the input graphs.
Computes upper bounds for general edit costs.
Computes the exact graph edit distance for general edit costs.
Selects ged::BranchUniform.
const std::string & get_graph_name(GEDGraph::GraphID graph_id) const
Returns the graph name.
GEDGraph::GraphID add_graph(const std::string &graph_name="", const std::string &graph_class="")
Adds a new uninitialized graph to the environment. Call init() after calling this method...
Computes a lower bound for uniform edit costs.
Computes an upper bound for general edit costs.
Computes an upper bound for general edit costs.
std::size_t NodeID
Internally used vertex ID type.
Uses LSAPE instances to approximate GED via simulated annealing.
Mixed integer linear programming formulation of the graph edit distance.
Abstract class for defining edit cost functions.
double get_lower_bound(GEDGraph::GraphID g_id, GEDGraph::GraphID h_id) const
Returns lower bound for edit distance between the input graphs.
Provides the API of GEDLIB.
Selects ged::BranchCompact.