networkr 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardoc/checksums +10 -0
- data/.yardoc/complete +0 -0
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
- data/Gemfile.lock +1 -1
- data/README.md +148 -11
- data/doc/BinaryMinHeap.html +870 -0
- data/doc/Networkr.html +1035 -0
- data/doc/Networkr/DiGraph.html +1013 -0
- data/doc/Networkr/Graph.html +1285 -0
- data/doc/Networkr/MultiGraph.html +532 -0
- data/doc/Networkr/Tracker.html +573 -0
- data/doc/NetworkrError.html +211 -0
- data/doc/_index.html +187 -0
- data/doc/class_list.html +51 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +481 -0
- data/doc/file.README.html +128 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +128 -0
- data/doc/js/app.js +243 -0
- data/doc/js/full_list.js +216 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +555 -0
- data/doc/top-level-namespace.html +114 -0
- data/lib/networkr/algorithms/dijkstra.rb +8 -6
- data/lib/networkr/algorithms/karger.rb +19 -18
- data/lib/networkr/algorithms/kosaraju.rb +52 -38
- data/lib/networkr/algorithms/prim.rb +17 -14
- data/lib/networkr/graphs/digraph.rb +9 -12
- data/lib/networkr/graphs/graph.rb +11 -20
- data/lib/networkr/graphs/multigraph.rb +25 -30
- data/lib/networkr/version.rb +1 -1
- data/lib/utils/heap.rb +1 -1
- data/networkr.gemspec +7 -2
- metadata +37 -5
@@ -0,0 +1,114 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>
|
7
|
+
Top Level Namespace
|
8
|
+
|
9
|
+
— Documentation by YARD 0.9.5
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
|
16
|
+
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
18
|
+
pathId = "";
|
19
|
+
relpath = '';
|
20
|
+
</script>
|
21
|
+
|
22
|
+
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
24
|
+
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
26
|
+
|
27
|
+
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<div class="nav_wrap">
|
31
|
+
<iframe id="nav" src="class_list.html"></iframe>
|
32
|
+
<div id="resizer"></div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="main" tabindex="-1">
|
36
|
+
<div id="header">
|
37
|
+
<div id="menu">
|
38
|
+
|
39
|
+
<a href="_index.html">Index</a> »
|
40
|
+
|
41
|
+
|
42
|
+
<span class="title">Top Level Namespace</span>
|
43
|
+
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<div id="search">
|
47
|
+
|
48
|
+
<a class="full_list_link" id="class_list_link"
|
49
|
+
href="class_list.html">
|
50
|
+
|
51
|
+
<svg width="24" height="24">
|
52
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
53
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
54
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
55
|
+
</svg>
|
56
|
+
</a>
|
57
|
+
|
58
|
+
</div>
|
59
|
+
<div class="clear"></div>
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<iframe id="search_frame" src="class_list.html"></iframe>
|
63
|
+
|
64
|
+
<div id="content"><h1>Top Level Namespace
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
</h1>
|
69
|
+
<div class="box_info">
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
</div>
|
82
|
+
|
83
|
+
<h2>Defined Under Namespace</h2>
|
84
|
+
<p class="children">
|
85
|
+
|
86
|
+
|
87
|
+
<strong class="modules">Modules:</strong> <span class='object_link'><a href="Networkr.html" title="Networkr (module)">Networkr</a></span>
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
<strong class="classes">Classes:</strong> <span class='object_link'><a href="BinaryMinHeap.html" title="BinaryMinHeap (class)">BinaryMinHeap</a></span>, <span class='object_link'><a href="NetworkrError.html" title="NetworkrError (class)">NetworkrError</a></span>
|
92
|
+
|
93
|
+
|
94
|
+
</p>
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
</div>
|
105
|
+
|
106
|
+
<div id="footer">
|
107
|
+
Generated on Sun Jul 24 17:23:15 2016 by
|
108
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
109
|
+
0.9.5 (ruby-2.1.2).
|
110
|
+
</div>
|
111
|
+
|
112
|
+
</div>
|
113
|
+
</body>
|
114
|
+
</html>
|
@@ -1,10 +1,12 @@
|
|
1
|
-
# dijkstra
|
2
|
-
# single-source shortest path
|
3
|
-
|
4
|
-
#Takes undirected, weighted graph, nonnegative weights
|
5
|
-
# O(|V|**2)
|
6
|
-
|
7
1
|
module Networkr
|
2
|
+
|
3
|
+
# Dijkstra's algorithm for computing the shortest paths from a single source.
|
4
|
+
#
|
5
|
+
# @param g [Networkr::Graph] an undirected, weighted graph. Weights must be non-negative.
|
6
|
+
# @param source_node node in the graph, can be any hashable object
|
7
|
+
# @return [Hash] with destination nodes as keys and distances as values
|
8
|
+
#
|
9
|
+
# Complexity: O(|V|**2)
|
8
10
|
class << self
|
9
11
|
def dijkstra(g, source_node)
|
10
12
|
nodes_processed = [source_node]
|
@@ -1,12 +1,12 @@
|
|
1
|
-
=begin
|
2
|
-
Karger's algorithm
|
3
|
-
|
4
|
-
computes a minumum cut of a connected graph
|
5
|
-
|
6
|
-
takes undirected multigraph
|
7
|
-
=end
|
8
|
-
|
9
1
|
module Networkr
|
2
|
+
|
3
|
+
# Karger's algorithm for computing a minimum cut of a connected graph
|
4
|
+
#
|
5
|
+
# @param g [Networkr::MultiGraph] an undirected multigraph
|
6
|
+
# @return [Numeric] the number of edges crossed by minimum cut
|
7
|
+
# @note Karger's algorithm is a randomized algorithm and does not guarantee to return the minimum cut. However, running the algorithm |V|**2 log|V| times produces a minimum cut with high probability. Use Networkr::karger to run the algorithm once. Use Networkr::karger_repeated to run it |V|**2 log|V| times.
|
8
|
+
#
|
9
|
+
# Complexity (of running Networkr::karger once): O(|V|**2)
|
10
10
|
class << self
|
11
11
|
def karger(g)
|
12
12
|
while g.length > 2
|
@@ -20,24 +20,25 @@ module Networkr
|
|
20
20
|
g.adj[node1][node2].length
|
21
21
|
end
|
22
22
|
|
23
|
-
def contract(g, node1, node2)
|
24
|
-
g.children_of(node2).each_key do |node|
|
25
|
-
g.add_edge(node1, node) if node != node1
|
26
|
-
g.adj[node].delete(node2)
|
27
|
-
end
|
28
|
-
g.adj.delete(node2)
|
29
|
-
g.nodes.delete(node2)
|
30
|
-
end
|
31
|
-
|
32
23
|
def karger_repeated(g)
|
33
24
|
g_copy = g.deep_copy
|
34
25
|
|
35
26
|
n = g.length
|
36
27
|
mincut = n
|
37
|
-
(n **
|
28
|
+
(n ** 2 * Math.log(n)).to_i.times do
|
38
29
|
mincut = karger(g_copy) if karger(g_copy) < mincut
|
39
30
|
end
|
40
31
|
mincut
|
41
32
|
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def contract(g, node1, node2)
|
36
|
+
g.children_of(node2).each_key do |node|
|
37
|
+
g.add_edge(node1, node) if node != node1
|
38
|
+
g.adj[node].delete(node2)
|
39
|
+
end
|
40
|
+
g.adj.delete(node2)
|
41
|
+
g.nodes.delete(node2)
|
42
|
+
end
|
42
43
|
end
|
43
44
|
end
|
@@ -1,30 +1,50 @@
|
|
1
1
|
require "set"
|
2
2
|
|
3
|
-
# O(V+E), finds strongly connected components of a directed graph
|
4
|
-
|
5
3
|
module Networkr
|
6
|
-
class Tracker
|
7
|
-
attr_accessor :explored, :current_source, :leaders, :current_time,
|
8
|
-
:finishing_times
|
9
4
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
5
|
+
# Kosaraju's algorithm for finding the strongly connected components of a directed graph.
|
6
|
+
#
|
7
|
+
# Complexity: O(V+E)
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# @param g [Networkr::DiGraph] a directed graph
|
11
|
+
# @param g_rev [Networkr::DiGraph] reversed graph of g
|
12
|
+
# @return [Array<Numeric>] sizes (numbers of nodes) of strongly connected components in descending order
|
13
|
+
def kosaraju_scc_sizes(original_g, g_rev)
|
14
|
+
tracker1 = Tracker.new
|
15
|
+
tracker2 = Tracker.new
|
16
|
+
tracker2 = kosaraju(original_g, g_rev, tracker1, tracker2)
|
17
|
+
sizes(tracker2)
|
16
18
|
end
|
17
|
-
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
# @param g [Networkr::DiGraph] a directed graph
|
21
|
+
# @param g_rev [Networkr::DiGraph] reversed graph of g
|
22
|
+
# @return [Numeric] number of strongly connected components
|
23
|
+
def kosaraju_num_scc(original_g, g_rev)
|
24
|
+
tracker1 = Tracker.new
|
25
|
+
tracker2 = Tracker.new
|
26
|
+
tracker2 = kosaraju(original_g, g_rev, tracker1, tracker2)
|
27
|
+
num_scc(tracker2)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def kosaraju(original_g, g_rev, tracker1, tracker2)
|
32
|
+
dfs_loop(g_rev, tracker1)
|
33
|
+
sorted_g_adj = Hash[original_g.adj.sort_by { |k, v| tracker1.finishing_times[k] }]
|
34
|
+
sorted_g = DiGraph.new
|
35
|
+
sorted_g.adj = sorted_g_adj
|
36
|
+
dfs_loop(sorted_g, tracker2)
|
37
|
+
tracker2
|
38
|
+
end
|
39
|
+
|
40
|
+
def dfs_loop(g, tracker)
|
41
|
+
g.adj.keys.reverse_each do |i|
|
22
42
|
stack = [i]
|
23
43
|
tracker.current_source = i
|
24
44
|
while !stack.empty?
|
25
45
|
v = stack.last
|
26
46
|
if !tracker.explored.include?(v)
|
27
|
-
dfs(
|
47
|
+
dfs(g, stack, v, tracker)
|
28
48
|
else
|
29
49
|
if tracker.finishing_times[v] == nil
|
30
50
|
tracker.leaders[v] = tracker.current_source
|
@@ -37,15 +57,15 @@ module Networkr
|
|
37
57
|
end
|
38
58
|
end
|
39
59
|
|
40
|
-
def dfs(
|
60
|
+
def dfs(g, stack, v, tracker)
|
41
61
|
tracker.explored << v
|
42
|
-
if !
|
62
|
+
if !g.adj[v]
|
43
63
|
tracker.leaders[v] = v
|
44
64
|
tracker.current_time += 1
|
45
65
|
tracker.finishing_times[v] = tracker.current_time
|
46
66
|
stack.pop
|
47
67
|
else
|
48
|
-
|
68
|
+
g.adj[v].each_key do |w|
|
49
69
|
if !tracker.explored.include?(w)
|
50
70
|
stack << w
|
51
71
|
end
|
@@ -53,25 +73,6 @@ module Networkr
|
|
53
73
|
end
|
54
74
|
end
|
55
75
|
|
56
|
-
def kosaraju(original_graph, graph_rev, tracker1, tracker2)
|
57
|
-
dfs_loop(graph_rev, tracker1)
|
58
|
-
sorted_graph_adj = Hash[original_graph.adj.sort_by { |k, v| tracker1.finishing_times[k] }]
|
59
|
-
sorted_graph = DiGraph.new
|
60
|
-
sorted_graph.adj = sorted_graph_adj
|
61
|
-
dfs_loop(sorted_graph, tracker2)
|
62
|
-
tracker2
|
63
|
-
end
|
64
|
-
|
65
|
-
def kosaraju_scc_sizes(original_graph, graph_rev, tracker1, tracker2)
|
66
|
-
tracker2 = kosaraju(original_graph, graph_rev, tracker1, tracker2)
|
67
|
-
sizes(tracker2)
|
68
|
-
end
|
69
|
-
|
70
|
-
def kosaraju_num_scc(original_graph, graph_rev, tracker1, tracker2)
|
71
|
-
tracker2 = kosaraju(original_graph, graph_rev, tracker1, tracker2)
|
72
|
-
num_scc(tracker2)
|
73
|
-
end
|
74
|
-
|
75
76
|
def sizes(tracker2)
|
76
77
|
frequencies = Hash.new(0)
|
77
78
|
tracker2.leaders.each do |k, v|
|
@@ -85,4 +86,17 @@ module Networkr
|
|
85
86
|
tracker2.leaders.length
|
86
87
|
end
|
87
88
|
end
|
89
|
+
|
90
|
+
class Tracker
|
91
|
+
attr_accessor :explored, :current_source, :leaders, :current_time,
|
92
|
+
:finishing_times
|
93
|
+
|
94
|
+
def initialize
|
95
|
+
@explored = Set.new
|
96
|
+
@current_source = nil
|
97
|
+
@leaders = {}
|
98
|
+
@current_time = 0
|
99
|
+
@finishing_times = {}
|
100
|
+
end
|
101
|
+
end
|
88
102
|
end
|
@@ -1,29 +1,32 @@
|
|
1
|
-
=begin
|
2
|
-
Prim's algorithm for calculating minimum spanning tree.
|
3
|
-
|
4
|
-
takes weighted, undirected graph
|
5
|
-
returns tree
|
6
|
-
=end
|
7
1
|
module Networkr
|
2
|
+
|
3
|
+
# Prim's algorithm for finding a minimum spanning tree for a weighted undirected graph.
|
4
|
+
#
|
5
|
+
# @param g [Networkr::Graph] weighted, undirected graph
|
6
|
+
# @param source_node random node in graph, can be any hashable object
|
7
|
+
# @return [Networkr::Graph] minimum spanning tree
|
8
|
+
#
|
9
|
+
# Complexity: O(|V|**2)
|
8
10
|
class << self
|
9
|
-
def prim(g,
|
10
|
-
|
11
|
+
def prim(g, source_node)
|
12
|
+
nodes_spanned = [source_node]
|
11
13
|
tree_so_far = Graph.new
|
12
|
-
while
|
13
|
-
e = min_edge(g,
|
14
|
+
while nodes_spanned.length != g.length
|
15
|
+
e = min_edge(g, nodes_spanned)
|
14
16
|
tree_so_far.add_edge(e[0][0], e[0][1], weight: e[1])
|
15
|
-
|
17
|
+
nodes_spanned << e[0][1]
|
16
18
|
end
|
17
19
|
tree_so_far
|
18
20
|
end
|
19
21
|
|
20
|
-
|
22
|
+
private
|
23
|
+
def min_edge(g, nodes_spanned)
|
21
24
|
min_edge = nil
|
22
25
|
min_cost = 1.0/0
|
23
|
-
|
26
|
+
nodes_spanned.each do |u|
|
24
27
|
if g.adj[u]
|
25
28
|
g.adj[u].each do |v, options|
|
26
|
-
if !
|
29
|
+
if !nodes_spanned.include?(v) && options[:weight] < min_cost
|
27
30
|
min_edge = [u, v]
|
28
31
|
min_cost = options[:weight]
|
29
32
|
end
|
@@ -1,16 +1,13 @@
|
|
1
|
-
# require_relative "graph.rb"
|
2
|
-
=begin
|
3
|
-
Class for directed graphs.
|
4
|
-
|
5
|
-
DiGraphs hold directed edges. Self loops are allowed but parallel edges are not.
|
6
|
-
|
7
|
-
See Also
|
8
|
-
--------
|
9
|
-
Graph
|
10
|
-
MultiGraph
|
11
|
-
=end
|
12
|
-
|
13
1
|
module Networkr
|
2
|
+
|
3
|
+
# Class for directed graphs.
|
4
|
+
#
|
5
|
+
# DiGraphs hold directed edges. Self loops are allowed but parallel edges are not.
|
6
|
+
#
|
7
|
+
# See Also
|
8
|
+
# --------
|
9
|
+
# Graph
|
10
|
+
# MultiGraph
|
14
11
|
class DiGraph < Graph
|
15
12
|
|
16
13
|
attr_accessor :pred, :succ
|
@@ -1,12 +1,14 @@
|
|
1
|
+
module Networkr
|
2
|
+
|
1
3
|
# Class for undirected graphs.
|
2
4
|
#
|
3
5
|
# A Graph stores nodes and edges with optional attributes.
|
4
6
|
#
|
5
|
-
# Graphs hold undirected edges. Self loops are allowed but parallel
|
7
|
+
# Graphs hold undirected edges. Self loops are allowed but parallel edges are not.
|
6
8
|
#
|
7
9
|
# Nodes can be arbitrary hashable Ruby objects with optional attributes.
|
8
10
|
#
|
9
|
-
# Edges are represented as links between nodes with
|
11
|
+
# Edges are represented as links between nodes with optional attributes.
|
10
12
|
#
|
11
13
|
# Parameters
|
12
14
|
# ----------
|
@@ -15,12 +17,13 @@
|
|
15
17
|
# See Also
|
16
18
|
# --------
|
17
19
|
# DiGraph
|
20
|
+
# MultiGraph
|
18
21
|
#
|
19
22
|
# Examples
|
20
23
|
# --------
|
21
24
|
# Create an empty graph with no nodes and edges.
|
22
25
|
#
|
23
|
-
# >>> g = Graph
|
26
|
+
# >>> g = Networkr::Graph.new
|
24
27
|
#
|
25
28
|
# g can be grown in several ways
|
26
29
|
#
|
@@ -36,7 +39,7 @@
|
|
36
39
|
#
|
37
40
|
# >>> g.add_edge(1, 2)
|
38
41
|
#
|
39
|
-
# If some edges connect nodes not yet in the graph, the nodes are added automatically. There are no
|
42
|
+
# If some edges connect nodes not yet in the graph, the nodes are added automatically. There are no errors when adding nodes or edges that already exist.
|
40
43
|
#
|
41
44
|
# **Attributes:**
|
42
45
|
#
|
@@ -55,7 +58,7 @@
|
|
55
58
|
# >>> g.nodes[1][:score] = 10
|
56
59
|
# >>> g.nodes[1].delete(:score) # remove attribute
|
57
60
|
# >>> g.nodes
|
58
|
-
# { 1
|
61
|
+
# { 1 => { username: "janedoe" }, 3 => { username: "johndoe" } }
|
59
62
|
#
|
60
63
|
# Add/update edge attributes using add_edge or g.adj:
|
61
64
|
#
|
@@ -63,21 +66,6 @@
|
|
63
66
|
# >>> g.adj[1][2][:weight] = 4
|
64
67
|
# >>> g.adj[1][2]
|
65
68
|
# { weight: 4 }
|
66
|
-
#
|
67
|
-
# **Representation:**
|
68
|
-
# :TODO
|
69
|
-
# g.to_s
|
70
|
-
#
|
71
|
-
# 1-2 { weight: 4 }
|
72
|
-
# 2-6 { weight: 10 }
|
73
|
-
# 4-6 { weight: 8 }
|
74
|
-
# 3-5 { weight: 5 }
|
75
|
-
# 5-6 { weight: 1 }
|
76
|
-
|
77
|
-
class NetworkrError < RuntimeError
|
78
|
-
end
|
79
|
-
|
80
|
-
module Networkr
|
81
69
|
class Graph
|
82
70
|
attr_accessor :graph, :nodes, :adj
|
83
71
|
|
@@ -181,3 +169,6 @@ module Networkr
|
|
181
169
|
end
|
182
170
|
end
|
183
171
|
end
|
172
|
+
|
173
|
+
class NetworkrError < RuntimeError
|
174
|
+
end
|