networkx 0.1.0 → 0.1.1

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +18 -11
  3. data/CONTRIBUTING.md +2 -2
  4. data/Guardfile +1 -1
  5. data/ISSUE_TEMPLATE.md +15 -0
  6. data/PULL_REQUEST_TEMPLATE.md +12 -0
  7. data/README.md +4 -4
  8. data/RELEASE_POLICY.md +20 -0
  9. data/lib/networkx.rb +37 -1
  10. data/lib/networkx/auxillary_functions/cliques.rb +65 -0
  11. data/lib/networkx/auxillary_functions/cycles.rb +104 -0
  12. data/lib/networkx/auxillary_functions/dag.rb +54 -0
  13. data/lib/networkx/auxillary_functions/eccentricity.rb +36 -0
  14. data/lib/networkx/auxillary_functions/mis.rb +23 -0
  15. data/lib/networkx/auxillary_functions/mst.rb +35 -0
  16. data/lib/networkx/auxillary_functions/union_find.rb +24 -0
  17. data/lib/networkx/auxillary_functions/vitality.rb +13 -0
  18. data/lib/networkx/auxillary_functions/wiener.rb +13 -0
  19. data/lib/networkx/converters/to_csv.rb +47 -0
  20. data/lib/networkx/converters/to_json.rb +39 -0
  21. data/lib/networkx/digraph.rb +228 -0
  22. data/lib/networkx/flow/capacityscaling.rb +255 -0
  23. data/lib/networkx/flow/edmondskarp.rb +113 -0
  24. data/lib/networkx/flow/preflowpush.rb +252 -0
  25. data/lib/networkx/flow/shortestaugmentingpath.rb +157 -0
  26. data/lib/networkx/flow/utils.rb +160 -0
  27. data/lib/networkx/graph.rb +341 -0
  28. data/lib/networkx/link_analysis/hits.rb +59 -0
  29. data/lib/networkx/link_analysis/pagerank.rb +47 -0
  30. data/lib/networkx/multidigraph.rb +240 -0
  31. data/lib/networkx/multigraph.rb +171 -0
  32. data/lib/networkx/operators/all.rb +61 -0
  33. data/lib/networkx/operators/binary.rb +244 -0
  34. data/lib/networkx/operators/product.rb +204 -0
  35. data/lib/networkx/operators/unary.rb +17 -0
  36. data/lib/networkx/shortest_path/astar.rb +71 -0
  37. data/lib/networkx/shortest_path/dense.rb +31 -0
  38. data/lib/networkx/shortest_path/unweighted.rb +139 -0
  39. data/lib/networkx/shortest_path/weighted.rb +408 -0
  40. data/lib/networkx/to_matrix.rb +52 -0
  41. data/lib/networkx/traversals/bfs.rb +58 -0
  42. data/lib/networkx/traversals/dfs.rb +79 -0
  43. data/lib/networkx/traversals/edge_dfs.rb +90 -0
  44. data/lib/networkx/version.rb +1 -1
  45. data/networkx.gemspec +4 -1
  46. metadata +70 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f43ce74dd6bd8fbe91d6b5f29f3b7af355881e9
4
- data.tar.gz: 0275c9f6161b6bcf973af9f18a989969ce757bd0
3
+ metadata.gz: 805b70cf94db86eb3c9e144fe644e6f94f4e664a
4
+ data.tar.gz: 71f71c73039b7b666763268ce87c3780bd9853fb
5
5
  SHA512:
6
- metadata.gz: 17623a41e26fceebed54169c423dbe95a3ee59456a3cc4d3d888e74b70d8e2a58b7329d1565026babdc5196ae37b19422432eaa6e74cce03bbcef21c883c5312
7
- data.tar.gz: 8727b100efab027667eb7c8f3aa13bb3396b56e28a21437b3e21eda904bb99e7ebc9fc35a31451e3661f909faba8c6e57a14c2be1c832100526c1dcfedda4c1e
6
+ metadata.gz: 0f19f6aba21c6c12c7ce027e3067dc00e071235661e8f63287f92dc27ed3e332751cbb3526484e8095520e8d1fd29dfd7672f9fd93b55169372043ed6aa220d0
7
+ data.tar.gz: fe7846c3da4f617441bdb86720861074cb98da48c849b8f3507c867b7dbfee2909d4eb336bc79c904be407b887c8653ef46036d89021e31cdb37ffa7f93b1786
@@ -8,7 +8,7 @@ AllCops:
8
8
  - 'benchmarks/*'
9
9
  - 'profile/*'
10
10
  DisplayCopNames: true
11
- TargetRubyVersion: 2.1
11
+ TargetRubyVersion: 2.2
12
12
 
13
13
  # Preferred codebase style ---------------------------------------------
14
14
 
@@ -52,9 +52,6 @@ Style/EmptyElse:
52
52
  Style/EmptyMethod:
53
53
  EnforcedStyle: compact
54
54
 
55
- Style/FileName:
56
- Enabled: false
57
-
58
55
  Style/FormatString:
59
56
  EnforcedStyle: percent
60
57
 
@@ -73,33 +70,43 @@ Style/Documentation:
73
70
  ### Metrics ------------------------------------------------------------
74
71
 
75
72
  Metrics/AbcSize:
76
- Max: 20
73
+ Enabled: true
77
74
 
78
75
  Metrics/BlockLength:
79
- Exclude:
80
- - 'spec/**/*'
76
+ Enabled: true
81
77
 
82
78
  Metrics/ClassLength:
83
79
  Max: 200
84
80
 
85
81
  Metrics/CyclomaticComplexity:
86
- Max: 7
82
+ Enabled: true
83
+
84
+ Metrics/PerceivedComplexity:
85
+ Enabled: true
86
+
87
+ Metrics/BlockNesting:
88
+ Enabled: true
87
89
 
88
90
  Metrics/LineLength:
89
91
  Max: 120
90
92
 
91
93
  Metrics/MethodLength:
92
- Max: 15
94
+ Enabled: true
93
95
 
94
96
  Metrics/ModuleLength:
95
- Max: 200
97
+ Enabled: true
96
98
 
97
99
  Style/MultilineBlockChain:
98
- Enabled: false
100
+ Enabled: true
99
101
 
100
102
  Metrics/ParameterLists:
101
103
  Max: 10
102
104
 
105
+ ### Naming -------------------------------------------------------------
106
+
107
+ Naming/VariableNumber:
108
+ EnforcedStyle: snake_case
109
+
103
110
  ### RSpec --------------------------------------------------------------
104
111
 
105
112
  RSpec/MessageSpies:
@@ -14,8 +14,8 @@ Please proceed with a Pull Request only after you're assigned. It'd be sad if yo
14
14
  1. Clone this repository and install all the required gem dependencies.
15
15
 
16
16
  ```sh
17
- git clone https://github.com/athityakumar/daru-io.git
18
- cd daru-io
17
+ git clone https://github.com/athityakumar/networkx.rb.git
18
+ cd networkx.rb
19
19
  gem install bundler
20
20
  bundle install
21
21
  ```
data/Guardfile CHANGED
@@ -1,7 +1,7 @@
1
1
  guard :rspec, cmd: 'rspec' do
2
2
  watch(%r{^spec/.+_spec\.rb$})
3
3
  watch(%r{^lib/networkx/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
- watch('spec/spec_helper.rb') { 'spec' }
4
+ watch('spec/spec_helper.rb') { 'spec' }
5
5
  end
6
6
 
7
7
  # TODO: Run Rubocop in the background
@@ -0,0 +1,15 @@
1
+ ### Description
2
+
3
+ Thanks for opening this issue. Add a brief description of what this issue is, and how to recreate it. Do tag the relevant issue(s) and PR(s) below. If required, add the stack trace of the error.
4
+
5
+ - Relevant Issues : (optional)
6
+ - Relevant PRs : (optional)
7
+ - Type of issue :
8
+ - User mode :
9
+ - [ ] Installation
10
+ - [ ] Feature request
11
+ - [ ] Bug in existing feature
12
+ - Developer mode :
13
+ - [ ] Code quality
14
+ - [ ] Tests
15
+ - [ ] Documentation
@@ -0,0 +1,12 @@
1
+ ### Description
2
+
3
+ Thanks for contributing this Pull Request. Add a brief description of what this Pull Request does. Do tag the relevant issue(s) and PR(s) below. If required, add some screenshot(s) to support your changes.
4
+
5
+ - Relevant Issues : (required)
6
+ - Relevant PRs : (optional)
7
+ - Type of change :
8
+ - [ ] New feature
9
+ - [ ] Bug fix for existing feature
10
+ - [ ] Code quality improvement
11
+ - [ ] Addition or Improvement of tests
12
+ - [ ] Addition or Improvement of documentation
data/README.md CHANGED
@@ -13,6 +13,8 @@
13
13
 
14
14
  ### Installing
15
15
 
16
+ [(Back to top)](#list-of-contents)
17
+
16
18
  - Clone the repository with `git clone git@github.com:athityakumar/networkx.rb.git`
17
19
  - Navigate to networkx with `cd networkx.rb`
18
20
  - Install dependencies with `gem install bundler && bundle install`
@@ -30,6 +32,8 @@ g.add_edge('start', 'stop')
30
32
 
31
33
  ### Roadmap
32
34
 
35
+ [(Back to top)](#list-of-contents)
36
+
33
37
  Quite easily, any networkx user would be able to understand the number of details that have been implemented in the Python library. As a humble start towards the release of v0.1.0, the following could be the goals to achieve :
34
38
 
35
39
  - `Node` : This class should be capable of handling different types of nodes (not just `String` / `Integer`). A possible complex use-case could be XML nodes.
@@ -40,10 +44,6 @@ Quite easily, any networkx user would be able to understand the number of detail
40
44
 
41
45
  - `DirectedGraph` : Inherits from `Graph` class. Uses directions between `Edge`s.
42
46
 
43
- [(Back to top)](#list-of-contents)
44
-
45
- After months of extensive searching, we realised there was not a single repository that could guide a newbie to machine learning and natural language processing in Ruby. Thus, after a series of naming discussions, `sciruby-examples` was born.
46
-
47
47
  ### Contributing
48
48
 
49
49
  [(Back to top)](#list-of-contents)
@@ -0,0 +1,20 @@
1
+ # RELEASE POLICY
2
+
3
+ Applicable from networkx v0.0.0 onwards
4
+
5
+ ### Versioning
6
+
7
+ NetworkX follows semantic versioning whereby the version number is always in the form MAJOR.MINOR.PATCH
8
+
9
+ - Patch bump : Bug fixes
10
+ - Minor bump : New features (with backwards compatibility)
11
+ - Major bump : API breaking changes
12
+
13
+ For Major and Minor bumps release candidates should be released around 2 weeks prior to the bump and are indicated by MAJOR.MINOR.0.rc.
14
+
15
+ For more information see the full semantic versioning specification at http://semver.org/.
16
+
17
+ ### Release Timing
18
+
19
+ Patch releases should be done after every fix of a major bug (as tagged in the github issue tracker).
20
+ Major releases should be kept to the minimum.
@@ -1 +1,37 @@
1
- require 'networkx/version'
1
+ require 'set'
2
+ require 'nmatrix'
3
+ require 'rb_heap'
4
+ require 'securerandom'
5
+ require_relative 'networkx/version'
6
+ require_relative 'networkx/graph'
7
+ require_relative 'networkx/digraph'
8
+ require_relative 'networkx/multigraph'
9
+ require_relative 'networkx/multidigraph'
10
+ require_relative 'networkx/traversals/bfs'
11
+ require_relative 'networkx/traversals/dfs'
12
+ require_relative 'networkx/traversals/edge_dfs'
13
+ require_relative 'networkx/shortest_path/unweighted'
14
+ require_relative 'networkx/to_matrix'
15
+ require_relative 'networkx/shortest_path/dense'
16
+ require_relative 'networkx/shortest_path/weighted'
17
+ require_relative 'networkx/shortest_path/astar'
18
+ require_relative 'networkx/operators/product'
19
+ require_relative 'networkx/operators/binary'
20
+ require_relative 'networkx/operators/unary'
21
+ require_relative 'networkx/operators/all'
22
+ require_relative 'networkx/flow/utils'
23
+ require_relative 'networkx/flow/edmondskarp'
24
+ require_relative 'networkx/flow/shortestaugmentingpath'
25
+ require_relative 'networkx/flow/capacityscaling'
26
+ require_relative 'networkx/flow/preflowpush'
27
+ require_relative 'networkx/auxillary_functions/cliques'
28
+ require_relative 'networkx/auxillary_functions/dag'
29
+ require_relative 'networkx/auxillary_functions/eccentricity'
30
+ require_relative 'networkx/auxillary_functions/mis'
31
+ require_relative 'networkx/auxillary_functions/mst'
32
+ require_relative 'networkx/auxillary_functions/union_find'
33
+ require_relative 'networkx/auxillary_functions/vitality'
34
+ require_relative 'networkx/auxillary_functions/wiener'
35
+ require_relative 'networkx/auxillary_functions/cycles'
36
+ require_relative 'networkx/link_analysis/hits'
37
+ require_relative 'networkx/link_analysis/pagerank'
@@ -0,0 +1,65 @@
1
+ module NetworkX
2
+ # TODO: Reduce method complexity and method length
3
+
4
+ # Returns all cliques in the graph
5
+ #
6
+ # @param graph [Graph, MultiGraph] a graph
7
+ #
8
+ # @return [Array<Array<Object>>] Arrays of nodes in the cliques
9
+ def self.find_cliques(graph)
10
+ return nil if graph.nodes.empty?
11
+ q = [nil]
12
+ adj = {}
13
+ graph.nodes.each_key { |u| adj[u] = [] }
14
+ graph.adj.each { |u, u_edges| u_edges.each_key { |v| adj[u] << v if u != v } }
15
+
16
+ subg = graph.nodes.keys
17
+ cand = graph.nodes.keys
18
+ u = subg.max { |n_1, n_2| (cand & adj[n_1]).length <=> (cand & adj[n_2]).length }
19
+ ext_u = cand - adj[u]
20
+ stack = []
21
+ cliques = []
22
+ begin
23
+ loop do
24
+ if !ext_u.empty?
25
+ q_elem = ext_u.pop
26
+ cand.delete(q_elem)
27
+ q[-1] = q_elem
28
+ adj_q = adj[q_elem]
29
+ subg_q = subg & adj_q
30
+ if subg_q.empty?
31
+ cliques << q[0..(q.length - 1)]
32
+ else
33
+ cand_q = cand & adj_q
34
+ unless cand_q.empty?
35
+ stack << [subg, cand, ext_u]
36
+ q << nil
37
+ subg = subg_q
38
+ cand = cand_q
39
+ u = subg.max { |n_1, n_2| (cand & adj[n_1]).length <=> (cand & adj[n_2]).length }
40
+ ext_u = cand - adj[u]
41
+ end
42
+ end
43
+ else
44
+ q.pop
45
+ subg, cand, ext_u = stack.pop
46
+ end
47
+ end
48
+ rescue NoMethodError
49
+ return cliques
50
+ end
51
+ end
52
+
53
+ # Returns the number of cliques in a graph containing a node
54
+ #
55
+ # @param graph [Graph, MultiGraph] a graph
56
+ # @param node [Object] a node
57
+ #
58
+ # @return [Numeric] Number of cliques containing the given node
59
+ def self.number_of_cliques(graph, node)
60
+ cliques = find_cliques(graph)
61
+ num_cliq_arr = []
62
+ cliques.each { |c| num_cliq_arr << 1 if c.include?(node) }
63
+ num_cliq_arr.length
64
+ end
65
+ end
@@ -0,0 +1,104 @@
1
+ module NetworkX
2
+ # TODO: Reduce method complexity and method length
3
+
4
+ # Returns all basis cycles in graph
5
+ #
6
+ # @param graph [Graph] a graph
7
+ # @param root [Object, Nil] root for the graph cycles
8
+ #
9
+ # @return [Array<Array<Object>>] Arrays of nodes in the cycles
10
+ def self.cycle_basis(graph, root=nil)
11
+ gnodes = graph.nodes.keys
12
+ cycles = []
13
+ until gnodes.empty?
14
+ root = gnodes.shift if root.nil?
15
+ stack = [root]
16
+ pred = {root => root}
17
+ used = {root => []}
18
+ until stack.empty?
19
+ z = stack.shift
20
+ zused = used[z]
21
+ graph.adj[z].each_key do |u|
22
+ if !used.key?(u)
23
+ pred[u] = z
24
+ stack << u
25
+ used[u] = [z]
26
+ elsif u == z
27
+ cycles << [z]
28
+ elsif !zused.include?(u)
29
+ pn = used[u]
30
+ cycle = [u, z]
31
+ p = pred[z]
32
+ until pn.include?(p)
33
+ cycle << p
34
+ p = pred[p]
35
+ end
36
+ cycle << p
37
+ cycles << cycle
38
+ used[u] << z
39
+ used[u] = used[u].uniq
40
+ end
41
+ end
42
+ end
43
+ gnodes -= pred.keys
44
+ root = nil
45
+ end
46
+ cycles
47
+ end
48
+
49
+ # TODO: Reduce method complexity and method length
50
+
51
+ # Returns the cycle containing the given node
52
+ #
53
+ # @param graph [Graph, DiGraph] a graph
54
+ # @param node [Object] node to be included in the cycle
55
+ #
56
+ # @return [Array<Array<Object>>] Arrays of nodes in the cycle
57
+ def self.find_cycle(graph, node)
58
+ explored = Set.new
59
+ cycle = []
60
+ final_node = nil
61
+ unless explored.include?(node)
62
+ edges = []
63
+ seen = [node]
64
+ active_nodes = [node]
65
+ previous_head = nil
66
+
67
+ edge_dfs(graph, node).each do |edge|
68
+ tail, head = edge
69
+ next if explored.include?(head)
70
+ if !previous_head.nil? && tail != previous_head
71
+ loop do
72
+ popped_edge = edges.pop
73
+ if popped_edge.nil?
74
+ edges = []
75
+ active_nodes = [tail]
76
+ break
77
+ else
78
+ popped_head = popped_edge[1]
79
+ active_nodes.delete!(popped_head)
80
+ end
81
+
82
+ unless edges.empty?
83
+ last_head = edges[-1][1]
84
+ break if tail == last_head
85
+ end
86
+ end
87
+ end
88
+ edges << edge
89
+
90
+ if active_nodes.include?(head)
91
+ cycle += edges
92
+ final_node = head
93
+ break
94
+ else
95
+ seen << head
96
+ active_nodes << head
97
+ previous_head = head
98
+ end
99
+ end
100
+ cycle.each_with_index { |edge, i| return cycle[i..(cycle.length - 1)] if final_node == edge[0] }
101
+ end
102
+ raise ArgumentError, 'No cycle found!' if cycle.empty?
103
+ end
104
+ end
@@ -0,0 +1,54 @@
1
+ module NetworkX
2
+ # Returns the descendants of a given node
3
+ #
4
+ # @param graph [Graph, DiGraph, MultiGraph, MultiDiGraph] a graph
5
+ # @param source [Object] node to find descendents of
6
+ #
7
+ # @return [Array<Object>] Array of the descendants
8
+ def self.descendants(graph, source)
9
+ raise ArgumentError, 'Source is not present in the graph!' unless graph.node?(source)
10
+ des = single_source_shortest_path_length(graph, source).map { |u, _| u }.uniq
11
+ des - [source]
12
+ end
13
+
14
+ # Returns the ancestors of a given node
15
+ #
16
+ # @param graph [Graph, DiGraph, MultiGraph, MultiDiGraph] a graph
17
+ # @param source [Object] node to find ancestors of
18
+ #
19
+ # @return [Array<Object>] Array of the ancestors
20
+ def self.ancestors(graph, source)
21
+ raise ArgumentError, 'Source is not present in the graph!' unless graph.node?(source)
22
+ anc = single_source_shortest_path_length(graph.reverse, source).map { |u, _| u }.uniq
23
+ anc - [source]
24
+ end
25
+
26
+ # TODO: Reduce method complexity and method length
27
+
28
+ # Returns the nodes arranged in the topologically sorted fashion
29
+ #
30
+ # @param graph [DiGraph] a graph
31
+ #
32
+ # @return [Array<Object>] Array of the nodes
33
+ def self.topological_sort(graph)
34
+ raise ArgumentError, 'Topological Sort not defined on undirected graphs!' unless graph.directed?
35
+ nodes = []
36
+ indegree_map = Hash[graph.nodes.each_key.map { |u| [u, graph.in_degree(u)] if graph.in_degree(u) > 0 }.compact]
37
+ zero_indegree = graph.nodes.each_key.map { |u| u if graph.in_degree(u).zero? }.compact
38
+
39
+ until zero_indegree.empty?
40
+ node = zero_indegree.shift
41
+ raise ArgumentError, 'Graph changed during iteration!' unless graph.nodes.key?(node)
42
+ graph.adj[node].each_key do |child|
43
+ indegree_map[child] -= 1
44
+ if indegree_map[child].zero?
45
+ zero_indegree << child
46
+ indegree_map.delete(child)
47
+ end
48
+ end
49
+ nodes << node
50
+ end
51
+ raise ArgumentError, 'Graph contains cycle or graph changed during iteration!' unless indegree_map.empty?
52
+ nodes
53
+ end
54
+ end