//! Given pGraph with data about edge weights, computes the distance of the shortest paths from sourceNode //! and returns the result in the nodes of pDAGGraph. //! Updates the edges if bUpdateEdges is set to true. Default is false. In that case only the node data is updated with the shortest distance to sourceNode. //! @note Requires initial values for the nodes of pDAGGraph (edges are not needed) void Dijkstra(const TPt<TNodeEDatNet<TFlt, TFlt>>& pGraph, int sourceNode, double dThreshold, TPt<TNodeEDatNet<TFlt, TFlt>>& pDAGGraph, bool bUpdateEdges = false) { double logThreshold = log(dThreshold); if(dThreshold==0) logThreshold=-DBL_MAX; // List of visited nodes std::map<int, bool> visitedNodes; // Stores the edge vertices to build the final DAG std::map<int, int> mapPrevious; std::priority_queue<std::pair<int,double>, std::vector<std::pair<int,double>>, Order> nodesToVisit; // Distance from source node to itself is 0 pDAGGraph->SetNDat(sourceNode, 0); nodesToVisit.push(std::make_pair(sourceNode,0)); // Beginning of the loop of Dijkstra algorithm while(!nodesToVisit.empty()) { // Find the vertex in queue with the smallest distance and remove it int iParentID = -1; while (!nodesToVisit.empty() && visitedNodes[iParentID = nodesToVisit.top().first]) nodesToVisit.pop(); if (iParentID == -1) break; // mark the vertex with the shortest distance visitedNodes[iParentID]=true; auto parent = pGraph->GetNI(iParentID); int numChildren = parent.GetOutDeg(); for(int i = 0; i < numChildren; ++i) { int iChildID = parent.GetOutNId(i); // Accumulate the shortest distance from source double alt = pDAGGraph->GetNDat(iParentID) - log(parent.GetOutEDat(i).Val); if(alt >= logThreshold) { auto it = visitedNodes.find(iChildID); if (alt < pDAGGraph->GetNDat(iChildID) && it->second == false) { //1. update distance //2. update the predecessor //3. push new shortest rank of chidren nodes pDAGGraph->SetNDat(iChildID, alt); mapPrevious[iChildID]= iParentID; nodesToVisit.push(std::make_pair(iChildID,alt)); } } } } if(bUpdateEdges) for(auto it=mapPrevious.begin(); it!= mapPrevious.end(); ++it) { pDAGGraph->AddEdge(it->second, it->first); pDAGGraph->SetEDat(it->second,it->first, pGraph->GetEDat(it->second,it->first)); } }
TPt<TNodeEDatNet<TFlt, TFlt>> GenerateDAG1(const TPt<TNodeEDatNet<TFlt, TFlt>> &pGraph, const std::vector<int>& seedNodes, double threshold) { // Copy pGraph into pGraph_DAG1 auto pGraph_DAG1 = TNodeEDatNet<TFlt, TFlt>::New(); for (auto NI = pGraph->BegNI(); NI < pGraph->EndNI(); NI++) pGraph_DAG1->AddNode(NI.GetId()); for (auto EI = pGraph->BegEI(); EI < pGraph->EndEI(); EI++) { pGraph_DAG1->AddEdge(EI.GetSrcNId(),EI.GetDstNId()); pGraph_DAG1->SetEDat(EI.GetSrcNId(),EI.GetDstNId(), pGraph->GetEDat(EI.GetSrcNId(),EI.GetDstNId())); } // Create a super root in order to update in one pass all the shortest paths from vSeedIDs nodes int superRootID = pGraph_DAG1->GetMxNId()+1; pGraph_DAG1->AddNode(superRootID); for(int srcNode: seedNodes) { pGraph_DAG1->AddEdge(superRootID, srcNode); pGraph_DAG1->SetEDat(superRootID, srcNode, 1.0); } pGraph_DAG1 = MIOA(pGraph_DAG1, superRootID, threshold); // Remove the artificial super root node pGraph_DAG1->DelNode(superRootID); // Add back other edges with the condition r(u)<r(v) for (auto EI = pGraph->BegEI(); EI < pGraph->EndEI(); EI++) { int u = EI.GetSrcNId(), v = EI.GetDstNId(); if(pGraph_DAG1->GetNDat(u)< pGraph_DAG1->GetNDat(v)) { if (!pGraph_DAG1->IsEdge(u,v)) { pGraph_DAG1->AddEdge(u,v); pGraph_DAG1->SetEDat(u,v,EI.GetDat()); } } } //Reset Node data from the original graph for (auto NI = pGraph->BegNI(); NI < pGraph->EndNI(); NI++) pGraph_DAG1->SetNDat(NI.GetId(),NI.GetDat().Val); return pGraph_DAG1; }
//??????? TPt<TNodeEDatNet<TFlt, TFlt>> GenerateDAG2(const TPt<TNodeEDatNet<TFlt, TFlt>>& pGraph, const std::vector<int> &vSeedIDs, double dThreshold) { // Vector of MIOA graphs per seed node std::vector<TPt<TNodeEDatNet<TFlt, TFlt>>> vMIOAGraphs; // Compute the union of MIOA for each node of vSeedIDs for(auto it=vSeedIDs.begin(); it!=vSeedIDs.end(); ++it) vMIOAGraphs.push_back(MIOA(pGraph, *it, dThreshold)); auto pOut = GraphUnion(vMIOAGraphs); // Set node data for (auto NI = pOut->BegNI(); NI < pOut->EndNI(); NI++) pOut->SetNDat(NI.GetId(), FLT_MAX); // Copy the edge weights from pGraph for (auto EI = pOut->BegEI(); EI < pOut->EndEI(); EI++) pOut->SetEDat(EI.GetSrcNId(), EI.GetDstNId(), pGraph->GetEDat(EI.GetSrcNId(), EI.GetDstNId())); // Create a super root in order to update in one pass all the shortest paths from vSeedIDs nodes int superRootID = pGraph->GetMxNId()+1; pOut->AddNode(superRootID); for(auto it=vSeedIDs.begin(); it!=vSeedIDs.end(); ++it) { pOut->AddEdge(superRootID, *it); pOut->SetEDat(superRootID, *it, 1.0); } Dijkstra(pOut, superRootID, dThreshold, pOut); // Remove the artificial super root node pOut->DelNode(superRootID); // Traverse the edges and prune the graph for (auto EI = pOut->BegEI(); EI < pOut->EndEI(); EI++) { if(EI.GetDstNDat().Val < EI.GetSrcNDat().Val) pOut->DelEdge(EI.GetSrcNId(), EI.GetDstNId()); } //Reset Node data from the original graph for (auto NI = pGraph->BegNI(); NI < pGraph->EndNI(); NI++) pOut->SetNDat(NI.GetId(),NI.GetDat().Val); return pOut; }
// Test edge data sorting TEST(TNodeEdgeNet, SortEdgeData) { int NNodes = 10000; int NEdges = 100000; TPt <TNodeEdgeNet<TInt, TInt> > Net; TPt <TNodeEdgeNet<TInt, TInt> > Net1; TPt <TNodeEdgeNet<TInt, TInt> > Net2; int i; int n; int x,y; bool Sorted; int Min; int Value; Net = TNodeEdgeNet<TInt, TInt>::New(); EXPECT_EQ(1,Net->Empty()); // create the nodes with node data x*x % NNodes for (i = 0; i < NNodes; i++) { x = (i*13) % NNodes; Net->AddNode(x, (x*x) % NNodes); } EXPECT_EQ(0,Net->Empty()); EXPECT_EQ(NNodes,Net->GetNodes()); // create random edges with edge data x*y % NEdges for (i = 0; i < NEdges; i++) { x = (long) (drand48() * NNodes); y = (long) (drand48() * NNodes); n = Net->AddEdge(x, y, (i*37) % NEdges, (x*y) % NEdges); } EXPECT_EQ(NEdges,Net->GetEdges()); EXPECT_EQ(0,Net->Empty()); EXPECT_EQ(1,Net->IsOk()); for (i = 0; i < NNodes; i++) { EXPECT_EQ(1,Net->IsNode(i)); } EXPECT_EQ(0,Net->IsNode(NNodes)); EXPECT_EQ(0,Net->IsNode(NNodes+1)); EXPECT_EQ(0,Net->IsNode(2*NNodes)); // test node data for (TNodeEdgeNet<TInt, TInt>::TNodeI NI = Net->BegNI(); NI < Net->EndNI(); NI++) { EXPECT_EQ((NI.GetId()*NI.GetId()) % NNodes, Net->GetNDat(NI.GetId())); } // test edge data for (TNodeEdgeNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { EXPECT_EQ((EI.GetSrcNId()*EI.GetDstNId()) % NEdges, Net->GetEDat(EI.GetId())); } // test sorting of edge IDs (unsorted) Min = -1; Sorted = true; for (TNodeEdgeNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { Value = EI.GetId(); if (Min > Value) { Sorted = false; } Min = Value; } EXPECT_EQ(false,Sorted); // sort the nodes by edge IDs (sorted) Net->SortEIdById(); // test sorting of edge IDs Min = -1; Sorted = true; for (TNodeEdgeNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { Value = EI.GetId(); if (Min > Value) { Sorted = false; } Min = Value; } EXPECT_EQ(true,Sorted); // test sorting of edge data (unsorted) Min = -1; Sorted = true; for (TNodeEdgeNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { Value = Net->GetEDat(EI.GetId()); if (Min > Value) { Sorted = false; } Min = Value; } EXPECT_EQ(false,Sorted); // sort the nodes by edge data Net->SortEIdByDat(); // test sorting of edge data (sorted) Min = -1; Sorted = true; for (TNodeEdgeNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { Value = Net->GetEDat(EI.GetId()); if (Min > Value) { Sorted = false; } Min = Value; } EXPECT_EQ(true,Sorted); // test sorting of edge IDs (unsorted) Min = -1; Sorted = true; for (TNodeEdgeNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { Value = EI.GetId(); if (Min > Value) { Sorted = false; } Min = Value; } EXPECT_EQ(false,Sorted); // test edge data for (TNodeEdgeNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { EXPECT_EQ((EI.GetSrcNId()*EI.GetDstNId()) % NEdges, Net->GetEDat(EI.GetId())); } // test node data for (TNodeEdgeNet<TInt, TInt>::TNodeI NI = Net->BegNI(); NI < Net->EndNI(); NI++) { EXPECT_EQ((NI.GetId()*NI.GetId()) % NNodes, Net->GetNDat(NI.GetId())); } }
// Test update edge data TEST(TNodeEdgeNet, UpdateEdgeData) { int NNodes = 10000; int NEdges = 100000; TPt <TNodeEdgeNet<TInt, TInt> > Net; TPt <TNodeEdgeNet<TInt, TInt> > Net1; TPt <TNodeEdgeNet<TInt, TInt> > Net2; int i; int n; int NCount; int x,y; Net = TNodeEdgeNet<TInt, TInt>::New(); EXPECT_EQ(1,Net->Empty()); // create the nodes for (i = 0; i < NNodes; i++) { Net->AddNode(i); } EXPECT_EQ(0,Net->Empty()); EXPECT_EQ(NNodes,Net->GetNodes()); // create random edges and edge data x+y+10 NCount = NEdges; while (NCount > 0) { x = (long) (drand48() * NNodes); y = (long) (drand48() * NNodes); n = Net->AddEdge(x, y, -1, x+y+10); // printf("0a %d %d %d\n",x,y,n); NCount--; } EXPECT_EQ(NEdges,Net->GetEdges()); EXPECT_EQ(0,Net->Empty()); EXPECT_EQ(1,Net->IsOk()); for (i = 0; i < NNodes; i++) { EXPECT_EQ(1,Net->IsNode(i)); } EXPECT_EQ(0,Net->IsNode(NNodes)); EXPECT_EQ(0,Net->IsNode(NNodes+1)); EXPECT_EQ(0,Net->IsNode(2*NNodes)); // add data to nodes, square of node ID for (TNodeEdgeNet<TInt, TInt>::TNodeI NI = Net->BegNI(); NI < Net->EndNI(); NI++) { Net->SetNDat(NI.GetId(), NI.GetId()*NI.GetId()); } // test node data for (TNodeEdgeNet<TInt, TInt>::TNodeI NI = Net->BegNI(); NI < Net->EndNI(); NI++) { EXPECT_EQ(NI.GetId()*NI.GetId(), Net->GetNDat(NI.GetId())); } // verify edge data, x+y+10 for (TNodeEdgeNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { EXPECT_EQ(EI.GetSrcNId()+EI.GetDstNId()+10, Net->GetEDat(EI.GetId())); } // update edge data, x+y+5 for (TNodeEdgeNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { Net->SetEDat(EI.GetId(),EI.GetSrcNId()+EI.GetDstNId()+5); } // verify edge data, x+y+5 for (TNodeEdgeNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { EXPECT_EQ(EI.GetSrcNId()+EI.GetDstNId()+5, Net->GetEDat(EI.GetId())); } // test node data again for (TNodeEdgeNet<TInt, TInt>::TNodeI NI = Net->BegNI(); NI < Net->EndNI(); NI++) { EXPECT_EQ(NI.GetId()*NI.GetId(), Net->GetNDat(NI.GetId())); } }
// Test update edge data void UpdateEdgeData() { int NNodes = 10000; int NEdges = 100000; TPt <TNodeEDatNet<TInt, TInt> > Net; TPt <TNodeEDatNet<TInt, TInt> > Net1; TPt <TNodeEDatNet<TInt, TInt> > Net2; int i; int n; int NCount; int x,y; bool t; int SrcNId; int DstNId; int EdgeDat; int Value; bool ok; Net = TNodeEDatNet<TInt, TInt>::New(); t = Net->Empty(); // create the nodes for (i = 0; i < NNodes; i++) { Net->AddNode(i); } t = Net->Empty(); n = Net->GetNodes(); // create random edges and edge data x+y+10 NCount = NEdges; while (NCount > 0) { x = (long) (drand48() * NNodes); y = (long) (drand48() * NNodes); // Net->GetEdges() is not correct for the loops (x == y), // skip the loops in this test if (x != y && !Net->IsEdge(x,y)) { n = Net->AddEdge(x, y, x+y+10); NCount--; } } PrintNStats("UpdateEdgeData:Net", Net); // verify edge data, x+y+10 ok = true; for (TNodeEDatNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { SrcNId = EI.GetSrcNId(); DstNId = EI.GetDstNId(); EdgeDat = Net->GetEDat(SrcNId, DstNId); Value = SrcNId+DstNId+10; if (EdgeDat != Value) { ok = false; } } printf("network UpdateEdgeData:Net, status1 %s\n", (ok == true) ? "ok" : "ERROR"); // update edge data, x+y+5 for (TNodeEDatNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { Net->SetEDat(EI.GetSrcNId(),EI.GetDstNId(),EI.GetSrcNId()+EI.GetDstNId()+5); } // verify edge data, x+y+5 ok = true; for (TNodeEDatNet<TInt, TInt>::TEdgeI EI = Net->BegEI(); EI < Net->EndEI(); EI++) { SrcNId = EI.GetSrcNId(); DstNId = EI.GetDstNId(); EdgeDat = Net->GetEDat(SrcNId, DstNId); Value = SrcNId+DstNId+5; if (EdgeDat != Value) { ok = false; } } printf("network UpdateEdgeData:Net, status2 %s\n", (ok == true) ? "ok" : "ERROR"); }