lib/rgraph/graph.rb in rgraph-0.0.13 vs lib/rgraph/graph.rb in rgraph-0.0.14
- old
+ new
@@ -50,44 +50,43 @@
def average_degree
degrees.inject(:+) / @nodes.size.to_f
end
def cumulative_degree
- cached_degrees = degrees
- out = []
-
- 0.upto(degrees.max - 1) do |i|
- out[i] = cached_degrees.select{|degree| degree > i}.count
- end
+ out = (0..(degrees.max - 1)).map { |i| degrees.select{|degree| degree > i}.count }
out.map{|a| a / out.max.to_f}
end
def idistance
- dist = Array.new(@nodes.size) { Array.new(@nodes.size, 0) }
+ dist = matrix(@nodes.size, 0)
- @nodes.sort{|a,b| a.id <=> b.id}.each_with_index do |n1, i|
- @nodes.sort{|a,b| a.id <=> b.id}.each_with_index do |n2, j|
- if i != j
- dist[i][j] = n1.neighbours.include?(n2) ? @links.select{ |link| (link.source == n1 || link.source == n2) && (link.target == n1 || link.target == n2) }.first.weight.to_i : @infinity
- end
+ sorted = @nodes.sort { |a,b| a.id <=> b.id}
+
+ sorted.each_with_index do |n1, i|
+ sorted.each_with_index do |n2, j|
+ next if i == j
+ dist[i][j] = n1.has_neighbour?(n2) ? link_between(n1, n2).weight.to_i : @infinity
end
end
dist
end
def distances
- @path = Array.new(@nodes.size) { Array.new(@nodes.size, nil) }
+ @path = matrix(@nodes.size, [nil])
@distance = idistance
@distance.each_index do |k|
@distance.each_index do |i|
@distance.each_index do |j|
new_dist = @distance[i][k] + @distance[k][j]
if @distance[i][j] > new_dist
@distance[i][j] = new_dist
- @path[i][j] = k
+ @path[i][j] = [k]
end
+ if @distance[i][j] == new_dist && !(@path[i][j].include? k) && ! [i,j].include?(k)
+ @path[i][j] << k
+ end
end
end
end
@distance
end
@@ -97,45 +96,55 @@
fdistance = @distance.flatten.select{|d| d != @infinity}
fdistance.inject(:+) / fdistance.count.to_f
end
- def shortest_paths
- tmp = []
+ def shortest_paths(args = {})
+ multiples = args[:multiples] || false
+ @shortest_paths = []
- distances unless @my_shortest_paths
+ distances
0.upto(@nodes.size - 1).each do |i|
- i.upto(@nodes.size - 1).each do |j|
- next if i == j
- sp = shortest_path(i, j)
- tmp << sp unless sp.empty?
+ (i + 1).upto(@nodes.size - 1).each do |j|
+ @shortest_paths += shortest_path(i, j, multiples)
end
end
- @shortest_paths = tmp
+ @shortest_paths
end
- def shortest_path(i, j)
+ def shortest_path(i, j, multiples = false)
return [] if @distance[i][j] == @infinity
- k = @path[i][j]
+ path = @path[i][j].count == 1 || multiples ? @path[i][j] : [@path[i][j].first]
+ out = []
- case k
- when @infinity
- []
- when nil
- [i,j]
- else
- #We need to do this or k will appear three times
- shortest_path(i, k)[0..-2] + [k] + shortest_path(k, j)[1..-1]
+ path.each do |k|
+
+ case k
+ when @infinity
+ out << []
+ when nil
+ out << [i,j]
+ else
+ i_k = shortest_path(i, k)
+ k_j = shortest_path(k, j)
+
+ i_k.each do |ik|
+ k_j.each do |kj|
+ out << ik[0..-2] + [k] + kj[1..-1]
+ end
+ end
+ end
end
+ out
end
def between(i)
- shortest_paths unless @shortest_paths
+ shortest_paths(multiples: true)
n = @shortest_paths.select{|c| c[1..-2].include?(i)}.size.to_f
m = @shortest_paths.size.to_f
n / m
end
@@ -247,10 +256,18 @@
nodes.each do |node|
@nodes << node unless get_node_by_id(node.id)
end
end
+ def link_between(n1, n2)
+ @links.select{ |l| (l.source == n1 && l.target == n2) || (l.source == n2 && l.target == n1) }.first
+ end
+
def possible_connections(node)
total = node.neighbours.count
total * (total - 1) / 2
+ end
+
+ def matrix(size, value)
+ Array.new(size) { Array.new(size, value) }
end
end