GEDLIB  1.0
compact_mip.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_COMPACT_MIP_IPP_
28 #define SRC_METHODS_COMPACT_MIP_IPP_
29 
30 
31 namespace ged {
32 
33 template<class UserNodeLabel, class UserEdgeLabel>
34 CompactMIP<UserNodeLabel, UserEdgeLabel>::
35 ~CompactMIP() {}
36 
37 template<class UserNodeLabel, class UserEdgeLabel>
38 CompactMIP<UserNodeLabel, UserEdgeLabel>::
39 CompactMIP(const GEDData<UserNodeLabel, UserEdgeLabel> & ged_data) :
40 MIPBasedMethod<UserNodeLabel, UserEdgeLabel>(ged_data),
41 x_(),
42 z_() {}
43 
44 template<class UserNodeLabel, class UserEdgeLabel>
45 void
47 mip_populate_model_(const GEDGraph & g, const GEDGraph & h, GRBModel & model) {
48 
49  // Clear the variables and the constant for the objective.
50  x_.clear();
51  z_.clear();
52 
53  // Add substitution variables to the model.
54  std::pair<GEDGraph::NodeID, GEDGraph::NodeID> key;
55  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
56  key.first = *i;
57  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
58  key.second = *k;
59  if ((*i == 0) and (*k == 0) and this->map_root_to_root_) {
60  x_[key] = model.addVar(1, 1, 0, variable_type_());
61  }
62  else {
63  x_[key] = model.addVar(0, 1, 0, variable_type_());
64  }
65  z_[key] = model.addVar(0, GRB_INFINITY, 1, GRB_CONTINUOUS);
66  }
67  }
68 
69  // Add deletion variables to the model.
70  key.second = GEDGraph::dummy_node();
71  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
72  key.first = *i;
73  x_[key] = model.addVar(0, 1, 0, variable_type_());
74  z_[key] = model.addVar(0, GRB_INFINITY, 1, GRB_CONTINUOUS);
75  }
76 
77  // Add insertion variables to the model.
78  key.first = GEDGraph::dummy_node();
79  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
80  key.second = *k;
81  x_[key] = model.addVar(0, 1, 0, variable_type_());
82  z_[key] = model.addVar(0, GRB_INFINITY, 1, GRB_CONTINUOUS);
83  }
84 
85 
86  // Add node constraints to the model.
87  GRBLinExpr lhs;
88  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
89  key.first = *i;
90  key.second = GEDGraph::dummy_node();
91  lhs = x_.at(key);
92  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
93  key.second = *k;
94  lhs += x_.at(key);
95  }
96  model.addConstr(lhs, GRB_EQUAL, 1);
97  }
98  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
99  key.second = *k;
100  key.first = GEDGraph::dummy_node();
101  lhs = x_.at(key);
102  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
103  key.first = *i;
104  lhs += x_.at(key);
105  }
106  model.addConstr(lhs, GRB_EQUAL, 1);
107  }
108 
109  // Add substitution constraints to the model.
110  double u{0};
111  double edit_cost{0};
112  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
113  key.first = *i;
114  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
115  key.second = *k;
116  edit_cost = this->ged_data_.node_cost(g.get_node_label(*i), h.get_node_label(*k));
117  lhs = edit_cost - z_.at(key);
118  u = edit_cost;
119  for (auto j = g.nodes().first; j != g.nodes().second; j++) {
120  key.first = *j;
121  for (auto l = h.nodes().first; l != h.nodes().second; l++) {
122  key.second = *l;
123  edit_cost = this->ged_data_.edge_cost(g.get_edge_label(*i, *j), h.get_edge_label(*k, *l)) / 2;
124  u += edit_cost;
125  lhs += edit_cost * x_.at(key);
126  }
127  }
128  key.second = GEDGraph::dummy_node();
129  for (auto j = g.nodes().first; j != g.nodes().second; j++) {
130  key.first = *j;
131  edit_cost = this->ged_data_.edge_cost(g.get_edge_label(*i, *j), dummy_label()) / 2;
132  u += edit_cost;
133  lhs += edit_cost * x_.at(key);
134  }
135  key.first = GEDGraph::dummy_node();
136  for (auto l = h.nodes().first; l != h.nodes().second; l++) {
137  key.second = *l;
138  edit_cost = this->ged_data_.edge_cost(dummy_label(), h.get_edge_label(*k, *l)) / 2;
139  u += edit_cost;
140  lhs += edit_cost * x_.at(key);
141  }
142  key.first = *i;
143  key.second = *k;
144  lhs -= (1 - x_.at(key)) * u;
145  model.addConstr(lhs, GRB_LESS_EQUAL, 0);
146  }
147  }
148 
149  // Add deletion constraints to the model.
150  key.second = GEDGraph::dummy_node();
151  for (auto i = g.nodes().first; i != g.nodes().second; i++) {
152  key.first = *i;
153  edit_cost = this->ged_data_.node_cost(g.get_node_label(*i), dummy_label());
154  lhs = edit_cost - z_.at(key);
155  u = edit_cost;
156  for (auto j = g.nodes().first; j != g.nodes().second; j++) {
157  key.first = *j;
158  for (auto l = h.nodes().first; l != h.nodes().second; l++) {
159  key.second = *l;
160  edit_cost = this->ged_data_.edge_cost(g.get_edge_label(*i, *j), dummy_label()) / 2;
161  u += edit_cost;
162  lhs += edit_cost * x_.at(key);
163  }
164  }
165  key.second = GEDGraph::dummy_node();
166  for (auto j = g.nodes().first; j != g.nodes().second; j++) {
167  key.first = *j;
168  edit_cost = this->ged_data_.edge_cost(g.get_edge_label(*i, *j), dummy_label()) / 2;
169  u += edit_cost;
170  lhs += edit_cost * x_.at(key);
171  }
172  key.first = *i;
173  lhs -= (1 - x_.at(key)) * u;
174  model.addConstr(lhs, GRB_LESS_EQUAL, 0);
175  }
176 
177  // Add insertion constraints to the model.
178  key.first = GEDGraph::dummy_node();
179  for (auto k = h.nodes().first; k != h.nodes().second; k++) {
180  key.second = *k;
181  edit_cost = this->ged_data_.node_cost(dummy_label(), h.get_node_label(*k));
182  lhs = edit_cost - z_.at(key);
183  u = edit_cost;
184  for (auto j = g.nodes().first; j != g.nodes().second; j++) {
185  key.first = *j;
186  for (auto l = h.nodes().first; l != h.nodes().second; l++) {
187  key.second = *l;
188  edit_cost = this->ged_data_.edge_cost(dummy_label(), h.get_edge_label(*k, *l)) / 2;
189  u += edit_cost;
190  lhs += edit_cost * x_.at(key);
191  }
192  }
193  key.first = GEDGraph::dummy_node();
194  for (auto l = h.nodes().first; l != h.nodes().second; l++) {
195  key.second = *l;
196  edit_cost = this->ged_data_.edge_cost(dummy_label(), h.get_edge_label(*k, *l)) / 2;
197  u += edit_cost;
198  lhs += edit_cost * x_.at(key);
199  }
200  key.second = *k;
201  lhs -= (1 - x_.at(key)) * u;
202  model.addConstr(lhs, GRB_LESS_EQUAL, 0);
203  }
204 
205 
206 }
207 
208 template<class UserNodeLabel, class UserEdgeLabel>
209 void
211 mip_model_to_node_map_(const GEDGraph & g, const GEDGraph & h, GRBModel & model, NodeMap & node_map) {
212 
213  GEDGraph::NodeID i, k;
214  for (auto it = x_.begin(); it != x_.end(); it++) {
215  if (it->second.get(GRB_DoubleAttr_X) > 0) {
216  i = it->first.first;
217  k = it->first.second;
218  node_map.add_assignment(i, k);
219  }
220  }
221 
222  // Set induced cost.
223  node_map.set_induced_cost(model.get(GRB_DoubleAttr_ObjVal));
224 
225 }
226 
227 template<class UserNodeLabel, class UserEdgeLabel>
228 bool
230 mip_model_to_lsape_projection_problem_(const GEDGraph & g, const GEDGraph & h, GRBModel & model, DMatrix & lsape_instance) {
231  GEDGraph::NodeID i, k;
232  for (auto it = x_.begin(); it != x_.end(); it++) {
233  i = std::min(it->first.first, g.num_nodes());
234  k = std::min(it->first.second, h.num_nodes());
235  lsape_instance(i, k) -= it->second.get(GRB_DoubleAttr_X);
236  }
237  return true;
238 }
239 
240 template<class UserNodeLabel, class UserEdgeLabel>
241 char
243 variable_type_() const {
244  if (this->relax_) {
245  return GRB_CONTINUOUS;
246  }
247  return GRB_BINARY;
248 }
249 
250 }
251 
252 
253 #endif /* SRC_METHODS_COMPACT_MIP_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
const GEDData< UserNodeLabel, UserEdgeLabel > & ged_data_
The data on which the method is run.
Definition: ged_method.hpp:124
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...
Mixed integer linear programming formulation of the graph edit distance.
Definition: compact_mip.hpp:43
LabelID get_node_label(NodeID node) const
Returns the label of a given node.
Definition: ged_graph.ipp:126
virtual void mip_populate_model_(const GEDGraph &g, const GEDGraph &h, GRBModel &model) final
Runs the local search from an initial node map.
Definition: compact_mip.ipp:47
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...
std::size_t NodeID
Internally used vertex ID type.
Definition: ged_graph.hpp:108
bool map_root_to_root_
If true, the model populated by mip_populate_model_() must enforce that the nodes with ID 0 are mappe...