00001 #ifndef ATOUR_CONSTRAINT_CC
00002 #define ATOUR_CONSTRAINT_CC
00003
00004 #include<scil/scil.h>
00005 #include<scil/var_map.h>
00006 #include<LEDA/graph.h>
00007 #include<LEDA/graph_alg.h>
00008 #include<LEDA/set.h>
00009 #include<scil/constraints/atour.h>
00010
00011 using namespace SCIL;
00012 using namespace LEDA;
00013
00014 #define VALONE 1000000
00015
00016 class ATOUR::dir_degree_equality : public cons_obj {
00017 private:
00018 const graph& G;
00019 node v;
00020 double deg;
00021 scil_map<edge>& VM;
00022 bool in;
00023
00024 public:
00025
00026 dir_degree_equality(subproblem& S_,
00027 const graph& G_, node v_, scil_map<edge>& VM_,
00028 double d, bool i_)
00029
00030
00031 : cons_obj(Equal, d), G(G_), VM(VM_) {
00032 v=v_; deg=d, in=i_;
00033 };
00034
00035 virtual
00036 ~dir_degree_equality()
00037 {};
00038
00039 node gnode() { return v; };
00040
00041 virtual void non_zero_entries(row& r) {
00042 edge e;
00043 if(in) {
00044 forall_out_edges(e, v) {
00045 r+=VM(e);
00046 }
00047 } else {
00048 forall_in_edges(e, v) {
00049 r+=VM(e);
00050 }
00051 };
00052 };
00053 };
00054
00055 class ATOUR::dir_cutset_inequality : public cons_obj {
00056 private:
00057 graph& G;
00058 scil_map<edge>& VM;
00059 node_array<bool> cut;
00060 double rhs;
00061
00062 public:
00063
00064 dir_cutset_inequality(graph& Gt, scil_map<edge>& VM_, list<node>& L)
00065 : cons_obj(Less, L.size()-1), G(Gt), VM(VM_) {
00066 node v;
00067 cut.init(G, false);
00068 forall(v,L) cut[v]=true;
00069 }
00070
00071 void non_zero_entries(row& r) {
00072 edge e;
00073 forall_edges(e,G) {
00074 if(coeff(e)==1) r+=VM(e);
00075 }
00076 }
00077
00078 virtual
00079 ~dir_cutset_inequality() {};
00080
00081 double coeff(edge e) {
00082 if(e==nil) return 0;
00083 if((cut[G.source(e)]) && (cut[G.target(e)])) return 1;
00084 return(0);
00085 };
00086 };
00087
00088
00089 ATOUR::ATOUR(graph& G_, scil_map<edge>& VM_)
00090 : G(G_), VM(VM_)
00091 { };
00092
00093 void ATOUR::init(subproblem& S) {
00094 node v;
00095 forall_nodes(v, G) {
00096 S.add_basic_constraint(new dir_degree_equality(S,G,v,VM,1, true));
00097 S.add_basic_constraint(new dir_degree_equality(S,G,v,VM,1, false));
00098 }
00099 }
00100
00101 ATOUR::status ATOUR::separate(subproblem& S) {
00102
00103 int i=0;
00104 edge_array<int> val(G);
00105 edge e;
00106 forall_edges(e, G) val[e]=leda::max((int) (VALONE*S.value(VM(e))),0);
00107
00108
00109 graph H;
00110 node u;
00111 node_array<node> HtoG(H, G.number_of_nodes(), u);
00112 node_array<node> GtoH(G);
00113
00114 forall_nodes(u, G) { GtoH[u]=H.new_node(); HtoG[GtoH[u]]=u; }
00115
00116 forall_edges(e, G) if(val[e]>=VALONE-5)
00117 H.new_edge(GtoH[source(e)], GtoH[target(e)]);
00118
00119 node_array<int> CC(H);
00120 int k=COMPONENTS(H,CC);
00121 list<node> CCL[k];
00122 forall_nodes(u,H) CCL[CC[u]].append(HtoG[u]);
00123 cout<<k<<" Connected Components\n";
00124
00125 if(k>1) {
00126 for(int j=0;j<k;j++) {
00127 cons_obj* c=new dir_cutset_inequality(G,VM,CCL[j]);
00128 if (c->violated(S)) {
00129 i++;
00130 S.add_basic_constraint(c, Dynamic);
00131 } else delete c;
00132 }
00133 }
00134
00135
00136 if(i>0) {
00137 cout<<i<<" Heuristic\n"; return constraint_found;
00138 }
00139
00140
00141
00142 list<node> mc=MIN_CUT(G, val);
00143 cons_obj* c=new dir_cutset_inequality(G,VM,mc);
00144 if (c->violated(S)) {
00145 i++; S.add_basic_constraint(c, Dynamic);
00146 } else delete c;
00147 if(i>0) {
00148 cout<<"Exact CUT fount inequality\n";
00149 return constraint_found;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 if(i>0) {
00206 return constraint_found;
00207 }
00208
00209 return no_constraint_found;
00210 }
00211
00212 ATOUR::status ATOUR::feasible(solution& S) {
00213 node_array<node> GtoH(G);
00214 graph H;
00215 node u;
00216 forall_nodes(u, G)
00217 GtoH[u]=H.new_node();
00218 edge e;
00219 forall_edges(e,G) {
00220 if(S.value(VM(e))>0.5) H.new_edge(GtoH[source(e)], GtoH[target(e)]);
00221 }
00222 if (Is_Connected(H)) return feasible_solution;
00223 return infeasible_solution;
00224 }
00225 #undef VALONE
00226
00227 #endif