27 #ifndef SRC_METHODS_BRANCH_COMPACT_IPP_ 28 #define SRC_METHODS_BRANCH_COMPACT_IPP_ 33 template<
class UserNodeLabel,
class UserEdgeLabel>
34 BranchCompact<UserNodeLabel, UserEdgeLabel>::
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},
45 template<
class UserNodeLabel,
class UserEdgeLabel>
54 template<
class UserNodeLabel,
class UserEdgeLabel>
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)};
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)};
72 branch_g = branches_g.erase(branch_g);
73 branch_h = branches_h.erase(branch_h);
75 else if (comp == -1) {
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;
93 else if (comp == -1) {
100 lower_bound += (
static_cast<double>(std::max(branches_g.size(), branches_h.size())) * min_edit_cost);
104 template<
class UserNodeLabel,
class UserEdgeLabel>
108 if (option ==
"sort-method") {
112 else if (arg ==
"COUNTING") {
113 sort_method_ = COUNTING;
116 throw ged::Error(std::string(
"Invalid argument \"") + arg +
"\" for option upper-bound. Usage: options = \"[--sort-method STD|COUNTING] [...]\"");
123 template<
class UserNodeLabel,
class UserEdgeLabel>
127 return "[--sort-method <arg>]";
130 template<
class UserNodeLabel,
class UserEdgeLabel>
134 sort_method_ = COUNTING;
138 template<
class UserNodeLabel,
class UserEdgeLabel>
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));
148 branches_[graph.
id()] = branches;
152 template<
class UserNodeLabel,
class UserEdgeLabel>
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);
162 switch (sort_method) {
164 std::sort(sorted_edge_labels_[*node].begin(), sorted_edge_labels_[*node].end());
173 template<
class UserNodeLabel,
class UserEdgeLabel>
174 const std::vector<LabelID> &
178 return sorted_edge_labels_.at(node);
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){}
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){}
196 template<
class UserNodeLabel,
class UserEdgeLabel>
200 compare(
const Branch_ & rhs)
const {
201 if (node_label < rhs.node_label) {
204 if (node_label > rhs.node_label) {
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) {
214 else if (*label_l < *label_r){
217 else if (*label_l > *label_r){
221 if ((label_l == sorted_edge_labels.end()) and (label_r == rhs.sorted_edge_labels.end())) {
224 if (label_l == sorted_edge_labels.end()) {
230 template<
class UserNodeLabel,
class UserEdgeLabel>
235 return compare(rhs) == -1;
238 template<
class UserNodeLabel,
class UserEdgeLabel>
243 return compare(rhs) == 1;
246 template<
class UserNodeLabel,
class UserEdgeLabel>
251 return compare(rhs) == 0;
const GEDData< UserNodeLabel, UserEdgeLabel > & ged_data_
The data on which the method is run.
void set_lower_bound(double lower_bound)
Sets the lower bound for GED.
A wrapper structure for the result of calls to ged::GEDMethod::run_as_util() and ged::GEDMethod::ged_...
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.
LabelID get_node_label(NodeID node) const
Returns the label of a given node.
LabelID get_edge_label(EdgeID edge) const
Returns the label of a given edge.
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.
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.
std::pair< node_iterator, node_iterator > nodes() const
Provides access to all nodes in the graph.
The normalized input graphs used by GEDLIB. All labels are integers.
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.
GraphID id() const
Returns the ID of the graph.