00001
00002
00003 #ifndef SCIL_KCONNECTED_CC
00004 #define SCIL_KCONNECTED_CC
00005
00006 #define LEPS 1e-4
00007 #define UEPS 1e4
00008
00009 using namespace boost;
00010 using namespace SCIL;
00011 using namespace std;
00012
00013 template <typename Graph>
00014 KCONNECTED<Graph>::KCONNECTED(Graph& G_, var_map<edge_descriptor>& VM_, int k_)
00015 : G(G_), VM(VM_), k(k_) {
00016 edge_descriptor e;
00017 feps = 1.0e-4;
00018 BGL_FORALL_EDGES_T(e, G, Graph)
00019 if(VM[e].type() != Vartype_Binary) {
00020 cerr << "kconnected.cc: All variables in VM need to be";
00021 cerr << " Vartype_Binary" << endl;
00022 exit(1);
00023 }
00024
00025 BOOST_CONCEPT_ASSERT((VertexAndEdgeListGraphConcept<Graph>));
00026
00027 BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<Graph>));
00028 }
00029
00030 template <typename Graph>
00031 void KCONNECTED<Graph>::init(subproblem& S) {
00032 if (S.configuration("KCONNECTED_Debug_Out")=="true")
00033 cerr << "KCONNECTED::init\n";
00034
00035 typedef typename GraphTraits::directed_category directed_category;
00036 if (!(is_same<directed_category,undirected_tag>::value
00037 || is_base_and_derived<undirected_tag, directed_category>::value)) {
00038 cerr << "kconnected.cc: The graph has to be undirected." << endl;
00039 exit(1);
00040 };
00041
00042
00043 map<vertex_descriptor, map<vertex_descriptor, int> > edge_count;
00044 BGL_FORALL_EDGES_T(e, G, Graph)
00045 edge_count[source(e, G)][target(e, G)] = 0;
00046 BGL_FORALL_EDGES_T(e, G, Graph) {
00047 edge_count[source(e, G)][target(e, G)]++;
00048 edge_count[target(e, G)][source(e, G)]++;
00049 if (edge_count[source(e, G)][target(e, G)] > 1) {
00050 cerr << "kconnected.cc: The graph should not contain parallel edges.";
00051 cerr << endl;
00052 exit(1);
00053 }
00054 }
00055 BGL_FORALL_VERTICES_T(v, G, Graph) {
00056 row r;
00057 typename GraphTraits::out_edge_iterator oe_it, oe_it_end;
00058 for(tie(oe_it, oe_it_end)=out_edges(v, G); oe_it != oe_it_end; oe_it++)
00059 r += VM[*oe_it];
00060 if(r.size() > 0 )
00061 S.add_basic_constraint(r>=k, Static);
00062 }
00063 return;
00064 };
00065
00066 template <typename Graph>
00067 typename KCONNECTED<Graph>::status KCONNECTED<Graph>::feasible(solution& S) {
00068 if (S.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00069 cerr << "KCONNECTED::feasible\n";
00070 map<edge_descriptor, int> w;
00071
00072 BGL_FORALL_EDGES_T(e, G, Graph) {
00073 w[e] = int(double(UEPS) * S.value(VM[e]));
00074 if( w[e] < 0 )
00075 w[e] = 0;
00076 }
00077
00078 MIN_CUT<Graph> *min_cut = new MIN_CUT<Graph>(G, w);
00079 int cv = (min_cut->run())->first;
00080 if( cv < k * UEPS )
00081 return infeasible_solution;
00082 else
00083 return feasible_solution;
00084 }
00085
00086 template <typename Graph>
00087 int KCONNECTED<Graph>::cutTreeSeparation(solution& sol,
00088 list<cons_obj*>& newCons) {
00089 if (sol.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00090 cerr << "KCONNECTED::cutTreeSeparation\n";
00091
00092 int numfound = 0;
00093 map<edge_descriptor, double> ctc;
00094 map<vertex_descriptor, vertex_descriptor> p;
00095 map<vertex_descriptor, double> fl;
00096 BGL_FORALL_VERTICES_T(v, G, Graph) {
00097 p[v] = 0;
00098 fl[v] = -1.;
00099 }
00100 BGL_FORALL_EDGES_T(b, G, Graph) {
00101 ctc[b] = sol.value(VM[b]);
00102 if( ctc[b] < 1e-4 )
00103 ctc[b] = 1e-4;
00104 }
00105 computeCutTree(G, ctc, p, fl);
00106
00107 BGL_FORALL_VERTICES_T(v, G, Graph) {
00108 if( p[v] == v || fl[v] >= double(k) - .0001 )
00109 continue;
00110 if (sol.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00111 cerr << "fl: " << fl[v] << endl;
00112 row s;
00113 int rt = 0;
00114
00115
00116 vertex_descriptor ov = p[v];
00117 p[v] = v;
00118
00119
00120 typedef map<vertex_descriptor, set<vertex_descriptor>* > vertex_partition;
00121 vertex_partition vpartition;
00122
00123 BGL_FORALL_VERTICES_T(w, G, Graph) {
00124 vpartition[w] = new set<vertex_descriptor>();
00125 vpartition[w]->insert(w);
00126 }
00127
00128
00129 int num_blocks = num_vertices(G);
00130
00131 BGL_FORALL_VERTICES_T(w, G, Graph) {
00132 set<vertex_descriptor> *tmp = vpartition[p[w]];
00133 vpartition[w]->insert(tmp->begin(), tmp->end());
00134 typename set<vertex_descriptor>::iterator it;
00135
00136 for(it = tmp->begin(); it != tmp->end(); it++)
00137 vpartition[*it] = vpartition[w];
00138 num_blocks--;
00139 }
00140
00141 if (sol.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00142 cerr << "blocks: " << num_blocks << endl;
00143 BGL_FORALL_EDGES_T(f, G, Graph) {
00144
00145 if( *(vpartition[source(f, G)]) == *(vpartition[target(f, G)] ))
00146 s += VM[f];
00147 }
00148 newCons.push_back(s>=double(k));
00149 if (sol.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00150 cerr << s << endl;
00151 numfound++;
00152 p[v] = ov;
00153 }
00154 return numfound;
00155 }
00156
00157 template<typename Graph>
00158 typename KCONNECTED<Graph>::status KCONNECTED<Graph>::standard_separation(subproblem& S) {
00159 if (S.configuration("KCONNECTED_Debug_Out")=="true")
00160 cerr << "KCONNECTED::standard_separation\n";
00161 solution sol;
00162 sol.save_solution(S);
00163 list<cons_obj*> newCons;
00164 bool found = false;
00165
00166 if( cutTreeSeparation(sol, newCons) ) {
00167
00168 list<cons_obj*>::const_iterator c;
00169 for(c = newCons.begin(); c != newCons.end(); c++) {
00170 if (sol.originating_subproblem()->configuration("KCONNECTED_Debug_Out")=="true")
00171 cerr << "vio: " << (*c)->violation(S) << endl;
00172 if( (*c)->violation(S) > feps ) {
00173 S.add_basic_constraint(*c);
00174 found = true;
00175 }
00176 else
00177 delete *c;
00178 }
00179
00180 }
00181 if( found )
00182 return constraint_found;
00183
00184 return no_constraint_found;
00185 }
00186
00187 template <typename Graph>
00188 void KCONNECTED<Graph>::info() {
00189 cout<<"Configurations:\n";
00190 cout<<"KCONNECTED_Debug_Out [true|false]\n";
00191 };
00192 #endif