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.
- checksums.yaml +4 -4
- data/.rubocop.yml +18 -11
- data/CONTRIBUTING.md +2 -2
- data/Guardfile +1 -1
- data/ISSUE_TEMPLATE.md +15 -0
- data/PULL_REQUEST_TEMPLATE.md +12 -0
- data/README.md +4 -4
- data/RELEASE_POLICY.md +20 -0
- data/lib/networkx.rb +37 -1
- data/lib/networkx/auxillary_functions/cliques.rb +65 -0
- data/lib/networkx/auxillary_functions/cycles.rb +104 -0
- data/lib/networkx/auxillary_functions/dag.rb +54 -0
- data/lib/networkx/auxillary_functions/eccentricity.rb +36 -0
- data/lib/networkx/auxillary_functions/mis.rb +23 -0
- data/lib/networkx/auxillary_functions/mst.rb +35 -0
- data/lib/networkx/auxillary_functions/union_find.rb +24 -0
- data/lib/networkx/auxillary_functions/vitality.rb +13 -0
- data/lib/networkx/auxillary_functions/wiener.rb +13 -0
- data/lib/networkx/converters/to_csv.rb +47 -0
- data/lib/networkx/converters/to_json.rb +39 -0
- data/lib/networkx/digraph.rb +228 -0
- data/lib/networkx/flow/capacityscaling.rb +255 -0
- data/lib/networkx/flow/edmondskarp.rb +113 -0
- data/lib/networkx/flow/preflowpush.rb +252 -0
- data/lib/networkx/flow/shortestaugmentingpath.rb +157 -0
- data/lib/networkx/flow/utils.rb +160 -0
- data/lib/networkx/graph.rb +341 -0
- data/lib/networkx/link_analysis/hits.rb +59 -0
- data/lib/networkx/link_analysis/pagerank.rb +47 -0
- data/lib/networkx/multidigraph.rb +240 -0
- data/lib/networkx/multigraph.rb +171 -0
- data/lib/networkx/operators/all.rb +61 -0
- data/lib/networkx/operators/binary.rb +244 -0
- data/lib/networkx/operators/product.rb +204 -0
- data/lib/networkx/operators/unary.rb +17 -0
- data/lib/networkx/shortest_path/astar.rb +71 -0
- data/lib/networkx/shortest_path/dense.rb +31 -0
- data/lib/networkx/shortest_path/unweighted.rb +139 -0
- data/lib/networkx/shortest_path/weighted.rb +408 -0
- data/lib/networkx/to_matrix.rb +52 -0
- data/lib/networkx/traversals/bfs.rb +58 -0
- data/lib/networkx/traversals/dfs.rb +79 -0
- data/lib/networkx/traversals/edge_dfs.rb +90 -0
- data/lib/networkx/version.rb +1 -1
- data/networkx.gemspec +4 -1
- metadata +70 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 805b70cf94db86eb3c9e144fe644e6f94f4e664a
|
4
|
+
data.tar.gz: 71f71c73039b7b666763268ce87c3780bd9853fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f19f6aba21c6c12c7ce027e3067dc00e071235661e8f63287f92dc27ed3e332751cbb3526484e8095520e8d1fd29dfd7672f9fd93b55169372043ed6aa220d0
|
7
|
+
data.tar.gz: fe7846c3da4f617441bdb86720861074cb98da48c849b8f3507c867b7dbfee2909d4eb336bc79c904be407b887c8653ef46036d89021e31cdb37ffa7f93b1786
|
data/.rubocop.yml
CHANGED
@@ -8,7 +8,7 @@ AllCops:
|
|
8
8
|
- 'benchmarks/*'
|
9
9
|
- 'profile/*'
|
10
10
|
DisplayCopNames: true
|
11
|
-
TargetRubyVersion: 2.
|
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
|
-
|
73
|
+
Enabled: true
|
77
74
|
|
78
75
|
Metrics/BlockLength:
|
79
|
-
|
80
|
-
- 'spec/**/*'
|
76
|
+
Enabled: true
|
81
77
|
|
82
78
|
Metrics/ClassLength:
|
83
79
|
Max: 200
|
84
80
|
|
85
81
|
Metrics/CyclomaticComplexity:
|
86
|
-
|
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
|
-
|
94
|
+
Enabled: true
|
93
95
|
|
94
96
|
Metrics/ModuleLength:
|
95
|
-
|
97
|
+
Enabled: true
|
96
98
|
|
97
99
|
Style/MultilineBlockChain:
|
98
|
-
Enabled:
|
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:
|
data/CONTRIBUTING.md
CHANGED
@@ -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/
|
18
|
-
cd
|
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
data/ISSUE_TEMPLATE.md
ADDED
@@ -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)
|
data/RELEASE_POLICY.md
ADDED
@@ -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.
|
data/lib/networkx.rb
CHANGED
@@ -1 +1,37 @@
|
|
1
|
-
require '
|
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
|