//splits graph into connected components void split_graph(ListDigraph& g, vector<ListDigraph*>& graphs){ Undirector<ListDigraph> undirected(g); ListDigraph::NodeMap<int> components(g); stronglyConnectedComponents(undirected, components); int num_subgraphs = 0; for(ListDigraph::NodeIt n(g); n != INVALID; ++n){ if(components[n] > num_subgraphs) num_subgraphs = components[n]; } num_subgraphs++; ListDigraph::NodeMap<ListDigraph::Node> map(g); for(int i = 0; i < num_subgraphs; i++){ ListDigraph temp; for(ListDigraph::NodeIt n(g); n != INVALID; ++n){ if(components[n] == i){ map[n] = temp.addNode(); } } for(ListDigraph::NodeIt n(g); n != INVALID; ++n){ if(components[n] == i){ for(ListDigraph::OutArcIt o(g, n); o != INVALID; ++o){ temp.addArc(map[g.source(o)], map[g.target(o)]); } } } graphs.push_back(&temp); } }
void drawGraphToFileWithArcMap(ListDigraph& g, ListDigraph::ArcMap<int>& map){ ofstream myfile; myfile.open("graph.dot"); myfile << "digraph g {\n"; for (ListDigraph::ArcIt a(g); a!= INVALID; ++a) { myfile << g.id(g.source(a)) << " -> " << g.id(g.target(a)) << " [label=\"" << map[a] << "\"] \n"; } myfile << "}\n"; myfile.close(); }
void drawGraphToFile(ListDigraph& g){ ofstream myfile; myfile.open("graph.dot"); myfile << "digraph g {\n"; for (ListDigraph::ArcIt a(g); a!= INVALID; ++a) { myfile << g.id(g.source(a)) << " -> " << g.id(g.target(a)) << "\n"; } myfile << "}\n"; myfile.close(); }
// This routine visualize a digraph 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 ViewListDigraph(ListDigraph &g, DNodeStringMap &vname, // node names DNodePosMap &px, // x-position of the nodes DNodePosMap &py, // y-position of the nodes DNodeColorMap &vcolor, // color of node (see myutils.h) ArcColorMap &ecolor, // color of edge string text) // text displayed below the figure { char tempname[1000],cmd[1000]; FILE *fp; double minpx=DBL_MAX,minpy=DBL_MAX,maxpx=-DBL_MAX,maxpy=-DBL_MAX,delta,factor; string str; // obtain a temporary file name strcpy(tempname,".viewdigraphtempname"); fp = fopen(tempname,"w+"); if (fp==NULL) {cout << "Error to open temporary file to visualize digraph.\n"; return(0);} for (DNodeIt 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; // using larger values makes small nodes delta = fmax(maxpx - minpx,maxpy - minpy); // Generate a text file with the graph format of neato program fprintf(fp,"digraph g {\n"); fprintf(fp,"\tsize = \"10, 10\";\n"); fprintf(fp,"\tnode [style = filled, shape = \"circle\"];\n"); for (DNodeIt v(g); v!=INVALID; ++v) { if (vcolor[v]==NOCOLOR) continue; fprintf(fp,"\t%s [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); } for (ArcIt e(g); e!=INVALID; ++e) { if (ecolor[e]==NOCOLOR) continue; fprintf(fp,"\t%s -> %s [color=\"%s\" ];\n",vname[g.source(e)].c_str(),vname[g.target(e)].c_str(),ColorName(ecolor[e]).c_str()); } fprintf(fp,"label=\"%s\";\nfontsize=50;\n",text.c_str()); fprintf(fp,"}\n"); fclose(fp); sprintf(cmd,"neato -Tpdf %s -o %s.pdf",tempname,tempname); system(cmd); str = tempname; str = str + ".pdf"; view_pdffile(str); return(1); }
// ****************** TSP WITH REFUELING ********************************** // Directed version of adjacency matrix. Used to handle with the TSP with Refueling Problem. AdjacencyMatrixDirected::AdjacencyMatrixDirected(ListDigraph &dgraph, ArcValueMap &graphweight, double NonArcValue): DNode2Index(dgraph), Arc2Index(dgraph) { int i; g = &dgraph; this->NonArcValue = NonArcValue; weight = &graphweight; Nnodes = countNodes(dgraph); // number of nodes in the input dgraph Narcs = countArcs(dgraph); // number of edges in the input dgraph Nmatrix = Nnodes*Nnodes; // full matrix AdjMatrix = (double *) malloc(sizeof(double)*Nmatrix); Index2DNode = (DNode *) malloc(sizeof(Node)*Nnodes); Index2Arc = (Arc *) malloc(sizeof(Arc)*Narcs); if ((AdjMatrix==NULL)||(Index2DNode==NULL)||(Index2Arc==NULL)) { cout << "Out of memory in constructor of AdjacencyMatrixDirected\n"; ADJMAT_FreeNotNull(AdjMatrix); ADJMAT_FreeNotNull(Index2DNode); ADJMAT_FreeNotNull(Index2Arc); exit(0);} i = 0; for (DNodeIt v(*g); v != INVALID; ++v) { Index2DNode[i] = v; AdjacencyMatrixDirected::DNode2Index[v] = i; i++; } // Initially all edges have infinity weight for (int i=0;i<Nmatrix;i++) AdjMatrix[i] = NonArcValue; // Then, update the existing edges with the correct weight for (ArcIt a(dgraph); a != INVALID; ++a) { DNode u,v; int i_u,i_v; u = dgraph.source(a); v = dgraph.target(a); // obtain the extremities of e i_u = DNode2Index[u]; i_v = DNode2Index[v]; AdjMatrix[i_u*Nnodes+i_v] = graphweight[a]; } }
int main(){ ListDigraph MyGraph; ListDigraph::NodeMap< long long int > idNodeMap ( MyGraph ); ListDigraph::NodeMap< double > xKoordNodeMap (MyGraph ); ListDigraph::NodeMap< double > yKoordNodeMap (MyGraph ); ListDigraph::NodeMap< long double > capacityNodeMap( MyGraph ); ListDigraph::NodeMap< bool > typeNodeMap( MyGraph ); ListDigraph::ArcMap< long double > distanceArcMap( MyGraph ); ListDigraph::ArcMap < bool > switchArcMap( MyGraph, true ); // Alle Kanten sollen an / true sein ListDigraph::ArcMap < bool > stateArcMap( MyGraph, false ); // Keine Infraktion (false) am Anfang ListDigraph::NodeMap< bool > stateNodeMap( MyGraph, false ); try { digraphReader( MyGraph, "/Users/sonneundasche/Desktop/MilkyWayDaten/MilkyWay_Solution.lgf") .nodeMap( "Type", typeNodeMap ) .run(); } catch (Exception& error) { // check if there was any error std::cerr << "Error: " << error.what() << std::endl; return -1; } // ------------------------------------------------------------------- // ---------------- Erzeuge die Glättungs Kanten ----------------- // ------------------------------------------------------------------- // Zur Abspeicherung der IDs der Glättungs Arcs // int glattArcID[ glattArcNr ]; // int m = 0; // // for ( int in = 0; in < supplyNodesNr; in++ ) // for ( int out = 0; out < supplyNodesNr ; out++ ) { // glattArcID[ m ] = MyGraph.id( MyGraph.addArc( MyGraph.nodeFromId( in ), MyGraph.nodeFromId( out ) )); // m++; // // //vice versa "in/out" // glattArcID[ m ] = MyGraph.id( MyGraph.addArc( MyGraph.nodeFromId( out ), MyGraph.nodeFromId( in ) )); // m++; // } // ------------------------------------------------------------------- // ---------------- Erzeuge eine FilterMap und Init ----------------- // ------------------------------------------------------------------- // ---------------- um Glättung umzuschalten ---------------------- // ------------------------------------------------------------------- // FilterArcs< ListDigraph >::ArcFilterMap glattArcFilterMap( MyGraph ); // FilterArcs< ListDigraph >::FilterArcs glattFilterGraph( MyGraph, glattArcFilterMap ); // // // Alle auf TRUE setzen // for ( FilterArcs< ListDigraph >::ArcIt a( glattFilterGraph ) ; a != INVALID ; ++a ) // glattArcFilterMap[ a ] = 1; // // // Glättungskanten auf FALSE setzen // for ( int i = 0; i < glattArcNr; i++ ) // glattArcFilterMap[ glattFilterGraph.arcFromId( glattArcID[ i ] ) ] = 0; // // ------------------------------------------------------------------- // ---------------- Zufalls Glättungskanten umschalten ------------- // ------------------------------------------------------------------- // ------------------------------------------------------------------- // ---------------- Infectious Dynamics Calculation (Range) ---------- // ------------------------------------------------------------------- // +++++ Hier sollte noch ein SubGraph / FilterMap erstellt werden für die Glättung // ++++ Gesamtschleife mit Abbruch kommt noch int infStartAmount = 1; // Anzahl der Molkerei-Knoten die am Anfang infiziert sind int infSumInfected = infStartAmount; // StartRange: Anzahl infizierten Knoten + Anfangswert // int ctrlRange[ ]; // Range die über die Out Arcs gezählt wird int ctrlRangeALL = 0; int infSumArry[ 3 ]; // AbbruchBed.: Falls nach drei Rechen-Schritten "Range" gleich, dann brich ab. infSumArry[ 0 ] = infStartAmount; // Zwangsbed., damit der Loop anfängt // ---------------- Zufällig eine Molkerei/Node infizieren ------------- // for ( int i = 0; i < infStartAmount; i++) // stateNodeMap[ MyGraph.nodeFromId( rnd( 0, ( supplyNodesNr - 1 ) ) ) ] = 1; // for ( int i = 0; i < sumSup; i++) // stateNodeMap[ MyGraph.nodeFromId( i ) ] = 1; // ------------------------------------------------------------------- // ----------------- Durchlauf durch den Graphen ---------------- // ------------------------------------------------------------------- // ++++ Man kann entweder zuerst Nodes oder Arcs durchschauen // ++++ Falls Arcs zuerst gezählt werden, breitet sich die Krankheit in weniger // ++++ Rechenschritten aus, da in anschließenden Schritt infizierte Kanten Knoten infinzieren. // ++++ Dieser Weg wird hier aus Performance-Gründen gegangen. Uns interessiert nicht die Ausbreitungsgeschw. do { // ---------------- Arc Infectious States ---------------- for ( ListDigraph::ArcIt a( MyGraph ) ; a != INVALID; ++a ) { // if ( stateArcMap[ a ] == 0 ) //Falls noch nicht infiziert if ( stateNodeMap[ MyGraph.source( a ) ] == 1 ) // Falls der QuellKnoten Infiziert, Kante auch stateArcMap[ a ] = 1; } // ---------------- Node Infectious States ---------------- for ( ListDigraph::NodeIt n( MyGraph ) ; n != INVALID; ++n ) { if ( stateNodeMap[ n ] == 0 ) // Optimierung: Nur abfragen falls es noch nicht infiziert ist for (ListDigraph::InArcIt in( MyGraph, n ) ; in != INVALID; ++in ) if ( stateArcMap[ in ] ) { stateNodeMap[ n ] = 1; infSumInfected++; // Zähle die Neuinfektion falls Knoten an ist continue; // Schleife verlassen, falls eine Kante an ist } } // Billiges Aufschieben der Werte. Damit man schauen kann, ob dreimal nichts geschah infSumArry[ 2 ] = infSumArry [ 1 ]; infSumArry[ 1 ] = infSumArry [ 0 ]; infSumArry[ 0 ] = infSumInfected; } while ( ( infSumArry[ 0 ] != infSumArry[ 1 ] ) || ( infSumArry[ 1 ] != infSumArry [ 2 ] ) ); // ------------------------------------------------------------------- // ----------------- Test Funktion zur Überprüfung der Werte ---------------- // ------------------------------------------------------------------- // +++ Einfache Berechnung des AUS-Grades // GesamtRange for ( ListDigraph::NodeIt n( MyGraph ) ; n != INVALID; ++n) for ( ListDigraph::OutArcIt o( MyGraph, n ) ; o != INVALID; ++o ){ ctrlRangeALL++; // ++++>> hier den Range Array einfügen } // ----------------- Graph schreiben ---------------- digraphWriter( MyGraph, cout ) .nodeMap( "NodeStates", stateNodeMap ) .skipArcs() .run(); cout << endl << "Range-Berechnungs-Zeit: " << time.realTime() << endl; cout << endl << "Range-Wert: " << infSumInfected << endl; return 0; }
//find minflow by reducing the maximal amount of flow (with maxflow) from a feasible flow void find_minflow_IBFS(ListDigraph& g, ListDigraph::ArcMap<int>& demands, ListDigraph::ArcMap<int>& flow, ListDigraph::NodeMap<int>& labels, ListDigraph::Node s, ListDigraph::Node t) { ListDigraph::ArcMap<int> feasible_flow(g); find_feasible_flow(g, demands, feasible_flow); //Create IBFS graph and solve maxflow in it IBFSGraph* g_ibfs = new IBFSGraph(IBFSGraph::IB_INIT_FAST); int num_nodes = countNodes(g); int num_arcs = countArcs(g); //we need a special labeling for IBFS, because we won't have s and t there //ListDigraph::Node label_to_node[num_nodes]; ListDigraph::Node* label_to_node = new ListDigraph::Node[num_nodes]; ListDigraph::NodeMap<int> labels_ibfs(g); int index_counter = 0; for(ListDigraph::NodeIt n(g); n != INVALID; ++n){ if(n == s || n == t) continue; labels_ibfs[n] = index_counter; index_counter++; label_to_node[labels_ibfs[n]] = n; } g_ibfs->initSize(num_nodes-2, num_arcs-countOutArcs(g, s) - countInArcs(g, t)); /** for(ListDigraph::NodeIt n(g); n != INVALID; ++n){ if(countInArcs(g, n) == 0){ g_ibfs->addNode(labels[n], 0, MAX_CAPACITY); } else if(countOutArcs(g, n) == 0){ g_ibfs->addNode(labels[n], MAX_CAPACITY, 0); } } **/ ListDigraph::ArcMap<int> arc_labels(g); //ListDigraph::Arc arc_labels_reverse[num_arcs]; ListDigraph::Arc* arc_labels_reverse = new ListDigraph::Arc[num_arcs]; int counter = 0; for(ListDigraph::ArcIt a(g); a != INVALID; ++a){ arc_labels[a] = counter; arc_labels_reverse[counter] = a; counter++; } for(ListDigraph::ArcIt a(g); a != INVALID; ++a){ if(g.source(a) == s){ g_ibfs->addNode(labels_ibfs[g.target(a)], 0, MAX_CAPACITY); } else if(g.target(a) == t){ g_ibfs->addNode(labels_ibfs[g.source(a)], MAX_CAPACITY, 0); } else{ g_ibfs->addEdge(labels_ibfs[g.target(a)], labels_ibfs[g.source(a)], feasible_flow[a]-demands[a], MAX_CAPACITY); } } g_ibfs->initGraph(); g_ibfs->computeMaxFlow(); /** while(g_ibfs->arcs != g_ibfs->arcEnd){ //cout << "LABEL:: " << g_ibfs->arcs->label << "\n"; if(g_ibfs->arcs->label != -1){ ListDigraph::Arc a = arc_labels_reverse[g_ibfs->arcs->label]; int flow_on_arc = MAX_CAPACITY - g_ibfs->arcs->rCap; int flow_on_reverse = (feasible_flow[a]-demands[a]) - g_ibfs->arcs->rev->rCap; //cout << g_ibfs->arcs->rCap << " " << g_ibfs->arcs->rev->rCap << "\n"; //cout << feasible_flow[a] << " " << flow_on_arc << " " << flow_on_reverse << " "; flow[a] = feasible_flow[a] + flow_on_arc - flow_on_reverse; //cout << flow[a] << "\n"; } g_ibfs->arcs++; } for(ListDigraph::OutArcIt o(g, s); o != INVALID; ++o){ for (ListDigraph::OutArcIt oa(g, g.target(o)); oa != INVALID; ++oa) { flow[o] += flow[oa]; } } for(ListDigraph::InArcIt i(g, t); i != INVALID; ++i){ for(ListDigraph::InArcIt ia(g, g.source(i)); ia != INVALID; ++ia){ flow[i] += flow[ia]; } } **/ }