GEDLIB  1.0
f2.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_F2_IPP_
28 #define SRC_METHODS_F2_IPP_
29 
30 namespace ged {
31 
32 template<class UserNodeLabel, class UserEdgeLabel>
33 F2<UserNodeLabel, UserEdgeLabel>::
34 ~F2() {}
35 
36 template<class UserNodeLabel, class UserEdgeLabel>
37 F2<UserNodeLabel, UserEdgeLabel>::
38 F2(const GEDData<UserNodeLabel, UserEdgeLabel> & ged_data) :
39 MIPBasedMethod<UserNodeLabel, UserEdgeLabel>(ged_data),
40 x_(),
41 y_() {}
42 
43 template<class UserNodeLabel, class UserEdgeLabel>
44 void
46 mip_populate_model_(const GEDGraph & g, const GEDGraph & h, GRBModel & model) {
47 
48  // Clear the variables and the constant for the objective.
49  x_.clear();
50  y_.clear();
51  GRBLinExpr obj = 0.0;
52 
53  // Collect node deletion costs.
54  std::vector<double> del_cost;
55  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
56  del_cost.push_back(this->ged_data_.node_cost(g.get_node_label(*i), dummy_label()));
57  obj += del_cost.back();
58  }
59 
60  // Collect node insertion costs.
61  std::vector<double> ins_cost;
62  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
63  ins_cost.push_back(this->ged_data_.node_cost(dummy_label(), h.get_node_label(*k)));
64  obj += ins_cost.back();
65  }
66 
67  // Add x variables to the model.
68  std::pair<GEDGraph::NodeID, GEDGraph::NodeID> key_x;
69  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
70  key_x.first = *i;
71  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
72  key_x.second = *k;
73  if ((*i == 0) and (*k == 0) and this->map_root_to_root_) {
74  x_[key_x] = model.addVar(1, 1, 0, variable_type_());
75  }
76  else {
77  x_[key_x] = model.addVar(0, 1, 0, variable_type_());
78  }
79  obj += (this->ged_data_.node_cost(g.get_node_label(*i), h.get_node_label(*k)) - del_cost.at(*i) - ins_cost.at(*k)) * x_.at(key_x);
80  }
81  }
82 
83  // Collect edge deletion costs.
84  del_cost.clear();
85  for (auto e = g.edges().first; e != g.edges().second; e++) {
86  del_cost.push_back(this->ged_data_.edge_cost(g.get_edge_label(*e), dummy_label()));
87  obj += del_cost.back();
88  }
89 
90 
91  // Collect edge insertion costs.
92  ins_cost.clear();
93  for (auto f = h.edges().first; f != h.edges().second; f++) {
94  ins_cost.push_back(this->ged_data_.edge_cost(dummy_label(), h.get_edge_label(*f)));
95  obj += ins_cost.back();
96  }
97 
98  // Add y variables to the model.
99  std::pair<GEDGraph::EdgeID, GEDGraph::EdgeID> key_y;
100  std::size_t counter_e{0};
101  std::size_t counter_f{0};
102  for (auto e = g.edges().first; e != g.edges().second; e++, counter_e++) {
103  key_y.first = *e;
104  counter_f = 0;
105  for (auto f = h.edges().first; f != h.edges().second; f++, counter_f++) {
106  key_y.second = *f;
107  y_[key_y] = model.addVar(0, 1, 0, variable_type_());
108  obj += (this->ged_data_.edge_cost(g.get_edge_label(*e), h.get_edge_label(*f)) - del_cost.at(counter_e) - ins_cost.at(counter_f)) * y_.at(key_y);
109  }
110  }
111 
112  // Set the objective.
113  model.setObjective(obj, GRB_MINIMIZE);
114 
115  // Add node constraints to the model.
116  GRBLinExpr lhs;
117  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
118  key_x.first = *i;
119  lhs = 0;
120  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
121  key_x.second = *k;
122  lhs += x_.at(key_x);
123  }
124  model.addConstr(lhs, GRB_LESS_EQUAL, 1);
125  }
126  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
127  key_x.second = *k;
128  lhs = 0;
129  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
130  key_x.first = *i;
131  lhs += x_.at(key_x);
132  }
133  model.addConstr(lhs, GRB_LESS_EQUAL, 1);
134  }
135 
136  // Add node-edge constraints to the model.
137  for (auto e = g.edges().first; e != g.edges().second; e++, counter_e++) {
138  key_y.first = *e;
139  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
140  key_x.second = *k;
141  lhs = 0;
142  for (auto f = h.incident_edges(*k).first; f != h.incident_edges(*k).second; f++) {
143  key_y.second = *f;
144  lhs += y_.at(key_y);
145  }
146  key_x.first = g.tail(*e);
147  lhs -= x_.at(key_x);
148  key_x.first = g.head(*e);
149  lhs -= x_.at(key_x);
150  model.addConstr(lhs, GRB_LESS_EQUAL, 0);
151  }
152  }
153 
154 }
155 
156 template<class UserNodeLabel, class UserEdgeLabel>
157 void
159 mip_model_to_node_map_(const GEDGraph & g, const GEDGraph & h, GRBModel & model, NodeMap & node_map) {
160 
161  // Initialize local variables.
162  std::vector<bool> delete_node(g.num_nodes(), true);
163  std::vector<bool> insert_node(h.num_nodes(), true);
164  GEDGraph::NodeID i, k;
165 
166  // Add node substitutions.
167  for (auto it = x_.begin(); it != x_.end(); it++) {
168  if (it->second.get(GRB_DoubleAttr_X) > 0) {
169  i = it->first.first;
170  k = it->first.second;
171  node_map.add_assignment(i, k);
172  delete_node[i] = false;
173  insert_node[k] = false;
174  }
175  }
176 
177  // Add node deletions.
178  for (i = 0; i < g.num_nodes(); i++) {
179  if (delete_node.at(i)) {
180  node_map.add_assignment(i, GEDGraph::dummy_node());
181  }
182  }
183 
184  // Add node insertions.
185  for (k = 0; k < h.num_nodes(); k++) {
186  if (insert_node.at(k)) {
187  node_map.add_assignment(GEDGraph::dummy_node(), k);
188  }
189  }
190 
191  // Set induced cost.
192  node_map.set_induced_cost(model.get(GRB_DoubleAttr_ObjVal));
193 
194 }
195 
196 template<class UserNodeLabel, class UserEdgeLabel>
197 bool
199 mip_model_to_lsape_projection_problem_(const GEDGraph & g, const GEDGraph & h, GRBModel & model, DMatrix & lsape_instance) {
200 
201  std::vector<double> delete_node(g.num_nodes(), 0);
202  std::vector<double> insert_node(h.num_nodes(), 0);
203 
204  GEDGraph::NodeID i, k;
205  for (auto it = x_.begin(); it != x_.end(); it++) {
206  i = it->first.first;
207  k = it->first.second;
208  lsape_instance(i, k) -= it->second.get(GRB_DoubleAttr_X);
209  delete_node[i] += it->second.get(GRB_DoubleAttr_X);
210  insert_node[k] += it->second.get(GRB_DoubleAttr_X);
211  }
212  for (i = 0; i < g.num_nodes(); i++) {
213  lsape_instance(i, h.num_nodes()) = delete_node.at(i);
214  }
215  for (k = 0; k < h.num_nodes(); k++) {
216  lsape_instance(g.num_nodes(), k) = insert_node.at(k);
217  }
218  return true;
219 }
220 
221 template<class UserNodeLabel, class UserEdgeLabel>
222 char
224 variable_type_() const {
225  if (this->relax_) {
226  return GRB_CONTINUOUS;
227  }
228  return GRB_BINARY;
229 }
230 
231 }
232 
233 #endif /* SRC_METHODS_F2_IPP_ */
bool relax_
If true, the model populated by mip_populate_model_() must be continuous.
std::size_t num_nodes() const
Returns the number of nodes.
Definition: ged_graph.ipp:211
A class for node maps.
Definition: node_map.hpp:43
virtual void mip_populate_model_(const GEDGraph &g, const GEDGraph &h, GRBModel &model) final
Runs the local search from an initial node map.
Definition: f2.ipp:46
const GEDData< UserNodeLabel, UserEdgeLabel > & ged_data_
The data on which the method is run.
Definition: ged_method.hpp:124
NodeID head(EdgeID edge) const
Returns the head of an edge.
Definition: ged_graph.ipp:199
virtual void mip_model_to_node_map_(const GEDGraph &g, const GEDGraph &h, GRBModel &model, NodeMap &node_map) final
Given a, possibly sub-optimally, solved unrelaxed model, this method constructs a node map and sets i...
Definition: f2.ipp:159
NodeID tail(EdgeID edge) const
Returns the tail of an edge.
Definition: ged_graph.ipp:178
LabelID get_node_label(NodeID node) const
Returns the label of a given node.
Definition: ged_graph.ipp:126
static NodeID dummy_node()
Returns a dummy node.
Definition: ged_graph.ipp:56
LabelID get_edge_label(EdgeID edge) const
Returns the label of a given edge.
Definition: ged_graph.ipp:135
std::pair< incident_edge_iterator, incident_edge_iterator > incident_edges(NodeID node) const
Provides access to all incident edges of a node.
Definition: ged_graph.ipp:150
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
virtual bool mip_model_to_lsape_projection_problem_(const GEDGraph &g, const GEDGraph &h, GRBModel &model, DMatrix &lsape_instance) final
Given a, possibly sub-optimally, solved model, this method constructs an LSAPE instance for projectin...
Definition: f2.ipp:199
void add_assignment(GEDGraph::NodeID i, GEDGraph::NodeID k)
Add node substitution, insertion, or deletion to the node map.
Definition: node_map.ipp:183
void set_induced_cost(double induced_cost)
Sets the induced cost of the node map.
Definition: node_map.ipp:204
constexpr LabelID dummy_label()
Returns a dummy label.
Global namespace for GEDLIB.
std::size_t NodeID
Internally used vertex ID type.
Definition: ged_graph.hpp:108
Mixed integer linear programming formulation of the graph edit distance.
Definition: f2.hpp:42
std::pair< edge_iterator, edge_iterator > edges() const
Provides access to all edge in the graph.
Definition: ged_graph.ipp:217
bool map_root_to_root_
If true, the model populated by mip_populate_model_() must enforce that the nodes with ID 0 are mappe...