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

dcmst.cc

00001 #include <boost/graph/adjacency_list.hpp>
00002 #include <boost/graph/graph_traits.hpp>
00003 #include <boost/graph/iteration_macros.hpp>
00004 #include <iostream>
00005 #include <fstream>
00006 #include <list>
00007 #include <scil/scil.h>
00008 #include <scil/constraints/matching.h>
00009 #include <scil/constraints/spantree.h>
00010 #include <string>
00011 
00012 
00013 #define OUTPUT
00014 #define INPATH ""
00015 #define OUTPATH ""
00016 #define EPS 1e-8
00017 
00018 using std::cout;
00019 using std::cerr;
00020 using std::endl;
00021 using std::ifstream;
00022 using std::atoi;
00023 
00024 using namespace boost;
00025 using namespace SCIL;
00026 
00027 typedef adjacency_list<vecS, vecS, undirectedS> Graph;
00028 typedef boost::graph_traits<Graph> GraphTraits;
00029 typedef GraphTraits::vertex_descriptor vertex_descriptor;
00030 typedef GraphTraits::edge_descriptor edge_descriptor;
00031 
00032 bool readExtTsplibFile(const char*fileName, Graph& G, 
00033    map<vertex_descriptor, int>& nc, map<vertex_descriptor, int>& node_mapG,
00034    map<edge_descriptor, double>& edge_mapG) {
00035    FILE* dcmstFile = fopen(fileName, "r");
00036    if(dcmstFile == NULL){
00037       cerr<<"dcmstFile "<<fileName<<" could not be opened."<<endl;
00038       exit(1);
00039    }
00040 
00041    const unsigned int maxCharPerLine = 1024;
00042    char lineBuf[maxCharPerLine + 1];
00043    bool dimensionFound = false;
00044    bool formatFound = false;
00045    bool constraintSectionFound = false;
00046    bool dataSectionFound = false;
00047    bool allInteger = true;
00048    unsigned int nNodes = 0;
00049    unsigned int nEdges = 0;
00050 
00051    while(fgets(lineBuf,maxCharPerLine,dcmstFile)){
00052       //the first keyword that has to be found is DIMENSION
00053       if(strncmp(lineBuf,"DIMENSION",strlen("DIMENSION"))==0){
00054          if(sscanf(lineBuf,"DIMENSION : %d",&nNodes)!=1){
00055             cerr<<"Error when reading dimension of problem."<<endl;
00056             exit(1);
00057          }
00058          dimensionFound= true;
00059       }
00060       else if(strncmp(lineBuf,"EDGE_DATA_FORMAT",
00061          strlen("EDGE_DATA_FORMAT"))==0) {
00062          if(strncmp(lineBuf,"EDGE_DATA_FORMAT : EDGE_WEIGHT_LIST",
00063             strlen("EDGE_DATA_FORMAT : EDGE_WEIGHT_LIST"))) {
00064             cerr<<"Invalid EDGE_DATA_FORMAT, must be EDGE_WEIGHT_LIST."<<endl;
00065             exit(1);
00066          }
00067          formatFound= true;
00068       }
00069       else if(strncmp(lineBuf,"NODE_DEGREE_CONSTRAINT_SECTION",
00070          strlen("NODE_DEGREE_CONSTRAINT_SECTION"))==0) {
00071          constraintSectionFound= true;
00072          int tempA;
00073          int tempB;
00074 
00075          while(true) {
00076             if(fscanf(dcmstFile,"%d %d",&tempA,&tempB)!=2) {
00077                if(tempA== -1)
00078                   break;
00079                else {
00080                   cerr<<"Error while reading degree constraints for nodes.";
00081                   cerr<<endl;
00082                   exit(1);
00083                }
00084             }
00085          }
00086       }
00087       else if(strncmp(lineBuf,"EDGE_DATA_SECTION", 
00088          strlen("EDGE_DATA_SECTION"))==0) {
00089          dataSectionFound= true;
00090          int tempA;
00091          int tempB;
00092          double tempC;
00093          nEdges= 0;
00094          while(true) {
00095             if(fscanf(dcmstFile,"%d %d %lf",&tempA,&tempB,&tempC)==3)
00096                ++nEdges;
00097             else {
00098                if(tempA== -1)
00099                   break;
00100                else {
00101                   cerr<<"Error while reading edges."<<endl;
00102                   exit(1);
00103                }
00104             }
00105          }
00106       }
00107    }
00108 
00109    if(!dimensionFound){
00110       cerr<<"Keyword DIMENSION not found in file "<<fileName<<endl;
00111       exit(1);
00112    }
00113 
00114    if(!formatFound){
00115       cerr<<"Keyword EDGE_DATA_FORMAT not found in file "<<fileName<<endl;
00116       exit(1);
00117    }
00118 
00119    if(!constraintSectionFound){
00120       cerr<<"Keyword NODE_DEGREE_CONSTRAINT_SECTION not found in file ";
00121       cerr<<fileName<<endl;
00122       exit(1);
00123    }
00124 
00125    if(!dataSectionFound){
00126       cerr<<"Keyword EDGE_DATA_SECTION not found in file "<<fileName<<endl;
00127       exit(1);
00128    }
00129 
00130    //rewind the file for getting data
00131    if(fseek(dcmstFile,0L,SEEK_SET)){
00132       cerr<<"Error while rewinding file "<<fileName<<"."<<endl;
00133       exit(1);
00134    }
00135 
00136    //initialize the nodes
00137    vertex_descriptor* nodes = new vertex_descriptor[nNodes];
00138    for(unsigned int i=0; i<nNodes; ++i) {
00139       nodes[i] = add_vertex(G);
00140       node_mapG[nodes[i]] = i;
00141    }
00142 
00143    //initialize the degree constraints of the nodes with nNodes-1
00144    //(that means no constraint)
00145    BGL_FORALL_VERTICES(v, G, Graph)
00146       nc[v] = nNodes-1;
00147 
00148    while(fgets(lineBuf,maxCharPerLine,dcmstFile)) {
00149       if(strncmp(lineBuf,"NODE_DEGREE_CONSTRAINT_SECTION", 
00150          strlen("NODE_DEGREE_CONSTRAINT_SECTION"))==0) {
00151          int tempA;
00152          int tempB;
00153          while(true) {
00154             if(fscanf(dcmstFile,"%d %d",&tempA,&tempB)==2) {
00155                //save the degree constraints for those nodes that have a real 
00156                //restriction
00157                if(0 < tempB && tempB < (int)nNodes-1)
00158                   nc[nodes[tempA]]= tempB;
00159             }
00160             else {
00161                if(tempA==-1)
00162                   break;
00163                else {
00164                   cerr<<"Error while reading degree constraints for nodes.";
00165                   cerr<<endl;
00166                   exit(1);
00167                }
00168             }
00169          }
00170       }
00171       else if(strncmp(lineBuf,"EDGE_DATA_SECTION", 
00172          strlen("EDGE_DATA_SECTION"))==0) {
00173          int tempA;
00174          int tempB;
00175          double tempC;
00176          int i=0;
00177          while(true) {
00178             if(fscanf(dcmstFile,"%d %d %lf",&tempA,&tempB,&tempC)==3) {
00179                if(fabs(tempC - floor(tempC)) >= EPS)
00180                   allInteger = false;
00181                else
00182                   tempC = round(tempC); //make it really integer
00183                //set the edges and store their costs in the temporary array
00184                edge_descriptor new_edge;
00185                new_edge = (add_edge(nodes[tempA], nodes[tempB], G)).first;
00186                edge_mapG[new_edge] = tempC;
00187             }
00188             else {
00189                if(tempA== -1)
00190                   break;
00191                else {
00192                   cerr<<"Error while reading edges."<<endl;
00193                   exit(1);
00194                }
00195             }
00196          }
00197       }
00198    }
00199 
00200    //we remove trivial node degree constraints
00201    BGL_FORALL_VERTICES(v, G, Graph) {
00202       if( (int)out_degree(v, G) <= nc[v] )
00203          nc[v] = nNodes-1;
00204    }
00205 
00206    delete[]nodes;
00207    if(fclose(dcmstFile)){
00208       cerr<<"error in closing file "<<fileName<<endl;
00209       exit(1);
00210    }
00211    return true;
00212 }
00213 
00214 /*------------------------------------------------------------------*/
00215 struct edgeCostsPair{
00216    const edge_descriptor e;
00217    const double c;
00218    edgeCostsPair(const edge_descriptor _e, const double _c) : e(_e), c(_c) {}
00219    bool operator<(const edgeCostsPair& a) const{
00220       return c < a.c;
00221    }
00222 };
00223 
00224 class dcmst_heuristic : public primal_heuristic {
00225    private:
00226       Graph& G;
00227       var_map<edge_descriptor>& VM;
00228       map<vertex_descriptor, int>& dc; //degree constraints
00229 
00230    public:
00231       dcmst_heuristic(Graph& G_, var_map<edge_descriptor>& VM_, 
00232          map<vertex_descriptor, int>& dc_): G(G_), VM(VM_), dc(dc_) { }
00233 
00234       int heuristic(subproblem& S, solution& newSol) {
00235          /* extended Kruskal heuristic */
00236          map<vertex_descriptor, int> act_degree;
00237          BGL_FORALL_VERTICES(v, G, Graph)
00238             act_degree[v] = 0;
00239 
00240          std::list<edgeCostsPair> edgesPriority;
00241 
00242          newSol.save_solution(S);
00243          BGL_FORALL_EDGES(e, G, Graph) {
00244             newSol.set_value(VM[e], 0.);
00245             edgesPriority.push_back(edgeCostsPair(e, 1. - S.value(VM[e])));
00246          }
00247          edgesPriority.sort();
00248 
00249          unsigned int E_T_counter = 0;
00250          typedef map<vertex_descriptor,set<vertex_descriptor> >vertexPartition;
00251          vertexPartition V_T; //= new vertexPartition();
00252          //Initialize the vertex_partition
00253          BGL_FORALL_VERTICES(v, G, Graph) {
00254             //(V_T)[v] = set<vertex_descriptor>;
00255             (V_T)[v].insert(v);
00256          }
00257 
00258          int cr = 0;
00259          for(std::list<edgeCostsPair>::const_iterator it=edgesPriority.begin();
00260             it != edgesPriority.end(); ++it) {
00261             const vertex_descriptor s = source(it->e, G);
00262             const vertex_descriptor t = target(it->e, G);
00263 
00264             if( act_degree[s] + 1 <= dc[s] && act_degree[t] + 1 <= dc[t] 
00265                && ((V_T)[s]) != ((V_T)[t]) ) {
00266                newSol.set_value(VM[it->e], 1.);
00267                ++E_T_counter;
00268                ++act_degree[s];
00269                ++act_degree[t];
00270                //Union sets of vertices s with sets of vertices t
00271                BGL_FORALL_VERTICES(v, G, Graph) {
00272                   set<vertex_descriptor> tmp = (V_T)[t];
00273                   (V_T)[v].insert(tmp.begin(), tmp.end());
00274                   set<vertex_descriptor>::iterator it;
00275                   //Update the pointers of the vertices in V_T[t]
00276                   for(it = tmp.begin(); it != tmp.end(); it++)
00277                      (V_T)[*it] = (V_T)[s];
00278                }
00279             }
00280 
00281             if(E_T_counter == num_vertices(G) - 1)
00282                break;
00283          }
00284 
00285          //FIXME
00286          /*
00287          BGL_FORALL_VERTICES(v, G, Graph)
00288             delete (*V_T)[v];
00289             */
00290          //delete V_T;
00291 
00292          if(E_T_counter != num_vertices(G) - 1) {
00293             //cout << "extendedKruskal could not find a dcst" << endl;
00294             return 0;
00295          }
00296 
00297          return 1;
00298       }
00299 };
00300 
00301 /*------------------------------------------------------------------*/
00302 
00303 
00304 int main(int argc, char** argv)
00305 {
00306 
00307    //initialize the input and output file names
00308    if( argc < 2 ) {
00309       cerr << "Please give the name of an input file!" << endl;
00310       return 1;
00311    }
00312 
00313    char* pch = strrchr(argv[argc - 1],'/');
00314    std::string outname;
00315    if( pch != NULL ) {
00316       outname += pch;
00317       outname.erase(0, 1);
00318    }
00319    else
00320       outname += argv[argc - 1];
00321 
00322    std::string logname = OUTPATH + outname;
00323    outname = OUTPATH + outname + ".res";
00324    //------------------------------------------------------
00325 
00326    //initialize the graph
00327    Graph G;
00328    map<vertex_descriptor, int> node_mapG;
00329    map<edge_descriptor, double> edge_mapG;
00330    map<vertex_descriptor, int> nc;
00331    if( !readExtTsplibFile(argv[1], G, nc, node_mapG, edge_mapG) )
00332       return 1;
00333    //------------------------------------------------------
00334 
00335    //initialize the ILP
00336    ILP_Problem IP(Optsense_Min);
00337    var_map<edge_descriptor> VM;
00338    std::list<var> vl;
00339    var va;
00340 
00341    BGL_FORALL_EDGES(e, G, Graph) {
00342       vl.push_back(IP.add_binary_variable(edge_mapG[e]));
00343       VM[e] = vl.back();
00344    }
00345    //------------------------------------------------------
00346 
00347    //add the symbolic constraints
00348    IP.add_sym_constraint(new SpanTree<Graph>(G, VM));
00349 
00350    IP.add_sym_constraint(new MATCHING<Graph>(G, nc, VM, false));
00351    //------------------------------------------------------
00352    IP.set_primal_heuristic(new dcmst_heuristic(G, VM, nc));
00353    //------------------------------------------------------
00354 
00355    //solve the problem
00356    IP.optimize();
00357    //------------------------------------------------------
00358 
00359    //write the solution and running time to the result file 
00360 #ifdef OUTPUT
00361    ofstream outFile;
00362    outFile.open(outname.c_str());
00363    if( outFile.fail() ) {
00364       cerr << "File " << outname << " could not be opened." << endl;
00365       exit(1);
00366    }
00367 
00368    //output the solution
00369    outFile << "\nName: " << argv[argc - 1] << endl;
00370 
00371    int base = 1;
00372    double sum = 0.;
00373    solution sol = IP.get_solution();
00374 
00375    BGL_FORALL_EDGES(e, G, Graph) {
00376       sum += double(edge_mapG[e]) * sol.value(VM[e]);
00377       if( sol.value(VM[e]) > 1. - EPS ) {
00378          if( node_mapG[source(e, G)] < node_mapG[target(e, G)] ) {
00379             outFile << node_mapG[source(e, G)] + base;
00380             outFile << " -- " << node_mapG[target(e, G)] + base << endl;
00381          } else {
00382             outFile << node_mapG[target(e, G)] + base;
00383             outFile << " -- " << node_mapG[source(e, G)] + base << endl;
00384          }
00385       }
00386    }
00387    outFile << endl;
00388    outFile.precision(2);
00389    outFile << fixed << "solution value: " << sum << endl;
00390 
00391 #endif //OUTPUT
00392    //------------------------------------------------------
00393    return 0;
00394 }
Generated on Mon Mar 28 22:03:48 2011 for SCIL by  doxygen 1.6.3