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
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
00131 if(fseek(dcmstFile,0L,SEEK_SET)){
00132 cerr<<"Error while rewinding file "<<fileName<<"."<<endl;
00133 exit(1);
00134 }
00135
00136
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
00144
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
00156
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);
00183
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
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;
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
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;
00252
00253 BGL_FORALL_VERTICES(v, G, Graph) {
00254
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
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
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
00286
00287
00288
00289
00290
00291
00292 if(E_T_counter != num_vertices(G) - 1) {
00293
00294 return 0;
00295 }
00296
00297 return 1;
00298 }
00299 };
00300
00301
00302
00303
00304 int main(int argc, char** argv)
00305 {
00306
00307
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
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
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
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
00356 IP.optimize();
00357
00358
00359
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
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 }