Main Page   Class Hierarchy   Compound List   File List   Contact   Download   Symbolic Constraints   Examples  

SteinerArborescence.cc

00001 #ifndef SCIL_STEINER_ARBORESCENCE_CC
00002 #define SCIL_STEINER_ARBORESCENCE_CC
00003 
00004 #define LEPS 1e-4
00005 
00006 using namespace SCIL;
00007 using std::cerr;
00008 using std::endl;
00009 
00010 template <typename Graph>
00011 SteinerArborescence<Graph>::SteinerArborescence(Graph& G_,
00012    vertex_descriptor root_, std::list<vertex_descriptor>& terminals_, 
00013    var_map<edge_descriptor>& VM_)
00014    : G(G_), root(root_), terminals(terminals_), VM(VM_) {
00015    feps = 1.0e-4;
00016    BGL_FORALL_EDGES_T(e, G, Graph)
00017       if(VM[e].type() != Vartype_Binary) {
00018          cerr << "SteinerArborescence.cc: All variables in VM";
00019          cerr << " need to be Vartype_Binary" << endl;
00020          exit(1);
00021       }
00022    //Graph has to be bidirectional
00023    BOOST_CONCEPT_ASSERT((boost::BidirectionalGraphConcept<Graph>));
00024    BOOST_CONCEPT_ASSERT((boost::VertexAndEdgeListGraphConcept<Graph>));
00025 }
00026 
00027 template <typename Graph>
00028 void SteinerArborescence<Graph>::init(subproblem& S) {
00029    if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00030       cerr << "SteinerArborescence::init\n";
00031    //the root node must not be a terminal
00032    typename std::list<vertex_descriptor>::iterator it;
00033    it = search_n(terminals.begin(), terminals.end(), 1, root);
00034    if( it != terminals.end() ) {
00035       cerr << "SteinerArborescence: The root node must not be a terminal!" << endl;
00036       exit(1);
00037    }
00038 
00039    //all terminals have indegree 1
00040    //all Steiner nodes have indegree <=1
00041    BGL_FORALL_VERTICES_T(v, G, Graph) {
00042       row r;
00043       typename GraphTraits::in_edge_iterator ie_it, ie_it_end;
00044       for(tie(ie_it, ie_it_end) = in_edges(v,G); ie_it != ie_it_end; ie_it++)
00045          r += VM[*ie_it];
00046       it = search_n(terminals.begin(), terminals.end(), 1, v);
00047       if( it != terminals.end() )
00048          S.add_basic_constraint(r==1., Static);
00049       else if( v != root )
00050          S.add_basic_constraint(r<=1., Static);
00051    }
00052    row r;
00053    typename GraphTraits::out_edge_iterator oe_it, oe_it_end;
00054    for(tie(oe_it, oe_it_end) = out_edges(root, G); oe_it != oe_it_end; oe_it++)
00055       r += VM[*oe_it];
00056    S.add_basic_constraint(r>=1.,Static);
00057 
00058    int i = 0;
00059    BGL_FORALL_VERTICES_T(v, G, Graph) {
00060       vertex_descriptor new_vertex_Gmf = add_vertex(Gmf);
00061       vertex_descriptor new_vertex_Fmf = add_vertex(Fmf);
00062       vertices_GtoGmf[v] = new_vertex_Gmf;
00063       vertices_GtoFmf[v] = new_vertex_Fmf;
00064       vertex_index_Gmf[new_vertex_Gmf] = i;
00065       vertex_index_Fmf[new_vertex_Fmf] = i;
00066       i++;
00067    }
00068    //Maps each original edge (u,v) in Gmf to its reverse edge (v,u)
00069    BGL_FORALL_EDGES_T(e, G, Graph) {
00070       edge_descriptor original_edge_Gmf, original_edge_Fmf, reverse_edge_Gmf, reverse_edge_Fmf;
00071       vertex_descriptor s = vertices_GtoGmf[source(e, G)];
00072       vertex_descriptor t = vertices_GtoGmf[target(e, G)];
00073       vertex_descriptor u = vertices_GtoFmf[source(e, G)];
00074       vertex_descriptor v = vertices_GtoFmf[target(e, G)];
00075       original_edge_Gmf = add_edge(s, t, Gmf).first;
00076       original_edge_Fmf = add_edge(v, u, Fmf).first;
00077       is_original_edge_Gmf[original_edge_Gmf] = true;
00078       is_original_edge_Fmf[original_edge_Fmf] = true;
00079       if(!edge(target(e, G), source(e, G), G).second){
00080          reverse_edge_Gmf = (add_edge(t, s, Gmf)).first;
00081          is_original_edge_Gmf[reverse_edge_Gmf] = false;
00082          reverse_edge_Fmf = (add_edge(u, v, Fmf)).first;
00083          is_original_edge_Fmf[reverse_edge_Fmf] = false;
00084       }
00085       else if(edge(t, s, Gmf).second){
00086          reverse_edge_Gmf = edge(t, s, Gmf).first;
00087          rev_Gmf[original_edge_Gmf] = reverse_edge_Gmf;
00088          rev_Gmf[reverse_edge_Gmf] = original_edge_Gmf;
00089          reverse_edge_Fmf = edge(u, v, Fmf).first;
00090          rev_Fmf[original_edge_Fmf] = reverse_edge_Fmf;
00091          rev_Fmf[reverse_edge_Fmf] = original_edge_Fmf;
00092       } 
00093       edges_GmfToG[original_edge_Gmf] = e;
00094       edges_FmfToG[original_edge_Fmf] = e;
00095    }
00096 
00097    return;
00098 };
00099 
00101 /* This visitors sets the boolean values of all vertices in map reached to true
00102    if a vertex is visited
00103  */
00104 template <typename Graph>
00105 class SteinerArborescence<Graph>::dfs_visitor : public default_dfs_visitor {
00106    public:
00107       dfs_visitor(map<vertex_descriptor, bool>* _reached) : reached(_reached) {}
00109       void discover_vertex(vertex_descriptor u, const Graph &G) const {
00110          (*reached)[u] = true;
00111       }
00113       map<vertex_descriptor, bool> *reached;
00114 };
00115 
00116 template <typename Graph>
00117 typename SteinerArborescence<Graph>::status 
00118 SteinerArborescence<Graph>::feasible(solution& S) {
00119    if (S.originating_subproblem()->configuration("SteinerArborescence_Debug_Out")=="true")
00120       cerr << "SteinerArborescence::feasible\n";
00121    map<vertex_descriptor, vertex_descriptor> GtoH;
00122    Graph H;
00123    BGL_FORALL_VERTICES_T(u1, G, Graph)
00124       GtoH[u1] = add_vertex(H);
00125    BGL_FORALL_EDGES_T(e, G, Graph)
00126       if(S.value(VM[e])>0.5) 
00127          add_edge(GtoH[source(e, G)], GtoH[target(e, G)], H);
00128 
00129    //Input for depth_first_visit
00130    map<vertex_descriptor, bool> reached;
00131    typedef map<vertex_descriptor, default_color_type> color_map_t;
00132    color_map_t color_map;
00133    BGL_FORALL_VERTICES_T(v, H, Graph) {
00134       reached[v] = false;
00135       color_map[v] = white_color;
00136    }
00137    associative_property_map<color_map_t> pm_color(color_map);
00138    dfs_visitor vis(&reached);
00139    //depth_first_visit visits just the connected component containing GtoH[root]
00140    depth_first_visit(H, GtoH[root], vis, pm_color);
00141 
00142    std::list<vertex_descriptor> reached_vertices;
00143    BGL_FORALL_VERTICES_T(v, H, Graph)
00144       if(reached[v]) reached_vertices.push_back(v);
00145    //FIXME
00146 
00147    vertex_descriptor u1;
00148    BOOST_FOREACH(u1, terminals) {
00149    //  if( reached.search(GtoH[u1]) == nil )
00150    //   return infeasible_solution;
00151       if ( !reached[GtoH[u1]] ) return infeasible_solution;
00152    }
00153    return feasible_solution;
00154 }
00155 
00156 template <typename Graph>
00157 int SteinerArborescence<Graph>::separate_flipped(subproblem& S) {
00158    if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00159       cerr << "SteinerArborescence::seperate_flipped\n";
00160    int numfound = 0;
00161    capacity_map_t c;
00162    capacity_map_t d;
00163    capacity_map_t residual_capacity;
00164    BGL_FORALL_EDGES_T(e, Fmf, Graph)
00165       residual_capacity[e] = 0;
00166    BGL_FORALL_EDGES_T(e, Fmf, Graph) {
00167       if(is_original_edge_Fmf[e]) {
00168          //edge is an original edge
00169          c[e] = (int) (1000. * S.value(VM[edges_FmfToG[e]]));
00170          if( c[e] == 0 )
00171             c[e] = 1;
00172       } else {
00173          //edge is a reverse edge
00174          c[e] = 0;
00175       }
00176    }
00177    //ColorMap for boykov_kolmogorov_max_flow
00178    color_map_t color_map;
00179    BGL_FORALL_VERTICES_T(v, Fmf, Graph)
00180       color_map[v] = white_color;
00181    //Predecessor map for boykov_kolmogorov_max_flow
00182    predecessor_map_t pred_map;
00183    //Distance map for boykov_kolmogorov_max_flow
00184    vdistance_map_t vdist_map;
00185 
00186 
00187    //Property maps for boykov_kolmogorov_max_flow
00188    associative_property_map<capacity_map_t> pm_capacity(d);
00189    associative_property_map<capacity_map_t> pm_res_cap(residual_capacity);
00190    associative_property_map<rev_edge_map_t> pm_rev(rev_Fmf);
00191    associative_property_map<vertex_index_map_t> pm_vi(vertex_index_Fmf);
00192    associative_property_map<color_map_t> pm_color(color_map);
00193    associative_property_map<predecessor_map_t> pm_pred(pred_map);
00194    associative_property_map<vdistance_map_t> pm_vdist(vdist_map);
00195 
00196    vertex_descriptor v;
00197    BOOST_FOREACH(v, terminals) {
00198       std::list<vertex_descriptor> cut;
00199       BGL_FORALL_EDGES_T(e, Fmf, Graph) 
00200          d[e] = c[e];
00201       map<edge_descriptor, bool> fixed;
00202       BGL_FORALL_EDGES_T(e, Fmf, Graph)
00203          fixed[e] = false;
00204       int cv = 0;
00205       int go = 0;
00206       bool added = true;
00207       while( added ) {
00208          BGL_FORALL_VERTICES_T(u, Fmf, Graph)
00209             color_map[u] = white_color;
00210          cv = boykov_kolmogorov_max_flow(Fmf, pm_capacity, pm_res_cap, pm_rev,
00211                  pm_pred, pm_color, pm_vdist, pm_vi, vertices_GtoFmf[v],
00212                  vertices_GtoFmf[root]);
00213          go++;
00214          added = false;
00215          cut.clear();
00216          typename GraphTraits::vertex_iterator v_it, v_it_end;
00217          /* Vertices that are colored black by boykov_kolmogorov_max_flow are in
00218             the source tree and form a minimum s-t-cut
00219           */
00220          for(tie(v_it,v_it_end) = vertices(Fmf); v_it != v_it_end; v_it++)
00221             if (color_map[*v_it] == black_color) cut.push_back(*v_it);
00222          if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00223             cerr << "cv: " << cv << endl;
00224          if( cv < 1000 && cut.size() >= 1 && cut.size() < num_vertices(Fmf) - 1 ) {
00225             row r;
00226             vertex_descriptor w;
00227             BOOST_FOREACH(w, cut) {
00228                BGL_FORALL_OUTEDGES_T(w, e, Fmf, Graph) {
00229                   if (search_n(cut.begin(),cut.end(),1,target(e,Fmf)) == cut.end()
00230                       && is_original_edge_Fmf[e] /* && !fixed[e] */ ) {
00231                      r += VM[edges_FmfToG[e]];
00232                      d[e] = 1000;
00233                      fixed[e] = true;
00234                   }
00235                }
00236             }
00237             cons_obj* con = (r>=1.);
00238             if( con->violation(S) > feps ) {
00239                S.add_basic_constraint(r>=1., Dynamic);
00240                if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00241                   if( go > 1 )
00242                      cerr << go << "  added: " << r << " >= 1" << endl;
00243                numfound++;
00244                added = true;
00245             }
00246             delete con;
00247          }
00248       }
00249    }
00250  
00251 
00252 
00253 }
00254 
00255 template <typename Graph>
00256 typename SteinerArborescence<Graph>::status
00257 SteinerArborescence<Graph>::standard_separation(subproblem& S){
00258    return separation(S, false);
00259 }
00260 
00261 template <typename Graph>
00262 typename SteinerArborescence<Graph>::status 
00263 SteinerArborescence<Graph>::separation(subproblem& S,
00264    bool separate_fast) {
00265    if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00266       cerr << "SteinerArborescence::standard_separation\n";
00267 
00268    int numfound = 0;
00269    capacity_map_t c;
00270    capacity_map_t d;
00271    capacity_map_t residual_capacity;
00272    BGL_FORALL_EDGES_T(e, Gmf, Graph)
00273       residual_capacity[e] = 0;
00274    BGL_FORALL_EDGES_T(e, Gmf, Graph) {
00275       if(is_original_edge_Gmf[e]) {
00276          //edge is an original edge
00277          c[e] = (int) (1000. * S.value(VM[edges_GmfToG[e]]));
00278          if( c[e] == 0 )
00279             c[e] = 1;
00280       } else {
00281          //edge is a reverse edge
00282          c[e] = 0;
00283       }
00284    }
00285    //ColorMap for boykov_kolmogorov_max_flow
00286    color_map_t color_map;
00287    BGL_FORALL_VERTICES_T(v, Gmf, Graph)
00288       color_map[v] = white_color;
00289    //Predecessor map for boykov_kolmogorov_max_flow
00290    predecessor_map_t pred_map;
00291    //Distance map for boykov_kolmogorov_max_flow
00292    vdistance_map_t vdist_map;
00293 
00294 
00295    //Property maps for boykov_kolmogorov_max_flow
00296    associative_property_map<capacity_map_t> pm_capacity(d);
00297    associative_property_map<capacity_map_t> pm_res_cap(residual_capacity);
00298    associative_property_map<rev_edge_map_t> pm_rev(rev_Gmf);
00299    associative_property_map<vertex_index_map_t> pm_vi(vertex_index_Gmf);
00300    associative_property_map<color_map_t> pm_color(color_map);
00301    associative_property_map<predecessor_map_t> pm_pred(pred_map);
00302    associative_property_map<vdistance_map_t> pm_vdist(vdist_map);
00303 
00304    vertex_descriptor v;
00305    BOOST_FOREACH(v, terminals) {
00306       std::list<vertex_descriptor> cut;
00307       BGL_FORALL_EDGES_T(e, Gmf, Graph) 
00308          d[e] = c[e];
00309       map<edge_descriptor, bool> fixed;
00310       BGL_FORALL_EDGES_T(e, Gmf, Graph)
00311          fixed[e] = false;
00312       int cv = 0;
00313       int go = 0;
00314       bool added = true;
00315       while( added ) {
00316          BGL_FORALL_VERTICES_T(u, Gmf, Graph)
00317             color_map[u] = white_color;
00318          cv = boykov_kolmogorov_max_flow(Gmf, pm_capacity, pm_res_cap, pm_rev,
00319                  pm_pred, pm_color, pm_vdist, pm_vi, vertices_GtoGmf[root],
00320                  vertices_GtoGmf[v]);
00321          go++;
00322          added = false;
00323          cut.clear();
00324          typename GraphTraits::vertex_iterator v_it, v_it_end;
00325          /* Vertices that are colored black by boykov_kolmogorov_max_flow are in
00326             the source tree and form a minimum s-t-cut
00327           */
00328          for(tie(v_it,v_it_end) = vertices(Gmf); v_it != v_it_end; v_it++)
00329             if (color_map[*v_it] == black_color) cut.push_back(*v_it);
00330          if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00331             cerr << "cv: " << cv << endl;
00332          if( cv < 1000 && cut.size() >= 1 && cut.size() < num_vertices(Gmf) - 1 ) {
00333             row r;
00334             vertex_descriptor w;
00335             BOOST_FOREACH(w, cut) {
00336                BGL_FORALL_OUTEDGES_T(w, e, Gmf, Graph) {
00337                   if (search_n(cut.begin(),cut.end(),1,target(e,Gmf)) == cut.end()
00338                       && is_original_edge_Gmf[e] /* && !fixed[e] */ ) {
00339                      r += VM[edges_GmfToG[e]];
00340                      d[e] = 1000;
00341                      fixed[e] = true;
00342                   }
00343                }
00344             }
00345             cons_obj* con = (r>=1.);
00346             if( con->violation(S) > feps ) {
00347                S.add_basic_constraint(r>=1., Dynamic);
00348                if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00349                   if( go > 1 )
00350                      cerr << go << "  added: " << r << " >= 1" << endl;
00351                numfound++;
00352                added = true;
00353             }
00354             delete con;
00355          }
00356       }
00357    }
00358    //Stop separating if fast separation was chosen
00359    if (separate_fast) {
00360       if ( numfound )
00361          return constraint_found;
00362       return no_constraint_found;
00363    }
00364    numfound += separate_flipped(S);
00365    if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00366       cerr << "numfound: " << numfound << endl;
00367 
00368    //cerr << "separating type 4 ineqs" << endl;
00369    std::map<vertex_descriptor, double> nodecut;
00370    std::map<vertex_descriptor, row> noderow;
00371    BGL_FORALL_VERTICES_T(v, Gmf, Graph) {
00372       if( search_n(terminals.begin(), terminals.end(), 1, vertices_GtoGmf[v])
00373           != terminals.end() || vertices_GtoGmf[root] == v )
00374          continue;
00375       double t = 0;
00376       row r;
00377       BGL_FORALL_INEDGES_T(v, e, Gmf, Graph){
00378          if(is_original_edge_Gmf[e]){
00379             t += c[e];
00380             r += VM[edges_GmfToG[e]];
00381          }
00382       }
00383       nodecut[v] = t;
00384       noderow[v] = r;
00385       //cerr << nodecut[v] << " ";
00386    }
00387    //cerr << endl;
00388 
00389    BGL_FORALL_VERTICES_T(v, Gmf, Graph) {
00390       if(search_n(terminals.begin(), terminals.end(), 1, v) != terminals.end()
00391          || v == vertices_GtoGmf[root] )
00392          continue;
00393       std::list<vertex_descriptor> cut, cut2;
00394       bool stop = false;
00395 
00396       //Initialize data for boykov_kolmogorov_max_flow that was changed
00397       associative_property_map<capacity_map_t> pm_cap(c);
00398       BGL_FORALL_EDGES_T(e, Gmf, Graph)
00399          residual_capacity[e] = 0;
00400       BGL_FORALL_VERTICES_T(v, Gmf, Graph)
00401          color_map[v] = white_color;
00402 
00403       int cv = 0;
00404       cv = boykov_kolmogorov_max_flow(Gmf, pm_cap, pm_res_cap, pm_rev, pm_pred,
00405               pm_color, pm_vdist, pm_vi, vertices_GtoGmf[root], v);
00406 
00407       cut.clear();
00408       typename GraphTraits::vertex_iterator v_it, v_it_end;
00409       /* Vertices that are colored black by boykov_kolmogorov_max_flow are in
00410          the source tree and form a minimum s-t-cut
00411        */
00412       for(tie(v_it,v_it_end) = vertices(Gmf); v_it != v_it_end; v_it++){
00413          if (color_map[*v_it] == black_color)
00414             cut.push_back(*v_it);
00415          else
00416             cut2.push_back(*v_it);
00417       }
00418       //cerr << "cv: " << cv << endl;
00419 
00420       if( cut.size() >= 1 && cut.size() < num_vertices(Gmf) - 1 ) {
00421          vertex_descriptor w;
00422          BOOST_FOREACH(w, terminals) {
00423             if( search_n(cut.begin(),cut.end(),1,vertices_GtoGmf[w])==cut.end() ) {
00424                stop = true;
00425                //cerr << "terminal not in cut" << endl;
00426                break;
00427             }
00428          }
00429          if( stop )
00430             break;
00431 
00432          row r;
00433          BOOST_FOREACH(w, cut) {
00434             BGL_FORALL_OUTEDGES_T(w, e, Gmf, Graph) {
00435                if(search_n(cut.begin(),cut.end(),1,target(e, Gmf)) == cut.end()
00436                   && is_original_edge_Gmf[e])
00437                   r += VM[edges_GmfToG[e]];
00438             }
00439          }
00440          BOOST_FOREACH(w, cut2) {
00441             if( cv - nodecut[w] < 20. ) {
00442                cons_obj* con = (r-noderow[w]>=0.);
00443                if( con->violation(S) > feps ) {
00444                   S.add_basic_constraint(r-noderow[w]>=0., Dynamic);
00445                   //cerr << "added: " << r-noderow[w] << " >= 0" << endl;
00446                   numfound++;
00447                }
00448                delete con;
00449             }
00450          }
00451       }
00452    }
00453 
00454    if( numfound )
00455       return constraint_found;
00456 
00457    return no_constraint_found;
00458 }
00459 
00460 template <typename Graph>
00461 typename SteinerArborescence<Graph>::status 
00462 SteinerArborescence<Graph>::fast_separation(subproblem& S) {
00463    return separation(S, true);
00464 }
00465 
00466 template<typename Graph>
00467 void SteinerArborescence<Graph>::info() {
00468    cout<<"Configurations:\n";
00469    cout<<"SteinerArborescence_Debug_Out [true|false]\n";
00470 };
00471 #endif
Generated on Mon Mar 28 22:03:50 2011 for SCIL by  doxygen 1.6.3