// Test edge subgraph conversion TEST(subgraph, TestConvertESubGraphs) { PNEGraph NEGraph; PNGraph NGraph; TIntV NIdV; TIntV EIdV; int i; NGraph = GetTestTNGraph(); EXPECT_EQ(20,NGraph->GetNodes()); EXPECT_EQ(60,NGraph->GetEdges()); for (i = 0; i < 20; i += 2) { NIdV.Add(i); } // TODO: fix TSnap::ConvertSubGraph<PUNGraph>(NGraph, NIdV, true), it fails // UNGraph = TSnap::ConvertSubGraph<PUNGraph>(NGraph, NIdV, true); NEGraph = TSnap::ConvertGraph<PNEGraph>(NGraph); EXPECT_EQ(20,NEGraph->GetNodes()); EXPECT_EQ(60,NEGraph->GetEdges()); // select every second edge i = 0; for (TNEGraph::TEdgeI EI = NEGraph->BegEI(); EI < NEGraph->EndEI(); EI++) { if (i == 0) { EIdV.Add(EI.GetId()); } i = (i + 1) % 2; } NGraph = TSnap::ConvertESubGraph<PNGraph>(NEGraph, EIdV); EXPECT_EQ(20,NGraph->GetNodes()); EXPECT_EQ(30,NGraph->GetEdges()); }
void OnlyD3CEdges(PNGraph& dir_graph, PNGraph& d3c_graph, bool recip_edges) { // Add all of the nodes into the new graph for (TNGraph::TNodeI node = dir_graph->BegNI(); node < dir_graph->EndNI(); node++) { int curr_node = node.GetId(); d3c_graph->AddNode(curr_node); } for (TNGraph::TNodeI node = dir_graph->BegNI(); node < dir_graph->EndNI(); node++) { int curr_node = node.GetId(); auto curr_node_it = dir_graph->GetNI(curr_node); for (int out_edge = 0; out_edge < curr_node_it.GetOutDeg(); ++out_edge) { int out_node = curr_node_it.GetOutNId(out_edge); for (int in_edge = 0; in_edge < curr_node_it.GetInDeg(); ++in_edge) { int in_node = curr_node_it.GetInNId(in_edge); if (out_node == in_node && !recip_edges) { continue; } if (dir_graph->IsEdge(out_node, in_node) || recip_edges) { if (!d3c_graph->IsEdge(out_node, in_node)) { d3c_graph->AddEdge(out_node, in_node); } if (!d3c_graph->IsEdge(in_node, curr_node)) { d3c_graph->AddEdge(in_node, curr_node); } if (!d3c_graph->IsEdge(curr_node, out_node)) { d3c_graph->AddEdge(curr_node, out_node); } } } } } #ifdef _VERBOSE_ std::cout << "Original graph edge count: " << dir_graph->GetEdges() << std::endl << "D3C graph edge count: " << d3c_graph->GetEdges() << std::endl; #endif }
// Test node subgraph conversion void TestConvertSubGraphs() { PNGraph NGraph; PUNGraph UNGraph; int N1, N2, N3; int E1, E2, E3; TIntV NIdV; int i; NGraph = GetTestTNGraph(); N1 = NGraph->GetNodes(); E1 = NGraph->GetEdges(); for (i = 0; i < 20; i += 2) { NIdV.Add(i); } // TODO: fix TSnap::ConvertSubGraph<PUNGraph>(NGraph, NIdV, true), it fails // UNGraph = TSnap::ConvertSubGraph<PUNGraph>(NGraph, NIdV, true); UNGraph = TSnap::ConvertSubGraph<PUNGraph>(NGraph, NIdV); N2 = UNGraph->GetNodes(); E2 = UNGraph->GetEdges(); NGraph = TSnap::ConvertSubGraph<PNGraph>(UNGraph, NIdV); N3 = NGraph->GetNodes(); E3 = NGraph->GetEdges(); printf("---- TestConvertSubGraphs -----\n"); printf("nodes: %d,%d,%d, edges: %d,%d,%d\n", N1, N2, N3, E1, E2, E3); printf("\n"); }
int main(int argc, char* argv[]) { Env = TEnv(argc, argv, TNotify::StdNotify); Env.PrepArgs(TStr::Fmt("Node Centrality. build: %s, %s. Time: %s", __TIME__, __DATE__, TExeTm::GetCurTm())); TExeTm ExeTm; Try const TStr InFNm = Env.GetIfArgPrefixStr("-i:", "../as20graph.txt", "Input un/directed graph"); const TStr OutFNm = Env.GetIfArgPrefixStr("-o:", "node_centrality.tab", "Output file"); printf("Loading %s...", InFNm.CStr()); PNGraph Graph = TSnap::LoadEdgeList<PNGraph>(InFNm); //PNGraph Graph = TSnap::GenRndGnm<PNGraph>(10, 10); //TGraphViz::Plot(Graph, gvlNeato, InFNm+".gif", InFNm, true); printf("nodes:%d edges:%d\n", Graph->GetNodes(), Graph->GetEdges()); PUNGraph UGraph = TSnap::ConvertGraph<PUNGraph>(Graph); // undirected version of the graph TIntFltH BtwH, EigH, PRankH, CcfH, CloseH, HubH, AuthH; //printf("Computing...\n"); printf("Treat graph as DIRECTED: "); printf(" PageRank... "); TSnap::GetPageRank(Graph, PRankH, 0.85); printf(" Hubs&Authorities..."); TSnap::GetHits(Graph, HubH, AuthH); printf("\nTreat graph as UNDIRECTED: "); printf(" Eigenvector..."); TSnap::GetEigenVectorCentr(UGraph, EigH); printf(" Clustering..."); TSnap::GetNodeClustCf(UGraph, CcfH); printf(" Betweenness (SLOW!)..."); TSnap::GetBetweennessCentr(UGraph, BtwH, 1.0); printf(" Constraint (SLOW!)..."); TNetConstraint<PUNGraph> NetC(UGraph, true); printf(" Closeness (SLOW!)..."); for (TUNGraph::TNodeI NI = UGraph->BegNI(); NI < UGraph->EndNI(); NI++) { const int NId = NI.GetId(); CloseH.AddDat(NId, TSnap::GetClosenessCentr<PUNGraph>(UGraph, NId, false)); } printf("\nDONE! saving..."); FILE *F = fopen(OutFNm.CStr(), "wt"); fprintf(F,"#Network: %s\n", InFNm.CStr()); fprintf(F,"#Nodes: %d\tEdges: %d\n", Graph->GetNodes(), Graph->GetEdges()); fprintf(F,"#NodeId\tDegree\tCloseness\tBetweennes\tEigenVector\tNetworkConstraint\tClusteringCoefficient\tPageRank\tHubScore\tAuthorityScore\n"); for (TUNGraph::TNodeI NI = UGraph->BegNI(); NI < UGraph->EndNI(); NI++) { const int NId = NI.GetId(); const double DegCentr = UGraph->GetNI(NId).GetDeg(); const double CloCentr = CloseH.GetDat(NId); const double BtwCentr = BtwH.GetDat(NId); const double EigCentr = EigH.GetDat(NId); const double Constraint = NetC.GetNodeC(NId); const double ClustCf = CcfH.GetDat(NId); const double PgrCentr = PRankH.GetDat(NId); const double HubCentr = HubH.GetDat(NId); const double AuthCentr = AuthH.GetDat(NId); fprintf(F, "%d\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n", NId, DegCentr, CloCentr, BtwCentr, EigCentr, Constraint, ClustCf, PgrCentr, HubCentr, AuthCentr); } fclose(F); Catch printf("\nrun time: %s (%s)\n", ExeTm.GetTmStr(), TSecTm::GetCurTm().GetTmStr().CStr()); return 0; }
void PlotSngVec(const PNGraph& Graph, const TStr& FNmPref, TStr DescStr) { TFltV LeftSV, RightSV; TSnap::GetSngVec(Graph, LeftSV, RightSV); LeftSV.Sort(false); RightSV.Sort(false); TFltV BinV; if (DescStr.Empty()) { DescStr = FNmPref; } TGUtil::MakeExpBins(LeftSV, BinV, 1.01); TGnuPlot::PlotValV(BinV, "sngVecL."+FNmPref, TStr::Fmt("%s. G(%d, %d). Left signular vector", DescStr.CStr(), Graph->GetNodes(), Graph->GetEdges()), "Rank", "Component of left singular vector", gpsLog10XY, false, gpwLinesPoints); TGnuPlot::PlotValV(BinV, "sngVecL."+FNmPref, TStr::Fmt("%s. G(%d, %d). Right signular vector", DescStr.CStr(), Graph->GetNodes(), Graph->GetEdges()), "Rank", "Component of right singular vector", gpsLog10XY, false, gpwLinesPoints); }
void TGraphKey::TakeSig(const PNGraph& Graph, const int& MnSvdGraph, const int& MxSvdGraph) { const int Edges = Graph->GetEdges(); Nodes = Graph->GetNodes(); VariantId = 0; SigV.Gen(2+Nodes, 0); // degree sequence TIntPrV DegV(Nodes, 0); for (TNGraph::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) { DegV.Add(TIntPr(NodeI.GetInDeg(), NodeI.GetOutDeg())); } DegV.Sort(false); SigV.Add(TFlt(Nodes)); SigV.Add(TFlt(Edges)); for (int i = 0; i < DegV.Len(); i++) { SigV.Add(DegV[i].Val1()); SigV.Add(DegV[i].Val2()); } // singular values signature // it turns out that it is cheaper to do brute force isomorphism // checking than to calculate SVD and then check isomorphism if (Nodes >= MnSvdGraph && Nodes < MxSvdGraph) { // perform full SVD TFltVV AdjMtx(Nodes+1, Nodes+1); TFltV SngValV; TFltVV LSingV, RSingV; TIntH NodeIdH; // create adjecency matrix for (TNGraph::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) { NodeIdH.AddKey(NodeI.GetId()); } for (TNGraph::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) { const int NodeId = NodeIdH.GetKeyId(NodeI.GetId()) + 1; for (int e = 0; e < NodeI.GetOutDeg(); e++) { const int DstNId = NodeIdH.GetKeyId(NodeI.GetOutNId(e)) + 1; // no self edges if (NodeId != DstNId) AdjMtx.At(NodeId, DstNId) = 1; } } try { // can fail to converge but results seem to be good TSvd::Svd(AdjMtx, LSingV, SngValV, RSingV); } catch(...) { printf("\n***No SVD convergence: G(%d, %d): SngValV.Len():%d\n", Nodes(), Graph->GetEdges(), SngValV.Len()); } // round singular values SngValV.Sort(false); for (int i = 0; i < SngValV.Len(); i++) { SigV.Add(TMath::Round(SngValV[i], RoundTo)); } } //printf("SIG:\n"); for (int i = 0; i < SigV.Len(); i++) { printf("\t%f\n", SigV[i]); } SigV.Pack(); }
void GetGraphs(const vector <TStr>& Parameters, const TStr& ModelGen, const TStr&ModelPlt) { PNGraph G; size_t PSize = Parameters.size(); if (GRAPHGEN >= PSize || MTXGEN >= PSize || KRONGEN >= PSize || KRONFIT >= PSize) Error("GetGraphs", "Wrong index in array of parameters"); GetModel(Parameters[GRAPHGEN], G); if (G->GetNodes() == 0) Error("GetGraphs", "Empty graph"); TFltPrV MDegIn, MDegOut; TSnap::GetInDegCnt(G, MDegIn); TSnap::GetOutDegCnt(G, MDegOut); PlotDegrees(Parameters, MDegIn, MDegOut, "model"); TFile << "Model nodes: " << G->GetNodes() << ", model edges: " << G->GetEdges() << endl; TFile << "Maximum output degree in model graph: " << MDegOut[MDegOut.Len()-1].GetVal1() << endl; TFile << "Maximum input degree in model graph: " << MDegIn[MDegIn.Len()-1].GetVal1() << endl; if (ModelGen == "model+kron"){ // generate (or read) Kronecker initiator matrix TKronMtx FitMtxM; if (!GetMtx(Parameters[MTXGEN], FitMtxM)) GenNewMtx(G, Parameters[KRONFIT], FitMtxM); PrintMtx(FitMtxM, TFile); TFile << "Scaling for the number of edges... " << endl; FitMtxM.SetForEdges(G->GetNodes(), G->GetEdges()); int ModelNodes = G->GetNodes(), ModelEdges = G->GetEdges(); Env = TEnv(Parameters[KRONGEN], TNotify::NullNotify); TStr IsDir = Env.GetIfArgPrefixStr("-isdir:", "false", "Produce directed graph (true, false)"); const TInt NIter = Env.GetIfArgPrefixInt("-i:", 1, "Number of iterations of Kronecker product"); if (pow(FitMtxM.GetDim(), static_cast<double>(NIter)) != ModelNodes) Error("GetGraphs", "Inconsistent value of -i: parameter, KronNodes != ModelNodes"); // in and out average degrees of Kronecker graphs TFltPrV KronDegAvgIn, KronDegAvgOut; GenKron(Parameters[KRONGEN], FitMtxM, KronDegAvgIn, KronDegAvgOut); PlotDegrees(Parameters, KronDegAvgIn, KronDegAvgOut, "kron"); } }
double DirectedModularity(PNGraph& graph, std::vector<int>& communities) { if (graph->GetNodes() != communities.size()) { throw std::logic_error("Number of nodes does not match community size."); } int num_edges = graph->GetEdges(); double score = 0.0; int num_unique = 10; std::map<int, double> outdeg_sums; std::map<int, double> indeg_sums; for (TNGraph::TNodeI node = graph->BegNI(); node < graph->EndNI(); node++) { int comm = communities[node.GetId()]; outdeg_sums[comm] += node.GetOutDeg(); indeg_sums[comm] += node.GetInDeg(); } for (auto& kv : outdeg_sums) { score -= (kv.second / num_edges) * indeg_sums[kv.first]; } for (TNGraph::TNodeI node = graph->BegNI(); node < graph->EndNI(); node++) { int node_ID = node.GetId(); for (int e = 0; e < node.GetOutDeg(); ++e) { int nbr = node.GetOutNId(e); if (communities[node_ID] == communities[nbr]) { score += 1.0; } } } return score / num_edges; }
void analyzeSimNetProps() { const char *eFName = "epidemicRoutingNetEdges.txt"; const char *pFName = "prophetRoutingNetEdges.txt"; PNGraph eGraph = TSnap::LoadEdgeListStr<PNGraph>(eFName, 0, 1); PNEGraph pGraph = TSnap::LoadEdgeListStr<PNEGraph>(pFName, 0, 1); PNGraph randGraph = TSnap::GenRndGnm<PNGraph>(eGraph->GetNodes(), eGraph->GetEdges(), true, TInt::Rnd); chdir("dot"); for (int i=0; i<10; i++) { TIntV NIdV; for (int j = 0; j < 10; j++) { int randNode = eGraph->GetRndNId(); NIdV.AddUnique(randNode); } // Plot the mesage propagtion in Endroy-Renyi graphs PNGraph randFlow = TSnap::GetSubGraph<PNGraph>(randGraph, NIdV); char randf[50]; sprintf(randf,"%d-erdos.dot",i); TSnap::SaveGViz(randFlow, randf, TStr("Edros-Renyi random graph")); // Now plot epidemic routing PNGraph epidemicFlow = TSnap::GetSubGraph<PNGraph>(eGraph, NIdV); char epf[50]; sprintf(epf,"%d-epidemic.dot",i); TSnap::SaveGViz(epidemicFlow, epf, TStr("Epidemic routing")); } }
void TGStat::TakeStat(const PNGraph& Graph, const TSecTm& _Time, TFSet StatFSet, const TStr& GraphName) { printf("\n===TakeStat: G(%u, %u)\n", Graph->GetNodes(), Graph->GetEdges()); TExeTm ExeTm, FullTm; Time = _Time; GraphNm = GraphName; if (StatFSet.In(gsvNone)) { return; } TakeBasicStat(Graph, false); TakeDiam(Graph, StatFSet, false); if (StatFSet.In(gsdWcc) || StatFSet.In(gsdWccHops) || StatFSet.In(gsvFullDiam) || StatFSet.In(gsvEffWccDiam)) { PNGraph WccGraph = TSnap::GetMxWcc(Graph); TakeBasicStat(WccGraph, true); TakeDiam(WccGraph, StatFSet, true); } // degrees TakeDegDistr(Graph, StatFSet); // components TakeConnComp(Graph, StatFSet); // spectral TakeSpectral(Graph, StatFSet, -1); // clustering coeffient if (StatFSet.In(gsdClustCf) || StatFSet.In(gsvClustCf)) { TakeClustCf(Graph); } if (StatFSet.In(gsdTriadPart)) { TakeTriadPart(Graph); } printf(" [%s]\n", FullTm.GetTmStr()); }
void GetSngVec(const PNGraph& Graph, TFltV& LeftSV, TFltV& RightSV) { const int Nodes = Graph->GetNodes(); TFltVV LSingV, RSingV; TFltV SngValV; if (Nodes < 500) { // perform full SVD TFltVV AdjMtx(Nodes+1, Nodes+1); TIntH NodeIdH; // create adjecency matrix for (TNGraph::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) { NodeIdH.AddKey(NodeI.GetId()); } for (TNGraph::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) { const int NodeId = NodeIdH.GetKeyId(NodeI.GetId()) + 1; for (int e = 0; e < NodeI.GetOutDeg(); e++) { const int DstNId = NodeIdH.GetKeyId(NodeI.GetOutNId(e)) + 1; // no self edges if (NodeId != DstNId) AdjMtx.At(NodeId, DstNId) = 1; } } try { // can fail to converge but results seem to be good TSvd::Svd1Based(AdjMtx, LSingV, SngValV, RSingV); } catch(...) { printf("\n***No SVD convergence: G(%d, %d)\n", Nodes, Graph->GetEdges()); } } else { // Lanczos TNGraphMtx GraphMtx(Graph); TSparseSVD::LanczosSVD(GraphMtx, 1, 8, ssotFull, SngValV, LSingV, RSingV); } TFlt MxSngVal = TFlt::Mn; int ValN = 0; for (int i = 0; i < SngValV.Len(); i++) { if (MxSngVal < SngValV[i]) { MxSngVal = SngValV[i]; ValN = i; } } LSingV.GetCol(ValN, LeftSV); RSingV.GetCol(ValN, RightSV); IsAllValVNeg(LeftSV, true); IsAllValVNeg(RightSV, true); }
void analyzeSimNetProps(TStr messGraph, TStr netGraph) { // Make graphs PNGraph eGraph = TSnap::LoadEdgeListStr<PNGraph>(netGraph, 0, 1); PNGraph mGraph = TSnap::LoadEdgeListStr<PNGraph>(messGraph, 0, 1); PNGraph randGraph = TSnap::GenRndGnm<PNGraph>(mGraph->GetNodes(), mGraph->GetEdges(), true, TInt::Rnd); // Induce network graph from the entire network based on message graph TIntV NIdV; for (TNGraph::TNodeI NI = mGraph->BegNI(); NI < mGraph->EndNI(); NI++) NIdV.AddUnique(NI.GetId()); PNGraph indGraph = TSnap::GetSubGraph<PNGraph>(eGraph, NIdV); //printf("%s:: ", messGraph.CStr()); printf("nodes %d; ", indGraph->GetNodes()); //printf("induced edges %d, random edges %d\n", indGraph->GetEdges(), randGraph->GetEdges()); printf("%d\t%d\t%d\n", indGraph->GetNodes(), indGraph->GetEdges(), mGraph->GetEdges()); }
// Test graph conversion TEST(subgraph, TestConvertGraphs) { PNGraph NGraph; PUNGraph UNGraph; NGraph = GetTestTNGraph(); EXPECT_EQ(20,NGraph->GetNodes()); EXPECT_EQ(60,NGraph->GetEdges()); UNGraph = TSnap::ConvertGraph<PUNGraph>(NGraph); EXPECT_EQ(20,UNGraph->GetNodes()); EXPECT_EQ(60,UNGraph->GetEdges()); NGraph = TSnap::ConvertGraph<PNGraph>(UNGraph); EXPECT_EQ(20,NGraph->GetNodes()); EXPECT_EQ(120,NGraph->GetEdges()); }
void SaveAndPlot(const PNGraph& G, const TStr& name, bool isCum){ TFltPrV in, out; TSnap::GetInDegCnt(G, in); TSnap::GetOutDegCnt(G, out); int nodes = G->GetNodes(), edges = G->GetEdges(); TSnap::PlotDegDistr(in, nodes, edges, name, name, isCum, false, true); TSnap::PlotDegDistr(out, nodes, edges, name, name, isCum, false, false); }
void PlotSngValRank(const PNGraph& Graph, const int& SngVals, const TStr& FNmPref, TStr DescStr) { TFltV SngValV; TSnap::GetSngVals(Graph, SngVals, SngValV); SngValV.Sort(false); if (DescStr.Empty()) { DescStr = FNmPref; } TGnuPlot::PlotValV(SngValV, "sngVal."+FNmPref, TStr::Fmt("%s. G(%d, %d). Largest eig val = %f", DescStr.CStr(), Graph->GetNodes(), Graph->GetEdges(), SngValV[0].Val), "Rank", "Singular value", gpsLog10XY, false, gpwLinesPoints); }
void graphson(PNGraph Graph){ std::ofstream graph; graph.open("graph.json"); graph << "{\n"; graph << " \"graph\": {\n"; graph << " " << "\"mode\": \"NORMAL\", \n"; graph << " " << "\"vertices\": [\n"; int i = 0; for (TNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { i++; graph << " " << "{\n"; graph << " " << "\"_id\": \"" << NI.GetId() << "\",\n"; graph << " " << "\"_type\": \"vertex\"\n"; if (i == Graph->GetNodes()) { graph << " " << "}\n"; } else { graph << " " << "},\n"; } } graph << " " << "],\n"; graph << " " << "\"edges\": [\n"; i = 0; printf("Edges: %d", Graph->GetEdges()); for (TNGraph::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) { graph << " " << "{\n" << " " << "\"_id\": \"" << i++ << "\",\n" << " " << "\"_type\": \"edge\"\n" << " " << "\"_outV\": \"" << EI.GetSrcNId() << "\"\n" << " " << "\"_inV\": \""<< EI.GetDstNId() << "\"\n"; if (i == Graph->GetEdges()) graph << " " << "}\n"; else graph << " " << "},\n"; } graph << " " << "]\n"; graph << " " << "}\n"; graph << "}\n"; graph.close(); }
void PrintGraphStat(const PNGraph& G) { PNGraph WCC = TSnap::GetMxWcc(G); PNGraph SCC = TSnap::GetMxScc(G); TFltPrV DegCCfV; int ClosedTriads, OpenTriads, FullDiam; double EffDiam; printf("Nodes\t%d\n", G->GetNodes()); printf("Edges\t%d\n", G->GetEdges()); printf("Nodes in largest WCC\t%d (%.3f)\n", WCC->GetNodes(), WCC->GetNodes()/double(G->GetNodes())); printf("Edges in largest WCC\t%d (%.3f)\n", WCC->GetEdges(), WCC->GetEdges()/double(G->GetEdges())); printf("Nodes in largest SCC\t%d (%.3f)\n", SCC->GetNodes(), SCC->GetNodes()/double(G->GetNodes())); printf("Edges in largest SCC\t%d (%.3f)\n", SCC->GetEdges(), SCC->GetEdges()/double(G->GetEdges())); const double CCF = TSnap::GetClustCf(G, DegCCfV, ClosedTriads, OpenTriads); printf("Average clustering coefficient\t%.4f\n", CCF); printf("Number of triangles\t%d\n", ClosedTriads); printf("Fraction of closed triangles\t%.4g\n", ClosedTriads/double(ClosedTriads+OpenTriads)); TSnap::GetBfsEffDiam(G, 1000, false, EffDiam, FullDiam); printf("Diameter (longest shortest path)\t%d\n", FullDiam); printf("90-percentile effective diameter\t%.2g\n", EffDiam); }
int main(int argc, char* argv[]) { Env = TEnv(argc, argv, TNotify::StdNotify); Env.PrepArgs(TStr::Fmt("Motifs. build: %s, %s. Time: %s", __TIME__, __DATE__, TExeTm::GetCurTm())); TExeTm ExeTm; Try const TStr InFNm = Env.GetIfArgPrefixStr("-i:", "../as20graph.txt", "Input directed graph file (single directed edge per line)"); const int MotifSz = Env.GetIfArgPrefixInt("-m:", 3, "Motif size (has to be 3 or 4)"); const bool DrawMotifs = Env.GetIfArgPrefixBool("-d:", true, "Draw motif shapes (requires GraphViz)"); TStr OutFNm = Env.GetIfArgPrefixStr("-o:", "", "Output file prefix"); if (OutFNm.Empty()) { OutFNm = InFNm.GetFMid(); } EAssert(MotifSz==3 || MotifSz==4); // load graph PNGraph G; if (InFNm.GetFExt().GetLc()==".ungraph") { TFIn FIn(InFNm); G=TSnap::ConvertGraph<PNGraph>(TUNGraph::Load(FIn), true); } else if (InFNm.GetFExt().GetLc()==".ngraph") { TFIn FIn(InFNm); G=TNGraph::Load(FIn); } else { G = TSnap::LoadEdgeList<PNGraph>(InFNm, 0, 1); } bool IsOk = true; for (int nid = 0; nid < G->GetNodes(); nid++) { if (! G->IsNode(nid)) { IsOk=false; break; } } if (! IsOk) { printf("Nodes of the input graph have to be numbered 0...N-1\nRenumbering nodes...\n"); PNGraph OG = G; G = TNGraph::New(); TGraphEnumUtils::GetNormalizedGraph(OG, G); } // G = TSnap::GenRndGnm<PNGraph>(100, Kilo(1)); // count frequency of connected subgraphs in G that have MotifSz nodes TD34GraphCounter GraphCounter(MotifSz); TSubGraphEnum<TD34GraphCounter> GraphEnum; GraphEnum.GetSubGraphs(G, MotifSz, GraphCounter); FILE *F = fopen(TStr::Fmt("%s-counts.tab", OutFNm.CStr()).CStr(), "wt"); fprintf(F, "MotifId\tNodes\tEdges\tCount\n"); for (int i = 0; i < GraphCounter.Len(); i++) { const int gid = GraphCounter.GetId(i); PNGraph SG = GraphCounter.GetGraph(gid); if (DrawMotifs) { TGraphViz::Plot(SG, gvlNeato, TStr::Fmt("%s-motif%03d.gif", OutFNm.CStr(), i), TStr::Fmt("GId:%d Count: %llu", gid, GraphCounter.GetCnt(gid))); } fprintf(F, "%d\t%d\t%d\t%llu\n", gid, SG->GetNodes(), SG->GetEdges(), GraphCounter.GetCnt(gid)); } printf("done."); fclose(F); Catch printf("\nrun time: %s (%s)\n", ExeTm.GetTmStr(), TSecTm::GetCurTm().GetTmStr().CStr()); return 0; }
// Test the default constructor TEST(TNGraph, DefaultConstructor) { PNGraph Graph; Graph = TNGraph::New(); EXPECT_EQ(0,Graph->GetNodes()); EXPECT_EQ(0,Graph->GetEdges()); EXPECT_EQ(1,Graph->IsOk()); EXPECT_EQ(1,Graph->Empty()); EXPECT_EQ(1,Graph->HasFlag(gfDirected)); }
// Test small graph TEST(TNGraph, GetSmallGraph) { PNGraph Graph; Graph = TNGraph::GetSmallGraph(); EXPECT_EQ(5,Graph->GetNodes()); EXPECT_EQ(6,Graph->GetEdges()); EXPECT_EQ(1,Graph->IsOk()); EXPECT_EQ(0,Graph->Empty()); EXPECT_EQ(1,Graph->HasFlag(gfDirected)); }
// Test edge subgraph conversion void TestConvertESubGraphs() { PNEGraph NEGraph; PNGraph NGraph; int N1, N2, N3; int E1, E2, E3; TIntV NIdV; TIntV EIdV; int i; NGraph = GetTestTNGraph(); N1 = NGraph->GetNodes(); E1 = NGraph->GetEdges(); for (i = 0; i < 20; i += 2) { NIdV.Add(i); } // TODO: fix TSnap::ConvertSubGraph<PUNGraph>(NGraph, NIdV, true), it fails // UNGraph = TSnap::ConvertSubGraph<PUNGraph>(NGraph, NIdV, true); NEGraph = TSnap::ConvertGraph<PNEGraph>(NGraph); N2 = NEGraph->GetNodes(); E2 = NEGraph->GetEdges(); // select every second edge i = 0; for (TNEGraph::TEdgeI EI = NEGraph->BegEI(); EI < NEGraph->EndEI(); EI++) { if (i == 0) { EIdV.Add(EI.GetId()); } i = (i + 1) % 2; } NGraph = TSnap::ConvertESubGraph<PNGraph>(NEGraph, EIdV); N3 = NGraph->GetNodes(); E3 = NGraph->GetEdges(); printf("---- TestConvertESubGraphs -----\n"); printf("nodes: %d,%d,%d, edges: %d,%d,%d\n", N1, N2, N3, E1, E2, E3); printf("\n"); }
// Test graph conversion void TestConvertGraphs() { PNGraph NGraph; PUNGraph UNGraph; int N1, N2, N3; int E1, E2, E3; NGraph = GetTestTNGraph(); N1 = NGraph->GetNodes(); E1 = NGraph->GetEdges(); UNGraph = TSnap::ConvertGraph<PUNGraph>(NGraph); N2 = UNGraph->GetNodes(); E2 = UNGraph->GetEdges(); NGraph = TSnap::ConvertGraph<PNGraph>(UNGraph); N3 = NGraph->GetNodes(); E3 = NGraph->GetEdges(); printf("---- TestConvertGraphs -----\n"); printf("nodes: %d,%d,%d, edges: %d,%d,%d\n", N1, N2, N3, E1, E2, E3); printf("\n"); }
void GetSngVals(const PNGraph& Graph, const int& SngVals, TFltV& SngValV) { const int Nodes = Graph->GetNodes(); IAssert(SngVals > 0); if (Nodes < 100) { // perform full SVD TFltVV AdjMtx(Nodes+1, Nodes+1); TFltVV LSingV, RSingV; TIntH NodeIdH; // create adjecency matrix for (TNGraph::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) { NodeIdH.AddKey(NodeI.GetId()); } for (TNGraph::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) { const int NodeId = NodeIdH.GetKeyId(NodeI.GetId()) + 1; for (int e = 0; e < NodeI.GetOutDeg(); e++) { const int DstNId = NodeIdH.GetKeyId(NodeI.GetOutNId(e)) + 1; // no self edges if (NodeId != DstNId) AdjMtx.At(NodeId, DstNId) = 1; } } try { // can fail to converge but results seem to be good TSvd::Svd1Based(AdjMtx, LSingV, SngValV, RSingV); } catch(...) { printf("\n***No SVD convergence: G(%d, %d)\n", Nodes, Graph->GetEdges()); } } else { // Lanczos TNGraphMtx GraphMtx(Graph); int CalcVals = int(2*SngVals); //if (CalcVals > Nodes) { CalcVals = int(2*Nodes); } //if (CalcVals > Nodes) { CalcVals = Nodes; } //while (SngValV.Len() < SngVals && CalcVals < 10*SngVals) { try { if (SngVals > 4) { TSparseSVD::SimpleLanczosSVD(GraphMtx, 2*SngVals, SngValV, false); } else { TFltVV LSingV, RSingV; // this is much more precise, but also much slower TSparseSVD::LanczosSVD(GraphMtx, SngVals, 3*SngVals, ssotFull, SngValV, LSingV, RSingV); } } catch(...) { printf("\n ***EXCEPTION: TRIED %d GOT %d values** \n", 2*SngVals, SngValV.Len()); } if (SngValV.Len() < SngVals) { printf(" ***TRIED %d GOT %d values** \n", CalcVals, SngValV.Len()); } // CalcVals += SngVals; //} } SngValV.Sort(false); //if (SngValV.Len() > SngVals) { // SngValV.Del(SngVals, SngValV.Len()-1); } //else { // while (SngValV.Len() < SngVals) SngValV.Add(1e-6); } //IAssert(SngValV.Len() == SngVals); }
// Test node subgraph conversion TEST(subgraph, TestConvertSubGraphs) { PNGraph NGraph; PUNGraph UNGraph; TIntV NIdV; int i; NGraph = GetTestTNGraph(); EXPECT_EQ(20,NGraph->GetNodes()); EXPECT_EQ(60,NGraph->GetEdges()); for (i = 0; i < 20; i += 2) { NIdV.Add(i); } // TODO: fix TSnap::ConvertSubGraph<PUNGraph>(NGraph, NIdV, true), it fails // UNGraph = TSnap::ConvertSubGraph<PUNGraph>(NGraph, NIdV, true); UNGraph = TSnap::ConvertSubGraph<PUNGraph>(NGraph, NIdV); EXPECT_EQ(10,UNGraph->GetNodes()); EXPECT_EQ(10,UNGraph->GetEdges()); NGraph = TSnap::ConvertSubGraph<PNGraph>(UNGraph, NIdV); EXPECT_EQ(10,NGraph->GetNodes()); EXPECT_EQ(20,NGraph->GetEdges()); }
void GetSngVec(const PNGraph& Graph, const int& SngVecs, TFltV& SngValV, TVec<TFltV>& LeftSV, TVec<TFltV>& RightSV) { const int Nodes = Graph->GetNodes(); SngValV.Clr(); LeftSV.Clr(); RightSV.Clr(); TFltVV LSingV, RSingV; if (Nodes < 100) { // perform full SVD TFltVV AdjMtx(Nodes+1, Nodes+1); TIntH NodeIdH; // create adjecency matrix (1-based) for (TNGraph::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) { NodeIdH.AddKey(NodeI.GetId()); } for (TNGraph::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) { const int NodeId = NodeIdH.GetKeyId(NodeI.GetId())+1; for (int e = 0; e < NodeI.GetOutDeg(); e++) { const int DstNId = NodeIdH.GetKeyId(NodeI.GetOutNId(e))+1; // no self edges if (NodeId != DstNId) AdjMtx.At(NodeId, DstNId) = 1; } } try { // can fail to converge but results seem to be good TSvd::Svd1Based(AdjMtx, LSingV, SngValV, RSingV); } catch(...) { printf("\n***No SVD convergence: G(%d, %d)\n", Nodes, Graph->GetEdges()); } } else { // Lanczos TNGraphMtx GraphMtx(Graph); TSparseSVD::LanczosSVD(GraphMtx, SngVecs, 2*SngVecs, ssotFull, SngValV, LSingV, RSingV); //TGAlg::SaveFullMtx(Graph, "adj_mtx.txt"); //TLAMisc::DumpTFltVVMjrSubMtrx(LSingV, LSingV.GetRows(), LSingV.GetCols(), "LSingV2.txt"); // save MTX } TFltIntPrV SngValIdV; for (int i = 0; i < SngValV.Len(); i++) { SngValIdV.Add(TFltIntPr(SngValV[i], i)); } SngValIdV.Sort(false); SngValV.Sort(false); for (int v = 0; v < SngValIdV.Len(); v++) { LeftSV.Add(); LSingV.GetCol(SngValIdV[v].Val2, LeftSV.Last()); RightSV.Add(); RSingV.GetCol(SngValIdV[v].Val2, RightSV.Last()); } IsAllValVNeg(LeftSV[0], true); IsAllValVNeg(RightSV[0], true); }
// Tests sequential table to graph function. TEST(TTable, ToGraph) { TTableContext Context; Schema LJS; LJS.Add(TPair<TStr,TAttrType>("Src", atInt)); LJS.Add(TPair<TStr,TAttrType>("Dst", atInt)); TIntV RelevantCols; RelevantCols.Add(0); RelevantCols.Add(1); PTable T1 = TTable::LoadSS(LJS, "table/soc-LiveJournal1_small.txt", &Context, RelevantCols); EXPECT_EQ(499, T1->GetNumRows().Val); EXPECT_EQ(499, T1->GetNumValidRows().Val); TVec<TPair<TStr, TAttrType> > S = T1->GetSchema(); PNGraph Graph = TSnap::ToGraph<PNGraph>(T1, S[0].GetVal1(), S[1].GetVal1(), aaFirst); EXPECT_EQ(689,Graph->GetNodes()); EXPECT_EQ(499,Graph->GetEdges()); EXPECT_EQ(1,Graph->IsOk()); }
/// Rewire the network. Keeps node degrees as is but randomly rewires the edges. /// Use this function to generate a random graph with the same degree sequence /// as the OrigGraph. /// See: On the uniform generation of random graphs with prescribed degree /// sequences by R. Milo, N. Kashtan, S. Itzkovitz, M. E. J. Newman, U. Alon. /// URL: http://arxiv.org/abs/cond-mat/0312028 PNGraph GenRewire(const PNGraph& OrigGraph, const int& NSwitch, TRnd& Rnd) { const int Nodes = OrigGraph->GetNodes(); const int Edges = OrigGraph->GetEdges(); PNGraph GraphPt = TNGraph::New(); TNGraph& Graph = *GraphPt; Graph.Reserve(Nodes, -1); TExeTm ExeTm; // generate a graph that satisfies the constraints printf("Randomizing edges (%d, %d)...\n", Nodes, Edges); TIntPrSet EdgeSet(Edges); for (TNGraph::TNodeI NI = OrigGraph->BegNI(); NI < OrigGraph->EndNI(); NI++) { const int NId = NI.GetId(); for (int e = 0; e < NI.GetOutDeg(); e++) { EdgeSet.AddKey(TIntPr(NId, NI.GetOutNId(e))); } Graph.AddNode(NI); } // edge switching uint skip=0; for (uint swps = 0; swps < 2*uint(Edges)*uint(NSwitch); swps++) { const int keyId1 = EdgeSet.GetRndKeyId(Rnd); const int keyId2 = EdgeSet.GetRndKeyId(Rnd); if (keyId1 == keyId2) { skip++; continue; } const TIntPr& E1 = EdgeSet[keyId1]; const TIntPr& E2 = EdgeSet[keyId2]; TIntPr NewE1(E1.Val1, E2.Val1), NewE2(E1.Val2, E2.Val2); if (NewE1.Val1!=NewE2.Val1 && NewE1.Val2!=NewE2.Val1 && NewE1.Val2!=NewE2.Val1 && NewE1.Val2!=NewE2.Val2 && ! EdgeSet.IsKey(NewE1) && ! EdgeSet.IsKey(NewE2)) { EdgeSet.DelKeyId(keyId1); EdgeSet.DelKeyId(keyId2); EdgeSet.AddKey(TIntPr(NewE1)); EdgeSet.AddKey(TIntPr(NewE2)); } else { skip++; } if (swps % Edges == 0) { printf("\r %uk/%uk: %uk skip [%s]", swps/1000u, 2*uint(Edges)*uint(NSwitch)/1000u, skip/1000u, ExeTm.GetStr()); if (ExeTm.GetSecs() > 2*3600) { printf(" *** Time limit!\n"); break; } // time limit 2 hours } } printf("\r total %uk switchings attempted, %uk skiped [%s]\n", 2*uint(Edges)*uint(NSwitch)/1000u, skip/1000u, ExeTm.GetStr()); for (int e = 0; e < EdgeSet.Len(); e++) { Graph.AddEdge(EdgeSet[e].Val1, EdgeSet[e].Val2); } return GraphPt; }
void PlotSngValDistr(const PNGraph& Graph, const int& SngVals, const TStr& FNmPref, TStr DescStr) { const int NBuckets = 50; TFltV SngValV; for (int f = 1; SngValV.Empty() && f < 4; f++) { TSnap::GetSngVals(Graph, f*SngVals, SngValV); } SngValV.Sort(true); THash<TFlt, TFlt> BucketCntH; double Step = (SngValV.Last()-SngValV[0]) / double(NBuckets-1); for (int i = 0; i < NBuckets; i++) { BucketCntH.AddDat(SngValV[0]+Step*(i+0.5), 0); } for (int i = 0; i < SngValV.Len(); i++) { const int Bucket = (int) floor((SngValV[i]-SngValV[0]) / Step); BucketCntH[Bucket] += 1; } TFltPrV EigCntV; BucketCntH.GetKeyDatPrV(EigCntV); if (DescStr.Empty()) { DescStr = FNmPref; } TGnuPlot::PlotValV(EigCntV, "sngDistr."+FNmPref, TStr::Fmt("%s. G(%d, %d). Largest eig val = %f", DescStr.CStr(), Graph->GetNodes(), Graph->GetEdges(), SngValV.Last().Val), "Singular value", "Count", gpsAuto, false, gpwLinesPoints); }
// Test subgraphs TEST(subgraph, TestSubTNGraphs) { PNGraph Graph; PNGraph Graph1; PNGraph Graph2; PNGraph Graph3; PNGraph Graph4; int i; TIntV NIdV; TIntV NIdV1; Graph = GetTestTNGraph(); EXPECT_EQ(20,Graph->GetNodes()); EXPECT_EQ(60,Graph->GetEdges()); for (i = 10; i < 15; i++) { NIdV.Add(i); } Graph1 = TSnap::GetSubGraph(Graph, NIdV); EXPECT_EQ(5,Graph1->GetNodes()); EXPECT_EQ(9,Graph1->GetEdges()); Graph2 = TSnap::GetSubGraph(Graph, NIdV, true); EXPECT_EQ(5,Graph2->GetNodes()); EXPECT_EQ(9,Graph2->GetEdges()); for (i = 0; i < 20; i += 2) { NIdV1.Add(i); } Graph3 = TSnap::GetSubGraph(Graph, NIdV1, true); EXPECT_EQ(10,Graph3->GetNodes()); EXPECT_EQ(10,Graph3->GetEdges()); Graph4 = TSnap::GetSubGraphRenumber(Graph, NIdV1); EXPECT_EQ(10,Graph4->GetNodes()); EXPECT_EQ(10,Graph4->GetEdges()); }
// Print graph statistics void PrintGStats(const char s[], PNGraph Graph) { printf("graph %s, nodes %d, edges %d, empty %s\n", s, Graph->GetNodes(), Graph->GetEdges(), Graph->Empty() ? "yes" : "no"); }