private KeyDat <int, int>[] GetShortestPaths(IEnumerable <int> src_vtx) { Set <KeyDat <int, int> > visited = new Set <KeyDat <int, int> >(); foreach (int item in src_vtx) { visited.Add(new KeyDat <int, int>(item, 0)); } Queue <KeyDat <int, int> > queue = new Queue <KeyDat <int, int> >(visited); while (queue.Count > 0) { KeyDat <int, int> vtx_kd = queue.Dequeue(); SparseVector <double> vtx_info = m_mtx[vtx_kd.Key]; if (vtx_info != null) { foreach (IdxDat <double> item in vtx_info) { if (!visited.Contains(new KeyDat <int, int>(item.Idx))) { KeyDat <int, int> new_vtx_kd = new KeyDat <int, int>(item.Idx, vtx_kd.Dat + 1); visited.Add(new_vtx_kd); queue.Enqueue(new_vtx_kd); } } } } return(visited.ToArray()); }
// *** IEquatable<KeyDat<KeyT, DatT>> interface implementation *** public bool Equals(KeyDat <KeyT, DatT> other) { return(other.mKey.Equals(mKey)); }
// *** IComparable<KeyDat<KeyT, DatT>> interface implementation *** public int CompareTo(KeyDat <KeyT, DatT> other) { return(mKey.CompareTo(other.Key)); }
public double[] PageRank(IEnumerable <int> src_vtx_list, double damping, int max_steps, double eps, double[] init_pr, bool no_bounding, SparseMatrix <double> .ReadOnly inlinks) { Utils.ThrowException((m_vtx.Count == 0 || !HasPositiveEdges()) ? new InvalidOperationException() : null); Utils.ThrowException((damping < 0 || damping >= 1) ? new ArgumentOutOfRangeException("damping") : null); Utils.ThrowException(max_steps <= 0 ? new ArgumentOutOfRangeException("max_steps") : null); Utils.ThrowException(eps < 0 ? new ArgumentOutOfRangeException("eps") : null); Utils.ThrowException((init_pr != null && init_pr.Length != m_vtx.Count) ? new ArgumentValueException("init_pr") : null); // *** inlinks needs to be the transposed form of this.Edges; to check if this is true, uncomment the following line //Utils.ThrowException((inlinks != null && !((SparseMatrix<double>.ReadOnly)m_mtx.GetTransposedCopy()).ContentEquals(inlinks)) ? new ArgumentValueException("inlinks") : null); int src_vtx_count = 0; if (src_vtx_list != null) { foreach (int src_vtx_idx in src_vtx_list) { src_vtx_count++; Utils.ThrowException((src_vtx_idx < 0 || src_vtx_idx >= m_vtx.Count) ? new ArgumentOutOfRangeException("src_vtx_list item") : null); } } // precompute weight sums double[] wgt_sum = new double[m_vtx.Count]; for (int i = 0; i < m_vtx.Count; i++) { wgt_sum[i] = 0; if (m_mtx[i] != null) { foreach (IdxDat <double> other_vtx in m_mtx[i]) { wgt_sum[i] += other_vtx.Dat; } } } // initialize rank_vec double[] rank_vec = new double[m_vtx.Count]; if (init_pr != null) { double rank_sum = 0; foreach (double val in init_pr) { rank_sum += val; Utils.ThrowException(val < 0 ? new ArgumentOutOfRangeException("init_pr item") : null); } Utils.ThrowException(rank_sum == 0 ? new ArgumentValueException("init_pr") : null); for (int vtx_idx = 0; vtx_idx < m_vtx.Count; vtx_idx++) { rank_vec[vtx_idx] = init_pr[vtx_idx] / rank_sum; } } else { if (src_vtx_count == 0) { double init_rank = 1.0 / (double)m_vtx.Count; for (int vtx_idx = 0; vtx_idx < m_vtx.Count; vtx_idx++) { rank_vec[vtx_idx] = init_rank; } } else { double init_rank = 1.0 / (double)src_vtx_count; for (int vtx_idx = 0; vtx_idx < m_vtx.Count; vtx_idx++) { rank_vec[vtx_idx] = 0; } foreach (int src_vtx_idx in src_vtx_list) { rank_vec[src_vtx_idx] = init_rank; } } } // transpose adjacency matrix if (inlinks == null) { inlinks = m_mtx.GetTransposedCopy(); } // compute shortest paths KeyDat <int, int>[] vtx_info = null; if (src_vtx_count > 0 && !no_bounding) { KeyDat <int, int>[] tmp = GetShortestPaths(src_vtx_list); vtx_info = new KeyDat <int, int> [tmp.Length]; int i = 0; foreach (KeyDat <int, int> item in tmp) { vtx_info[i++] = new KeyDat <int, int>(item.Dat, item.Key); } Array.Sort(vtx_info); } // main loop int step = 0; double diff; do { //DateTime then = DateTime.Now; // compute new Page Rank for each vertex double[] new_rank_vec = new double[m_vtx.Count]; if (src_vtx_count == 0 || no_bounding) { for (int vtx_idx = 0; vtx_idx < m_vtx.Count; vtx_idx++) { double new_rank = 0; if (inlinks.ContainsRowAt(vtx_idx)) { foreach (IdxDat <double> other_vtx in inlinks[vtx_idx]) { new_rank += other_vtx.Dat / wgt_sum[other_vtx.Idx] * (double)rank_vec[other_vtx.Idx]; } } new_rank_vec[vtx_idx] = new_rank; } } else { for (int i = 0; i < vtx_info.Length && (init_pr != null || vtx_info[i].Key <= step + 1); i++) { int vtx_idx = vtx_info[i].Dat; double new_rank = 0; if (inlinks.ContainsRowAt(vtx_idx)) { foreach (IdxDat <double> other_vtx in inlinks[vtx_idx]) { new_rank += other_vtx.Dat / wgt_sum[other_vtx.Idx] * (double)rank_vec[other_vtx.Idx]; } } new_rank_vec[vtx_idx] = new_rank; } } // normalize new_rank_vec by distributing (1.0 - rank_sum) to source vertices double rank_sum = 0; for (int i = 0; i < new_rank_vec.Length; i++) { rank_sum += new_rank_vec[i]; } if (rank_sum <= 0.999999) { if (src_vtx_count == 0) { double distr_rank = (1.0 - rank_sum) / (double)m_vtx.Count; for (int i = 0; i < new_rank_vec.Length; i++) { new_rank_vec[i] += distr_rank; } } else { double distr_rank = (1.0 - rank_sum) / (double)src_vtx_count; foreach (int src_vtx_idx in src_vtx_list) { new_rank_vec[src_vtx_idx] += distr_rank; } } } // incorporate damping factor if (src_vtx_count == 0) { double distr_rank = (1.0 - damping) / (double)m_vtx.Count; for (int i = 0; i < new_rank_vec.Length; i++) { new_rank_vec[i] = damping * new_rank_vec[i] + distr_rank; } } else { double distr_rank = (1.0 - damping) / (double)src_vtx_count; for (int i = 0; i < new_rank_vec.Length; i++) { new_rank_vec[i] = damping * new_rank_vec[i]; } foreach (int src_vtx_idx in src_vtx_list) { new_rank_vec[src_vtx_idx] += distr_rank; } } // compute difference diff = 0; for (int i = 0; i < m_vtx.Count; i++) { diff += Math.Abs(rank_vec[i] - new_rank_vec[i]); } rank_vec = new_rank_vec; step++; //Console.WriteLine("Step {0}\tTime {1}", step, (DateTime.Now - then).TotalMilliseconds); } while (step < max_steps && diff > eps); return(rank_vec); }