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