networkr 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ &mdash; 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> &raquo;
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 ** 3).times do
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
- def initialize
11
- @explored = Set.new
12
- @current_source = nil
13
- @leaders = {}
14
- @current_time = 0
15
- @finishing_times = {}
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
- class << self
20
- def dfs_loop(graph, tracker)
21
- graph.adj.keys.reverse_each do |i|
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(graph, stack, v, tracker)
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(graph, stack, v, tracker)
60
+ def dfs(g, stack, v, tracker)
41
61
  tracker.explored << v
42
- if !graph.adj[v]
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
- graph.adj[v].each_key do |w|
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, start)
10
- vertices_spanned = [start]
11
+ def prim(g, source_node)
12
+ nodes_spanned = [source_node]
11
13
  tree_so_far = Graph.new
12
- while vertices_spanned.length != g.length
13
- e = min_edge(g, vertices_spanned)
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
- vertices_spanned << e[0][1]
17
+ nodes_spanned << e[0][1]
16
18
  end
17
19
  tree_so_far
18
20
  end
19
21
 
20
- def min_edge(g, vertices_spanned)
22
+ private
23
+ def min_edge(g, nodes_spanned)
21
24
  min_edge = nil
22
25
  min_cost = 1.0/0
23
- vertices_spanned.each do |u|
26
+ nodes_spanned.each do |u|
24
27
  if g.adj[u]
25
28
  g.adj[u].each do |v, options|
26
- if !vertices_spanned.include?(v) && options[:weight] < min_cost
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 edges are not.
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 option attributes.
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 erros when adding nodes or edges that already exist.
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: { username: "janedoe" }, 3: { username: "johndoe" } }
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