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

stableset.cc

00001 #ifndef SCIL_STABLESET_CC
00002 #define SCIL_STABLESET_CC
00003 
00004 #define HIDE_THRES 5
00005 #define LEPS 1e-8
00006 
00007 using namespace SCIL;
00008 using namespace boost;
00009 using namespace std;
00010 //using std::cout;
00011 //using std::cerr;
00012 //using std::endl;
00013 
00014 template <typename Graph>
00015 STABLESET<Graph>::STABLESET(Graph& G_, var_map<vertex_descriptor>& VM_)
00016    : G(G_), VM(VM_) {
00017    feps = 1.0e-4;
00018    BGL_FORALL_VERTICES_T(v, G, Graph)
00019       if(VM[v].type() != Vartype_Binary) {
00020          cerr << "stableset.cc: All variables in VM need to be";
00021          cerr << "Vartype_Binary" << endl;
00022          exit(1);
00023       }
00024 };
00025 
00026 
00027 template <typename Graph>
00028 void STABLESET<Graph>::init(subproblem& S) {
00029    if(S.configuration("STABLESET_Debug_Out")=="true")
00030       cerr << "STABLESET::init\n";
00031    //Check whether Graph is undirected
00032    typedef typename GraphTraits::directed_category directed_category;
00033    if (!(is_same<directed_category,undirected_tag>::value
00034          || is_base_and_derived<undirected_tag, directed_category>::value)) {
00035       cerr << "kconnected.cc: The graph has to be undirected." << endl;
00036       exit(1);
00037    }
00038    //Graph has to provide out_edges()
00039    BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<Graph>));
00040    //Graph has to provide vertices() and edges()
00041    BOOST_CONCEPT_ASSERT((VertexAndEdgeListGraphConcept<Graph>));
00042    //Graph has to provide clear_vertex()
00043    BOOST_CONCEPT_ASSERT((MutableGraphConcept<Graph>));
00044    //add edge inequalities
00045    int i = 0;
00046    BGL_FORALL_EDGES_T(e, G, Graph) {
00047       row r;
00048       r += VM[source(e, G)];
00049       r += VM[target(e, G)];
00050       S.add_basic_constraint(r<=1., Static);
00051    }
00052 
00053    return;
00054 };
00055 
00056 template <typename Graph>
00057 int STABLESET<Graph>::exactOddCycleSeparation(subproblem& S, int maxnum) {
00058    if(S.configuration("STABLESET_Debug_Out")=="true")
00059       cerr << "STABLESET::exactOddCycleSeparation\n";
00060 
00061    Graph G1;
00062    map<vertex_descriptor, bool> node_mapG1;
00063    map<edge_descriptor, bool> edge_mapG1;
00064    map<vertex_descriptor, vertex_descriptor> GtoG1a;
00065    map<vertex_descriptor, vertex_descriptor> GtoG1b;
00066    map<vertex_descriptor, int> node_used;
00067    map<vertex_descriptor, vertex_descriptor> G1toG;
00068    map<edge_descriptor, edge_descriptor> back;
00069    BGL_FORALL_VERTICES_T(v, G, Graph)
00070       node_used[v] = 0;
00071 
00072    /* G1 consists of two copies G' and G" of the original graph G. */
00073    BGL_FORALL_VERTICES_T(v, G, Graph) {
00074       vertex_descriptor new_vertex;
00075       new_vertex = add_vertex(G1);
00076       GtoG1a[v] =  new_vertex;
00077       node_mapG1[new_vertex] = false;
00078       new_vertex = add_vertex(G1);
00079       GtoG1b[v] = new_vertex;
00080       node_mapG1[new_vertex] = true;
00081       G1toG[GtoG1a[v]]=v;
00082       G1toG[GtoG1b[v]]=v;
00083    }
00084    if(S.configuration("STABLESET_Debug_Out")=="true")
00085       cerr << "exactOddCycleSeparation: nodes added\n";
00086 
00087    /* G' and G" are joined by cross edges v' -- v" and v" -- v'
00088       for every node v of the original graph G. */
00089    BGL_FORALL_EDGES_T(e, G, Graph) {
00090       edge_descriptor new_edge;
00091       new_edge = (add_edge(GtoG1a[source(e,G)], GtoG1b[target(e,G)], G1)).first;
00092       back[new_edge] = e;
00093       edge_mapG1[new_edge] = true;
00094       new_edge = (add_edge(GtoG1b[source(e,G)], GtoG1a[target(e,G)], G1)).first;
00095       back[new_edge] = e;
00096       edge_mapG1[new_edge] = true;
00097    }
00098 
00099    if(S.configuration("STABLESET_Debug_Out")=="true")
00100       cerr << "exactOddCycleSeparation: edges added\n";
00101    //Typedefs for Dijkstra in- and output
00102    typedef map<edge_descriptor, double> costs_t;
00103    typedef map<vertex_descriptor, size_t> vertex_index_t;
00104    typedef map<vertex_descriptor, vertex_descriptor> pred_t;
00105    typedef map<vertex_descriptor, double> dist_t;
00106 
00107    costs_t costs;
00108    BGL_FORALL_EDGES_T(e, G1, Graph) {
00109       double co = 1. - S.value(VM[G1toG[source(e, G1)]]);
00110       co += S.value(VM[G1toG[target(e, G1)]]);
00111       costs[e] = ( co > 0. ) ? co : 0.;       
00112    }
00113    
00114    //vertex_index_map is needed to handle vertices stored in a std::list
00115    vertex_index_t vertex_index_map;
00116    int i = 0;
00117    BGL_FORALL_VERTICES_T(v, G, Graph)
00118       vertex_index_map[v] = i++;
00119 
00120    if(S.configuration("STABLESET_Debug_Out")=="true")
00121       cerr << "exactOddCycleSeparation: costs initialized\n";
00122 
00123    //Stores predecessor of vertices
00124    pred_t pred;
00125    //Stores distance of vertices to source vertex
00126    dist_t dist;
00127    int numfound = 0;
00128 
00129    //Property-maps required for Dijkstra
00130    associative_property_map<costs_t> pm_costs(costs);
00131    associative_property_map<vertex_index_t> pm_vertex_index(vertex_index_map);
00132    associative_property_map<pred_t> pm_pred(pred);
00133    associative_property_map<dist_t> pm_dist(dist);
00134 
00135    vertex_descriptor s, t;
00136 
00137    /* Backup Graphs to restore the nodes, which will be cleared if they are used
00138       more than HIDE_THRES times */
00139    Graph G_bak = G, G1_bak = G1;
00140    /* Shortest paths between two nodes v' and v" in G1 with weight < 1 
00141       correspond to violated odd cycle inequalities. */
00142    BGL_FORALL_VERTICES_T(v, G, Graph) {
00143       if( numfound >= maxnum )
00144          break;
00145       /* Hide nodes that have already been used in several constraints. */
00146       BGL_FORALL_VERTICES_T(s, G, Graph) {
00147          if( node_used[s] > HIDE_THRES && out_degree(s, G) != 0 ) {
00148             clear_vertex(s, G);
00149             clear_vertex(GtoG1a[s], G1);
00150             clear_vertex(GtoG1b[s], G1);
00151          }
00152       }
00153       // Degree of 0 = "hidden" vertex
00154       if ( out_degree(v, G) == 0 )
00155          continue;
00156 
00157       s = GtoG1a[v];
00158       t = GtoG1b[v];
00159       if(S.configuration("STABLESET_Debug_Out")=="true")
00160          cerr << "exactOddCycleSeparation: DIJKSTRA START:\n";
00161       dijkstra_shortest_paths(G1, s, weight_map(pm_costs).vertex_index_map
00162          (pm_vertex_index).distance_map(pm_dist).predecessor_map(pm_pred));
00163       double w = dist[t];
00164 
00165       if(S.configuration("STABLESET_Debug_Out")=="true")
00166          cerr << "exactOddCycleSeparation: DIJKSTRA w:" << 1 << 1 << w << endl; 
00167       
00168       if( (w < 1. - LEPS) && (pred[t] != t) ) {
00169          // Follow the path starting with pred[t] until s is reached,  
00170          bool duplicates = false;
00171          std::list<vertex_descriptor> cycle;
00172          std::list<double> cyclecosts;
00173          map<vertex_descriptor, bool> seen;
00174          BGL_FORALL_VERTICES_T(v, G, Graph)
00175             seen[v] = false;
00176          row r;
00177 
00178          vertex_descriptor a, b;
00179          double z = 0;
00180 
00181          /* Mark the start node. */
00182          seen[G1toG[t]] = true;
00183          node_used[G1toG[t]]++;
00184 
00185          while( !duplicates ) {
00186             edge_descriptor e = (edge(t, pred[t], G1)).first;
00187             
00188             /* Determine the nodes in the original graph. */
00189             a = G1toG[t];
00190             b = G1toG[pred[t]];
00191 
00192             /* Append the node of the original graph to the cycle list. */
00193             cycle.push_back(a);
00194             r += VM[a];
00195             z += costs[e];
00196             cyclecosts.push_back(costs[e]);
00197 
00198             if( seen[b] ) 
00199                duplicates = true;
00200             else {
00201                seen[b] = true;
00202                node_used[b]++;
00203             }
00204 
00205             t = pred[t];
00206          }
00207 
00208          /* If b is the start node, we are done.
00209             Otherwise we have to remove nodes from the front of the path 
00210             until we reach the first duplicate node.
00211             We also have to adapt the constraint. */
00212          s = G1toG[s];
00213          while( cycle.front() != b ) {
00214             t = cycle.front();
00215             cycle.pop_front();
00216             r -= VM[t];
00217             node_used[t]--;
00218             z -= cyclecosts.front();
00219             cyclecosts.pop_front();
00220          }
00221 
00222          /* Add the constraint to the subproblem. */
00223          if( z < 1. - feps ) {
00224             r.normalize();
00225             double rhs = floor((double(cycle.size()) - 1.) / 2.);
00226             S.add_basic_constraint(r<=rhs);
00227             if(S.configuration("STABLESET_Debug_Out")=="true") {
00228                cerr << "exactOddCycleSeparation: added constraint! rhs = ";
00229                cerr << 1 << 1 << rhs << endl;
00230             }
00231             numfound++;
00232          }
00233       }
00234    }
00235    if(S.configuration("STABLESET_Debug_Out")=="true") {
00236       cerr << "exactOddCycleSeparation: constraints added:" ;
00237       cerr << 1 << 0 << numfound << endl;
00238    }
00239    G = G_bak;
00240    G1 = G1_bak;
00241 
00242    return numfound;
00243 }
00244 
00245 template <typename Graph>
00246 int STABLESET<Graph>::heuristicCliqueSeparation(subproblem& S, int maxnum){
00247    vertex_descriptor v;
00248    //switch the strategie for finding a start Vertex
00249    for(int strat = 0; strat < 2; strat++){
00250       vertex_descriptor startVertex = NULL;
00251       BGL_FORALL_VERTICES_T(v, G, Graph){
00252          if(startVertex == NULL){
00253             startVertex = v;
00254             continue;
00255          }
00256          if(strat == 0)
00257             if(fabs(S.value(VM[v])-.5) < fabs(S.value(VM[startVertex])-.5))
00258                startVertex = v;
00259             else
00260                if(S.value(VM[v]) < 1 && (S.value(VM[v]) > S.value(VM[startVertex])))
00261                   startVertex = v;
00262       }
00263       map<vertex_descriptor, bool> vertex_map;
00264       pair<adjacency_iterator, adjacency_iterator> vertexRange = adjacent_vertices(startVertex, G);
00265       adjacency_iterator adIt;
00266       //put all adjacent vertices in the vertex_map
00267       for(adIt = vertexRange.first; adIt != vertexRange.second; adIt++)
00268          vertex_map.insert(make_pair(*adIt,false));
00269       vertex_map.insert(make_pair(startVertex, true));
00270       bool cliqueFound = false;
00271       typename map<vertex_descriptor, bool> ::iterator mapIt;
00272       typename map<vertex_descriptor, bool> ::iterator mapIt2;
00273       //look for cliques
00274       while(! cliqueFound) {
00275          for(mapIt = vertex_map.begin(); mapIt != vertex_map.end(); mapIt++){
00276             if(mapIt->second == true)
00277                continue;
00278             vertexRange = adjacent_vertices(mapIt->first, G);
00279             for(mapIt2 = vertex_map.begin(); mapIt2 != vertex_map.end(); mapIt2++){
00280                if(mapIt2 != mapIt) {
00281                   for(adIt = vertexRange.first; adIt != vertexRange.second; adIt++)
00282                      if(*adIt == mapIt2->first)
00283                         break;
00284                   if(adIt == vertexRange.second)
00285                      vertex_map.erase(mapIt2);
00286                }
00287             }
00288             mapIt->second = true;
00289             break;
00290          }
00291          if(mapIt == vertex_map.end())
00292             cliqueFound = true;
00293       }
00294       row r;
00295       //create the cliqueconstraint
00296       for(mapIt = vertex_map.begin(); mapIt != vertex_map.end(); mapIt++)
00297          r += VM[mapIt->first];
00298       cons_obj* c = r<=1;
00299       if(c->violated(S)){
00300          S.add_basic_constraint(c);
00301          return 1;
00302       }
00303       delete c;
00304    }
00305    return 0;
00306 }
00307 
00308 
00309 
00310 template <typename Graph>
00311 typename STABLESET<Graph>::status STABLESET<Graph>::feasible(solution& S) {
00312    if(S.originating_subproblem()->configuration("STABLESET_Debug_Out")=="true")
00313       cerr << "STABLESET::feasible\n";
00314    /* A solution is feasible if the edge inequalities
00315     * x_i + x_j <= 1. 
00316     * for all edges ij \in E are satisfied.
00317     * Since these inequalities are added in init() and the solution 
00318     * is integer, the test below is obsolete and could be skipped.
00319     */
00320    BGL_FORALL_EDGES_T(e, G, Graph) {
00321       if( S.value(VM[source(e, G)]) && S.value(VM[target(e, G)]))
00322          return infeasible_solution;
00323    }
00324 
00325    return feasible_solution;
00326 }
00327 
00328 template <typename Graph>
00329 typename STABLESET<Graph>::status 
00330 STABLESET<Graph>::standard_separation(subproblem& S) {
00331    if(S.configuration("STABLESET_Debug_Out")=="true")
00332       cerr << "STABLESET::standard_separation\n";
00333    int num = 2000;
00334    if( heuristicCliqueSeparation(S, num) )
00335       return constraint_found;
00336    else {
00337       if( exactOddCycleSeparation(S, num) )
00338          return constraint_found;
00339       else
00340          return no_constraint_found;
00341    }
00342 }
00343 
00344 template <typename Graph>
00345 typename STABLESET<Graph>::status
00346 STABLESET<Graph>::fast_separation(subproblem& S) {
00347    if(S.configuration("STABLESET_Debug_Out")=="true")
00348       cerr << "STABLESET::fast_separation\n";
00349    int num = 2000;
00350    if( heuristicCliqueSeparation(S, num) )
00351       return constraint_found;
00352    else
00353       return no_constraint_found;
00354 }
00355 
00356 template <typename Graph>
00357 void STABLESET<Graph>::info() {
00358    cout<<"Configurations:\n";
00359    cout<<"STABLESET_Debug_Out [true|false]\n";
00360 };
00361 #endif
Generated on Mon Mar 28 22:03:50 2011 for SCIL by  doxygen 1.6.3