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

maxstableset.cc

00001 #include <boost/foreach.hpp>
00002 #include <boost/graph/adjacency_list.hpp>
00003 #include <boost/graph/depth_first_search.hpp>
00004 #include <boost/graph/graph_traits.hpp>
00005 #include <boost/graph/iteration_macros.hpp>
00006 #include <deque>
00007 #include <fstream>
00008 #include <iostream>
00009 #include <scil/scil.h>
00010 #include <scil/constraints/stableset.h>
00011 #include <string>
00012 #include <queue>
00013 
00014 #define INPATH ""
00015 
00016 using std::cout;
00017 using std::cerr;
00018 using std::endl;
00019 using std::ifstream;
00020 using std::atoi;
00021 
00022 using namespace boost;
00023 using namespace SCIL;
00024 
00025 typedef adjacency_list<vecS, vecS, undirectedS > Graph;
00026 typedef boost::graph_traits<Graph> GraphTraits;
00027 typedef GraphTraits::vertex_descriptor vertex_descriptor;
00028 typedef GraphTraits::edge_descriptor edge_descriptor;
00029 
00030 typedef adjacency_list<vecS, vecS, bidirectionalS > diGraph;
00031 typedef boost::graph_traits<diGraph> diGraphTraits;
00032 typedef diGraphTraits::vertex_descriptor divertex_descriptor;
00033 typedef diGraphTraits::edge_descriptor diedge_descriptor;
00034 
00036 
00039 class dfs_back_visitor : public default_dfs_visitor {
00040    public:
00042       dfs_back_visitor (std::list<diedge_descriptor>* _back) : back(_back) {}
00044       void back_edge(diedge_descriptor e, const diGraph &G) const {
00045          back->push_back(e);
00046       }
00048       std::list<diedge_descriptor> *back;
00049 };
00050 
00051 
00058 bool readgraphComplement(const char* infile, Graph& uG, 
00059    map<vertex_descriptor, double>& nc, map<vertex_descriptor, int>& node_mapG) {
00060 
00061    diGraph G;
00062    std::string path(INPATH);
00063    path += infile;
00064    ifstream file(path.c_str());
00065    if( file.fail() ) {
00066       cerr << "%%%%%%%% Could not open file " << infile << endl;
00067       cerr << "%%%%%%%% tried " << path << endl;
00068       return false;
00069    }
00070 
00071    char buf[1024];
00072    while( file.peek() != 'p' ) { //search for 'p' indicating the size of the graph
00073       file.getline(buf, 1024);
00074    }
00075 
00076    //read the size of the graph and the edge data
00077    char c;
00078    int s, t, numnodes, numedges;
00079    double u;
00080    file >> c; //skip the marker 'p'
00081    file >> buf; //skip the format string
00082    file >> numnodes; //read the number of nodes in the graph
00083    file >> numedges; //read the number of edges in the graph
00084 
00085    /* Create a complete graph with two edges (v1,v2) and (v2,v1) between all 
00086       pairs of nodes v1 and v2 */
00087    for(int i = 0; i < numnodes; i++)
00088       add_vertex(G);
00089    diGraphTraits::vertex_iterator it, iit, it_end;
00090    for(tie(it, it_end) = vertices(G); it != it_end; it++)
00091       for( iit = it+1; iit != it_end; iit++) {
00092          add_edge(*it, *iit, G);
00093          add_edge(*iit, *it, G);
00094       }
00095 
00096    std::vector<divertex_descriptor> an;
00097    BGL_FORALL_VERTICES(v, G, diGraph) {
00098       nc[v] = 1.0;
00099       an.push_back(v);
00100    }
00101 
00102    while((file >> c) && file.good()) {
00103       if( c == 'e' ) {
00104          file >> s >> t;
00105 
00106          add_edge(an[s-1], an[t-1], G);
00107          add_edge(an[t-1], an[s-1], G);
00108       } 
00109       else if( c == 'n' ) {
00110          file >> s >> u;
00111          nc[an[s-1]] = u;
00112       }
00113       else
00114          file.getline(buf, 1024);
00115    }
00116 
00117    //Find all parallel edges and delete them
00118    std::set<diedge_descriptor> parallel_edges;
00119    BGL_FORALL_EDGES(e, G, diGraph) {
00120       diGraphTraits::in_edge_iterator ie_it, ie_it_end;
00121       for(tie(ie_it, ie_it_end) = in_edges(target(e ,G), G);
00122          ie_it != ie_it_end && *ie_it != e; ie_it++) {
00123          if (source(*ie_it,G) == source(e, G)) { //parallel edge exists
00124             parallel_edges.insert(e);
00125             parallel_edges.insert(*ie_it);
00126          }
00127       }
00128    }
00129    diedge_descriptor e;
00130    BOOST_FOREACH(e, parallel_edges)
00131       remove_edge(e,G);
00132 
00133    //Make input-graph acyclic by deleting the back edges discoverd with dfs
00134    std::list<diedge_descriptor> back_edges;
00135    dfs_back_visitor vis(&back_edges);
00136    depth_first_search(G, visitor(vis));
00137    BOOST_FOREACH(e, back_edges)
00138       remove_edge(e, G);
00139 
00140    /* Transform bidirectional Graph G in undirected Graph uG
00141       Since both Graphs use vecS as VertexList vertex_descriptor is the same
00142       type as divertex_descriptor */
00143    BGL_FORALL_VERTICES(v, G, diGraph)
00144       add_vertex(uG);
00145    BGL_FORALL_EDGES(e, G, diGraph)
00146       add_edge(source(e, G), target(e, G), uG);
00147 
00148    vertex_descriptor v;
00149    int i = 1;
00150    BOOST_FOREACH(v, an) {
00151       node_mapG[v] = i++;
00152          }
00153    return true;
00154 }
00155 
00156 //TODO: Make the heuristic work.
00157 class stableset_heuristic : public primal_heuristic {
00158    private:
00159       Graph& G;
00160       var_map<vertex_descriptor>& VM;
00161       map<vertex_descriptor, double> nc;
00162       //compare function for priority queue
00163       template <typename T>
00164       struct greater_second : std::binary_function<T, T, bool> {
00165          inline bool operator() (const T& lhs, const T& rhs) {
00166             return (lhs.second > rhs.second);
00167          }
00168       };
00169 
00170    public:
00171       stableset_heuristic(Graph& G_, var_map<vertex_descriptor>& VM_,
00172          map<vertex_descriptor, double> nc_) : G(G_), VM(VM_), nc(nc_) { }
00173 
00174       int heuristic(subproblem& S, solution& newSol) {
00175          cerr << "primal heuristic" << endl;
00176          newSol.save_solution(S);
00177          map<vertex_descriptor, bool> seen;
00178          BGL_FORALL_VERTICES(v, G, Graph)
00179             seen[v] = false;
00180          typedef std::pair<vertex_descriptor, double> entry_t;
00181          typedef std::priority_queue<entry_t, std::deque<entry_t>, 
00182             greater_second<entry_t> > queue_t;
00183          queue_t prio;
00184          BGL_FORALL_VERTICES(v, G, Graph) {
00185             newSol.round_to_integer(VM[v]);
00186             prio.push(entry_t(v, out_degree(v, G)));
00187          }
00188 
00189          bool stop = false;
00190          while (!prio.empty()) {
00191             stop = false;
00192             if( newSol.value(VM[(prio.top()).first]) < .5 ) { 
00193                GraphTraits::adjacency_iterator it, it_end;
00194                for(tie(it,it_end) = adjacent_vertices((prio.top()).first,G);
00195                   it != it_end; it++) {
00196                   if( newSol.value(VM[*it]) > .5 ) {
00197                      stop = true;
00198                      break;
00199                   }
00200                }
00201                if( !stop )
00202                   newSol.set_value(VM[(prio.top()).first], 1.);
00203             }
00204             prio.pop();
00205          }
00206          return 1;
00207       }
00208 };
00209 
00210 
00211 int main(int argc, char** argv)
00212 {
00213    if( argc != 2 ) {
00214       cerr << "Please give the name of an input file!" << endl;
00215       return 1;
00216    }
00217 
00218    //initialize the graph
00219    Graph G;
00220    map<vertex_descriptor, int> node_mapG;
00221    map<edge_descriptor, double> edge_mapG;
00222 
00223    map<vertex_descriptor, double> nc;
00224    if( !readgraphComplement(argv[1], G, nc, node_mapG) )
00225       return 1;
00226 
00227    //initialize the ILP
00228    ILP_Problem IP(Optsense_Max);
00229    vertex_descriptor v;
00230    var_map<vertex_descriptor> VM;
00231    BGL_FORALL_VERTICES(v, G, Graph) 
00232       VM[v]=IP.add_binary_variable(nc[v]);
00233 
00234    //add the symbolic constraint
00235    IP.add_sym_constraint(new STABLESET<Graph>(G, VM));
00236 
00237    //set the primal heuristic
00238    //TODO: Make the heuristic work.
00239 //   IP.set_primal_heuristic(new stableset_heuristic(G, VM, nc));
00240 
00241    //solve the problem
00242    IP.optimize();
00243 
00244    //output the solution
00245    solution sol =  IP.get_solution();
00246    double sum = 0.;
00247    cout << "\nName: " << argv[1] << endl;
00248    BGL_FORALL_VERTICES(v, G, Graph) {
00249       sum += sol.value(VM[v]) * nc[v];
00250       if( sol.value(VM[v]) > .9 ) cout << node_mapG[v] << " ";
00251    }
00252    cout << endl;
00253    cout.precision(2);
00254    cout << fixed << "solution value: " << sum << endl;
00255 
00256    return 0;
00257 }
Generated on Mon Mar 28 22:03:49 2011 for SCIL by  doxygen 1.6.3