8 #include <ilcplex/ilocplex.h>
11 #include "utils/utils.hpp"
12 #include "utils/graph_typedefs.hpp"
22 using vertex_var_map = unordered_map<Vertex<Graph>, IloNumVar>;
26 edge_var_map<Graph> x;
27 unordered_map<size_t, edge_var_map<Graph> > y;
28 unordered_map<size_t, edge_var_map<Graph> > z;
29 unordered_map<size_t, vertex_var_map<Graph> > spy, ytp, scz, ztc;
36 const size_t n = num_vertices(g);
37 DEBUG3(std::cout <<
"creating x_ij/y_ij/z_ij"<<std::endl);
39 for(EdgeIterRange<Graph> e = edges(g); e.first != e.second; ++e.first){
40 const Vertex<Graph>& u = source(*e.first, g);
41 const Vertex<Graph>& v = target(*e.first, g);
42 const std::string uname = std::to_string(
get(vertex_name, g, u));
43 const std::string vname = std::to_string(
get(vertex_name, g, v));
44 const std::string name(
"x_" + uname +
"," + vname);
45 DEBUG4(std::cout <<
"creating "<<name<<std::endl);
46 vars.x.emplace(std::piecewise_construct, std::make_tuple(u, v), std::make_tuple(env, 0, 1, IloNumVar::Bool, name.c_str()));
48 for(
size_t l = 0; l < n - 1; ++l)
if((l % 2 == 0) == (I.matched_with(u) == v)){
49 edge_var_map<Graph>& yl_map = vars.y[l];
50 edge_var_map<Graph>& zl_map = vars.z[l];
52 const std::string yname_uv(
"y^" + std::to_string(l) +
"_" + uname +
"," + vname);
53 const std::string yname_vu(
"y^" + std::to_string(l) +
"_" + vname +
"," + uname);
54 yl_map.emplace(std::piecewise_construct, std::make_tuple(u,v), std::make_tuple(env, 0, 1, IloNumVar::Bool, yname_uv.c_str()));
55 yl_map.emplace(std::piecewise_construct, std::make_tuple(v,u), std::make_tuple(env, 0, 1, IloNumVar::Bool, yname_vu.c_str()));
57 const std::string zname_uv(
"z^" + std::to_string(l) +
"_" + uname +
"," + vname);
58 const std::string zname_vu(
"z^" + std::to_string(l) +
"_" + vname +
"," + uname);
59 zl_map.emplace(std::piecewise_construct, std::make_tuple(u,v), std::make_tuple(env, 0, 1, IloNumVar::Bool, zname_uv.c_str()));
60 zl_map.emplace(std::piecewise_construct, std::make_tuple(v,u), std::make_tuple(env, 0, 1, IloNumVar::Bool, zname_vu.c_str()));
63 DEBUG3(std::cout <<
"creating sp/tp/sc/tc interaction variables"<<std::endl);
65 for(VertexIterRange<Graph> v = vertices(g); v.first != v.second; ++v.first){
66 const std::string name(std::to_string(
get(vertex_name, g, *v.first)));
67 for(
size_t l = 0; l < n; ++l){
68 const std::string lname(std::to_string(l) +
"_");
71 vars.ytp[l][*v.first] = IloNumVar(env, 0, 1, IloNumVar::Bool, (
"y^" + lname + name +
",tp").c_str());
74 vars.spy[l][*v.first] = IloNumVar(env, 0, 1, IloNumVar::Bool, (
"y^" + lname +
"sp," + name).c_str());
76 vars.scz[l][*v.first] = IloNumVar(env, 0, 1, IloNumVar::Bool, (
"z^" + lname +
"sc," + name).c_str());
78 vars.ztc[l][*v.first] = IloNumVar(env, 0, 1, IloNumVar::Bool, (
"z^" + lname + name +
",tc").c_str());
86 void populate_constraints(IloEnv& env, IloRangeArray& c,
const var_collection<Graph>& vars,
const Instance<Graph>& I){
88 const size_t n = num_vertices(g);
91 DEBUG3(std::cout <<
"adding (2): of all the representations of ij, exactly x_ij should be chosen"<<std::endl);
93 VertexPair<Graph> uv = x.first;
94 VertexPair<Graph> vu = std::make_pair(uv.second, uv.first);
96 for(
size_t l = 0; l < n - 1; ++l)
if((l % 2 == 0) == (I.is_matching_edge(uv))){
97 expr += vars.y.at(l).at(uv);
98 expr += vars.y.at(l).at(vu);
99 expr += vars.z.at(l).at(uv);
100 expr += vars.z.at(l).at(vu);
107 DEBUG3(std::cout <<
"adding (3): all matching-edges should be chosen"<<std::endl);
109 if(I.is_matching_edge(x.first)) c.add(x.second == 1);
112 DEBUG3(std::cout <<
"adding (4)&(8): there should be at most sigma_p paths & sigma_c cycles"<<std::endl);
114 IloExpr y_expr(env), z_expr(env);
115 for(
size_t l = 0; l < n; ++l)
if(l % 2 == 0){
116 for(
auto y : vars.spy.at(l)) y_expr += y.second;
117 for(
auto z : vars.scz.at(l)) z_expr += z.second;
119 c.add(y_expr <= (
double)I.num_paths);
120 c.add(z_expr <= (
double)I.num_cycles);
124 DEBUG3(std::cout <<
"adding (5-7)&(9-11): everything that comes into layer l should leave layer l"<<std::endl);
125 for(
size_t l = 0; l < n; ++l){
126 for(VertexIterRange<Graph> v = vertices(g); v.first != v.second; ++v.first){
127 IloExpr y_expr(env), z_expr(env);
128 for(AdjIterRange<Graph> nh = adjacent_vertices(*v.first, g); nh.first != nh.second; ++nh.first){
130 if((l % 2 == 0) == (I.matched_with(*v.first) == *nh.first)){
133 y_expr += vars.y.at(l).at(std::make_pair(*v.first, *nh.first));
134 z_expr += vars.z.at(l).at(std::make_pair(*v.first, *nh.first));
139 y_expr -= vars.y.at(l-1).at(std::make_pair(*nh.first, *v.first));
140 z_expr -= vars.z.at(l-1).at(std::make_pair(*nh.first, *v.first));
145 if(l % 2 == 1) y_expr += vars.ytp.at(l).at(*v.first);
else y_expr -= vars.spy.at(l).at(*v.first);
148 z_expr += vars.ztc.at(l).at(*v.first);
149 z_expr -= vars.scz.at(l).at(*v.first);
159 DEBUG3(std::cout <<
"adding (12): if a cycles starts at v, a cycle ends at v"<<std::endl);
160 for(VertexIterRange<Graph> v = vertices(g); v.first != v.second; ++v.first){
162 for(
size_t l = 0; l < n; ++l)
if(l % 2 == 0){
163 expr += vars.scz.at(l).at(*v.first);
164 expr -= vars.ztc.at(l).at(*v.first);
172 template<
class Graph>
173 void populate_model(IloModel& model, IloEnv& env, var_collection<Graph>& vars,
const Instance<Graph>& I){
174 const Graph& g(*I.g);
175 IloRangeArray c(env);
177 DEBUG2(std::cout <<
"creating variables"<<std::endl);
178 populate_variables(env, vars, I);
180 DEBUG2(std::cout <<
"creating optimization expression"<<std::endl);
181 IloExpr opt_exp(env);
182 for(EdgeIterRange<Graph> e = edges(g); e.first != e.second; ++e.first){
183 const Vertex<Graph>& u = source(*e.first, g);
184 const Vertex<Graph>& v = target(*e.first, g);
186 auto uv = vars.x.find(std::make_pair(u,v));
187 if(uv == vars.x.end()) uv = vars.x.find(std::make_pair(v,u));
188 assert(uv != vars.x.end());
190 opt_exp += (double)
get(edge_weight, g, *e.first) * uv->second;
192 model.add(IloMaximize(env, opt_exp));
194 DEBUG2(std::cout <<
"creating constraints"<<std::endl);
195 populate_constraints(env, c, vars, I);
Definition: read_adj_list.hpp:22
Definition: ilp_model.hpp:25