27 #ifndef SRC_METHODS_BRANCH_FAST_IPP_ 28 #define SRC_METHODS_BRANCH_FAST_IPP_ 33 template<
class UserNodeLabel,
class UserEdgeLabel>
34 BranchFast<UserNodeLabel, UserEdgeLabel>::
37 template<
class UserNodeLabel,
class UserEdgeLabel>
38 BranchFast<UserNodeLabel, UserEdgeLabel>::
39 BranchFast(
const GEDData<UserNodeLabel, UserEdgeLabel> & ged_data) :
40 LSAPEBasedMethod<UserNodeLabel, UserEdgeLabel>(ged_data),
41 sort_method_{COUNTING},
42 sorted_edge_labels_() {}
45 template<
class UserNodeLabel,
class UserEdgeLabel>
49 sorted_edge_labels_[graph.
id()] = SortedEdgeLabels_(graph, sort_method_);
52 template<
class UserNodeLabel,
class UserEdgeLabel>
56 sort_method_= COUNTING;
59 template<
class UserNodeLabel,
class UserEdgeLabel>
63 return "[--sort-method <arg>]";
66 template<
class UserNodeLabel,
class UserEdgeLabel>
70 if (option ==
"sort-method") {
74 else if (arg ==
"COUNTING") {
75 sort_method_ = COUNTING;
78 throw Error(std::string(
"Invalid argument \"") + arg +
"\" for option upper-bound. Usage: options = \"[--sort-method STD|COUNTING] [...]\"");
85 template<
class UserNodeLabel,
class UserEdgeLabel>
90 const SortedEdgeLabels_ & sorted_edge_labels_g = sorted_edge_labels_.at(g.
id());
91 const SortedEdgeLabels_ & sorted_edge_labels_h = sorted_edge_labels_.at(h.
id());
95 #pragma omp parallel for if(this->num_threads_ > 1) 97 for (std::size_t row_in_master = 0; row_in_master < master_problem.
num_rows(); row_in_master++) {
98 for (std::size_t col_in_master = 0; col_in_master < master_problem.
num_cols(); col_in_master++) {
100 master_problem(row_in_master, col_in_master) = compute_substitution_cost_(g, h, row_in_master, col_in_master, sorted_edge_labels_g, sorted_edge_labels_h);
102 else if (row_in_master < g.
num_nodes()) {
103 master_problem(row_in_master, h.
num_nodes()) = compute_deletion_cost_(g, row_in_master);
105 else if (col_in_master < h.
num_nodes()) {
106 master_problem(g.
num_nodes(), col_in_master) = compute_insertion_cost_(h, col_in_master);
114 template<
class UserNodeLabel,
class UserEdgeLabel>
118 sorted_edge_labels_() {
119 for (
auto node = g.
nodes().first; node != g.
nodes().second; node++) {
120 sorted_edge_labels_[*node] = std::vector<LabelID>();
124 switch (sort_method) {
126 std::sort(sorted_edge_labels_[*node].begin(), sorted_edge_labels_[*node].end());
135 template<
class UserNodeLabel,
class UserEdgeLabel>
139 sorted_edge_labels_() {}
141 template<
class UserNodeLabel,
class UserEdgeLabel>
145 operator=(
const SortedEdgeLabels_ & sorted_edge_labels) {
146 sorted_edge_labels_ = sorted_edge_labels.sorted_edge_labels_;
149 template<
class UserNodeLabel,
class UserEdgeLabel>
150 const std::vector<LabelID> &
154 return sorted_edge_labels_.at(node);
158 template<
class UserNodeLabel,
class UserEdgeLabel>
162 const SortedEdgeLabels_ & sorted_edge_labels_g,
const SortedEdgeLabels_ & sorted_edge_labels_h)
const {
168 double min_edge_ins_cost{std::numeric_limits<double>::infinity()};
169 for (
auto label_h = sorted_edge_labels_h.get_incident_labels(k).begin(); label_h != sorted_edge_labels_h.get_incident_labels(k).end(); label_h++) {
170 min_edge_ins_cost = std::min(min_edge_ins_cost, this->
ged_data_.edge_cost(
dummy_label(), *label_h));
172 cost +=
static_cast<double>(h.
degree(k) - g.
degree(i)) * min_edge_ins_cost * 0.5;
177 double min_edge_del_cost{std::numeric_limits<double>::infinity()};
178 for (
auto label_g = sorted_edge_labels_g.get_incident_labels(i).begin(); label_g != sorted_edge_labels_g.get_incident_labels(i).end(); label_g++) {
179 min_edge_del_cost = std::min(min_edge_del_cost, this->
ged_data_.edge_cost(*label_g,
dummy_label()));
181 cost +=
static_cast<double>(g.
degree(i) - h.
degree(k)) * min_edge_del_cost * 0.5;
185 double min_edge_subs_cost{std::numeric_limits<double>::infinity()};
186 for (
auto label_g = sorted_edge_labels_g.get_incident_labels(i).begin(); label_g != sorted_edge_labels_g.get_incident_labels(i).end(); label_g++) {
187 for (
auto label_h = sorted_edge_labels_h.get_incident_labels(k).begin(); label_h != sorted_edge_labels_h.get_incident_labels(k).end(); label_h++) {
188 if (*label_g != *label_h) {
189 min_edge_subs_cost = std::min(min_edge_subs_cost, this->
ged_data_.edge_cost(*label_g, *label_h));
195 std::size_t intersection_size{0};
196 auto label_g = sorted_edge_labels_g.get_incident_labels(i).begin();
197 auto label_h = sorted_edge_labels_h.get_incident_labels(k).begin();
198 while ((label_g != sorted_edge_labels_g.get_incident_labels(i).end()) and (label_h != sorted_edge_labels_h.get_incident_labels(k).end())) {
199 if (*label_g == *label_h) {
204 else if (*label_g < *label_h) {
213 if (std::min(g.
degree(i), h.
degree(k)) - intersection_size > 0) {
214 cost +=
static_cast<double>(std::min(g.
degree(i), h.
degree(k)) - intersection_size) * min_edge_subs_cost * 0.5;
221 template<
class UserNodeLabel,
class UserEdgeLabel>
230 for (
auto ij = incident_edges_i.first; ij != incident_edges_i.second; ij++) {
238 template<
class UserNodeLabel,
class UserEdgeLabel>
247 for (
auto kl = incident_edges_k.first; kl != incident_edges_k.second; kl++) {
virtual void lsape_populate_instance_(const GEDGraph &g, const GEDGraph &h, DMatrix &master_problem) final
Populates the LSAPE instance.
std::size_t num_nodes() const
Returns the number of nodes.
std::size_t num_threads_
The number of threads to be used.
const GEDData< UserNodeLabel, UserEdgeLabel > & ged_data_
The data on which the method is run.
virtual void lsape_set_default_options_() final
Sets all options that are not among the ones shared by all derived classes of ged::LSAPEBasedMethod t...
std::size_t degree(NodeID node) const
Returns node degree.
std::size_t num_cols() const
Returns the number of columns.
virtual std::string lsape_valid_options_string_() const final
Returns string of all valid options that are not among the ones shared by all derived classes of ged:...
virtual bool lsape_parse_option_(const std::string &option, const std::string &arg) final
Parses one option that is not among the ones shared by all derived classes of ged::LSAPEBasedMethod.
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.
Computes lower and upper bounds for general edit costs.
std::pair< incident_edge_iterator, incident_edge_iterator > incident_edges(NodeID node) const
Provides access to all incident edges of a node.
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.
constexpr LabelID dummy_label()
Returns a dummy label.
virtual void lsape_init_graph_(const GEDGraph &graph) final
Initializes global variables for one graph.
Global namespace for GEDLIB.
std::size_t NodeID
Internally used vertex ID type.
GraphID id() const
Returns the ID of the graph.
std::size_t num_rows() const
Returns the number of rows.