Scaffolding  0.1
This program can assemble genome scaffolds using the pairing information in paired-end reads.
ilp_model_3layers.hpp
1 
2 
3 #ifndef ILP_MODEL_HPP
4 #define ILP_MODEL_HPP
5 
6 #include <string>
7 #include <vector>
8 
9 #include "ilp_common.hpp"
10 
11 #include "utils/profiling.hpp"
12 
13 namespace scaffold{
14 
15  template<class Graph>
16  struct var_collection : public var_collection_virt<Graph> {
17  // variables for the second graph, containing the cycles
18  EdgeVarMap<Graph> y, z, z2;
19  vertex_var_map<Graph> sc;
20  // we're reusing var_collection_virt's tc
21  //vertex_var_map<Graph> tc;
22 
23  var_collection(const Instance<Graph>& _I):
24  var_collection_virt<Graph>::var_collection_virt(_I) {}
25  };
26 
27 
28  // block isolated cycles as lazy constraint callback
29  template<class Graph>
30  class LazyCyclesBlockCallback: public IloCplex::LazyConstraintCallbackI{
31  const var_collection<Graph>& vars;
32  callback_statistics& stats;
33  public:
34 
35  IloCplex::CallbackI* duplicateCallback() const{
36  return (new (getEnv()) LazyCyclesBlockCallback(getEnv(), vars, stats));
37  }
38 
39  LazyCyclesBlockCallback(IloEnv env, const var_collection<Graph>& _vars, callback_statistics& _stats):
40  IloCplex::LazyConstraintCallbackI(env),
41  vars(_vars),
42  stats(_stats)
43  {}
44 
45  void output_current_solution_graph(const AuxGraph& solution, const TranslateBiMap<Graph,AuxGraph>& translate) const;
46  void main();
47 
48  // adds an arc to the auxiliary graph, given an IloNumVar and a VertexPair
49  void add_arc_from_variable(
50  const IloNumVar& var,
51  const VertexPair<Graph>& uv,
52  const TranslateBiMap<Graph,AuxGraph>& translate,
53  AuxGraph& solution) const
54  {
55  if(is_true(getValue(var))){
56  const Vertex<Graph> u = uv.first;
57  const Vertex<Graph> v = uv.second;
58  const Vertex<AuxGraph> new_u = translate.left.at(u);
59  const Vertex<AuxGraph> new_v = translate.left.at(v);
60  boost::add_edge(new_u, new_v, solution);
61  DEBUG5(std::cout << "adding "<<VertexPairAndGraph<Graph>(uv, *vars.I.g)<<std::endl);
62  } else DEBUG5(std::cout << "not adding "<<VertexPairAndGraph<Graph>(uv, *vars.I.g)<< " since "<<getValue(var)<<" translates to "<<is_true(getValue(var))<<std::endl);
63  }
64 
65  }; // class
66 
67  // callback function
68  template<class Graph>
69  IloCplex::Callback GetLazyCyclesBlock(IloEnv env, const var_collection<Graph>& vars, callback_statistics& stats) {
70  return (new (env) LazyCyclesBlockCallback<Graph>(env, vars, stats));
71  }
72 
73 
74  template<class Graph>
75  void LazyCyclesBlockCallback<Graph>::output_current_solution_graph(const AuxGraph& solution, const TranslateBiMap<Graph,AuxGraph>& translate) const{
76  const Graph& g = *vars.I.g;
77  for(VertexIterRange<AuxGraph> i = boost::vertices(solution); i.first != i.second; ++i.first)
78  if(boost::out_degree(*(i.first), solution) != boost::in_degree(*(i.first), solution)){
79  const Vertex<Graph> u = translate.right.at(*(i.first));
80 
81  std::cout << "found vertex "<<VertexAndGraph<Graph>(u, g)<<" with outdeg = "<< out_degree(*(i.first), solution)<<" & indeg = "<< in_degree(*(i.first), solution) << std::endl;
82  std::cout << "we have: ";
83  if( is_true(getValue(vars.s.at(u)))) std::cout<<"s ";
84  if( is_true(getValue(vars.tp.at(u)))) std::cout<<"tp ";
85  if( is_true(getValue(vars.tc.at(u)))) std::cout<<"tc ";
86  for(VertexIterRange<AuxGraph> j = vertices(solution); j.first != j.second; ++j.first){
87  const Vertex<Graph> v = translate.right.at(*(j.first));
88  VertexPair<Graph> uv(u, v);
89  VertexPair<Graph> vu(v, u);
90 
91  if(contains(vars.y, uv) && is_true(getValue(vars.y.at(uv)))) std::cout << "y_"<<VertexPairAndGraph<Graph>(uv,g)<<", ";
92  if(contains(vars.y, vu) && is_true(getValue(vars.y.at(vu)))) std::cout << "y_"<<VertexPairAndGraph<Graph>(vu,g)<<", ";
93  if(contains(vars.z, uv) && is_true(getValue(vars.z.at(uv)))) std::cout << "z_"<<VertexPairAndGraph<Graph>(uv,g)<<", ";
94  if(contains(vars.z, vu) && is_true(getValue(vars.z.at(vu)))) std::cout << "z_"<<VertexPairAndGraph<Graph>(vu,g)<<", ";
95  if(contains(vars.z2, uv) && is_true(getValue(vars.z2.at(uv)))) std::cout << "z'_"<<VertexPairAndGraph<Graph>(uv,g)<<", ";
96  if(contains(vars.z2, vu) && is_true(getValue(vars.z2.at(vu)))) std::cout << "z'_"<<VertexPairAndGraph<Graph>(vu,g)<<", ";
97  }// for
98  std::cout << std::endl;
99 
100  Vertex<AuxGraph> ux = *(i.first);
101  while(boost::in_degree(ux, solution) > 0){
102  const Edge<AuxGraph>& in_edge = *(boost::in_edges(ux, solution).first);
103  ux = boost::source(in_edge, solution);
104  std::cout << VertexAndGraph<Graph>(translate.right.at(ux), g)<< " has indeg "<<boost::in_degree(ux, solution)<<std::endl;
105  }
106  while(boost::out_degree(ux, solution) > 0){
107  const Edge<AuxGraph>& out_edge = *(boost::out_edges(ux, solution).first);
108  ux = target(out_edge, solution);
109  std::cout << VertexAndGraph<Graph>(translate.right.at(ux), g)<< " has outdeg "<<boost::out_degree(ux, solution)<<std::endl;
110  }
111  exit(1);
112  }// if & for
113  }
114 
115  template<class Graph>
116  void LazyCyclesBlockCallback<Graph>::main(){
117  stats.time_spent.resume();
118  AuxGraph solution;
119 
120  const Instance<Graph>& I = vars.I;
121  const Graph& g = *I.g;
122 
123  DEBUG5(
124  std::cout << "solution edges: "<<std::endl;
125  for(EdgeIterRange<Graph> e = edges(g); e.first != e.second; ++e.first){
126  const Vertex<Graph>& u = boost::source(*e.first, g);
127  const Vertex<Graph>& v = boost::target(*e.first, g);
128  // get the appropriate x_ij variable
129  const VertexPair<Graph> uv(u, v);
130  const VertexPair<Graph> vu(v, u);
131  std::cout<<VertexPairAndGraph<Graph>(uv, g)<<" by ";
132 
133  if(contains(vars.y, uv) && is_true(getValue(vars.y.at(uv)))) std::cout << "y_"<<VertexPairAndGraph<Graph>(uv,g)<<", ";
134  if(contains(vars.y, vu) && is_true(getValue(vars.y.at(vu)))) std::cout << "y_"<<VertexPairAndGraph<Graph>(vu,g)<<", ";
135  if(contains(vars.z, uv) && is_true(getValue(vars.z.at(uv)))) std::cout << "z_"<<VertexPairAndGraph<Graph>(uv,g)<<", ";
136  if(contains(vars.z, vu) && is_true(getValue(vars.z.at(vu)))) std::cout << "z_"<<VertexPairAndGraph<Graph>(vu,g)<<", ";
137  if(contains(vars.z2, uv) && is_true(getValue(vars.z2.at(uv)))) std::cout << "z'_"<<VertexPairAndGraph<Graph>(uv,g)<<", ";
138  if(contains(vars.z2, vu) && is_true(getValue(vars.z2.at(vu)))) std::cout << "z'_"<<VertexPairAndGraph<Graph>(vu,g)<<", ";
139  std::cout << std::endl;
140  }
141  );
142 
143  // Step 1: construct solution graph
144  TranslateBiMap<Graph, AuxGraph> translate;
145  typedef typename TranslateBiMap<Graph, AuxGraph>::value_type TranslatePair;
146 
147  // create vertices
148  for( VertexIterRange<Graph> i = boost::vertices(g); i.first != i.second; ++i.first ){
149  const Vertex<Graph> orig_u = *(i.first);
150  const Vertex<AuxGraph> new_u = boost::add_vertex(solution);
151  translate.insert(TranslatePair(orig_u, new_u));
152  DEBUG5(std::cout << "adding "<<VertexAndGraph<Graph>(orig_u, g)<<std::endl);
153  }
154  // create arcs,
155  DEBUG5(std::cout << "adding y arcs"<<std::endl);
156  for( const auto& i : vars.y )
157  add_arc_from_variable(i.second, i.first, translate, solution);
158  DEBUG5(std::cout << "adding z arcs"<<std::endl);
159  for( const auto& i : vars.z )
160  add_arc_from_variable(i.second, i.first, translate, solution);
161  DEBUG5(std::cout << "adding z' arcs"<<std::endl);
162  for( const auto& i : vars.z2 )
163  add_arc_from_variable(i.second, i.first, translate, solution);
164 
165  // Step 2: remove all arcs reachable from s
166  std::stack<Vertex<AuxGraph> > pending;
167  DEBUG5(std::cout<<"coming from s: ");
168  for( const auto& i : vars.s )
169  if(is_true(getValue(i.second))) {
170  DEBUG5(std::cout << VertexAndGraph<Graph>(i.first, g)<<" ");
171  pending.push(translate.left.at(i.first));
172  }
173  DEBUG5(std::cout<<std::endl);
174 
175  DEBUG5(std::cout<<"coming from sc: ");
176  for( const auto& i : vars.sc )
177  if(is_true(getValue(i.second))) {
178  DEBUG5(std::cout << VertexAndGraph<Graph>(i.first, g)<<" ");
179  pending.push(translate.left.at(i.first));
180  }
181  DEBUG5(std::cout<<std::endl);
182 
183  DEBUG5(std::cout<<"going to tp: ";
184  for( const auto& i : vars.tp )
185  if(is_true(getValue(i.second))) std::cout << VertexAndGraph<Graph>(i.first, g)<<" ";
186  std::cout<< std::endl<<"going to tc: ";
187  for( const auto& i : vars.tc )
188  if(is_true(getValue(i.second))) std::cout << VertexAndGraph<Graph>(i.first, g)<<" ";
189  std::cout<<std::endl;
190  );
191 
192  // save the number of paths for level-2 debug output
193  DEBUG2(const unsigned num_p = pending.size();)
194 
195  while(!pending.empty()){
196  const Vertex<AuxGraph> u = pending.top(); pending.pop();
197  // note that u has an incoming arc y_s -> u, so, by flow conservation, it has only 1 outgoing arc
198  const unsigned char deg = boost::out_degree(u, solution);
199  assert(deg <= 1);
200  // if this outgoing arc is not to y_t, then add the next vertex to pending & remove the arc
201  if(deg == 1) {
202  const Edge<AuxGraph> e = *(boost::out_edges(u, solution).first);
203  const Vertex<AuxGraph> v = boost::target(e, solution);
204  DEBUG5(std::cout << VertexAndGraph<Graph>(translate.right.at(v), g) << " is on a path by edge from "<<VertexAndGraph<Graph>(translate.right.at(source(e, solution)), g)<<std::endl);
205  pending.push(v);
206  boost::remove_edge(e, solution);
207  }
208  }
209 
210  // Step 3: find a cycle in the remaining part of the graph
211  DEBUG5(std::cout<< "remaining arcs in auxilliary graph: "<<num_edges(solution)<<std::endl;);
212  unsigned num_new_cuts = 0;
213  if(num_edges(solution)){
214  DEBUG5(output_current_solution_graph(solution, translate));
215 
216 #ifdef LAZY_ADD_ALL_CYCLES
217  while(num_edges(solution)){
218 #endif
219  std::stack<Edge<AuxGraph> > e_pending;
220  e_pending.push(*(edges(solution).first));
221  IloExpr p_expr(getEnv()), rev_p_expr(getEnv()); // forbid the cycle and its reverse in D_p
222  IloExpr c_expr(getEnv()), rev_c_expr(getEnv()); // forbid the cycle and its reverse in D_c
223  unsigned count = 0;
224  DEBUG3(std::cout << "forbidding cycle: ");
225  while(!e_pending.empty()){
226  const Edge<AuxGraph> e = e_pending.top(); e_pending.pop();
227  const Vertex<AuxGraph> u = boost::source(e, solution);
228  const Vertex<AuxGraph> v = boost::target(e, solution);
229  const Vertex<Graph> old_u = translate.right.at(u);
230  const Vertex<Graph> old_v = translate.right.at(v);
231  const VertexPair<Graph> old_uv = VertexPair<Graph>(old_u, old_v);
232  const VertexPair<Graph> old_vu = VertexPair<Graph>(old_v, old_u);
233 
234  DEBUG3(std::cout << VertexPairAndGraph<Graph>(old_uv, g)<<" ");
235  boost::remove_edge(e, solution);
236  const unsigned char v_deg = boost::out_degree(v, solution);
237  assert(v_deg <= 1);
238  // if this outgoing arc is not to our initial arc, then add the next vertex to pending & remove the arc
239  if(v_deg == 1) e_pending.push(*(out_edges(v, solution).first));
240 
241  // forbid the cycle and its reverse in D_p & D_c
242  p_expr += vars.y.at(old_uv);
243  c_expr += vars.z.at(old_uv);
244 
245  rev_p_expr += vars.y.at(old_vu);
246  rev_c_expr += vars.z.at(old_vu);
247 
248  ++count;
249  }
250  DEBUG5(std::cout << " by allowing only <"<<count<<" of its edges");
251  DEBUG3(std::cout << std::endl);
252  add(p_expr < count);
253  add(c_expr < count);
254  add(rev_p_expr < count);
255  add(rev_c_expr < count);
256  num_new_cuts += 4;
257 #ifdef LAZY_ADD_ALL_CYCLES
258  }// while(num_edges(solution))
259 #endif
260  }// if(num_edges(solution))
261  // Step 4: collect statistical information
262  DEBUG2(std::cout << "======= callback called, found "<<num_p<<" paths & added "<<num_new_cuts<<" new cuts ======"<<std::endl);
263  stats.times_called++;
264  stats.cuts_added += num_new_cuts;
265  stats.time_spent.pause();
266  } // main()
267 
268 
269  // add a variable for an edge
270  template<class Graph>
271  void create_edge_variable(
272  IloEnv& env,
273  EdgeVarMap<Graph>& x,
274  const IloNumVar::Type& Type,
275  const size_t lower_bnd,
276  const size_t upper_bnd,
277  const Graph& g,
278  const Vertex<Graph>& u,
279  const Vertex<Graph>& v,
280  const std::string& prefix)
281  {
282  const std::string uname = std::to_string(boost::get(boost::vertex_name, g, u));
283  const std::string vname = std::to_string(boost::get(boost::vertex_name, g, v));
284  const std::string full_name(prefix + uname + "," + vname);
285  DEBUG5(std::cout << "creating "<<full_name<<std::endl);
286  x.emplace(std::piecewise_construct, std::make_tuple(u,v), std::make_tuple(env, lower_bnd, upper_bnd, Type, full_name.c_str()));
287  }
288 
289 
290  // initialize the variables for the ILP formulation
291  template<class Graph>
292  void populate_variables(IloEnv& env, var_collection<Graph>& vars){
293  const Instance<Graph>& I = vars.I;
294  const Graph& g = *I.g;
295  DEBUG5(std::cout << "creating x_{u,v}/y_uv"<<std::endl);
296  for(EdgeIterRange<Graph> e = edges(g); e.first != e.second; ++e.first){
297  const Vertex<Graph>& u = source(*e.first, g);
298  const Vertex<Graph>& v = target(*e.first, g);
299  const std::string uname = std::to_string(get(vertex_name, g, u));
300  const std::string vname = std::to_string(get(vertex_name, g, v));
301 
302  // Step 1: add variables x_e = 1 <=> e belogs to a solution path/cycle
303  create_edge_variable(env, vars.x, IloNumVar::Bool, 0, 1, g, u, v, "x_");
304  // Step 2: add variables y_ij
305  create_edge_variable(env, vars.y, IloNumVar::Bool, 0, 1, g, u, v, "y_");
306  create_edge_variable(env, vars.y, IloNumVar::Bool, 0, 1, g, v, u, "y_");
307 
308  // Step 3: add variables z_ij for D_c
309  create_edge_variable(env, vars.z, IloNumVar::Bool, 0, 1, g, u, v, "z_");
310  create_edge_variable(env, vars.z, IloNumVar::Bool, 0, 1, g, v, u, "z_");
311  if(!I.is_matching_edge(u, v)){
312  // non-matching edges go from layer 1 to layer 2 in D_c
313  create_edge_variable(env, vars.z2, IloNumVar::Bool, 0, 1, g, u, v, "z'_");
314  create_edge_variable(env, vars.z2, IloNumVar::Bool, 0, 1, g, v, u, "z'_");
315  }
316  }
317  DEBUG5(std::cout << "creating s/tp/tc interaction variables"<<std::endl);
318  // Step 3: add variables y_s,i and y_i,tp and y_i,tc
319  for(VertexIterRange<Graph> v = vertices(g); v.first != v.second; ++v.first){
320  const std::string name(std::to_string(get(vertex_name, g, *v.first)));
321  // on layer 0, come up from s
322  vars.s[*v.first] = IloNumVar(env, 0, 1, IloNumVar::Bool, ("y_s," + name).c_str());
323  vars.sc[*v.first] = IloNumVar(env, 0, 1, IloNumVar::Bool, ("z_s," + name).c_str());
324  // on layer 1, go up to tp
325  vars.tp[*v.first] = IloNumVar(env, 0, 1, IloNumVar::Bool, ("y_" + name + ",tp").c_str());
326  // on layer 2, go up to tc
327  vars.tc[*v.first] = IloNumVar(env, 0, 1, IloNumVar::Bool, ("z_" + name + ",tc").c_str());
328  }
329  }
330 
331  // initialize the constraints for the ILP formulation
332  template<class Graph>
333  void populate_constraints(IloEnv& env, IloRangeArray& c, const var_collection<Graph>& vars){
334  const Instance<Graph>& I = vars.I;
335  const Graph& g(*I.g);
336 
337  // constraint (1'): of all the representations of ij, exactly x_ij should be chosen!
338  DEBUG5(std::cout << "adding (1): of all the representations of e, exactly x_e should be chosen"<<std::endl);
339  for(auto x : vars.x){
340  const VertexPair<Graph>& uv = x.first;
341  const VertexPair<Graph> vu(uv.second, uv.first);
342  const unsigned layer = I.is_matching_edge(uv) ? 0 : 1;
343 
344  IloExpr expr(env);
345  expr += vars.y.at(uv);
346  expr += vars.y.at(vu);
347 
348  expr += vars.z.at(uv);
349  expr += vars.z.at(vu);
350  if(layer == 1){
351  expr += vars.z2.at(uv);
352  expr += vars.z2.at(vu);
353  }
354  expr -= x.second;
355  c.add(expr == 0);
356  }
357 
358  // constraint (2): all matching-edges should be chosen!
359  DEBUG5(std::cout << "adding (2): all matching-edges should be chosen"<<std::endl);
360  for(auto x : vars.x)
361  if(I.is_matching_edge(x.first)) c.add(x.second == 1);
362 
363  // constraint (4),(6): there should be at most sigma_p paths & sigma_c cycles
364  DEBUG5(std::cout << "adding (4)&(6): there should be at most sigma_p paths & sigma_c cycles"<<std::endl);
365  {
366  IloExpr p_expr(env), c_expr(env);
367  for(auto y : vars.tp) p_expr += y.second;
368  for(auto y : vars.tc) c_expr += y.second;
369  c.add(p_expr <= (double)I.num_paths);
370  c.add(c_expr <= (double)I.num_cycles);
371  }
372 
373  // constraint (3): everything that comes into layer l should leave layer l
374  DEBUG5(std::cout << "adding (3): flow conservation"<<std::endl);
375  for(unsigned layer = 0; layer < 2; ++layer){
376  for(VertexIterRange<Graph> u = boost::vertices(g); u.first != u.second; ++u.first){
377  IloExpr p_expr(env), c_expr(env);
378  for(AdjIterRange<Graph> nh = boost::adjacent_vertices(*u.first, g); nh.first != nh.second; ++nh.first){
379  const VertexPair<Graph> uv(*u.first, *nh.first);
380  // remember: layer 0 -> 1 contains only matching edges
381  if(I.is_matching_edge(uv) == (layer == 0)){
382  // flow goes to next layer along uv
383  DEBUG5(std::cout << " + y_" << VertexPairAndGraph<Graph>(uv, g));
384  p_expr += vars.y.at(uv);
385  c_expr += vars.z.at(uv);
386 
387  // on layer 1, flow goes to layer 2
388  if(layer == 1) c_expr += vars.z2.at(uv);
389  } else {
390  const VertexPair<Graph> vu(*nh.first, *u.first);
391  // flow comes from the other layer alog vu
392  DEBUG5(std::cout << " - y_"<<VertexPairAndGraph<Graph>(vu, g));
393  p_expr -= vars.y.at(vu);
394  c_expr -= vars.z.at(vu);
395  }// if
396 
397  }// for
398  if(layer == 0){
399  // on layer 0, flow comes up from s
400  DEBUG5(std::cout << " - y_s,"<<VertexAndGraph<Graph>(*u.first, g));
401  p_expr -= vars.s.at(*u.first);
402  c_expr -= vars.sc.at(*u.first);
403  } else {
404  // on layer 1, flow goes up to tp
405  DEBUG5(std::cout << " + y_"<<VertexAndGraph<Graph>(*u.first, g)<<",tp");
406  p_expr += vars.tp.at(*u.first);
407  }// if
408  c.add(p_expr == 0);
409  c.add(c_expr == 0);
410  DEBUG5(std::cout << " == 0"<< std::endl);
411  }// for
412  }// for
413  // flow conservation for layer 2:
414  for(VertexIterRange<Graph> u = boost::vertices(g); u.first != u.second; ++u.first){
415  IloExpr c_expr(env);
416  for(AdjIterRange<Graph> nh = boost::adjacent_vertices(*u.first, g); nh.first != nh.second; ++nh.first){
417  const VertexPair<Graph> vu(*nh.first, *u.first);
418  if(!I.is_matching_edge(vu)){
419  DEBUG5(std::cout << " - z'_"<<VertexPairAndGraph<Graph>(vu, g));
420  c_expr -= vars.z2.at(vu);
421  }
422  }// for
423  // on layer 2, flow goes up to tc
424  DEBUG5(std::cout << " + z_"<<VertexAndGraph<Graph>(*u.first, g)<<",tc");
425  c_expr += vars.tc.at(*u.first);
426  DEBUG5(std::cout << " == 0" << std::endl);
427  c.add(c_expr == 0);
428  }// for
429 
430 
431  // constraint (7): everything that goes to tc has to come in from s
432  DEBUG5(std::cout << "adding (7): cycle conservation"<<std::endl);
433  for(VertexIterRange<Graph> u = vertices(g); u.first != u.second; ++u.first){
434  IloExpr expr(env);
435  expr += vars.sc.at(*u.first);
436  expr -= vars.tc.at(*u.first);
437  c.add(expr >= 0);
438  }
439 
440  // constraint (5): each subset S of vertices should contain at most |S|-1 endpoints of arcs
441  //DEBUG5(std::cout << "adding (5): each subset S of vertices should contain at most |S|-1 endpoints of arcs"<<std::endl);
442  // done via callback!
443  }
444 
445 
446  // compute the ILP formulation for a graph g
447  template<class Graph>
448  void populate_model(IloModel& model, IloEnv& env, var_collection<Graph>& vars){
449  const Instance<Graph>& I = vars.I;
450  const Graph& g(*I.g);
451  IloRangeArray c(env);
452  // construct variables, keeping note of the x_ij, y^l_ij and z^l_ij variables
453  DEBUG3(std::cout << "creating variables"<<std::endl);
454  populate_variables(env, vars);
455  // add optimization function
456  DEBUG3(std::cout << "creating optimization expression"<<std::endl);
457  IloExpr opt_exp(env);
458  for(EdgeIterRange<Graph> e = edges(g); e.first != e.second; ++e.first){
459  const Vertex<Graph>& u = source(*e.first, g);
460  const Vertex<Graph>& v = target(*e.first, g);
461  // get the appropriate x_ij variable
462  auto uv = vars.x.find(std::make_pair(u,v));
463  if(uv == vars.x.end()) uv = vars.x.find(std::make_pair(v,u));
464  assert(uv != vars.x.end());
465  // add the term weight(e)*x_e
466  opt_exp += (double)boost::get(boost::edge_weight, g, *e.first) * uv->second;
467  }
468  model.add(IloMaximize(env, opt_exp));
469  // construct constraints
470  DEBUG3(std::cout << "creating constraints"<<std::endl);
471  populate_constraints(env, c, vars);
472  model.add(c);
473  }
474 
475 }
476 
477 #endif
478 
Definition: ilp_model_3layers.hpp:30
Definition: ilp_common.hpp:40
Definition: read_adj_list.hpp:22
Definition: ilp_model.hpp:25