networkr 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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