//Generate a random complete euclidean ListGraph bool GenerateRandomEuclideanListGraph(ListGraph &g, NodeStringMap &vname, // node names NodePosMap& px, // x-position of the nodes NodePosMap& py, // y-position of the nodes EdgeValueMap& weight, // weight of edges int n, // number of nodes double SizeX, // coordinate x is a random number in [0,SizeX) double SizeY) // coordinate y is a random number in [0,SizeY) { int i,j; // n=number of nodes Node *V; V = new Node[n]; if (V==NULL){ cout << "Memory allocation error, number of nodes " << n << " too large\n"; exit(0);} for (i=0;i<n;i++) { // insert nodes (random points in [0,100] x [0,100] ) V[i] = g.addNode(); // generate a new node px[V[i]] = SizeX*drand48(); py[V[i]] = SizeY*drand48(); vname[V[i]] = IntToString(i+1); // name of the node is i+1 } for (i=0;i<n;i++) for (j=i+1;j<n;j++) { Edge e = g.addEdge(V[i],V[j]); // generate an edge weight[e] = sqrt(pow(px[V[i]]-px[V[j]],2) + pow(py[V[i]]-py[V[j]],2)); } delete[] V; return(true); }
void ViewTspCircuit(TSP_Data &tsp) { ListGraph h; ListGraph::NodeMap<string> h_vname(h); // node names ListGraph::NodeMap<Node> h_g2h(tsp.g); // maps a node of g to a node of h ListGraph::NodeMap<double> h_posx(h); ListGraph::NodeMap<double> h_posy(h); ListGraph::NodeMap<int> vcolor(h); // color of the vertices ListGraph::EdgeMap<int> acolor(h); // color of edges ListGraph::EdgeMap<string> aname(h); // name of edges for (ListGraph::NodeIt v(tsp.g); v!=INVALID; ++v) { Node hv; hv = h.addNode(); h_g2h[v] = hv; h_posx[hv] = tsp.posx[v]; h_posy[hv] = tsp.posy[v]; h_vname[hv] = tsp.vname[v]; vcolor[hv] = BLUE; } for (int i=0;i<tsp.NNodes;i++) { ListGraph::Node u,v; ListGraph::Edge a; u = tsp.BestCircuit[i]; v = tsp.BestCircuit[(i+1) % tsp.NNodes]; a = h.addEdge(h_g2h[u] , h_g2h[v]); aname[a] = ""; acolor[a] = BLUE; } ViewListGraph(h,h_vname,aname,h_posx,h_posy,vcolor,acolor,"TSP Circuit with cost "+DoubleToString(tsp.BestCircuitValue)); }
int ViewGomoryHuTree(ListGraph &g, NodeStringMap &vname, NodePosMap &px, // xy-coodinates for each node NodePosMap &py, // GomoryHu<ListGraph, EdgeValueMap > &ght, string text) { ListGraph T; NodeNodeMap map(g); Edge te; EdgeStringMap tename(T); // name of T edges EdgeValueMap teweight(T); // name of T edges NodeStringMap tvname(T); // name of T nodes NodePosMap tpx(T); // xy-coodinates for each node NodePosMap tpy(T); // NodeColorMap tvcolor(T); // color of the vertices EdgeColorMap tecolor(T); // color of the edges for (NodeIt v(g); v != INVALID; ++v) { map[v] = T.addNode(); tvname[map[v]] = vname[v]; tvcolor[map[v]] = WHITE; tpx[map[v]] = px[v]; tpy[map[v]] = py[v]; } for (NodeIt u(g); u != INVALID; ++u) { if ((g).id(ght.predNode(u))==-1) continue; te = T.addEdge(map[u], map[ght.predNode(u)]); tename[te] = DoubleToString(ght.predValue(u)); teweight[te] = ght.predValue(u); tecolor[te] = BLUE; } return(ViewListGraph(T,tvname,tename,tpx,tpy,tvcolor,tecolor,text)); }
int ViewGomoryHuTree(ListGraph &g, NodeStringMap& vname, GomoryHu<ListGraph, EdgeValueMap > &ght, double threshold, string text) { ListGraph T; NodeNodeMap map(g); Edge te; EdgeStringMap tename(T); // name of T edges NodeStringMap tvname(T); // name of T nodes NodeColorMap tvcolor(T); // color of the vertices EdgeColorMap tecolor(T); // color of the edges for (NodeIt v(g); v != INVALID; ++v) { map[v] = T.addNode(); tvname[map[v]] = vname[v]; tvcolor[map[v]] = BLACK; } for (NodeIt u(g); u != INVALID; ++u) { if ((g).id(ght.predNode(u))==-1) continue; te = T.addEdge(map[u], map[ght.predNode(u)]); tename[te] = DoubleToString(ght.predValue(u)); if (ght.predValue(u)<threshold-MY_EPS) tecolor[te] = RED; else tecolor[te] = BLUE; } return(ViewListGraph(g,tvname,tename,tvcolor,tecolor,text)); }
ExtendedEdge::ExtendedEdge(ListGraph &g, ListGraph::Node u, ListGraph::Node v, int pos_u, int pos_v){ _adjacentNodes.push_back(g.id(u)); _adjacentNodes.push_back(g.id(v)); _adjacentNodesPos.push_back(pos_u); _adjacentNodesPos.push_back(pos_v); edge = g.addEdge(u,v); _id = g.id(edge); _length = 0; }
// Generate a triangulated ListGraph, building the Delaunay // triangulation of random points // Uses the geompack program, available in // http://people.sc.fsu.edu/~jburkardt/cpp_src/geompack/geompack.html bool GenerateTriangulatedListGraph(ListGraph &g, // return with generated graph NodeStringMap &vname, // return with name of the nodes NodePosMap& px, // return with x-position of the nodes NodePosMap& py, // return with y-position of the nodes EdgeValueMap& weight, // return with weight of edges int n, // number of nodes double SizeX, // coordinate x is a random number in [0,SizeX) double SizeY) // coordinate y is a random number in [0,SizeY) { int i; // n=number of nodes int ntri; // number of Delaunay triangles Node *V = new Node[n]; double *p = new double[2*n+2];// node coodinates are (x;y) = ( p[2*i] ; p[2*i+1] ) int *tri = new int[6*n]; // Each 3 elements are the indexes of a triangle int *tri_nabe = new int[6*n]; if ((V==NULL)||(p==NULL)||(tri==NULL)||(tri_nabe==NULL)){ cout << "Memory allocation error, number of nodes " << n << " too large\n"; exit(0);} for (i=0;i<n;i++) { V[i] = g.addNode(); // gera um vértice nó do grafo px[V[i]] = SizeX*drand48(); // nodes are random points py[V[i]] = SizeY*drand48(); p[2*i] = px[V[i]]; p[2*i+1] = py[V[i]]; vname[V[i]] = IntToString(i+1); // name of the node is i+1 } if (r8tris2 ( n, p, &ntri, tri, tri_nabe )) { printf("ERROR\n");Pause(); } for (i=0;i<ntri;i++) { int a,b,c; a = tri[3*i]-1; b = tri[3*i+1]-1; c = tri[3*i+2]-1; // each triangle if formed with nodes V[a] , V[b] , V[c] // insert edges without duplications if ((findEdge(g,V[a],V[b])==INVALID) && (findEdge(g,V[b],V[a])==INVALID)){ Edge e = g.addEdge(V[a],V[b]); weight[e] = sqrt(pow(px[V[a]]-px[V[b]],2) + pow(py[V[a]]-py[V[b]],2)); } if ((findEdge(g,V[a],V[c])==INVALID) && (findEdge(g,V[c],V[a])==INVALID)){ Edge e = g.addEdge(V[a],V[c]); weight[e] = sqrt(pow(px[V[a]]-px[V[c]],2) + pow(py[V[a]]-py[V[c]],2)); } if ((findEdge(g,V[b],V[c])==INVALID) && (findEdge(g,V[c],V[b])==INVALID)) { Edge e = g.addEdge(V[b],V[c]); weight[e] = sqrt(pow(px[V[b]]-px[V[c]],2) + pow(py[V[b]]-py[V[c]],2)); } } delete[] V; delete[] p; delete[] tri; delete[] tri_nabe; return(true); }
int main( void ){ Timer T(true); int init_nodes_num, final_nodes_num, edge_addition_num; init_nodes_num = 10; final_nodes_num = 50; edge_addition_num = 7; typedef ListEdgeSet< ListGraph > EdgeSet; ListGraph mListGraph; EdgeSet mNewEdges( mListGraph ); FullGraph fg(init_nodes_num); GraphCopy<FullGraph, ListGraph> cg( fg, mListGraph); // Create the seed nodes cg.run(); int mNumEdges = countEdges( mListGraph ); EdgeSet::Edge e; lemon::Random mRandom; mRandom.seedFromTime(); ListGraph::Node newNode, randNode; // new edges will be saved seperatly in an EdgeSet, not to change the original node degrees for ( int i = init_nodes_num; i < final_nodes_num; i++){ mNumEdges = countEdges( mListGraph ); mNewEdges.clear(); newNode = mListGraph.addNode(); while ( countEdges( mNewEdges ) != edge_addition_num ) { randNode = mListGraph.nodeFromId( mRandom[ mListGraph.maxNodeId() ] ) ; // --- CALCULATE THE PROBABILITY if ( mRandom.real() < (( (double)(countIncEdges(mListGraph, randNode)) / (double)( 2*mNumEdges ) )) ){ if ( findEdge( mNewEdges, newNode, randNode ) == INVALID){ // does the edge already exist? mNewEdges.addEdge( newNode, randNode ); } } } // Create the new edges in the original graph for (EdgeSet::EdgeIt e( mNewEdges ); e!=INVALID; ++e){ mListGraph.addEdge( mNewEdges.u( e ), mNewEdges.v(e) ); } } cout << T.realTime() << endl; cout << countEdges( mListGraph) << endl; cout << countEdges( fg ) << endl; }
MatrixGraph::MatrixGraph(const ListGraph& listGraph) { int edgesCount = listGraph.edgesCount(); int vertexCount = listGraph.vertexCount(); iMatrix = vector<vector<int> >(vertexCount, vector<int>(edgesCount, 0)); int edge = 0; for (int i = 0; i < vertexCount; ++i) { for (auto v : listGraph.getLists()[i]) { iMatrix[i][edge] = -1; iMatrix[v][edge] = 1; ++edge; } } }
void PrintListGraph(ListGraph &g, NodeStringMap &vname, EdgeValueMap &graphweight) { int Nnodes = countNodes(g); // number of nodes in the input graph int Nedges = countEdges(g); // number of edges in the input graph printf("-------------------------------------------------------\n"); printf("Number of nodes: %d\n",Nnodes); printf("Number of edges: %d\n",Nedges); for (NodeIt v(g); v!=INVALID; ++v) printf("%s\n",vname[v].c_str()); printf("\n"); printf("-------------------------------------------------------\n"); for (EdgeIt a(g); a!=INVALID; ++a) printf("%s -- %s %lf\n",vname[g.u(a)].c_str(),vname[g.v(a)].c_str(), graphweight[a]); printf("\n"); }
void ReadListGraphEdges(ListGraph &g,int nedges,ifstream & ifile, #if __cplusplus >= 201103L std::unordered_map<string,Node> & string2node, #else std::tr1::unordered_map<string,Node> & string2node, #endif EdgeValueMap &weight) { Node u,v; Edge a; string nomeu,nomev; double peso; for (int i=0;i<nedges;i++) { // format: <node_u> <node_v> <edge_weight> ifile >> nomeu; ifile >> nomev; ifile >> peso; if (ifile.eof()) {cout << "Reached unexpected end of file.\n"; exit(0);} auto test = string2node.find(nomeu); if (test == string2node.end()) {cout<<"ERROR: Unknown node: "<<nomeu<<endl;exit(0);} else u = string2node[nomeu]; test = string2node.find(nomev); if (test == string2node.end()) {cout<<"ERROR: Unknown node: "<<nomev<<endl;exit(0);} else v = string2node[nomev]; a = g.addEdge(u,v); weight[a] = peso; } }
// To read list of nodes in the format: <node_name> <double1> <double2> void ReadListGraphNodes(ListGraph &g,int nnodes,ifstream & ifile, #if __cplusplus >= 201103L std::unordered_map<string,Node> & string2node, #else std::tr1::unordered_map<string,Node> & string2node, #endif NodeStringMap &vname, NodePosMap &posx, NodePosMap &posy) { string STR; Node u,v; string token; for (int i=0;i<nnodes;i++) { getline(ifile,STR); if (ifile.eof()) {cout<<"Reached unexpected end of file.\n";exit(0);} while (STR=="") getline(ifile,STR); { istringstream ins; // Declare an input string stream. ins.str(STR); // Specify string to read. for (int p=0; getline(ins, token, ' ') ; p++) { if (p==0) { // For example, to read: node_name posx posy auto test = string2node.find(token); if (test!=string2node.end()){cout<<"ERROR: Repeated node: "<<token<<endl;exit(0);} v = g.addNode(); string2node[token] = v; vname[v] = token; posx[v]=DBL_MAX; posy[v]=DBL_MAX; } else if (p==1) { posx[v] = atof(token.c_str());} else if (p==2) { posy[v] = atof(token.c_str());} }} } }
int monitoramento_em_grafo_bipartido( ListGraph &g, NodeName &vname, ListGraph::NodeMap<double> &custo, ListGraph::NodeMap<int> &solucao) { int seed=0; GRBEnv env = GRBEnv(); GRBModel model = GRBModel(env); model.getEnv().set(GRB_IntParam_Seed, seed); model.set(GRB_StringAttr_ModelName, "Monitoramento em Grafo Bipartido"); // prob. name model.set(GRB_IntAttr_ModelSense, GRB_MINIMIZE); // is a minimization problem // ------------------------------------------------------ // Construa o modelo daqui para baixo // ------------------------------------------------------ // Exemplos de como voce pode declarar variaveis indexadas nos vertices ou nas arestas. // Nao necessariamente voce precisa dos dois tipos // ListGraph::NodeMap<GRBVar> x(g); // variables for each node // ListGraph::EdgeMap<GRBVar> y(g); // variables for each edge ListGraph::NodeMap<GRBVar> x(g); // variables for each node ListGraph::EdgeMap<GRBVar> y(g); // variables for each edge int name = 0; char namme[100]; for(ListGraph::NodeIt v(g); v != INVALID; ++v) { sprintf(namme,"PC_%s",vname[v].c_str()); x[v] = model.addVar(0.0, 1.0, custo[v],GRB_CONTINUOUS,namme); } model.update(); try { for(ListGraph::EdgeIt e(g); e != INVALID; ++e) { //Para cada aresta, um dos lados e 1 GRBLinExpr expr; expr += x[g.u(e)]; expr += x[g.v(e)]; model.addConstr(expr >= 1); } model.update(); // ------------------------------------------------------ // Construa o modelo daqui para cima // ------------------------------------------------------ //model.write("model.lp"); system("cat model.lp"); model.optimize(); for (ListGraph::NodeIt v(g); v!=INVALID; ++v) { if (x[v].get(GRB_DoubleAttr_X)>1-EPS) solucao[v] = 1; else solucao[v] = 0; //solucao[v] = 1; } return(1); } catch (...) {cout << "Error during callback..." << endl; return(0);} }
// This routine visualize a graph using a pdf viewer. It uses neato (from // graphviz.org) to generate a pdf file and a program to view the pdf file. The // pdf viewer name is given in the viewername parameter. int ViewListGraph(ListGraph &g, NodeStringMap &vname, // name of the nodes EdgeStringMap &ename, // name of edges NodePosMap& px, // x-position of the nodes NodePosMap& py, // y-position of the nodes NodeColorMap& vcolor, // color of node (see myutils.h) EdgeColorMap& ecolor, // color of edge string text) // text displayed below the figure { char tempname[1000],cmd[1000],outputname[1000]; FILE *fp; double minpx=DBL_MAX,minpy=DBL_MAX,maxpx=-DBL_MAX,maxpy=-DBL_MAX,delta,factor; // obtain a temporary file name strcpy(tempname,".viewgraphtempname"); sprintf(outputname,"%s.pdf",tempname); fp = fopen(tempname,"w+"); if (fp==NULL) {cout << "Error to open temporary file to visualize graph.\n"; return(0);} for (NodeIt v(g); v!=INVALID; ++v) { if (px[v] < minpx) minpx = px[v]; if (px[v] > maxpx) maxpx = px[v]; if (py[v] < minpy) minpy = py[v]; if (py[v] > maxpy) maxpy = py[v]; } factor = 40; // quanto maior, menor o desenho do vértice delta = fmax(maxpx - minpx,maxpy - minpy); // Generate a text file with the graph format of neato program fprintf(fp,"graph g {\n"); //fprintf(fp,"\tsize = \"10, 10\";\n"); //fprintf(fp,"\tnode [shape = \"circle\"];\n"); fprintf(fp,"\tnode [\n"); fprintf(fp,"shape = \"ellipse\",\n"); fprintf(fp,"style = \"bold\",\n"); fprintf(fp,"color = \"black\",\n"); fprintf(fp,"];\n"); for (NodeIt v(g); v!=INVALID; ++v) { if (vcolor[v]==NOCOLOR) continue; fprintf(fp,"\t%s [style = \"bold\", color=\"%s\", pos = \"%lf,%lf!\" ];\n", vname[v].c_str(),ColorName(vcolor[v]).c_str(),factor*(px[v]-minpx)/delta,factor*(py[v]-minpy)/delta); } int nar=0; for (EdgeIt e(g); e!=INVALID; ++e) { nar++; if (ecolor[e]==NOCOLOR) continue; fprintf(fp,"\t%s -- %s [label = \"%s\", color=\"%s\" ];\n",vname[g.u(e)].c_str(),vname[g.v(e)].c_str(),ename[e].c_str(),ColorName(ecolor[e]).c_str()); //cout << "e_" << nar << " = ( " << vname[g.u(e)] << " , " << vname[g.v(e)] << ")\n"; } //cout << "\n\n\nColocou "<< nar << " arestas\n\n\n"; fprintf(fp,"label=\"%s\";\nfontsize=50;\n",text.c_str()); fprintf(fp,"}\n"); fclose(fp); sprintf(cmd,"neato -Tpdf %s -o %s",tempname,outputname); system(cmd); //cout << "Grafo em "<< tempname << "\n"; view_pdffile(outputname); //pause(); return(1); }
/** second relaxation of tsp idea: remove some (random) node take mst add shortest two edges of the removed node */ int TSPRelaxation::mstOnSubgraph() { // create a copy of the graph ListGraph g; ListGraph::EdgeMap<int> weight(g); ListGraph::NodeMap<ListGraph::Node> nodemap(g); GraphCopy<ListGraph, ListGraph> copy(this->g, g); copy.edgeMap(this->weight, weight).nodeCrossRef(nodemap).run(); // remove a random node // removed will contain the node of this->g corresponding to the removed one afterwards int del = rand() % countNodes(g); ListGraph::Node removed; for (ListGraph::NodeIt n(g); n != INVALID; ++n) { if (del == 0) { removed = nodemap[n]; g.erase(n); break; } del--; } // calculate mst MST mst(g, weight); int w = mst.prim(); // search for two shortest edges incident to the removed node int mins[] = {numeric_limits<int>::max(), numeric_limits<int>::max()}; for (ListGraph::IncEdgeIt e(this->g, removed); e != INVALID; ++e) { // iterate over all incident nodes if (this->weight[e] < mins[0]) { // shortest found yet mins[1] = mins[0]; mins[0] = this->weight[e]; } // 2nd-shortest else if (this->weight[e] < mins[1]) mins[1] = this->weight[e]; } return w + mins[0] + mins[1]; }
bool ReadEuclideanListGraph(string filename, ListGraph &g, NodeStringMap & vname, EdgeValueMap & custo, NodePosMap & posx, NodePosMap & posy, NodeBoolMap& is_terminal) { int i,n,m, terminal; Node nu,nv; Edge a; char nomev[100]; Node v; double px,py; ifstream ifile; ifile.open(filename.c_str()); if (!ifile) return(false); PulaBrancoComentario(ifile); // format: <number_of_nodes> -1 // The value -1 is to indicate that there is no edge/arc, as edge weights // are given by the euclidean distance ifile >> n; ifile >> m; if (m!=-1) { printf("Wrong format in the euclidean graph of file %s.\n",filename.c_str()); return(false); } for (i=0;i<n;i++) { ifile >> nomev; ifile >> px; ifile >> py; ifile >> terminal; v = g.addNode(); vname[v] = nomev; posx[v] = px; posy[v] = py; if(terminal == 0) is_terminal[v] = false; else is_terminal[v] = true; } for (NodeIt v(g); v!=INVALID; ++v) { NodeIt u(g); u=v; for (++u; u!=INVALID; ++u) { a = g.addEdge(u,v); custo[a] = sqrt((posx[u]-posx[v])*(posx[u]-posx[v]) + (posy[u]-posy[v])*(posy[u]-posy[v])); } } ifile.close(); return(true); }
int main(int argc, char *argv[]) { int n; double box_width,box_height; ListGraph g; // graph declaration NodeName vname(g); // name of graph nodes ListGraph::NodeMap<double> px(g),py(g); // xy-coodinates for each node ListGraph::NodeMap<int> vcolor(g);// color of nodes ListGraph::EdgeMap<int> ecolor(g); // color of edges EdgeWeight lpvar(g); // used to obtain the contents of the LP variables EdgeWeight weight(g); // edge weights vector <Node> V; srand48(1); // double cutoff; // used to prune non promissing branches (of the B&B tree) if (argc!=5) {cout<<"Usage: "<< argv[0]<<" <number_of_nodes_in_graph> <number_of_pairs> <box_width> <box_height>"<< endl;exit(0);} n = atoi(argv[1]); int kPairs = atoi(argv[2]); box_width = atof(argv[3]); box_height = atof(argv[4]); GenerateTriangulatedListGraph(g,vname,px,py,weight,n,box_width,box_height); int nV = countNodes(g); int nA = countEdges(g); cout << nA << " " << nV << " " << kPairs << endl; for (NodeIt v(g);v!=INVALID;++v) cout << vname[v] << " " << px[v] << " " << py[v] << endl; for (EdgeIt e(g);e!=INVALID;++e) cout << vname[g.u(e)] << " " << vname[g.v(e)] << " " << 20*drand48() << " " << weight[e] << " " << 5*drand48() <<endl; for (int i = 0; i < kPairs; i++) { int v1 = ((int)((nV-1)*drand48() + 1)); int v2 = ((int)((nV-1)*drand48() + 1)); if (v1 != v2) { cout << v1 <<" " << v2 <<" "<< (25*drand48() + 25*drand48()) <<" " << (20*drand48() + nA)<< endl; } else { i--; } } return 0; }
int main( void ){ Timer T(true); int final_nodes_num, edge_addition_num; final_nodes_num = 30000; edge_addition_num = 7; ListGraph mGr; lemon::Random mRandom; mRandom.seedFromTime(); vector<int> nodeChoice; set<int> mRndNodes; vector<int> targets(edge_addition_num, -1); int currentIndex = 0; // First targets are all nodes for(auto &v : targets){ v = currentIndex++; mGr.addNode(); } while (countNodes(mGr)<final_nodes_num ) { // Add new node and connect to targets currentIndex = mGr.id( mGr.addNode() ); for(const auto &v : targets ){ mGr.addEdge( mGr.nodeFromId( currentIndex ), mGr.nodeFromId( v ) ); } // Add the nodes, which were connented again nodeChoice.insert(nodeChoice.end(), targets.begin(), targets.end() ); nodeChoice.insert(nodeChoice.end(), edge_addition_num, currentIndex); mRndNodes.clear(); while (mRndNodes.size() < edge_addition_num) { mRndNodes.insert( nodeChoice[ mRandom.integer( nodeChoice.size() ) ] ); } targets.clear(); targets.insert(targets.begin(), mRndNodes.begin(), mRndNodes.end() ); } cout << "time: " << T.realTime() << endl; cout << countNodes( mGr) << endl; cout << countEdges( mGr) << endl; graphWriter( mGr, "/Users/sonneundasche/Documents/FLI/DATA/05 LEMON Graphs/BaraBasiTEST.txt") .run(); InDegMap<ListGraph> inDeg(mGr); graphWriter( mGr, "/Users/sonneundasche/Documents/FLI/DATA/05 LEMON Graphs/BaraBasi_Degree_TEST.txt") .nodeMap("degree", inDeg) .skipEdges() .run(); }
AdjacencyMatrix::AdjacencyMatrix(ListGraph &graph,EdgeValueMap &graphweight,double NonEdgValue): Node2Index(graph),Edge2Index(graph) { int i; g = &graph; NonEdgeValue = NonEdgValue; weight = &graphweight; Nnodes = countNodes(graph); // number of nodes in the input graph Nedges = countEdges(graph); // number of edges in the input graph Nmatrix = (Nnodes*(Nnodes-1))/2; // no. of edges/elem. in strict. triang. inf. matrix AdjMatrix = (double *) malloc(sizeof(double)*Nmatrix); Index2Node = (Node *) malloc(sizeof(Node)*Nnodes); Index2Edge = (Edge *) malloc(sizeof(Edge)*Nedges); if ((AdjMatrix==NULL)||(Index2Node==NULL)||(Index2Edge==NULL)) { cout << "Out of memory in constructor of AdjacencyMatrix\n"; ADJMAT_FreeNotNull(AdjMatrix); ADJMAT_FreeNotNull(Index2Node); ADJMAT_FreeNotNull(Index2Edge); exit(0);} i = 0; for (NodeIt v(*g); v != INVALID; ++v) { Index2Node[i] = v; AdjacencyMatrix::Node2Index[v]=i; i++; } // Initially all edges have infinity weight for (int i=0;i<Nmatrix;i++) AdjMatrix[i] = NonEdgeValue; // Then, update the existing edges with the correct weight for (EdgeIt e(graph); e != INVALID; ++e) { Node u,v; int i_u,i_v; u = graph.u(e); v = graph.v(e); // obtain the extremities of e i_u = Node2Index[u]; i_v = Node2Index[v]; if (i_u > i_v) AdjMatrix[i_u*(i_u-1)/2+i_v] = graphweight[e]; else if (i_u < i_v) AdjMatrix[i_v*(i_v-1)/2+i_u] = graphweight[e]; else { cout << "Out of memory in constructor of AdjacencyMatrix\n"; exit(0);} } }
TEST_F(ClusteringCoefficientTest, AcyclicGraphTest) { ListGraph ig; //Create vertex Vertex* x = new Vertex(1); //create neighbor vertices Vertex* v1 = new Vertex(2); Vertex* v2 = new Vertex(3); Vertex* v3 = new Vertex(4); Vertex* v4 = new Vertex(5); ig.addVertex(x); ig.addVertex(v1); ig.addVertex(v2); ig.addVertex(v3); ig.addVertex(v4); ig.addEdge(x, v1); ig.addEdge(x, v2); ig.addEdge(x, v3); ig.addEdge(v4, x);; typedef ClusteringCoefficient<ListGraph, Vertex> Clustering; typedef Clustering::Coefficient Coef; Clustering clustering; Coef c = clustering.vertexClusteringCoefficient(x); Coef epsilon = 0.001; ASSERT_TRUE(fabs(c - 0.0) < epsilon); Coef c2 = clustering.clusteringCoefficient(ig, Vertex::Degree(4)); ASSERT_TRUE(fabs(c2 - 0.0) < epsilon); }
bool WriteListGraphGraphviz(ListGraph &g, NodeStringMap &vname, // vertex names EdgeStringMap &ename, // edge names NodeColorMap &vcolor, // vertex colors EdgeColorMap &acolor, // edge colors string filename) { ofstream out; string linha; out.open(filename.c_str()); if (out.is_open()) return(false); out << "graph g {\n"; out << "\tsize = \"8, 11\";\n"; out << "\tnode [shape = \"circle\"];\n"; for (NodeIt v(g); v!=INVALID; ++v) { linha = "\t"; linha += vname[v].c_str(); linha += " [color="; linha += ColorName(vcolor[v]); linha += "];\n"; out << linha; } for (EdgeIt a(g); a!=INVALID; ++a) { if (acolor[a]!=WHITE) { linha = "\t"; linha += vname[g.u(a)].c_str() ; linha += " -- "; linha += vname[g.v(a)].c_str(); linha += " [label = \""; linha += ename[a].c_str(); linha += "\""; linha += ", color=\""; linha += ColorName(acolor[a]); linha += "\" ];\n"; out << linha; } } out << "}\n"; out.close(); return(true); }
int mai() { //RandGraphGen gen = *(new RandGraphGen(7, 100, 5, true)); //gen.generate(); //gen.saveToFile("testPrimKruskal"); ListGraph mxg = *(new ListGraph()); ListGraph mxgW1 = *(new ListGraph()); ListGraph mxgW2 = *(new ListGraph()); mxg.open("testPrimKruskal"); std::cout << mxg << std::endl; std::cout << "Prim:\n"; try { mxg.Prim(mxgW1); std::cout << mxgW1 << std::endl; } catch (std::runtime_error err) { std::cout << err.what() <<std::endl; } std::cout << "Kruskal:\n"; try { mxg.Kruskal(mxgW2); std::cout << mxgW2 << std::endl; } catch (std::runtime_error err) { std::cout << err.what() << std::endl; } std::cin.get(); return 0; }
std::vector<bool>balanced_min_cut(const ListGraph&g){ assert(g.is_valid()); #ifndef USE_CUT_ORDER return {}; #else std::vector<int>out_begin; std::vector<int>out_dest; build_adj_array(out_begin, out_dest, g.node_count(), g.arc.size(), [&](int x){return g.arc[x].source;}, [&](int x){return g.arc[x].target;} ); std::vector<int>part(g.node_count()); // Call METIS int one = 1, two = 2, ignore, node_count = g.node_count(); idx_t options[METIS_NOPTIONS]; METIS_SetDefaultOptions(options); options[METIS_OPTION_NUMBERING] = 0; options[METIS_OPTION_CONTIG] = 1; options[METIS_OPTION_UFACTOR] = 100; //options[METIS_OPTION_NCUTS] = 10; METIS_PartGraphKway( (idx_t*)&node_count, (idx_t*)&one, (idx_t*)&out_begin[0], (idx_t*)&out_dest[0], nullptr, nullptr, nullptr, (idx_t*)&two, nullptr, nullptr, options, (idx_t*)&ignore, (idx_t*)&part[0] ); std::vector<bool>part_ret(g.node_count()); for(int i=0; i<g.node_count(); ++i) part_ret[i] = part[i] == 0; return std::move(part_ret); #endif }
//指定一些特殊分支,要求搜索一条路径时尽可能多的通过这些特殊分支 //例如:搜索一条串联通风路径(通过多个用风地点的一条路径) //采用二分匹配实现失败!!! static bool MaxKeyEdgePass_Match(Digraph& dg, EdgeArray& airEdges, Digraph::Node s, Digraph::Node t, EdgeArray& mpp) { EdgeArray p; if(!GraphUtils::DFS_Path(dg, s, t, p)) return false; typedef Digraph::NodeMap<Digraph::Node> DDMap; DDMap ddm(dg, INVALID); NodeArray left, right; left.push_back(s); right.push_back(t); for(size_t i=0;i<airEdges.size();i++) { Digraph::Arc e = airEdges[i]; Digraph::Node u = dg.source(e); Digraph::Node v = dg.target(e); p.clear(); bool ret = GraphUtils::DFS_Path(dg, v, t, p); if(!ret) continue; p.clear(); ret = GraphUtils::DFS_Path(dg, s, u, p); if(!ret) continue; left.push_back(v); right.push_back(u); } //cout<<"left="<<left.size()<<" right="<<right.size()<<endl; ListGraph g; ListGraph::NodeMap<Digraph::Node> udm(g); typedef std::vector<ListGraph::Node> UNodeArray; UNodeArray left_nodes, right_nodes; typedef std::map<Digraph::Node, ListGraph::Node> DUMap; DUMap dum; //添加节点 for(size_t i=0;i<left.size();i++) { Digraph::Node u = left[i]; ListGraph::Node uu = g.addNode(); udm[uu] = u; left_nodes.push_back(uu); //cout<<dg.id(u)<< " "; } //cout<<endl; for(size_t i=0;i<right.size();i++) { Digraph::Node u = right[i]; ListGraph::Node uu = g.addNode(); udm[uu] = u; right_nodes.push_back(uu); //cout<<dg.id(u)<<" "; } //cout<<endl; for(size_t i=0;i<right.size();i++) { Digraph::Node u = right[i]; ListGraph::Node uu = g.addNode(); udm[uu] = u; left_nodes.push_back(uu); //cout<<dg.id(u)<< " "; } //cout<<endl; for(size_t i=0;i<left.size();i++) { Digraph::Node u = left[i]; ListGraph::Node uu = g.addNode(); udm[uu] = u; right_nodes.push_back(uu); //cout<<dg.id(u)<< " "; } //cout<<endl; //添加分支 for(size_t i=0;i<left_nodes.size();i++) { ListGraph::Node uv = left_nodes[i]; for(size_t j=0;j<right_nodes.size();j++) { ListGraph::Node uu = right_nodes[j]; Digraph::Node v = udm[uv]; Digraph::Node u = udm[uu]; if(u == v) continue; p.clear(); if(GraphUtils::DFS_Path(dg, v, u, p)) { //ListGraph::Node uv = left_nodes[i]; //ListGraph::Node uu = right_nodes[j]; ListGraph::Edge e = g.addEdge(uu,uv); //cout<<"二分图:"<<dg.id(v)<<"<-->"<<dg.id(u)<<endl; } } } //二分图最大匹配 MaxMatching<ListGraph> mm(g); mm.run(); //cout<<"分支数:"<<countEdges(g)<<" 匹配数:"<<mm.matchingSize()<<endl; for(ListGraph::EdgeIt e(g);e!=INVALID;++e) { if(mm.matching(e)) { ListGraph::Node du = g.u(e); ListGraph::Node dv = g.v(e); Digraph::Node u = udm[du]; Digraph::Node v = udm[dv]; //cout<<"匹配:"<<dg.id(v)<<"<-->"<<dg.id(u)<<endl; if(ddm[u] != INVALID && ddm[v] == INVALID) { ddm[v] = u; //cout<<" v"<<dg.id(v)<<"-->v"<<dg.id(u) <<" v"<<dg.id(u)<<"-->"<<dg.id(ddm[u])<<endl; } else if(ddm[v] != INVALID && ddm[u] == INVALID) { ddm[u] = v; //cout<<" v"<<dg.id(v)<<"-->v"<<dg.id(ddm[v]) <<" v"<<dg.id(u)<<"-->"<<dg.id(v)<<endl; } } } NodeArray node_path; Digraph::Node u = s; bool ret = true; while(u != t) { Digraph::Node v = ddm[u]; //cout<<dg.id(u)<<"->"<<endl; if(v == INVALID) { //cout<<"错误"<<endl; ret = false; break; } //cout<<" ->"<<dg.id(v)<<" "<<endl; node_path.push_back(v); u = v; } if(ret) { u = s; for(size_t i=0;i<node_path.size();i++) { Digraph::Node v = node_path[i]; GraphUtils::DFS_Path(dg, u, v, mpp); u = v; } } return ret; }
void IMFT<Ptr>::twoFrameCorresponding(vector<ListGraph::Node> vecUFrame, vector<ListGraph::Node> vecVFrame) { if(m_isDebug) printf("2-Frame Corresponding : # F1 - %d, # F2 - %d\n", vecUFrame.size(), vecVFrame.size()); // make graph, weight map ListGraph g; ListGraph::NodeMap<V> gNodeMap(g); ListGraph::EdgeMap<double> gEdgeMap(g); // make nodes of UFrame : save node id of UFrame for(int i=0;i<vecUFrame.size();i++){ ListGraph::Node n = g.addNode(); V v; v.id = m_g.id(vecUFrame.at(i)); v.ptr = (*m_gNodeMap)[vecUFrame.at(i)].ptr; v.nFrame = 1; gNodeMap[n] = v; } // make nodes of VFrame : save node id of VFrame for(int i=0;i<vecVFrame.size();i++){ ListGraph::Node n = g.addNode(); V v; v.id = m_g.id(vecVFrame.at(i)); v.ptr = (*m_gNodeMap)[vecVFrame.at(i)].ptr; v.nFrame = 2; gNodeMap[n] = v; // connection for(ListGraph::NodeIt pn(g); pn != INVALID; ++pn){ if(gNodeMap[pn].nFrame != v.nFrame){ double weight = gain(gNodeMap[pn], v); gEdgeMap[g.addEdge(pn,n)] = weight; // ListGraph::Edge e = g.addEdge(pn,n); // gEdgeMap[e] = weight; // gNodeMap[m_g.u(e)].edgeID = g.id(e); // gNodeMap[m_g.v(e)].edgeID = g.id(e); } } } // maximum weighted matching MaxWeightedMatching<ListGraph, ListGraph::EdgeMap<double> > mwm(g, gEdgeMap); mwm.run(); int wsum = mwm.matchingWeight(); if(m_isDebug) printf("2-Frame Max = %d\n", wsum); // make edges of original graph using original nodes' ids for(ListGraph::EdgeIt e(g); e != INVALID; ++e){ if(mwm.matching(e)){ int origUId = gNodeMap[g.u(e)].id; int origVId = gNodeMap[g.v(e)].id; ListGraph::Node newU, newV; newU = m_g.nodeFromId(origUId); newV = m_g.nodeFromId(origVId); if(m_isDebug) printf("2-Frame Connection %d, %d nodes\n", origUId, origVId); double weight = gain((*m_gNodeMap)[newU], (*m_gNodeMap)[newV]); ListGraph::Edge e = m_g.addEdge(newU,newV); (*m_gEdgeMap)[e] = weight; (*m_gNodeMap)[m_g.u(e)].edgeID = m_g.id(e); (*m_gNodeMap)[m_g.v(e)].edgeID = m_g.id(e); // if u가 track이 없으면, track 생성하고, v도 track에 집어 넣음. // u가 track이 있으면, v를 그 track에 집어 넣음. if(cnt > m_nWindow){ int vId = m_g.id(m_g.u(e))-1; if(!(*m_gNodeMap)[m_g.nodeFromId(vId)].isTrack){ // generate a track of vId m_cntTrack ++; Track track; track.setNum(m_cntTrack); track.putNode((*m_gNodeMap)[m_g.nodeFromId(vId)].ptr, vId, (*m_gNodeMap)[m_g.nodeFromId(vId)].nFrame); (*m_gNodeMap)[m_g.nodeFromId(vId)].isTrack = 1; (*m_gNodeMap)[m_g.nodeFromId(vId)].nTrack = m_cntTrack; if(m_isDebug) printf("Generate new track # %d of node %d\n", m_cntTrack, vId); // add v(e) to the track track.putNode((*m_gNodeMap)[m_g.v(e)].ptr, m_g.id(m_g.v(e)), (*m_gNodeMap)[m_g.v(e)].nFrame); (*m_gNodeMap)[m_g.v(e)].isTrack = 1; (*m_gNodeMap)[m_g.v(e)].nTrack = m_cntTrack; m_tracks.push_back(track); } else{ // add v(e) to the track for(int i=0;i<m_tracks.size();i++){ if(m_tracks.at(i).num() == (*m_gNodeMap)[m_g.nodeFromId(vId)].nTrack){ m_tracks.at(i).putNode((*m_gNodeMap)[m_g.v(e)].ptr, m_g.id(m_g.v(e)), (*m_gNodeMap)[m_g.v(e)].nFrame); (*m_gNodeMap)[m_g.v(e)].nTrack = (*m_gNodeMap)[m_g.nodeFromId(vId)].nTrack; (*m_gNodeMap)[m_g.v(e)].isTrack = 1; if(m_isDebug) printf("put node %d to the track %d\n", m_g.id(m_g.v(e)), (*m_gNodeMap)[m_g.v(e)].nTrack); break; } } } } } } }
int Steiner::steiner(const set<ListGraph::Node> terminals) { if (this->s != 0) delete this->s; this->s = new ListGraph(); if (this->sweight != 0) delete this->sweight; this->sweight = new ListGraph::EdgeMap<int>(*this->s); // perform dijkstra for every terminal ListGraph::NodeMap<Dijkstra*> dijk(this->g); for (set<ListGraph::Node>::iterator it = terminals.begin(); it != terminals.end(); ++it) { dijk[*it] = new Dijkstra(this->g, this->weight); dijk[*it]->dijkstra(*it); } // build intermediate graph ListGraph intermediate; ListGraph::EdgeMap<int> iweight(intermediate); map<ListGraph::Node, ListGraph::Node> imapper; for (set<ListGraph::Node>::iterator it = terminals.begin(); it != terminals.end(); ++it) { ListGraph::Node n = intermediate.addNode(); imapper[n] = *it; } for (ListGraph::NodeIt it1(intermediate); it1 != INVALID; ++it1) { ListGraph::NodeIt it2 = it1; for (++it2; it2 != INVALID; ++it2) { ListGraph::Edge e = intermediate.addEdge(it1, it2); iweight[e] = (*dijk[imapper[it1]]->dist)[imapper[it2]]; } } // compute mst MST mst(intermediate, iweight); mst.prim(); // Kruskal mst(intermediate, iweight); // mst.kruskal(); // build final graph map<ListGraph::Node, ListGraph::Node> smapper; for (set<ListGraph::Edge>::iterator it = mst.mst->begin(); it != mst.mst->end(); ++it) { // for each edge in the mst // add end nodes to graph ListGraph::Node u = imapper[intermediate.u(*it)]; if (smapper.count(u) == 0) smapper[u] = this->s->addNode(); ListGraph::Node v = imapper[intermediate.v(*it)]; if (smapper.count(v) == 0) smapper[v] = this->s->addNode(); ListGraph::Node last = v; ListGraph::Node cur = v; do { // walk through path cur = (*dijk[u]->pred)[cur]; if (smapper.count(cur) == 0) smapper[cur] = this->s->addNode(); // add edge to graph, if not already existing if (findEdge(*this->s, smapper[last], smapper[cur]) == INVALID) { ListGraph::Edge e = this->s->addEdge(smapper[last], smapper[cur]); (*this->sweight)[e] = (*dijk[u]->dist)[last] - (*dijk[u]->dist)[cur]; } last = cur; } while (cur != u); } // compute overall weight int overallw = 0; for (ListGraph::EdgeIt e(*this->s); e != INVALID; ++e) { overallw += (*this->sweight)[e]; } // clean up dijkstras for (set<ListGraph::Node>::iterator it = terminals.begin(); it != terminals.end(); ++it) { delete dijk[*it]; } return overallw; }
int HeuristicGroupTSP(ListGraph &g, ListGraph::EdgeMap<double>& weights, vector< set<ListGraph::Node> > &S, vector<ListGraph::Node> &sol, long max_time, double &best_time, double &LB, string &alg_info) { /** * Computa solucao heuristica para o Group TSP. * * Entrada: * @param g grafo simples utilizado * @param weights pesos das arestas * @param S vetor de grupos de vertices (ver def. do problema) * @param max_time tempo maximo (em seg) que o procedimento deve ocorrer * * Saida: * @param sol sequencia de vertices que representa ciclo * @param best_time momento em que solucao atual foi encontrada * @param LB limite inferior encontrado para custo otimo * @param alg_info informacoes de execucao do algoritmo, ex: cadeia de * heuristicas utilizadas * * @return 0 = nao foi possivel encontrar solucao * 1 = solucao encontrada, mas nao necessariamente otima * 2 = solucao otima encontrada */ // Sample Algorithm // Until solution is not integral, sets highest variable to its closest // integer value. // Variables GroupTSPLPSolver::ReturnType rettype = GroupTSPLPSolver::OPTIMAL_FRACTIONARY; GroupTSPLPSolver solver(g, weights, S); ListGraph::NodeMap<double> lpsol_vertex(g); ListGraph::EdgeMap<double> lpsol_edge(g); ListGraph::NodeMap<bool> already_set(g, false); double objVal = 0; time_t start = time(NULL); LB = -1; // main loop cout << "STARTING\n"; while (rettype == GroupTSPLPSolver::OPTIMAL_FRACTIONARY) { cout << "Solving..\n"; rettype = solver.getSolution(lpsol_vertex, lpsol_edge, objVal); if (fabsl(LB - (-1)) < EPS) { LB = objVal; } if (rettype == GroupTSPLPSolver::OPTIMAL_FRACTIONARY) { // Round highest variable to closest value. double mx = -1; Node mx_idx=INVALID; for(NodeIt v(g); v!=INVALID; ++v) { if (!already_set[v]) { if (lpsol_vertex[v] > mx) { mx = lpsol_vertex[v]; mx_idx = v; } } } if (mx_idx != INVALID) { // int val = (lpsol_vertex[mx_idx] > 0.5 ? 1 : 0); int val = calculateIntegralWithProportionalProbability(lpsol_vertex[mx_idx]); cout << "Fixing " << g.id(mx_idx) << " to " << val << "\n"; solver.fixNodeVariable(mx_idx, val); already_set[mx_idx] = true; } else { // it seems we were unable to obtain a solution with integral x[e] break; } } } // OBTAIN SOLUTION best_time = time(NULL) - start; if (rettype != GroupTSPLPSolver::OPTIMAL_INTEGRAL) { return 0; } else { /* do dfs to find out the answer */ ListGraph::NodeMap<bool> vis(g, false); for(ListGraph::NodeIt v(g); v != INVALID; ++v) { if ( lpsol_vertex[v] > 1.0 - EPS ) { queue<ListGraph::Node> q; vis[v] = true; q.push(v); while (!q.empty()) { ListGraph::Node u = q.front(); q.pop(); sol.push_back(u); for(ListGraph::IncEdgeIt e(g, u); e != INVALID; ++e) { ListGraph::Node w = g.runningNode(e); if (lpsol_edge[e] > 1.0 - EPS && !vis[w]) { vis[w] = true; q.push(w); /* only pick one! */ break; } } } break; } } // check if there are vertices outside the cycle for(NodeIt v(g); v != INVALID; ++v) { if (lpsol_vertex[v] > 1-EPS && !vis[v]) { sol.clear(); return 0; } } return fabsl(objVal - LB) < EPS ? 2 : 1; } }
void callback() { // -------------------------------------------------------------------------------- // get the correct function to obtain the values of the lp variables if (where==GRB_CB_MIPSOL) // if this condition is true, all variables are integer {solution_value = &subtourelim::getSolution;} else if ((where==GRB_CB_MIPNODE) && (getIntInfo(GRB_CB_MIPNODE_STATUS)==GRB_OPTIMAL))// node with optimal fractional solution {solution_value = &subtourelim::getNodeRel;} else return; // return, as this code do not take advantage of the other options // -------------------------------------------------------------------------------- // Stores the edges with fractional values and integer values vector<Edge> FracEdges,OneEdges; // produces a subgraph h of g, with edges e with x[e]==1 // contracted, so we can apply Gomory-Hu tree in a small graph ListGraph::EdgeMap<bool> one_filter(tsp.g, false); // start without any edge ListGraph::EdgeMap<bool> non_zero_filter(tsp.g, false); // start without any edge for (EdgeIt e(tsp.g); e != INVALID; ++e) { if ((this->*solution_value)(x[e]) > 1-MY_EPS) OneEdges.push_back(e); // stores the edges with x[e]==1 else if ((this->*solution_value)(x[e]) > MY_EPS) FracEdges.push_back(e); // includes edges with 0 < x[e] < 1 }// define the subgraph with edges that have x[e]==1 try { // -------------------------------------------------------------------------------- // Use union-find to contract nodes (to obtain graph where each componente of g is contracted) //for (int i=0;i<tsp.NNodes;i++) UFIndexToNode[i]=INVALID; ListGraph::NodeMap<int> aux_map(tsp.g); UnionFind<ListGraph::NodeMap<int> > UFNodes(aux_map); for (NodeIt v(tsp.g); v!=INVALID; ++v) UFNodes.insert(v); for (vector<Edge>::iterator e_it=OneEdges.begin(); e_it != OneEdges.end(); ++e_it) UFNodes.join(tsp.g.u(*e_it),tsp.g.v(*e_it));// No problem if they are in a same component // -------------------------------------------------------------------------------- // Put in a separate set all edges that are not inside a component vector<Edge> CrossingEdges; for (EdgeIt e(tsp.g); e != INVALID; ++e) if (UFNodes.find(tsp.g.u(e)) != UFNodes.find(tsp.g.v(e))) CrossingEdges.push_back(e); // -------------------------------------------------------------------------------- // Generate an inverted list UFIndexToNode to find the node that represents a component vector<bool> ComponentIndex(tsp.NNodes); vector<Node> Index2h(tsp.NNodes); for(int i=0;i<tsp.NNodes;i++) ComponentIndex[i]=false; for (NodeIt v(tsp.g); v!=INVALID; ++v) ComponentIndex[UFNodes.find(v)]=true; // -------------------------------------------------------------------------------- // Generate graph of components, add one node for each component and edges ListGraph h; EdgeValueMap h_capacity(h); for(int i=0;i<tsp.NNodes;i++) // add nodes to the graph h if (ComponentIndex[i]) Index2h[i]=h.addNode(); for (vector<Edge>::iterator e_it=FracEdges.begin(); e_it != FracEdges.end(); ++e_it){ Node u = tsp.g.u(*e_it), v = tsp.g.v(*e_it), hu = Index2h[UFNodes.find(u)], hv = Index2h[UFNodes.find(v)]; Edge a = h.addEdge(hu , hv ); // add edges to the graph h h_capacity[a] = (this->*solution_value)(x[*e_it]); } // create a map to terminals NodeBoolMap HasTerminal(h); for (NodeIt uit(tsp.g); uit!=INVALID; ++uit) { // if it is not a station if(!postos[uit]) { HasTerminal[Index2h[UFNodes.find(uit)]] = true; } } // add the source to the 'terminal' HasTerminal[Index2h[UFNodes.find(source)]] = true; // -------------------------------------------------------------------------------- GomoryHu<ListGraph, EdgeValueMap> ght(h, h_capacity); ght.run(); // The Gomory-Hu tree is given as a rooted directed tree. Each node has // an arc that points to its father. The root node has father -1. // Remember that each arc in this tree represents a cut and the value of // the arc is the weight of the corresponding cut. So, if an arc has weight // less than 2, then we found a violated cut and in this case, we insert the // corresponding constraint. NodeBoolMap cutmap(h); for (NodeIt u(h); u != INVALID; ++u) { GRBLinExpr expr = 0; if (ght.predNode(u)==INVALID) continue; // skip the root node if (ght.predValue(u) > 2.0 - MY_EPS) continue; // value of the cut is good // this cut violate this conditions // check if there is a terminal in both components if (HasTerminal[u] && HasTerminal[ght.predNode(u)]) { ght.minCutMap(u, ght.predNode(u), cutmap); // now, we have a violated cut // Percorre as arestas que cruzam alguma componente e insere as que pertencem ao corte for (vector<Edge>::iterator e_it=CrossingEdges.begin();e_it!=CrossingEdges.end();++e_it){ Node u=tsp.g.u(*e_it), v=tsp.g.v(*e_it), hu = Index2h[UFNodes.find(u)], hv=Index2h[UFNodes.find(v)]; if (cutmap[hu] != cutmap[hv]) expr += x[*e_it]; } addLazy( expr >= 2 ); } } // Insere a restricao de sub caminho ------------------------------- // ----------------------------------------------------------------- // Mapeia as arestas da solucao int uncovered = 0; EdgeBoolMap covered(tsp.g, false); EdgeBoolMap active(tsp.g, false); for (EdgeIt a(tsp.g); a!=INVALID; ++a) { if (getSolution(x[a]) > 1 - MY_EPS) { active[a] = true; uncovered++; } else { active[a] = false; } } // ----------------------------------------------------------------- // Percorre os caminhos e insere as restricoes de consumo GRBLinExpr expr = 0; Node u = source; bool changed = false; while (uncovered > 0) { // u := vertice atual // v := vertice destino // a := arco percorrido for (ListGraph::IncEdgeIt ait(tsp.g,u); ait!=INVALID; ++ait) { // verifica se o arco esta na solucao Edge a(ait); if (active[a] && !covered[a]) { // soma a distancia percorrida changed = true; expr += x[a]*tsp.weight[a]; // verifica se o node destino e um posto Node v = tsp.g.v(a); if (u == v) { v = tsp.g.u(a); } if (postos[v]) { // se for um posto, termina aqui uma restricao de consumo addLazy( expr <= delta); expr = 0; } // atualiza o valor do vertice atual e diminui as arestas // que ainda nao foram cobertas u = v; covered[a] = true; uncovered--; break; } } // check the changed if (changed) { changed = false; } else // it is a dead end { break; } } // cout << "TERMINANDO CALLBACK" << endl; } catch (...) { cout << "Error during callback..." << endl; } }
// ATENÇÃO: Não modifique a assinatura deste método. bool brach_and_bound999999(TSP_Data_R &tsp, const vector<DNode> &terminais, const vector<DNode> &postos, const DNode source, int delta, int maxTime, vector<DNode> &sol, double &lbound){ // Converte o TSP direcionado para um nao direcionado com duas arestas ListGraph graph; EdgeValueMap weights(graph); // Adiciona os nos for (ListDigraph::NodeIt u(tsp.g); u!=INVALID; ++u) { Node v = graph.addNode(); } // Adiciona as arestas for (ListDigraph::ArcIt ait(tsp.g); ait!=INVALID; ++ait) { // pega os dois nos incidentes Arc a(ait); DNode u = tsp.g.source(a); DNode v = tsp.g.target(a); // cria a mesma aresta no grafo não direcionado Node gu = graph.nodeFromId(tsp.g.id(u)); Node gv = graph.nodeFromId(tsp.g.id(v)); // insere a aresta no grafo nao direcionado Edge e = graph.addEdge(gu, gv); // Atribui pesos as arestas weights[e] = tsp.weight[a]; } NodeStringMap nodename(graph); NodePosMap posicaox(graph); NodePosMap posicaoy(graph); TSP_Data utsp(graph, nodename, posicaox, posicaoy, weights); // utiliza o convertido ListGraph::EdgeMap<GRBVar> x(graph); GRBEnv env = GRBEnv(); GRBModel model = GRBModel(env); // TODO: [Opcional] Comente a linha abaixo caso não queira inserir cortes durante a execução do B&B model.getEnv().set(GRB_IntParam_LazyConstraints, 1); model.getEnv().set(GRB_IntParam_Seed, 0); model.set(GRB_StringAttr_ModelName, "TSPR - TSP with Refueling"); // name to the problem model.set(GRB_IntAttr_ModelSense, GRB_MINIMIZE); // is a minimization problem // Add one binary variable for each arc and also sets its cost in the objective function for (EdgeIt e(utsp.g); e!=INVALID; ++e) { char name[100]; Edge edge(e); unsigned uid = utsp.g.id(utsp.g.u(edge)); unsigned vid = utsp.g.id(utsp.g.v(edge)); sprintf(name,"x_%s_%s",tsp.vname[tsp.g.nodeFromId(uid)].c_str(),tsp.vname[tsp.g.nodeFromId(vid)].c_str()); x[e] = model.addVar(0.0, 1.0, utsp.weight[e],GRB_BINARY,name); } model.update(); // run update to use model inserted variables // converte os terminais e os postos vector<Node> uterminais; for (auto t : terminais) { unsigned tid = tsp.g.id(t); uterminais.push_back(utsp.g.nodeFromId(tid)); } NodeBoolMap upostos(utsp.g, false); for (auto p: postos) { unsigned pid = tsp.g.id(p); // upostos.push_back(utsp.g.nodeFromId(pid)); upostos[utsp.g.nodeFromId(pid)] = true; } // Adicione restrições abaixo // (1) Nós terminais devem ser visitados exatamente uma vez for (auto v : uterminais) { GRBLinExpr expr = 0; for (IncEdgeIt e(utsp.g,v); e!=INVALID; ++e){ expr += x[e]; } model.addConstr(expr == 2 ); } // (3) Nó source sempre presente no início do caminho Node usource = utsp.g.nodeFromId(tsp.g.id(source)); GRBLinExpr expr = 0; for (IncEdgeIt e(utsp.g,usource); e!=INVALID; ++e){ expr += x[e]; } model.addConstr(expr >= 1 ); try { model.update(); // Process any pending model modifications. //if (maxTime >= 0) model.getEnv().set(GRB_DoubleParam_TimeLimit,maxTime); subtourelim cb = subtourelim(utsp , x, usource, upostos, delta); model.setCallback(&cb); // TODO: [Opcional] Pode-se utilizar o valor de uma solução heurística p/ acelerar o algoritmo B&B (cutoff value). //cutoff = tsp.BestCircuitValue-MY_EPS; double cutoff = 0.0; if (cutoff > MY_EPS) model.getEnv().set(GRB_DoubleParam_Cutoff, cutoff ); model.update(); // Process any pending model modifications. model.optimize(); // Obtém o status da otimização int status = model.get(GRB_IntAttr_Status); if(status == GRB_INFEASIBLE || status == GRB_INF_OR_UNBD){ cout << "Modelo inviavel ou unbounded." << endl; return false; } // Limitante inferior e superior do modelo //lbound = model.get(GRB_DoubleAttr_ObjBoundC); if( model.get(GRB_IntAttr_SolCount) <= 0 ){ cout << "Modelo nao encontrou nenhuma solucao viavel no tempo. LowerBound = " << lbound << endl; return false; } else if (status == GRB_OPTIMAL){ if(verbose) cout << "O modelo foi resolvido ate a otimalidade." << endl; } else { if(verbose) cout << "O modelo encontrou uma solucao sub-otima (i.e. nao ha garantia de otimalidade)." << endl; } double custo_solucao = model.get(GRB_DoubleAttr_ObjVal); int uncovered=0; EdgeBoolMap cover(utsp.g, false); for (EdgeIt e(utsp.g); e!=INVALID; ++e) { if (BinaryIsOne(x[e].get(GRB_DoubleAttr_X))) { cover[e] = true; uncovered++; } } sol.push_back(tsp.g.nodeFromId(utsp.g.id(usource))); convertSol(x, sol, tsp, utsp, usource, cover, uncovered); // Calculo manual do custo da solução (deve ser igual ao ObjVal do Gurobi). double soma=0.0; ArcName aname(tsp.g); vector<Arc> edgesSol; ArcColorMap acolor(tsp.g); // if( verbose ) cout << "####### " << endl << "Edges of Solution (B&B):" << endl; // for (EdgeIt e(utsp.g); e!=INVALID; ++e){ // if (BinaryIsOne(x[e].get(GRB_DoubleAttr_X))){ // Note que se este método serve para variáveis binárias, p/ inteiras terá de usar outro método. // soma += utsp.weight[e]; // edgesSol.push_back(tsp.g.arcFromId(utsp.g.id(e))); // if( verbose) cout << "(" << tsp.vname[tsp.g.nodeFromId(utsp.g.id(utsp.g.u(e)))] << "," << tsp.vname[tsp.g.nodeFromId(utsp.g.id(utsp.g.v(e)))] << ")" << endl; // acolor[tsp.g.arcFromId(utsp.g.id(e))] = BLUE; // } // } // if( verbose ) cout << "####### " << endl; if( verbose ) cout << "####### " << endl << "Edges of Solution (B&B):" << endl; DNode u = sol[0]; for (int i=1; i<sol.size(); i++) { DNode v = sol[i]; soma += tsp.AdjMatD.Cost(u,v); if ( verbose ) cout << "(" << tsp.vname[u] << "," << tsp.vname[v] << ")" << endl; u = v; } if( verbose ) cout << "####### " << endl; if( verbose ) cout << "Custo calculado pelo B&B = "<< soma << " / " << custo_solucao << endl; if( verbose ){ cout << "Caminho encontrado a partir do vértice de origem (" << tsp.vname[source] << "): "; for(auto node : sol){ cout << tsp.vname[node] << " "; } // Obs: O caminho é gerado a partir do nó source, se o conjunto de arestas retornado pelo B&B for desconexo, o caminho retornado por 'path_search' será incompleto. cout << endl << "Custo calculado da solucao (caminho a partir do no origem) = " << solutionCost(tsp, sol) << endl; ostringstream out; out << "TSP with Refueling B&B, cost= " << custo_solucao; ViewListDigraph(tsp.g, tsp.vname, tsp.posx, tsp.posy, tsp.vcolor, acolor, out.str()); } return true; } catch(GRBException e) { cerr << "Gurobi exception has been thrown." << endl; cerr << "Error code = " << e.getErrorCode() << endl; cerr << e.getMessage(); } catch (...) { cout << "Model is infeasible" << endl; return false; } return false; }
int main(int argc, char *argv[]) { int time_limit; char name[1000]; double cutoff=0.0; ListGraph g; EdgeWeight lpvar(g); EdgeWeight weight(g); NodeName vname(g); ListGraph::NodeMap<double> posx(g),posy(g); string filename; int seed=1; // uncomment one of these lines to change default pdf reader, or insert new one //set_pdfreader("open"); // pdf reader for Mac OS X //set_pdfreader("xpdf"); // pdf reader for Linux //set_pdfreader("evince"); // pdf reader for Linux srand48(seed); time_limit = 3600; // solution must be obtained within time_limit seconds if (argc!=2) {cout<< endl << "Usage: "<< argv[0]<<" <graph_filename>"<<endl << endl << "Example: " << argv[0] << " gr_berlin52" << endl << " " << argv[0] << " gr_att48" << endl << endl; exit(0);} else if (!FileExists(argv[1])) {cout<<"File "<<argv[1]<<" does not exist."<<endl; exit(0);} filename = argv[1]; // Read the graph if (!ReadListGraph(filename,g,vname,weight,posx,posy)) {cout<<"Error reading graph file "<<argv[1]<<"."<<endl;exit(0);} TSP_Data tsp(g,vname,posx,posy,weight); ListGraph::EdgeMap<GRBVar> x(g); GRBEnv env = GRBEnv(); GRBModel model = GRBModel(env); #if GUROBI_NEWVERSION model.getEnv().set(GRB_IntParam_LazyConstraints, 1); model.getEnv().set(GRB_IntParam_Seed, seed); #else model.getEnv().set(GRB_IntParam_DualReductions, 0); // Dual reductions must be disabled when using lazy constraints #endif model.set(GRB_StringAttr_ModelName, "Undirected TSP with GUROBI"); // name to the problem model.set(GRB_IntAttr_ModelSense, GRB_MINIMIZE); // is a minimization problem // Add one binary variable for each edge and also sets its cost in the objective function for (ListGraph::EdgeIt e(g); e!=INVALID; ++e) { sprintf(name,"x_%s_%s",vname[g.u(e)].c_str(),vname[g.v(e)].c_str()); x[e] = model.addVar(0.0, 1.0, weight[e],GRB_BINARY,name); } model.update(); // run update to use model inserted variables // Add degree constraint for each node (sum of solution edges incident to a node is 2) for (ListGraph::NodeIt v(g); v!=INVALID; ++v) { GRBLinExpr expr; for (ListGraph::IncEdgeIt e(g,v); e!=INVALID; ++e) expr += x[e]; //aqui model.addConstr(expr == 2 ); what? ignorou! model.addConstr(expr == 2 ); } try { model.update(); // Process any pending model modifications. if (time_limit >= 0) model.getEnv().set(GRB_DoubleParam_TimeLimit,time_limit); subtourelim cb = subtourelim(tsp , x); model.setCallback(&cb); tsp.max_perturb2opt_it = 200; //1000; // number of iterations used in heuristic TSP_Perturb2OPT TSP_Perturb2OPT(tsp); if (tsp.BestCircuitValue < DBL_MAX) cutoff = tsp.BestCircuitValue-BC_EPS; // // optimum value for gr_a280=2579, gr_xqf131=566.422, gr_drilling198=15808.652 if (cutoff > 0) model.getEnv().set(GRB_DoubleParam_Cutoff, cutoff ); model.update(); // Process any pending model modifications. model.optimize(); double soma=0.0; for (ListGraph::EdgeIt e(g); e!=INVALID; ++e) { lpvar[e] = x[e].get(GRB_DoubleAttr_X); if (lpvar[e] > 1-BC_EPS ) { soma += weight[e]; if ( (vname[g.u(e)] == "243")||(vname[g.v(e)] == "243") || (vname[g.u(e)] == "242")||(vname[g.v(e)] == "242") ) { cout << "Achei, x("<< vname[g.u(e)] << " , " << vname[g.v(e)] << " = " << lpvar[e] <<"\n"; } } } cout << "Solution cost = "<< soma << endl; Update_Circuit(tsp,x); // Update the circuit in x to tsp circuit variable (if better) ViewTspCircuit(tsp); }catch (...) { if (tsp.BestCircuitValue < DBL_MAX) { cout << "Heuristic obtained optimum solution" << endl; ViewTspCircuit(tsp); return 0; }else { cout << "Graph is infeasible" << endl; return 1; } } }
int main(int argc, char *argv[]) { ListGraph g; // graph declaration string digraph_vcover_filename; NodeName vname(g); // name of graph nodes EdgeName ename(g); // name of graph edges ListGraph::NodeMap<double> px(g),py(g); // xy-coodinates for each node ListGraph::NodeMap<int> vcolor(g);// color of nodes ListGraph::EdgeMap<int> ecolor(g); // color of edges ListGraph::NodeMap<int> solucao(g); // vetor 0/1 que identifica vertices da solucao NodeWeight lpvar(g); // used to obtain the contents of the LP variables NodeWeight weight(g); // node weights vector <Node> V; srand48(1); // uncomment one of these lines to change default pdf reader, or insert new one //set_pdfreader("open"); // pdf reader for Mac OS X //set_pdfreader("xpdf"); // pdf reader for Linux set_pdfreader("evince"); // pdf reader for Linux //set_pdfreader("open -a Skim.app"); SetGraphLabelFontSize(50); if (argc!=2) {cout<<endl<<"Usage: "<< argv[0]<<" <digraph_vcover_filename>"<< endl << endl; cout << "Example: " << argv[0] << " gr_bipartido_1.in" << endl << endl; exit(0);} digraph_vcover_filename = argv[1]; ReadListGraph3(digraph_vcover_filename,g,vname,weight,px,py); vCover_Instance T(g,vname,px,py,weight); for (EdgeIt e(g); e != INVALID; ++e) ename[e] = vname[g.u(e)]+" , "+vname[g.v(e)]; cout << "Rede com " << T.nnodes << endl << endl; cout << "Computadores e seus custos:" << endl << endl; for (NodeIt v(g);v!=INVALID;++v) cout << "Computador[ " << vname[v] << " ] com custo " << weight[v] << "." << endl; cout << endl << "Conexoes entre computadores:" << endl << endl; for (EdgeIt e(g);e!=INVALID;++e) cout << "Conexao " << ename[e] << "." << endl; cout << endl << endl; // for (NodeIt v(g);v!=INVALID;++v) vcolor[v]=BLACK; // for (EdgeIt e(g); e != INVALID; ++e) ecolor[e] = BLUE; // for (EdgeIt e(g); e != INVALID; ++e) ename[e] = ""; // ViewListGraph(g,vname,ename,px,py,vcolor,ecolor,digraph_vcover_filename); // cout << "Pause\n"; getchar(); // Generate the binary variables and the objective function // Add one binary variable for each edge and set its cost in the objective function if (monitoramento_em_grafo_bipartido(g, vname, weight, solucao)) { // verificacao e apresentacao da solucao obtida for (ListGraph::EdgeIt e(g); e!=INVALID; ++e) if (!(solucao[g.u(e)] || solucao[g.v(e)])) { cout << "Nao foi obtida uma solucao viavel.\nConexao {" << vname[g.u(e)] << "---" << vname[g.v(e)] << "} nao monitorada." << endl << endl; exit(0);} double soma=0.0; for (ListGraph::NodeIt v(g);v!=INVALID;++v) vcolor[v]=BLUE; // all nodes BLUE for (ListGraph::EdgeIt e(g); e!=INVALID; ++e) ecolor[e]=BLUE; cout << "Computadores Selecionados" << endl ; for (ListGraph::NodeIt v(g); v!=INVALID; ++v) if (solucao[v]){soma += weight[v]; vcolor[v]=RED; cout << vname[v] << endl;} cout << endl << "Valor da Solucao = " << soma << "." << endl; ViewListGraph(g,vname,ename,px,py,vcolor,ecolor, "Solucao do Monitoramento com custo "+DoubleToString(soma)); return(0); }else{cout << "Programa linear gerado eh inviavel." << endl;return(1);} }