networkx 0.1.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/{CODE_OF_CONDUCT.md → .github/CODE_OF_CONDUCT.md} +0 -0
- data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +20 -10
- data/{ISSUE_TEMPLATE.md → .github/ISSUE_TEMPLATE.md} +1 -1
- data/{PULL_REQUEST_TEMPLATE.md → .github/PULL_REQUEST_TEMPLATE.md} +2 -4
- data/.github/workflows/ci.yml +17 -0
- data/.github/workflows/doc.yml +23 -0
- data/.rspec +0 -1
- data/.rubocop.yml +57 -71
- data/.yardopts +0 -1
- data/README.md +32 -34
- data/Rakefile +2 -3
- data/lib/networkx/auxillary_functions/cliques.rb +9 -12
- data/lib/networkx/auxillary_functions/cycles.rb +17 -7
- data/lib/networkx/auxillary_functions/dag.rb +10 -5
- data/lib/networkx/auxillary_functions/eccentricity.rb +2 -1
- data/lib/networkx/auxillary_functions/mis.rb +2 -2
- data/lib/networkx/auxillary_functions/mst.rb +1 -3
- data/lib/networkx/auxillary_functions/union_find.rb +92 -12
- data/lib/networkx/auxillary_functions/wiener.rb +1 -1
- data/lib/networkx/converters/to_csv.rb +1 -3
- data/lib/networkx/converters/to_json.rb +0 -2
- data/lib/networkx/digraph.rb +55 -49
- data/lib/networkx/flow/capacityscaling.rb +29 -35
- data/lib/networkx/flow/edmondskarp.rb +17 -15
- data/lib/networkx/flow/preflowpush.rb +29 -32
- data/lib/networkx/flow/shortestaugmentingpath.rb +17 -20
- data/lib/networkx/flow/utils.rb +6 -27
- data/lib/networkx/graph.rb +179 -72
- data/lib/networkx/link_analysis/hits.rb +9 -9
- data/lib/networkx/link_analysis/pagerank.rb +29 -31
- data/lib/networkx/multidigraph.rb +90 -81
- data/lib/networkx/multigraph.rb +91 -63
- data/lib/networkx/operators/all.rb +8 -4
- data/lib/networkx/operators/binary.rb +106 -128
- data/lib/networkx/operators/product.rb +61 -64
- data/lib/networkx/operators/unary.rb +1 -1
- data/lib/networkx/others/bridges.rb +30 -0
- data/lib/networkx/others/generators.rb +237 -0
- data/lib/networkx/others/grid_2d_graph.rb +38 -0
- data/lib/networkx/others/info.rb +11 -0
- data/lib/networkx/others/number_connected_components.rb +17 -0
- data/lib/networkx/others/reads.rb +52 -0
- data/lib/networkx/shortest_path/astar.rb +10 -8
- data/lib/networkx/shortest_path/dense.rb +1 -3
- data/lib/networkx/shortest_path/unweighted.rb +13 -16
- data/lib/networkx/shortest_path/weighted.rb +51 -42
- data/lib/networkx/to_matrix.rb +2 -3
- data/lib/networkx/traversals/bfs.rb +54 -2
- data/lib/networkx/traversals/dfs.rb +62 -6
- data/lib/networkx/traversals/edge_dfs.rb +36 -12
- data/lib/networkx/version.rb +1 -1
- data/lib/networkx.rb +7 -1
- data/networkx.gemspec +17 -14
- metadata +74 -84
- data/.rspec_formatter.rb +0 -24
- data/.travis.yml +0 -18
- data/Guardfile +0 -7
- data/RELEASE_POLICY.md +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 39e75c0ad21604275a008c53a29f282d681f3c50cb7648470cc6e4e2cffa5071
|
4
|
+
data.tar.gz: 93e93f5a2603beb715b38856518ed47e698c0978c5ff02a737a7baff68357e8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ce185b8e9246db7b791d4d1800b39d1ad9a5f1036c99899842554c31e2400469d775acd382c2dfc27275857db58e66228062502bffefb16ddca4c3a63b346fe
|
7
|
+
data.tar.gz: 9b615db49ec2ba5e06bbfecf1710849d079661b301a85493740434eae464bfd74c250c38c31ed2cc5dfb93983cb2c7315fe27452c2f6a243051ac1f80512816b
|
File without changes
|
@@ -11,10 +11,10 @@ Please proceed with a Pull Request only after you're assigned. It'd be sad if yo
|
|
11
11
|
|
12
12
|
# Developing the gem
|
13
13
|
|
14
|
-
1.
|
14
|
+
1. Fork this repository and clone it and install all the required gem dependencies.
|
15
15
|
|
16
16
|
```sh
|
17
|
-
git clone https://github.com
|
17
|
+
git clone https://github.com/`your_github_user_id`/networkx.rb.git
|
18
18
|
cd networkx.rb
|
19
19
|
gem install bundler
|
20
20
|
bundle install
|
@@ -22,13 +22,9 @@ Please proceed with a Pull Request only after you're assigned. It'd be sad if yo
|
|
22
22
|
|
23
23
|
2. Checkout to a different git branch (say, `adds-new-feature`).
|
24
24
|
|
25
|
-
3. Add
|
25
|
+
3. Add code (, test, and YARD documentation).
|
26
26
|
|
27
|
-
4.
|
28
|
-
|
29
|
-
5. Add tests to `spec/networkx/filename_spec.rb`. Add any files required for testing in the `spec/fixtures/` directory.
|
30
|
-
|
31
|
-
6. Run the rspec test-suite.
|
27
|
+
4. Run the rspec test-suite.
|
32
28
|
```sh
|
33
29
|
# Runs test suite for all files
|
34
30
|
bundle exec rspec
|
@@ -37,7 +33,7 @@ Please proceed with a Pull Request only after you're assigned. It'd be sad if yo
|
|
37
33
|
bundle exec rspec spec/networkx/filename_spec.rb
|
38
34
|
```
|
39
35
|
|
40
|
-
|
36
|
+
5. Run the rubocop for static code quality comments.
|
41
37
|
|
42
38
|
```sh
|
43
39
|
# Runs rubocop test for all files
|
@@ -47,4 +43,18 @@ Please proceed with a Pull Request only after you're assigned. It'd be sad if yo
|
|
47
43
|
bundle exec rubocop lib/networkx/filename.rb
|
48
44
|
```
|
49
45
|
|
50
|
-
|
46
|
+
6. Send a Pull Request back to this repository. :tada:
|
47
|
+
|
48
|
+
# Note: YARD Document
|
49
|
+
|
50
|
+
You can create YARD documentation
|
51
|
+
|
52
|
+
1. Create Document for `doc` directory with `yard` command
|
53
|
+
2. Create server via `yard server` command
|
54
|
+
3. open Browser with `open http://0.0.0.0:8808` e.t.c.
|
55
|
+
|
56
|
+
```
|
57
|
+
$ yard
|
58
|
+
$ yard server
|
59
|
+
$ open http://0.0.0.0:8808
|
60
|
+
```
|
@@ -1,12 +1,10 @@
|
|
1
|
-
### Description
|
2
|
-
|
3
1
|
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
2
|
|
5
|
-
- Relevant Issues : (
|
3
|
+
- Relevant Issues : (optional)
|
6
4
|
- Relevant PRs : (optional)
|
7
5
|
- Type of change :
|
8
6
|
- [ ] New feature
|
9
7
|
- [ ] Bug fix for existing feature
|
10
8
|
- [ ] Code quality improvement
|
11
9
|
- [ ] Addition or Improvement of tests
|
12
|
-
- [ ] Addition or Improvement of documentation
|
10
|
+
- [ ] Addition or Improvement of documentation
|
@@ -0,0 +1,17 @@
|
|
1
|
+
name: test
|
2
|
+
on: [push, pull_request]
|
3
|
+
jobs:
|
4
|
+
build:
|
5
|
+
name: ${{ matrix.os }} Ruby ${{ matrix.ruby }}
|
6
|
+
runs-on: ${{ matrix.os }}-latest
|
7
|
+
strategy:
|
8
|
+
matrix:
|
9
|
+
os: [ 'ubuntu', 'macos' ]
|
10
|
+
ruby: [ '2.7', '3.0', '3.1' ]
|
11
|
+
steps:
|
12
|
+
- uses: actions/checkout@v2
|
13
|
+
- uses: ruby/setup-ruby@v1
|
14
|
+
with:
|
15
|
+
ruby-version: ${{ matrix.ruby }}
|
16
|
+
bundler-cache: true
|
17
|
+
- run: bundle exec rspec
|
@@ -0,0 +1,23 @@
|
|
1
|
+
name: doc
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- main
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
build:
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
|
12
|
+
steps:
|
13
|
+
- uses: actions/checkout@v3
|
14
|
+
- uses: ruby/setup-ruby@v1
|
15
|
+
with:
|
16
|
+
ruby-version: 3.1
|
17
|
+
- name: Generate document
|
18
|
+
run: gem install -N yard && yard doc
|
19
|
+
- name: Publish Documentation on GitHub Pages
|
20
|
+
uses: peaceiris/actions-gh-pages@v3
|
21
|
+
with:
|
22
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
23
|
+
publish_dir: ./doc
|
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,116 +1,102 @@
|
|
1
|
-
require: rubocop-rspec
|
2
|
-
|
3
1
|
AllCops:
|
2
|
+
NewCops: enable
|
3
|
+
TargetRubyVersion: 2.7
|
4
4
|
Include:
|
5
5
|
- 'lib/**/*'
|
6
|
-
|
7
|
-
- '
|
8
|
-
- '
|
9
|
-
- '
|
6
|
+
- 'spec/**/*_spec.rb'
|
7
|
+
- 'Gemfile'
|
8
|
+
- 'Rakefile'
|
9
|
+
- '*.gemspec'
|
10
10
|
DisplayCopNames: true
|
11
|
-
TargetRubyVersion: 2.2
|
12
11
|
|
13
|
-
|
12
|
+
require:
|
13
|
+
- rubocop-rspec
|
14
|
+
- rubocop-rake
|
14
15
|
|
15
16
|
### Layouts ------------------------------------------------------------
|
16
17
|
|
17
|
-
|
18
|
-
EnforcedStyle: with_fixed_indentation
|
19
|
-
|
20
|
-
Layout/ExtraSpacing:
|
21
|
-
AllowForAlignment: true
|
22
|
-
|
23
|
-
Layout/SpaceAfterComma:
|
18
|
+
Lint/AmbiguousOperatorPrecedence:
|
24
19
|
Enabled: false
|
25
20
|
|
26
|
-
Layout/
|
27
|
-
EnforcedStyle: no_space
|
28
|
-
|
29
|
-
Layout/SpaceAroundOperators:
|
21
|
+
Layout/SpaceBeforeBlockBraces:
|
30
22
|
Enabled: false
|
31
23
|
|
32
24
|
Layout/SpaceInsideBlockBraces:
|
33
|
-
|
25
|
+
Enabled: false
|
34
26
|
|
35
27
|
Layout/SpaceInsideHashLiteralBraces:
|
36
28
|
EnforcedStyle: no_space
|
37
29
|
|
38
|
-
###
|
39
|
-
|
40
|
-
Style/AndOr:
|
41
|
-
EnforcedStyle: conditionals
|
30
|
+
### Metrics ------------------------------------------------------------
|
42
31
|
|
43
|
-
|
32
|
+
Metrics:
|
44
33
|
Enabled: false
|
45
34
|
|
46
|
-
|
35
|
+
### Naming -------------------------------------------------------------
|
36
|
+
|
37
|
+
Naming/MethodParameterName:
|
47
38
|
Enabled: false
|
48
39
|
|
49
|
-
|
50
|
-
|
40
|
+
Naming/PredicateName:
|
41
|
+
Enabled: false
|
51
42
|
|
52
|
-
|
53
|
-
EnforcedStyle: compact
|
43
|
+
### Styles -------------------------------------------------------------
|
54
44
|
|
55
|
-
Style/
|
56
|
-
|
45
|
+
Style/CombinableLoops:
|
46
|
+
Enabled: false # there is case that it can't combined loop.
|
57
47
|
|
58
|
-
Style/
|
59
|
-
Enabled: false
|
60
|
-
|
61
|
-
Style/SingleLineBlockParams:
|
48
|
+
Style/Documentation:
|
62
49
|
Enabled: false
|
63
50
|
|
64
|
-
Style/
|
51
|
+
Style/FrozenStringLiteralComment:
|
65
52
|
Enabled: false
|
66
53
|
|
67
|
-
Style/
|
68
|
-
Enabled: false #
|
69
|
-
|
70
|
-
### Metrics ------------------------------------------------------------
|
54
|
+
Style/NumericPredicate:
|
55
|
+
Enabled: false # it is easier to read `size > 0` than `size.positive?`
|
71
56
|
|
72
|
-
|
73
|
-
Enabled:
|
57
|
+
Style/OptionalBooleanParameter:
|
58
|
+
Enabled: false # it is necessary to change distructively.
|
74
59
|
|
75
|
-
|
76
|
-
Enabled:
|
60
|
+
Style/ParallelAssignment:
|
61
|
+
Enabled: false # one line style is compact.
|
77
62
|
|
78
|
-
|
79
|
-
|
63
|
+
Style/PreferredHashMethods:
|
64
|
+
Enabled: false
|
80
65
|
|
81
|
-
|
82
|
-
Enabled:
|
66
|
+
Style/SymbolArray:
|
67
|
+
Enabled: false # general array literal is easy to read. no problem.
|
83
68
|
|
84
|
-
|
85
|
-
Enabled:
|
69
|
+
Style/ZeroLengthPredicate:
|
70
|
+
Enabled: false # it is so easy to read `a.size > 0` as `!a.empty?`
|
86
71
|
|
87
|
-
|
88
|
-
Enabled: true
|
72
|
+
### RSpec --------------------------------------------------------------
|
89
73
|
|
90
|
-
|
91
|
-
|
74
|
+
RSpec/MessageSpies:
|
75
|
+
EnforcedStyle: receive
|
92
76
|
|
93
|
-
|
94
|
-
Enabled:
|
77
|
+
RSpec/DescribedClass:
|
78
|
+
Enabled: false
|
95
79
|
|
96
|
-
|
97
|
-
|
80
|
+
RSpec/ExampleLength:
|
81
|
+
Max: 25
|
98
82
|
|
99
|
-
|
100
|
-
Enabled:
|
83
|
+
RSpec/FilePath:
|
84
|
+
Enabled: false # too many offense
|
101
85
|
|
102
|
-
|
103
|
-
|
86
|
+
RSpec/ImplicitSubject:
|
87
|
+
Enabled: false # too many offenses
|
104
88
|
|
105
|
-
|
89
|
+
RSpec/MultipleExpectations:
|
90
|
+
Max: 15
|
106
91
|
|
107
|
-
|
108
|
-
|
92
|
+
RSpec/NestedGroups:
|
93
|
+
Max: 5
|
109
94
|
|
110
|
-
|
95
|
+
RSpec/PredicateMatcher:
|
96
|
+
Enabled: false
|
111
97
|
|
112
|
-
RSpec/
|
113
|
-
|
98
|
+
RSpec/RepeatedExampleGroupBody:
|
99
|
+
Enabled: false
|
114
100
|
|
115
|
-
RSpec/
|
116
|
-
|
101
|
+
RSpec/RepeatedExampleGroupDescription:
|
102
|
+
Enabled: false # too many offenses
|
data/.yardopts
CHANGED
data/README.md
CHANGED
@@ -1,57 +1,55 @@
|
|
1
1
|
# NetworkX.rb
|
2
2
|
|
3
|
-
[
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/networkx.svg)](https://badge.fury.io/rb/networkx)
|
4
4
|
|
5
|
-
|
5
|
+
[NetworkX](https://networkx.github.io/) is a very popular Python library, that handles various use-cases of the Graph Data Structure.
|
6
|
+
This project intends to provide a working alternative to the Ruby community, by closely mimicing as many features as possible.
|
6
7
|
|
7
|
-
|
8
|
+
## List of contents
|
8
9
|
|
9
10
|
- [Installing](#installing)
|
10
|
-
- [
|
11
|
+
- [Usage](#Usage)
|
12
|
+
- [Document](#document)
|
11
13
|
- [Contributing](#contributing)
|
12
14
|
- [License](#license)
|
13
15
|
|
14
|
-
|
16
|
+
## Installing
|
15
17
|
|
16
|
-
|
18
|
+
- install it yourself as:
|
19
|
+
```console
|
20
|
+
$ gem install networkx
|
21
|
+
```
|
17
22
|
|
18
|
-
|
19
|
-
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
|
24
|
+
- Or use Bundler & Gemfile
|
25
|
+
1. add this line to your application's Gemfile:
|
26
|
+
```ruby
|
27
|
+
gem 'networkx'
|
28
|
+
```
|
29
|
+
2. And then execute:
|
30
|
+
```console
|
31
|
+
$ bundle install
|
32
|
+
```
|
33
|
+
|
34
|
+
## Usage
|
23
35
|
|
24
36
|
```ruby
|
25
37
|
require 'networkx'
|
26
|
-
#=> true
|
27
38
|
|
28
|
-
|
29
|
-
g = NetworkX::Graph.new()
|
39
|
+
g = NetworkX::Graph.new
|
30
40
|
g.add_edge('start', 'stop')
|
31
41
|
```
|
32
42
|
|
33
|
-
|
34
|
-
|
35
|
-
[(Back to top)](#list-of-contents)
|
36
|
-
|
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 :
|
38
|
-
|
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
|
-
|
41
|
-
- `Edge` : This class should be capable of handling different types of edges. Though a basic undirected Graph doesn't store any metadata in the edges, weighted edges and parametric edges are something that need to be handled.
|
42
|
-
|
43
|
-
- `Graph` : The simplest of graphs. This class handles just connections between different `Node`s via `Edge`s.
|
44
|
-
|
45
|
-
- `DirectedGraph` : Inherits from `Graph` class. Uses directions between `Edge`s.
|
46
|
-
|
47
|
-
### Contributing
|
43
|
+
## Document
|
48
44
|
|
49
|
-
|
45
|
+
You can read [Document](https://SciRuby.github.io/networkx.rb/) for this library.
|
50
46
|
|
51
|
-
|
47
|
+
## Contributing
|
52
48
|
|
53
|
-
|
49
|
+
Your contributions are always welcome!
|
50
|
+
Please have a look at the [contribution guidelines](CONTRIBUTING.md) first. :tada:
|
54
51
|
|
55
|
-
|
52
|
+
## License
|
56
53
|
|
57
|
-
The MIT License 2017 - [Athitya Kumar](https://github.com/athityakumar).
|
54
|
+
The MIT License 2017 - [Athitya Kumar](https://github.com/athityakumar).
|
55
|
+
Please have a look at the [LICENSE.md](LICENSE.md) for more details.
|
data/Rakefile
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
module NetworkX
|
2
|
-
# TODO: Reduce method complexity and method length
|
3
|
-
|
4
2
|
# Returns all cliques in the graph
|
5
3
|
#
|
6
4
|
# @param graph [Graph, MultiGraph] a graph
|
@@ -8,6 +6,7 @@ module NetworkX
|
|
8
6
|
# @return [Array<Array<Object>>] Arrays of nodes in the cliques
|
9
7
|
def self.find_cliques(graph)
|
10
8
|
return nil if graph.nodes.empty?
|
9
|
+
|
11
10
|
q = [nil]
|
12
11
|
adj = {}
|
13
12
|
graph.nodes.each_key { |u| adj[u] = [] }
|
@@ -15,13 +14,16 @@ module NetworkX
|
|
15
14
|
|
16
15
|
subg = graph.nodes.keys
|
17
16
|
cand = graph.nodes.keys
|
18
|
-
u = subg.max { |
|
17
|
+
u = subg.max { |n1, n2| (cand & adj[n1]).length <=> (cand & adj[n2]).length }
|
19
18
|
ext_u = cand - adj[u]
|
20
19
|
stack = []
|
21
20
|
cliques = []
|
22
21
|
begin
|
23
22
|
loop do
|
24
|
-
if
|
23
|
+
if ext_u.empty?
|
24
|
+
q.pop
|
25
|
+
subg, cand, ext_u = stack.pop
|
26
|
+
else
|
25
27
|
q_elem = ext_u.pop
|
26
28
|
cand.delete(q_elem)
|
27
29
|
q[-1] = q_elem
|
@@ -36,17 +38,14 @@ module NetworkX
|
|
36
38
|
q << nil
|
37
39
|
subg = subg_q
|
38
40
|
cand = cand_q
|
39
|
-
u = subg.max { |
|
41
|
+
u = subg.max { |n1, n2| (cand & adj[n1]).length <=> (cand & adj[n2]).length }
|
40
42
|
ext_u = cand - adj[u]
|
41
43
|
end
|
42
44
|
end
|
43
|
-
else
|
44
|
-
q.pop
|
45
|
-
subg, cand, ext_u = stack.pop
|
46
45
|
end
|
47
46
|
end
|
48
47
|
rescue NoMethodError
|
49
|
-
|
48
|
+
cliques
|
50
49
|
end
|
51
50
|
end
|
52
51
|
|
@@ -58,8 +57,6 @@ module NetworkX
|
|
58
57
|
# @return [Numeric] Number of cliques containing the given node
|
59
58
|
def self.number_of_cliques(graph, node)
|
60
59
|
cliques = find_cliques(graph)
|
61
|
-
|
62
|
-
cliques.each { |c| num_cliq_arr << 1 if c.include?(node) }
|
63
|
-
num_cliq_arr.length
|
60
|
+
cliques.count { |c| c.include?(node) }
|
64
61
|
end
|
65
62
|
end
|
@@ -1,13 +1,11 @@
|
|
1
1
|
module NetworkX
|
2
|
-
# TODO: Reduce method complexity and method length
|
3
|
-
|
4
2
|
# Returns all basis cycles in graph
|
5
3
|
#
|
6
4
|
# @param graph [Graph] a graph
|
7
5
|
# @param root [Object, Nil] root for the graph cycles
|
8
6
|
#
|
9
7
|
# @return [Array<Array<Object>>] Arrays of nodes in the cycles
|
10
|
-
def self.cycle_basis(graph, root=nil)
|
8
|
+
def self.cycle_basis(graph, root = nil)
|
11
9
|
gnodes = graph.nodes.keys
|
12
10
|
cycles = []
|
13
11
|
until gnodes.empty?
|
@@ -19,7 +17,7 @@ module NetworkX
|
|
19
17
|
z = stack.shift
|
20
18
|
zused = used[z]
|
21
19
|
graph.adj[z].each_key do |u|
|
22
|
-
if !used.
|
20
|
+
if !used.has_key?(u)
|
23
21
|
pred[u] = z
|
24
22
|
stack << u
|
25
23
|
used[u] = [z]
|
@@ -46,8 +44,6 @@ module NetworkX
|
|
46
44
|
cycles
|
47
45
|
end
|
48
46
|
|
49
|
-
# TODO: Reduce method complexity and method length
|
50
|
-
|
51
47
|
# Returns the cycle containing the given node
|
52
48
|
#
|
53
49
|
# @param graph [Graph, DiGraph] a graph
|
@@ -67,6 +63,7 @@ module NetworkX
|
|
67
63
|
edge_dfs(graph, node).each do |edge|
|
68
64
|
tail, head = edge
|
69
65
|
next if explored.include?(head)
|
66
|
+
|
70
67
|
if !previous_head.nil? && tail != previous_head
|
71
68
|
loop do
|
72
69
|
popped_edge = edges.pop
|
@@ -76,7 +73,7 @@ module NetworkX
|
|
76
73
|
break
|
77
74
|
else
|
78
75
|
popped_head = popped_edge[1]
|
79
|
-
active_nodes.delete
|
76
|
+
active_nodes.delete(popped_head)
|
80
77
|
end
|
81
78
|
|
82
79
|
unless edges.empty?
|
@@ -101,4 +98,17 @@ module NetworkX
|
|
101
98
|
end
|
102
99
|
raise ArgumentError, 'No cycle found!' if cycle.empty?
|
103
100
|
end
|
101
|
+
|
102
|
+
# Returns whether the given undirected cycle has cycle.
|
103
|
+
#
|
104
|
+
# @param undirected_graph [Graph] an undirected graph
|
105
|
+
#
|
106
|
+
# @return [book] true if the given graph has cycle. otherwise, false.
|
107
|
+
def self.cycle?(undirected_graph)
|
108
|
+
uf = NetworkX::UnionFind.new
|
109
|
+
undirected_graph.edges.each do |x, y|
|
110
|
+
uf[x] == uf[y] ? (return [x, y]) : uf.unite(x, y)
|
111
|
+
end
|
112
|
+
false
|
113
|
+
end
|
104
114
|
end
|
@@ -7,6 +7,7 @@ module NetworkX
|
|
7
7
|
# @return [Array<Object>] Array of the descendants
|
8
8
|
def self.descendants(graph, source)
|
9
9
|
raise ArgumentError, 'Source is not present in the graph!' unless graph.node?(source)
|
10
|
+
|
10
11
|
des = single_source_shortest_path_length(graph, source).map { |u, _| u }.uniq
|
11
12
|
des - [source]
|
12
13
|
end
|
@@ -19,12 +20,11 @@ module NetworkX
|
|
19
20
|
# @return [Array<Object>] Array of the ancestors
|
20
21
|
def self.ancestors(graph, source)
|
21
22
|
raise ArgumentError, 'Source is not present in the graph!' unless graph.node?(source)
|
23
|
+
|
22
24
|
anc = single_source_shortest_path_length(graph.reverse, source).map { |u, _| u }.uniq
|
23
25
|
anc - [source]
|
24
26
|
end
|
25
27
|
|
26
|
-
# TODO: Reduce method complexity and method length
|
27
|
-
|
28
28
|
# Returns the nodes arranged in the topologically sorted fashion
|
29
29
|
#
|
30
30
|
# @param graph [DiGraph] a graph
|
@@ -32,13 +32,17 @@ module NetworkX
|
|
32
32
|
# @return [Array<Object>] Array of the nodes
|
33
33
|
def self.topological_sort(graph)
|
34
34
|
raise ArgumentError, 'Topological Sort not defined on undirected graphs!' unless graph.directed?
|
35
|
+
|
35
36
|
nodes = []
|
36
|
-
indegree_map =
|
37
|
-
|
37
|
+
indegree_map = graph.nodes.each_key.map do |u|
|
38
|
+
[u, graph.in_degree(u)] if graph.in_degree(u).positive?
|
39
|
+
end.compact.to_h
|
40
|
+
zero_indegree = graph.nodes.each_key.select { |u| graph.in_degree(u).zero? }
|
38
41
|
|
39
42
|
until zero_indegree.empty?
|
40
43
|
node = zero_indegree.shift
|
41
|
-
raise ArgumentError, 'Graph changed during iteration!' unless graph.nodes.
|
44
|
+
raise ArgumentError, 'Graph changed during iteration!' unless graph.nodes.has_key?(node)
|
45
|
+
|
42
46
|
graph.adj[node].each_key do |child|
|
43
47
|
indegree_map[child] -= 1
|
44
48
|
if indegree_map[child].zero?
|
@@ -49,6 +53,7 @@ module NetworkX
|
|
49
53
|
nodes << node
|
50
54
|
end
|
51
55
|
raise ArgumentError, 'Graph contains cycle or graph changed during iteration!' unless indegree_map.empty?
|
56
|
+
|
52
57
|
nodes
|
53
58
|
end
|
54
59
|
end
|
@@ -5,12 +5,13 @@ module NetworkX
|
|
5
5
|
# @param node [Object] node to find the eccentricity of
|
6
6
|
#
|
7
7
|
# @return [Array<Numeric>, Numeric] eccentricity/eccentricites of all nodes
|
8
|
-
def self.eccentricity(graph, node=nil)
|
8
|
+
def self.eccentricity(graph, node = nil)
|
9
9
|
e = {}
|
10
10
|
graph.nodes.each do |u, _|
|
11
11
|
length = single_source_shortest_path_length(graph, u)
|
12
12
|
l = length.length
|
13
13
|
raise ArgumentError, 'Found infinite path length!' unless l == graph.nodes.length
|
14
|
+
|
14
15
|
e[u] = length.max_by { |a| a[1] }[1]
|
15
16
|
end
|
16
17
|
node.nil? ? e : e[node]
|
@@ -1,6 +1,4 @@
|
|
1
1
|
module NetworkX
|
2
|
-
# TODO: Reduce method complexity and method length
|
3
|
-
|
4
2
|
# Returns the maximal independent set of a graph
|
5
3
|
#
|
6
4
|
# @param graph [Graph, DiGraph, MultiGraph, MultiDiGraph] a graph
|
@@ -9,9 +7,11 @@ module NetworkX
|
|
9
7
|
# @return [Numeric] radius of the graph
|
10
8
|
def self.maximal_independent_set(graph, nodes)
|
11
9
|
raise 'The array containing the nodes should be a subset of the graph!' if (graph.nodes.keys - nodes).empty?
|
10
|
+
|
12
11
|
neighbours = []
|
13
12
|
nodes.each { |u| graph.adj[u].each { |v, _| neighbours |= [v] } }
|
14
13
|
raise 'Nodes is not an independent set of graph!' if (neighbours - nodes).empty?
|
14
|
+
|
15
15
|
available_nodes = graph.nodes.keys - (neighbours | nodes)
|
16
16
|
until available_nodes.empty?
|
17
17
|
node = available_nodes.sample
|
@@ -11,8 +11,6 @@ module NetworkX
|
|
11
11
|
edges
|
12
12
|
end
|
13
13
|
|
14
|
-
# TODO: Reduce method complexity and method length
|
15
|
-
|
16
14
|
# Returns the minimum spanning tree of a graph
|
17
15
|
#
|
18
16
|
# @param graph [Graph, DiGraph] a graph
|
@@ -27,7 +25,7 @@ module NetworkX
|
|
27
25
|
edge = edges.shift
|
28
26
|
unless union_find.connected?(edge[0][0], edge[0][1])
|
29
27
|
union_find.union(edge[0][0], edge[0][1])
|
30
|
-
mst.add_edge(edge[0][0], edge[0][1], graph.adj[edge[0][0]][edge[0][1]])
|
28
|
+
mst.add_edge(edge[0][0], edge[0][1], **graph.adj[edge[0][0]][edge[0][1]])
|
31
29
|
end
|
32
30
|
end
|
33
31
|
mst
|