27 #ifndef SRC_METHODS_BRANCH_UNIFORM_IPP_ 28 #define SRC_METHODS_BRANCH_UNIFORM_IPP_ 33 template<
class UserNodeLabel,
class UserEdgeLabel>
34 BranchUniform<UserNodeLabel, UserEdgeLabel>::
37 template<
class UserNodeLabel,
class UserEdgeLabel>
38 BranchUniform<UserNodeLabel, UserEdgeLabel>::
39 BranchUniform(
const GEDData<UserNodeLabel, UserEdgeLabel> & ged_data) :
40 LSAPEBasedMethod<UserNodeLabel, UserEdgeLabel>(ged_data),
41 sort_method_{COUNTING},
42 wildcard_option_{
false},
43 sorted_edge_labels_() {}
46 template<
class UserNodeLabel,
class UserEdgeLabel>
50 sorted_edge_labels_[graph.
id()] = SortedEdgeLabels_(graph, sort_method_);
53 template<
class UserNodeLabel,
class UserEdgeLabel>
58 const SortedEdgeLabels_ & sorted_edge_labels_g = sorted_edge_labels_.at(g.
id());
59 const SortedEdgeLabels_ & sorted_edge_labels_h = sorted_edge_labels_.at(h.
id());
60 double min_edge_subs_cost{this->
ged_data_.min_edge_subs_cost(g, h)};
61 double min_edge_del_cost{this->
ged_data_.min_edge_del_cost(g)};
62 double min_edge_ins_cost{this->
ged_data_.min_edge_ins_cost(h)};
66 #pragma omp parallel for if(this->num_threads_ > 1) 68 for (std::size_t row_in_master = 0; row_in_master < master_problem.
num_rows(); row_in_master++) {
69 for (std::size_t col_in_master = 0; col_in_master < master_problem.
num_cols(); col_in_master++) {
71 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, min_edge_subs_cost, min_edge_del_cost, min_edge_ins_cost);
74 master_problem(row_in_master, h.
num_nodes()) = compute_deletion_cost_(g, row_in_master, min_edge_del_cost);
77 master_problem(g.
num_nodes(), col_in_master) = compute_insertion_cost_(h, col_in_master, min_edge_ins_cost);
83 template<
class UserNodeLabel,
class UserEdgeLabel>
87 sort_method_ = COUNTING;
88 wildcard_option_ =
false;
91 template<
class UserNodeLabel,
class UserEdgeLabel>
95 return "[--sort-method <arg>] [--wildcards <arg>]";
98 template<
class UserNodeLabel,
class UserEdgeLabel>
102 if (option ==
"sort-method") {
106 else if (arg ==
"COUNTING") {
107 sort_method_ = COUNTING;
110 throw Error(std::string(
"Invalid argument \"") + arg +
"\" for option upper-bound. Usage: options = \"[--sort-method STD|COUNTING] [...]\"");
114 else if (option ==
"wildcards") {
116 wildcard_option_ =
false;
118 else if (arg ==
"YES") {
119 wildcard_option_ =
true;
122 throw Error(std::string(
"Invalid argument \"") + arg +
"\" for option wildcards. Usage: options = \"[--wildcards YES|NO] [...]\"");
130 template<
class UserNodeLabel,
class UserEdgeLabel>
134 sorted_edge_labels_(){
135 for (
auto node = g.
nodes().first; node != g.
nodes().second; node++) {
136 sorted_edge_labels_[*node] = std::vector<LabelID>();
140 switch (sort_method) {
142 std::sort(sorted_edge_labels_[*node].begin(), sorted_edge_labels_[*node].end());
151 template<
class UserNodeLabel,
class UserEdgeLabel>
155 sorted_edge_labels_() {}
157 template<
class UserNodeLabel,
class UserEdgeLabel>
161 operator=(
const SortedEdgeLabels_ & sorted_edge_labels) {
162 sorted_edge_labels_ = sorted_edge_labels.sorted_edge_labels_;
165 template<
class UserNodeLabel,
class UserEdgeLabel>
166 const std::vector<LabelID> &
170 return sorted_edge_labels_.at(node);
174 template<
class UserNodeLabel,
class UserEdgeLabel>
178 const SortedEdgeLabels_ & sorted_edge_labels_g,
const SortedEdgeLabels_ & sorted_edge_labels_h,
179 double min_edge_subs_cost,
double min_edge_del_cost,
double min_edge_ins_cost)
const {
189 std::size_t num_incident_wildard_edges{0};
190 if (wildcard_option_) {
191 for (
auto label_h : sorted_edge_labels_h.get_incident_labels(k)) {
193 num_incident_wildard_edges++;
199 std::size_t intersection_size{0};
200 auto label_g = sorted_edge_labels_g.get_incident_labels(i).begin();
201 auto label_h = sorted_edge_labels_h.get_incident_labels(k).begin();
202 while ((label_g != sorted_edge_labels_g.get_incident_labels(i).end()) and (label_h != sorted_edge_labels_h.get_incident_labels(k).end())) {
203 if (*label_g == *label_h) {
208 else if (*label_g < *label_h) {
218 cost +=
static_cast<double>(g.
degree(i) - h.
degree(k)) * min_edge_del_cost * 0.5;
223 std::size_t num_inserted_edges{h.
degree(k) - g.
degree(i)};
225 if (wildcard_option_) {
226 if (min_edge_ins_cost >= min_edge_subs_cost) {
227 if (num_inserted_edges >= num_incident_wildard_edges) {
228 num_inserted_edges -= num_incident_wildard_edges;
229 num_incident_wildard_edges = 0;
232 num_incident_wildard_edges -= num_inserted_edges;
233 num_inserted_edges = 0;
237 std::size_t num_substituted_edges{g.
degree(i) - intersection_size};
239 if (num_substituted_edges < num_incident_wildard_edges) {
240 num_inserted_edges -= (num_incident_wildard_edges - num_substituted_edges);
241 num_incident_wildard_edges = num_substituted_edges;
245 cost +=
static_cast<double>(num_inserted_edges) * min_edge_ins_cost * 0.5;
250 cost +=
static_cast<double>(std::min(g.
degree(i), h.
degree(k)) - intersection_size - num_incident_wildard_edges) * 0.5 * min_edge_subs_cost;
256 template<
class UserNodeLabel,
class UserEdgeLabel>
264 cost +=
static_cast<double>(g.
degree(i)) * 0.5 * min_edge_del_cost;
270 template<
class UserNodeLabel,
class UserEdgeLabel>
278 std::size_t num_incident_wildard_edges{0};
279 if (wildcard_option_) {
282 num_incident_wildard_edges++;
286 cost +=
static_cast<double>(h.
degree(k) - num_incident_wildard_edges) * 0.5 * min_edge_ins_cost;
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.
std::size_t degree(NodeID node) const
Returns node degree.
std::size_t num_cols() const
Returns the number of columns.
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.
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.
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.