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