00001 #ifndef SPAN_TREE_CC
00002 #define SPAN_TREE_CC
00003
00004 #include<scil/scil.h>
00005 #include<scil/global.h>
00006 #include<boost/graph/iteration_macros.hpp>
00007 #include<boost/foreach.hpp>
00008 #include<boost/graph/boykov_kolmogorov_max_flow.hpp>
00009 #include<boost/graph/connected_components.hpp>
00010
00011
00012 using namespace SCIL;
00013 using namespace std;
00014 using namespace boost;
00015
00016 using boost::edge_capacity;
00017 using boost::edge_flow;
00018
00019 #define VALONE 10000
00020
00021 template
00022 <typename Graph>
00023 class SpanTree<Graph>::st_cutset_inequality : public cons_obj {
00024
00025 private:
00026 typedef typename graph_traits<Graph>::edge_descriptor edge;
00027 typedef typename graph_traits<Graph>::vertex_descriptor vertex;
00028
00029 private:
00030 Graph& G;
00031 var_map<edge>& VM;
00032 std::map<vertex,bool> cut;
00033 double rhs;
00034
00035 public:
00036
00037 st_cutset_inequality(Graph& Gt, var_map<edge>& VM_, std::list<vertex>& L)
00038 : cons_obj(Greater, 1), G(Gt), VM(VM_) {
00039
00040 vertex v;
00041 BGL_FORALL_VERTICES_T(v,G,Graph)
00042 cut[v] = false;
00043
00044 BOOST_FOREACH(v,L)
00045 cut[v] = true;
00046 }
00047
00048 void non_zero_entries(row& r) {
00049 BGL_FORALL_EDGES_T(e,G,Graph) {
00050 if(coeff(e)==1) r+=VM[e];
00051 }
00052 }
00053
00054 virtual
00055 ~st_cutset_inequality() {};
00056
00057 double coeff(edge e) {
00058 if(cut[source(e,G)] != cut[target(e,G)]) return 1;
00059 return(0);
00060 };
00061 };
00062
00063
00064 template
00065 <typename Graph>
00066 SpanTree<Graph>::SpanTree(Graph& G_, var_map<edge_descriptor>& VM_)
00067 : G(G_), VM(VM_)
00068 {
00069
00070
00071
00072
00073
00074
00075
00076 edge_descriptor e;
00077 BGL_FORALL_EDGES_T(e,G,Graph)
00078 if( VM[e].type() != Vartype_Binary ) {
00079 cerr << "spantree.cc: All variables in VM need to be ";
00080 cerr << "Vartype_Binary" << endl;
00081 exit(1);
00082 }
00083 };
00084
00085 template
00086 <typename Graph>
00087 void SpanTree<Graph>::init(subproblem& S) {
00088 if (S.configuration("SpanTree_Debug_Out")=="true")
00089 cerr << "SpanTree::init\n";
00090 row r;
00091 H_edge e1,e2;
00092 H_edge r1,r2;
00093
00094 BGL_FORALL_EDGES_T(e,G,Graph) {
00095 r+=VM[e];
00096 }
00097 S.add_basic_constraint(r == num_vertices(G)-1, Static);
00098
00099 BGL_FORALL_VERTICES_T(v,G,Graph){
00100 GtoH[v] = add_vertex(H);
00101 }
00102
00103
00104 property_map<bdGraph, edge_reverse_t>::type
00105 rev = get(edge_reverse, H);
00106 BGL_FORALL_EDGES_T(e,G,Graph){
00107 GtoH1[e] = add_edge( GtoH[source(e,G)], GtoH[target(e,G)], H ).first;
00108 GtoH2[e] = add_edge( GtoH[target(e,G)], GtoH[source(e,G)], H ).first;
00109 rev[GtoH1[e]] = GtoH2[e];
00110 rev[GtoH2[e]] = GtoH1[e];
00111 }
00112
00113 son = add_vertex(H);
00114 tan = add_vertex(H);
00115
00116 BGL_FORALL_VERTICES_T(v,G,Graph) {
00117 e1 = add_edge(son, GtoH[v], H).first;
00118 e2 = add_edge(GtoH[v], tan, H).first;
00119
00120
00121 r1 = add_edge(GtoH[v], son, H).first;
00122 r2 = add_edge(tan, GtoH[v], H).first;
00123 rev[e1] = r1;
00124 rev[r1] = e1;
00125 rev[e2] = r2;
00126 rev[r2] = e2;
00127 }
00128
00129 }
00130
00131
00132 template
00133 <typename Graph>
00134 void SpanTree<Graph>::min_cut(H_vertex u, property_map<bdGraph, edge_capacity_t>::type& C,
00135 property_map<bdGraph, edge_residual_capacity_t>::type& resC,
00136 property_map<bdGraph, vertex_reached_t>::type& R, int& k) {
00137
00138 R[u]=true;
00139 k++;
00140
00141 BGL_FORALL_OUTEDGES_T(u,e,H,bdGraph)
00142 if( (resC[e]>0) && (!R[target(e,H)]) )
00143 min_cut(target(e,H), C, resC, R, k);
00144
00145 BGL_FORALL_INEDGES_T(u,e,H,bdGraph)
00146 if((resC[e]<C[e]) && (!R[source(e,H)])) {
00147 min_cut(source(e,H), C, resC, R, k);
00148 };
00149 };
00150
00151
00152 template
00153 <typename Graph>
00154 typename SpanTree<Graph>::status SpanTree<Graph>::standard_separation(subproblem& S) {
00155 if (S.configuration("SpanTree_Debug_Out")=="true")
00156 cerr << "SpanTree::standard_separation\n";
00157
00158 status sta=no_constraint_found;
00159
00160 int j, k;
00161
00162 std::vector<int> Con(num_vertices(H));
00163
00164 property_map<bdGraph, edge_capacity_t>::type Cap
00165 = get(edge_capacity, H);
00166
00167 BGL_FORALL_EDGES_T(e, G, Graph) {
00168 j=(int) (VALONE*S.value(VM[e]));
00169 if(j<0) j=0;
00170 Cap[GtoH1[e]]=j;
00171 Cap[GtoH2[e]]=j;
00172 Con[GtoH[source(e,G)]]+=j;
00173 Con[GtoH[target(e,G)]]+=j;
00174 };
00175
00176 BGL_FORALL_OUTEDGES_T(son,he,H,bdGraph) {
00177 Cap[he]=std::max(Con[target(he,H)]-2*VALONE,0);
00178 }
00179
00180 BGL_FORALL_INEDGES_T(tan,he,H,bdGraph) {
00181 Cap[he]=std::max(2*VALONE-Con[source(he,H)],0);
00182 }
00183
00184 if(sta==constraint_found) return sta;
00185
00186 row q = 0;
00187 bool cancel;
00188 property_map<bdGraph, vertex_reached_t>::type
00189 R = get(vertex_reached_t(),H);
00190
00191 property_map<bdGraph, edge_residual_capacity_t>::type
00192 resCap = get(edge_residual_capacity, H);
00193
00194 BGL_FORALL_OUTEDGES_T(son, he, H, bdGraph) {
00195 k=Cap[he];
00196 Cap[he]=1000*VALONE;
00197
00198 j = boykov_kolmogorov_max_flow(H, son, tan);
00199
00200
00201 BGL_FORALL_VERTICES_T(hv,H,bdGraph)
00202 R[hv]=false;
00203 j=0;
00204 min_cut(son, Cap, resCap, R, j);
00205 row r;
00206 double d=0;
00207 BGL_FORALL_EDGES_T(f, G,Graph) {
00208 if((R[GtoH[source(f,G)]]) && (R[GtoH[target(f,G)]])) {
00209 r+=VM[f];
00210 d+=S.value(VM[f]);
00211 };
00212 }
00213 if(d>((double) j)-1.99) {
00214 cancel = false;
00215 if(q.size()!=0){
00216 q-=r;
00217 q.normalize(true);
00218 if(q.size()==0)
00219 cancel = true;
00220 }
00221 q = r;
00222 if(!cancel){
00223 S.add_basic_constraint(r<=j-2, Dynamic);
00224 sta=constraint_found;
00225 }
00226 };
00227 Cap[he]=k;
00228 };
00229 return sta;
00230 }
00231
00232 template
00233 <typename Graph>
00234 typename SpanTree<Graph>::status SpanTree<Graph>::feasible(solution& S) {
00235 if (S.has_os() && S.originating_subproblem()->configuration("SpanTree_Debug_Out")=="true")
00236 cerr << "SpanTree::init\n";
00237 std::map<vertex,vertex> GtoH;
00238 Graph H;
00239
00240 BGL_FORALL_VERTICES_T(v,G,Graph)
00241 GtoH[v] = add_vertex(H);
00242
00243 BGL_FORALL_EDGES_T(e,G,Graph)
00244 if(S.value(VM[e])>0.5) {
00245 add_edge(GtoH[source(e,G)], GtoH[target(e,G)], H);
00246 add_edge(GtoH[target(e,G)], GtoH[source(e,G)], H);
00247 }
00248
00249 std::vector<int> component(num_vertices(H));
00250 int num = connected_components(H, &component[0]);
00251
00252 if( num==1 ) return feasible_solution;
00253 if (S.has_os() && S.originating_subproblem()->configuration("SpanTree_Debug_Out")=="true")
00254 cerr << "integer feasible, but infeasible\n";
00255 return infeasible_solution;
00256 }
00257
00258 template
00259 <typename Graph>
00260 void SpanTree<Graph>::info() {
00261 cout<<"Configurations:\n";
00262 cout<<"SpanTree_Debug_Out [true|false]\n";
00263 };
00264
00265
00266 #undef VALONE
00267
00268 #endif