int GetWeightedPageRankMP1(const PNEANet Graph, TIntFltH& PRankH, const TStr& Attr, const double& C, const double& Eps, const int& MaxIter) { if (!Graph->IsFltAttrE(Attr)) return -1; TFltV Weights = Graph->GetFltAttrVecE(Attr); int mxid = Graph->GetMxNId(); TFltV OutWeights(mxid); Graph->GetWeightOutEdgesV(OutWeights, Weights); /*for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { OutWeights[NI.GetId()] = Graph->GetWeightOutEdges(NI, Attr); }*/ /*TIntFltH Weights; for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { Weights.AddDat(NI.GetId(), Graph->GetWeightOutEdges(NI, Attr)); }*/ const int NNodes = Graph->GetNodes(); TVec<TNEANet::TNodeI> NV; //const double OneOver = 1.0/double(NNodes); PRankH.Gen(NNodes); for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { NV.Add(NI); PRankH.AddDat(NI.GetId(), 1.0/NNodes); //IAssert(NI.GetId() == PRankH.GetKey(PRankH.Len()-1)); } TFltV TmpV(NNodes); for (int iter = 0; iter < MaxIter; iter++) { #pragma omp parallel for schedule(dynamic,10000) for (int j = 0; j < NNodes; j++) { TNEANet::TNodeI NI = NV[j]; TmpV[j] = 0; for (int e = 0; e < NI.GetInDeg(); e++) { const int InNId = NI.GetInNId(e); const TFlt OutWeight = OutWeights[InNId]; int EId = Graph->GetEId(InNId, NI.GetId()); const TFlt Weight = Weights[Graph->GetFltKeyIdE(EId)]; if (OutWeight > 0) { TmpV[j] += PRankH.GetDat(InNId) * Weight / OutWeight; } } TmpV[j] = C*TmpV[j]; // Berkhin (the correct way of doing it) //TmpV[j] = C*TmpV[j] + (1.0-C)*OneOver; // iGraph } double diff=0, sum=0, NewVal; #pragma omp parallel for reduction(+:sum) schedule(dynamic,10000) for (int i = 0; i < TmpV.Len(); i++) { sum += TmpV[i]; } const double Leaked = (1.0-sum) / double(NNodes); #pragma omp parallel for reduction(+:diff) schedule(dynamic,10000) for (int i = 0; i < PRankH.Len(); i++) { // re-instert leaked PageRank NewVal = TmpV[i] + Leaked; // Berkhin //NewVal = TmpV[i] / sum; // iGraph diff += fabs(NewVal-PRankH[i]); PRankH[i] = NewVal; } if (diff < Eps) { break; } } return 0; }
/// Removes any gaps in node labels. ##TPRManager::CheckGap void CheckGap (int GapLabel) { for (TNEANet::TNodeI NI = Net->BegNI(); NI != Net->EndNI(); NI++) { int NId = NI.GetId(); int OldLabel = LabelsV[NId]; if (OldLabel > GapLabel && OldLabel <= LabelLimit) { LabelsV[NId] = MaxLabel; LabelCounts[OldLabel]--; LabelCounts[MaxLabel]++; if (IsActive(NId)) { RemoveActive(NId); } } } LabelLimit = GapLabel - 1; }
TPRManager(PNEANet &Net) : Net(Net), CapIndex(0), FlowV(Net->GetMxEId()), ExcessV(Net->GetMxNId()), EdgeNumsV(Net->GetMxNId()), LabelsV(Net->GetMxNId()), LabelCounts(Net->GetNodes() + 1), LabelLimit(0), MaxLabel(Net->GetNodes()), ActiveNodeSet(Net->GetMxNId()), ActiveCount(0) { CapIndex = Net->GetIntAttrIndE(CapAttrName); for (int i = 0; i <= Net->GetNodes(); i++) { LabelCounts[i] = 0; } for (TNEANet::TEdgeI EI = Net->BegEI(); EI != Net->EndEI(); EI++) { int EId = EI.GetId(); IAssert(Capacity(EId) >= 0); FlowV[EId] = 0; } for (TNEANet::TNodeI NI = Net->BegNI(); NI != Net->EndNI(); NI++) { int NId = NI.GetId(); ExcessV[NId] = 0; EdgeNumsV[NId] = 0; ActiveNodeSet[NId] = 0; } LabelCounts[0] = Net->GetNodes(); }
/// Implements the Global Relabeling heuristic. ##TSnap::GlobalRelabel void GlobalRelabel (PNEANet &Net, TPRManager &PRM, const int& SrcNId, const int& SnkNId) { TIntQ NodeQ; int size = Net->GetMxNId(); TIntV NodeV(size); for (int i = 0; i < size; i++) { NodeV[i] = 0; } NodeQ.Push(SnkNId); NodeV[SnkNId] = 1; int MaxLabel = PRM.GetMaxLabel(); while (!NodeQ.Empty()) { // Backward search int NId = NodeQ.Top(); NodeQ.Pop(); const TNEANet::TNodeI &NI = Net->GetNI(NId); // Check all edges that point out of the current node for those over which flow can be returned. for (int EdgeN = 0; EdgeN < NI.GetOutDeg(); EdgeN++) { int OutNId = NI.GetOutNId(EdgeN); int EId = NI.GetOutEId(EdgeN); if (!NodeV[OutNId] && PRM.Flow(EId) > 0) { NodeV[OutNId] = 1; NodeQ.Push(OutNId); PRM.SetLabel(OutNId, PRM.Label(NId) + 1); } } // Check all edges that point into the current node for those over which flow can be added. for (int EdgeN = 0; EdgeN < NI.GetInDeg(); EdgeN++) { int InNId = NI.GetInNId(EdgeN); int EId = NI.GetInEId(EdgeN); if (!NodeV[InNId] && PRM.Capacity(EId) > PRM.Flow(EId)) { NodeV[InNId] = 1; NodeQ.Push(InNId); PRM.SetLabel(InNId, PRM.Label(NId) + 1); } } } for (TNEANet::TNodeI NI = Net->BegNI(); NI != Net->EndNI(); NI++) { int NId = NI.GetId(); if (NodeV[NId]) { if (PRM.Excess(NId) > 0 && PRM.Label(NId) < MaxLabel && NId != SnkNId) { if (!PRM.IsActive(NId)) { PRM.PushActive(NId); } } } else { if (PRM.IsActive(NId)) { PRM.RemoveActive(NId); } PRM.SetLabel(NId, MaxLabel); } } }
int GetWeightedPageRankMP2(const PNEANet Graph, TIntFltH& PRankH, const TStr& Attr, const double& C, const double& Eps, const int& MaxIter) { if (!Graph->IsFltAttrE(Attr)) return -1; const int NNodes = Graph->GetNodes(); TVec<TNEANet::TNodeI> NV; //const double OneOver = 1.0/double(NNodes); PRankH.Gen(NNodes); int MxId; for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { NV.Add(NI); PRankH.AddDat(NI.GetId(), 1.0/NNodes); int Id = NI.GetId(); if (Id > MxId) { MxId = Id; } } TFltV PRankV(MxId+1); TFltV OutWeights(MxId+1); TFltV Weights = Graph->GetFltAttrVecE(Attr); #pragma omp parallel for schedule(dynamic,10000) for (int j = 0; j < NNodes; j++) { TNEANet::TNodeI NI = NV[j]; int Id = NI.GetId(); OutWeights[Id] = Graph->GetWeightOutEdges(NI, Attr); PRankV[Id] = 1/NNodes; } TFltV TmpV(NNodes); for (int iter = 0; iter < MaxIter; iter++) { #pragma omp parallel for schedule(dynamic,10000) for (int j = 0; j < NNodes; j++) { TNEANet::TNodeI NI = NV[j]; TFlt Tmp = 0; for (int e = 0; e < NI.GetInDeg(); e++) { const int InNId = NI.GetInNId(e); const TFlt OutWeight = OutWeights[InNId]; int EId = Graph->GetEId(InNId, NI.GetId()); const TFlt Weight = Weights[Graph->GetFltKeyIdE(EId)]; if (OutWeight > 0) { Tmp += PRankH.GetDat(InNId) * Weight / OutWeight; } } TmpV[j] = C*Tmp; // Berkhin (the correct way of doing it) //TmpV[j] = C*TmpV[j] + (1.0-C)*OneOver; // iGraph } double sum = 0; #pragma omp parallel for reduction(+:sum) schedule(dynamic,10000) for (int i = 0; i < TmpV.Len(); i++) { sum += TmpV[i]; } const double Leaked = (1.0-sum) / double(NNodes); double diff = 0; #pragma omp parallel for reduction(+:diff) schedule(dynamic,10000) for (int i = 0; i < NNodes; i++) { TNEANet::TNodeI NI = NV[i]; double NewVal = TmpV[i] + Leaked; // Berkhin //NewVal = TmpV[i] / sum; // iGraph int Id = NI.GetId(); diff += fabs(NewVal-PRankV[Id]); PRankV[Id] = NewVal; } if (diff < Eps) { break; } } #pragma omp parallel for schedule(dynamic,10000) for (int i = 0; i < NNodes; i++) { TNEANet::TNodeI NI = NV[i]; PRankH[i] = PRankV[NI.GetId()]; } return 0; }