GEDLIB  1.0
f1.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_F1_IPP_
28 #define SRC_METHODS_F1_IPP_
29 
30 
31 namespace ged {
32 
33 template<class UserNodeLabel, class UserEdgeLabel>
34 F1<UserNodeLabel, UserEdgeLabel>::
35 ~F1() {}
36 
37 template<class UserNodeLabel, class UserEdgeLabel>
38 F1<UserNodeLabel, UserEdgeLabel>::
39 F1(const GEDData<UserNodeLabel, UserEdgeLabel> & ged_data) :
40 MIPBasedMethod<UserNodeLabel, UserEdgeLabel>(ged_data),
41 x_(),
42 y_(),
43 u_(),
44 v_(),
45 e_(),
46 f_() {}
47 
48 template<class UserNodeLabel, class UserEdgeLabel>
49 void
51 mip_populate_model_(const GEDGraph & g, const GEDGraph & h, GRBModel & model) {
52 
53  // Clear the variables.
54  x_.clear();
55  y_.clear();
56  u_.clear();
57  v_.clear();
58  e_.clear();
59  f_.clear();
60 
61  // Add u variables to the model (node deletions).
62  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
63  u_.push_back(model.addVar(0, 1, this->ged_data_.node_cost(g.get_node_label(*i), dummy_label()), variable_type_()));
64  }
65 
66  // Add v variables to the model (node insertions).
67  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
68  v_.push_back(model.addVar(0, 1, this->ged_data_.node_cost(dummy_label(), h.get_node_label(*k)), variable_type_()));
69  }
70 
71  // Add x variables to the model (node substitutions).
72  std::pair<GEDGraph::NodeID, GEDGraph::NodeID> key_x;
73  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
74  key_x.first = *i;
75  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
76  key_x.second = *k;
77  if ((*i == 0) and (*k == 0) and this->map_root_to_root_) {
78  x_[key_x] = model.addVar(1, 1, this->ged_data_.node_cost(g.get_node_label(*i), h.get_node_label(*k)), variable_type_());
79  }
80  else {
81  x_[key_x] = model.addVar(0, 1, this->ged_data_.node_cost(g.get_node_label(*i), h.get_node_label(*k)), variable_type_());
82  }
83  }
84  }
85 
86  // Add e variables to the model (edge deletions).
87  for (auto e = g.edges().first; e != g.edges().second; e++) {
88  e_[*e] = model.addVar(0, 1, this->ged_data_.edge_cost(g.get_edge_label(*e), dummy_label()), variable_type_());
89  }
90 
91  // Add f variables to the model (edge insertions).
92  for (auto f = h.edges().first; f != h.edges().second; f++) {
93  f_[*f] = model.addVar(0, 1, this->ged_data_.edge_cost(dummy_label(), h.get_edge_label(*f)), variable_type_());
94  }
95 
96  // Add y variables to the model (edge substitutions).
97  std::pair<GEDGraph::EdgeID, GEDGraph::EdgeID> key_y;
98  for (auto e = g.edges().first; e != g.edges().second; e++) {
99  key_y.first = *e;
100  for (auto f = h.edges().first; f != h.edges().second; f++) {
101  key_y.second = *f;
102  y_[key_y] = model.addVar(0, 1, this->ged_data_.edge_cost(g.get_edge_label(*e), h.get_edge_label(*f)), variable_type_());
103  }
104  }
105 
106  // Add node constraints to the model.
107  GRBLinExpr lhs;
108  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
109  key_x.first = *i;
110  lhs = u_.at(*i);
111  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
112  key_x.second = *k;
113  lhs += x_.at(key_x);
114  }
115  model.addConstr(lhs, GRB_EQUAL, 1);
116  }
117  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
118  key_x.second = *k;
119  lhs = v_.at(*k);
120  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
121  key_x.first = *i;
122  lhs += x_.at(key_x);
123  }
124  model.addConstr(lhs, GRB_EQUAL, 1);
125  }
126 
127  // Add edge constraints to the model.
128  for (auto e = g.edges().first; e != g.edges().second; e++) {
129  key_y.first = *e;
130  lhs = e_.at(*e);
131  for (auto f = h.edges().first; f != h.edges().second; f++) {
132  key_y.second = *f;
133  lhs += y_.at(key_y);
134  }
135  model.addConstr(lhs, GRB_EQUAL, 1);
136  }
137  for (auto f = h.edges().first; f != h.edges().second; f++) {
138  key_y.second = *f;
139  lhs = f_.at(*f);
140  for (auto e = g.edges().first; e != g.edges().second; e++) {
141  key_y.first = *e;
142  lhs += y_.at(key_y);
143  }
144  model.addConstr(lhs, GRB_EQUAL, 1);
145  }
146 
147  // Add topology constraints to the model.
148  for (auto e = g.edges().first; e != g.edges().second; e++) {
149  key_y.first = *e;
150  GEDGraph::NodeID i{g.tail(*e)};
151  GEDGraph::NodeID j{g.head(*e)};
152  for (auto f = h.edges().first; f != h.edges().second; f++) {
153  key_y.second = *f;
154  GEDGraph::NodeID k{h.tail(*f)};
155  GEDGraph::NodeID l{h.head(*f)};
156  key_x.first = i;
157  key_x.second = k;
158  lhs = x_.at(key_x);
159  key_x.second = l;
160  lhs += x_.at(key_x);
161  model.addConstr(lhs, GRB_GREATER_EQUAL, y_.at(key_y));
162  key_x.first = j;
163  lhs = x_.at(key_x);
164  key_x.second = k;
165  lhs += x_.at(key_x);
166  model.addConstr(lhs, GRB_GREATER_EQUAL, y_.at(key_y));
167  }
168  }
169 
170 }
171 
172 template<class UserNodeLabel, class UserEdgeLabel>
173 void
175 mip_model_to_node_map_(const GEDGraph & g, const GEDGraph & h, GRBModel & model, NodeMap & node_map) {
176 
177  // Add node substitutions.
178  GEDGraph::NodeID i, k;
179  for (auto it = x_.begin(); it != x_.end(); it++) {
180  if (it->second.get(GRB_DoubleAttr_X) > 0) {
181  i = it->first.first;
182  k = it->first.second;
183  node_map.add_assignment(i, k);
184  }
185  }
186 
187  // Add node deletions.
188  for (i = 0; i < g.num_nodes(); i++) {
189  if (u_.at(i).get(GRB_DoubleAttr_X) > 0) {
190  node_map.add_assignment(i, GEDGraph::dummy_node());
191  }
192  }
193 
194  // Add node insertions.
195  for (k = 0; k < h.num_nodes(); k++) {
196  if (v_.at(k).get(GRB_DoubleAttr_X) > 0) {
197  node_map.add_assignment(GEDGraph::dummy_node(), k);
198  }
199  }
200 
201  // Set induced cost.
202  node_map.set_induced_cost(model.get(GRB_DoubleAttr_ObjVal));
203 
204 }
205 
206 template<class UserNodeLabel, class UserEdgeLabel>
207 bool
209 mip_model_to_lsape_projection_problem_(const GEDGraph & g, const GEDGraph & h, GRBModel & model, DMatrix & lsape_instance) {
210  GEDGraph::NodeID i, k;
211  for (auto it = x_.begin(); it != x_.end(); it++) {
212  i = it->first.first;
213  k = it->first.second;
214  lsape_instance(i, k) -= it->second.get(GRB_DoubleAttr_X);
215  }
216  for (i = 0; i < g.num_nodes(); i++) {
217  lsape_instance(i, h.num_nodes()) -= u_.at(i).get(GRB_DoubleAttr_X);
218  }
219  for (k = 0; k < h.num_nodes(); k++) {
220  lsape_instance(g.num_nodes(), k) -= v_.at(k).get(GRB_DoubleAttr_X);
221  }
222  return true;
223 }
224 
225 template<class UserNodeLabel, class UserEdgeLabel>
226 char
228 variable_type_() const {
229  if (this->relax_) {
230  return GRB_CONTINUOUS;
231  }
232  return GRB_BINARY;
233 }
234 
235 }
236 
237 
238 #endif /* SRC_METHODS_F1_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
Mixed integer linear programming formulation of the graph edit distance.
Definition: f1.hpp:42
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_populate_model_(const GEDGraph &g, const GEDGraph &h, GRBModel &model) final
Runs the local search from an initial node map.
Definition: f1.ipp:51
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: f1.ipp:175
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< 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
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.
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: f1.ipp:209
std::size_t NodeID
Internally used vertex ID type.
Definition: ged_graph.hpp:108
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...