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

spantree.cc

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   // TODO: some more structure-requirements???
00070    /*if( is_undirected(G) == false ){
00071       cerr << "spantree.cc: The Graph has to be ";
00072       cerr << "undirected" << endl;
00073       exit(1);
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    // add edges e, inv(e) to H 
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       // add reverse edges too:
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)]) )     // resC != 0  <=>  flow != max
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)])) {  // resC != C  <=>  flow != 0
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    // Preparation: Calculate Capacity
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       // Make Constraint
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);     // regard H as undirected (to be more precise: bidirected graph)
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
Generated on Mon Mar 28 22:03:49 2011 for SCIL by  doxygen 1.6.3