28 #include "objscip/objscip.h" 30 #include "scip/cons_linear.h" 42 #define NINT(x) (floor(x+0.5)) 45 void ReaderTSP::getNodesFromFile(
46 std::ifstream& filedata,
57 while ( i < graph->nnodes && !filedata.eof() )
59 filedata >> nodenumber >> x_coords[i] >> y_coords[i];
63 if( nodenumber-1 != i)
64 cout<<
"warning: nodenumber <" <<nodenumber<<
"> does not match its index in node list <"<<i+1
65 <<
">. Node will get number "<<i+1<<
" when naming variables and constraints!"<<endl;
66 node->
x = x_coords[i];
67 node->
y = y_coords[i];
72 assert( i == graph->
nnodes );
76 SCIP_RETCODE ReaderTSP::addVarToEdges(
88 SCIP_CALL( SCIPcaptureVar(
scip, edge->
var) );
99 bool ReaderTSP::checkValid(
103 std::string edgeweighttype,
111 cout <<
"parse error in file <" << name <<
"> dimension should be greater than 0"<< endl ;
116 cout <<
"parse error in file <" << name <<
"> type should be TSP" << endl;
119 if ( !( edgeweighttype ==
"EUC_2D" || edgeweighttype ==
"MAX_2D" || edgeweighttype ==
"MAN_2D" 120 || edgeweighttype ==
"GEO" || edgeweighttype ==
"ATT") )
122 cout <<
"parse error in file <" << name
123 <<
"> unknown weight type, should be EUC_2D, MAX_2D, MAN_2D, ATT, or GEO" << endl;
128 cout <<
"error while reading file <" << name <<
">, graph is uninitialized. ";
129 cout <<
"Probably NODE_COORD_SECTION is missing" << endl;
152 SCIP_RETCODE retcode;
162 double* x_coords = NULL;
163 double* y_coords = NULL;
166 double** weights = NULL;
177 string name =
"MY_OWN_LITTLE_TSP";
180 string edgeweighttype =
"EUC_2D";
183 *result = SCIP_DIDNOTRUN;
186 ifstream filedata(filename);
188 return SCIP_READERROR;
193 while( !filedata.eof() )
195 if( token ==
"NAME:" )
197 else if( token ==
"NAME" )
198 filedata >> token >> name;
199 else if( token ==
"TYPE:" )
201 else if( token ==
"TYPE" )
202 filedata >> token >> type;
203 else if( token ==
"DIMENSION:" )
206 nedges = nnodes * (nnodes-1);
208 else if( token ==
"DIMENSION" )
210 filedata >> token >> nnodes;
211 nedges = nnodes * (nnodes-1);
213 else if( token ==
"EDGE_WEIGHT_TYPE:" )
214 filedata >> edgeweighttype;
215 else if( token ==
"EDGE_WEIGHT_TYPE" )
216 filedata >> token >> edgeweighttype;
217 else if( token ==
"NODE_COORD_SECTION" || token ==
"DISPLAY_DATA_SECTION" )
222 retcode = SCIP_READERROR;
228 assert(x_coords == NULL);
229 assert(y_coords == NULL);
231 x_coords =
new double[nnodes];
232 y_coords =
new double[nnodes];
233 getNodesFromFile(filedata, x_coords, y_coords, graph);
237 retcode = SCIP_NOMEMORY;
241 else if( token ==
"COMMENT:" || token ==
"COMMENT" ||
242 token ==
"DISPLAY_DATA_TYPE" || token ==
"DISPLAY_DATA_TYPE:" )
243 (void) getline( filedata, token );
244 else if( token ==
"EOF" )
246 else if( token ==
"" )
250 cout <<
"parse error in file <" << name <<
"> unknown keyword <" << token <<
">" << endl;
251 return SCIP_READERROR;
257 if( !checkValid(graph, name, type, edgeweighttype, nnodes) )
258 retcode = SCIP_READERROR;
260 assert(graph != NULL);
262 if( retcode == SCIP_OKAY )
264 edgeforw = &( graph->
edges[0] );
265 edgebackw= &( graph->
edges[nedges/2] );
268 weights =
new double* [nnodes];
269 for( i = 0; i < nnodes; ++i )
270 weights[i] =
new double[nnodes];
274 for( i = 0; i < nnodes; i++ )
276 nodestart = &graph->
nodes[i];
277 for( j = i+1; j < nnodes; j++ )
279 nodeend = &graph->
nodes[j];
282 edgeforw->
adjac = nodeend;
283 edgebackw->
adjac = nodestart;
284 edgeforw->
back = edgebackw;
285 edgebackw->
back = edgeforw;
288 x = x_coords[(*nodestart).id] - x_coords[(*nodeend).id];
289 y = y_coords[(*nodestart).id] - y_coords[(*nodeend).id];
290 if( edgeweighttype ==
"EUC_2D")
291 edgeforw->
length = sqrt( x*x + y*y );
292 else if( edgeweighttype ==
"MAX_2D")
293 edgeforw->
length = max( ABS(x), ABS(y) );
294 else if( edgeweighttype ==
"MAN_2D")
295 edgeforw->
length = ABS(x) + ABS(y);
296 else if( edgeweighttype ==
"ATT")
297 edgeforw->
length = ceil( sqrt( (x*x+y*y)/10.0 ) );
298 else if( edgeweighttype ==
"GEO")
300 const double pi = 3.141592653589793;
308 coords[0] = x_coords[(*nodestart).id];
309 coords[1] = y_coords[(*nodestart).id];
310 coords[2] = x_coords[(*nodeend).id];
311 coords[3] = y_coords[(*nodeend).id];
313 for( k = 0; k < 4; k++ )
315 degs[k] = coords[k] >= 0 ? floor(coords[k]) : ceil(coords[k]);
316 mins[k] = coords[k] - degs[k];
317 rads[k] = pi*(degs[k]+5.0*mins[k]/3.0)/180.0;
320 euler[0] = cos(rads[1]-rads[3]);
321 euler[1] = cos(rads[0]-rads[2]);
322 euler[2] = cos(rads[0]+rads[2]);
323 edgeforw->
length = floor(6378.388 * acos(0.5*((1.0+euler[0])*euler[1]-(1.0-euler[0])*euler[2]))+1.0);
332 weights[i][j] = edgeforw->
length;
333 weights[j][i] = edgebackw->
length;
369 if( retcode != SCIP_OKAY )
372 if( weights != NULL )
374 for( i = 0; i < nnodes; i++ )
386 for( i = 0; i < nnodes; i++ )
388 for( j = 0; j < nnodes; j++ )
389 printf(
" %4.0f ",weights[i][j]);
397 SCIP_CALL( SCIPcreateObjProb(
scip, name.c_str(),
new ProbDataTSP(graph), TRUE) );
400 for( i = 0; i < nedges/2; i++ )
404 stringstream varname;
405 edge = &graph->
edges[i];
409 SCIP_CALL( SCIPcreateVar(
scip, &var, varname.str().c_str(), 0.0, 1.0, edge->
length,
410 SCIP_VARTYPE_BINARY, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
413 SCIP_CALL( SCIPaddVar(
scip, var) );
414 SCIP_CALL( addVarToEdges(
scip, edge, var) );
417 SCIP_CALL( SCIPreleaseVar(
scip, &var) );
424 for( i = 0, node = &(graph->
nodes[0]); i < nnodes; i++, node++ )
427 stringstream consname;
428 consname <<
"deg_con_v" << node->
id+1;
431 SCIP_CALL( SCIPcreateConsLinear(
scip, &cons, consname.str().c_str(), 0, NULL, NULL, 2.0, 2.0,
432 TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
436 while( edge != NULL )
438 SCIP_CALL( SCIPaddCoefLinear(
scip, cons, edge->
var, 1.0) );
443 SCIP_CALL( SCIPaddCons(
scip, cons) );
444 SCIP_CALL( SCIPreleaseCons(
scip, &cons) );
451 FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE ) );
452 SCIP_CALL( SCIPaddCons(
scip, cons) );
453 SCIP_CALL( SCIPreleaseCons(
scip, &cons) );
456 *result = SCIP_SUCCESS;
474 *result = SCIP_DIDNOTRUN;
SCIP_Bool create_graph(int n, int m, GRAPH **gr)
SCIP_DECL_READERFREE(ReaderTSP::scip_free)
SCIP_DECL_READERWRITE(ReaderTSP::scip_write)
generator for global cuts in undirected graphs
SCIP_RETCODE SCIPcreateConsSubtour(SCIP *scip, SCIP_CONS **cons, const char *name, GRAPH *graph, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable)
struct GraphEdge * first_edge
C++ problem data for TSP.
C++ constraint handler for TSP subtour elimination constraints.
C++ file reader for TSP data files.
SCIP_DECL_READERREAD(ReaderTSP::scip_read)
void release_graph(GRAPH **gr)