networkx 0.1.0 → 0.2.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} +21 -11
- data/.github/ISSUE_TEMPLATE.md +15 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +10 -0
- data/.github/workflows/ci.yml +17 -0
- data/.github/workflows/doc.yml +23 -0
- data/.github/workflows/gem-push.yml +45 -0
- data/.rspec +0 -1
- data/.rubocop.yml +56 -63
- data/.yardopts +0 -1
- data/README.md +27 -27
- data/Rakefile +2 -3
- data/lib/networkx/auxillary_functions/cliques.rb +62 -0
- data/lib/networkx/auxillary_functions/cycles.rb +114 -0
- data/lib/networkx/auxillary_functions/dag.rb +59 -0
- data/lib/networkx/auxillary_functions/eccentricity.rb +37 -0
- data/lib/networkx/auxillary_functions/mis.rb +23 -0
- data/lib/networkx/auxillary_functions/mst.rb +33 -0
- data/lib/networkx/auxillary_functions/union_find.rb +104 -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 +45 -0
- data/lib/networkx/converters/to_json.rb +37 -0
- data/lib/networkx/digraph.rb +234 -0
- data/lib/networkx/flow/capacityscaling.rb +249 -0
- data/lib/networkx/flow/edmondskarp.rb +115 -0
- data/lib/networkx/flow/preflowpush.rb +249 -0
- data/lib/networkx/flow/shortestaugmentingpath.rb +154 -0
- data/lib/networkx/flow/utils.rb +139 -0
- data/lib/networkx/graph.rb +448 -0
- data/lib/networkx/link_analysis/hits.rb +59 -0
- data/lib/networkx/link_analysis/pagerank.rb +89 -0
- data/lib/networkx/multidigraph.rb +249 -0
- data/lib/networkx/multigraph.rb +199 -0
- data/lib/networkx/operators/all.rb +65 -0
- data/lib/networkx/operators/binary.rb +222 -0
- data/lib/networkx/operators/product.rb +201 -0
- data/lib/networkx/operators/unary.rb +17 -0
- 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 +73 -0
- data/lib/networkx/shortest_path/dense.rb +29 -0
- data/lib/networkx/shortest_path/unweighted.rb +136 -0
- data/lib/networkx/shortest_path/weighted.rb +417 -0
- data/lib/networkx/to_matrix.rb +51 -0
- data/lib/networkx/traversals/bfs.rb +110 -0
- data/lib/networkx/traversals/dfs.rb +135 -0
- data/lib/networkx/traversals/edge_dfs.rb +114 -0
- data/lib/networkx/version.rb +1 -1
- data/lib/networkx.rb +43 -1
- data/networkx.gemspec +14 -12
- metadata +118 -62
- data/.rspec_formatter.rb +0 -24
- data/.travis.yml +0 -18
- data/Guardfile +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4e86cfdb083751f6aa9d45d894dd4a83ec75623acd237c6cdc8e7cd356306409
|
4
|
+
data.tar.gz: 60ef78a9da3df8d7f61e297af48873795b21d9675138e953dd160597d9bfdc09
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7d64db11e72ecd05bba646d89116da859caa2e48b9063b158780e625c7fdf802cd840c3aace32a00314762805a27fa1373b36795462d7640f4ed7385466d403
|
7
|
+
data.tar.gz: 46886910fc5f3bb550fb089af740bb5c0e32cd5a1ff3dd2394a13256ddc3f6b4e9f32c48c37d2d827b2bc8edba36cd0894201aec833a2fb4d59318f7fb85b7ae
|
File without changes
|
@@ -11,24 +11,20 @@ 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
|
18
|
-
cd
|
17
|
+
git clone https://github.com/`your_github_user_id`/networkx.rb.git
|
18
|
+
cd networkx.rb
|
19
19
|
gem install bundler
|
20
20
|
bundle install
|
21
21
|
```
|
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
|
+
```
|
@@ -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,10 @@
|
|
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.
|
2
|
+
|
3
|
+
- Relevant Issues : (optional)
|
4
|
+
- Relevant PRs : (optional)
|
5
|
+
- Type of change :
|
6
|
+
- [ ] New feature
|
7
|
+
- [ ] Bug fix for existing feature
|
8
|
+
- [ ] Code quality improvement
|
9
|
+
- [ ] Addition or Improvement of tests
|
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
|
@@ -0,0 +1,45 @@
|
|
1
|
+
name: Ruby Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ main ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ main ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
build:
|
11
|
+
name: Build + Publish
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
permissions:
|
14
|
+
contents: read
|
15
|
+
packages: write
|
16
|
+
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v2
|
19
|
+
- name: Set up Ruby 2.6
|
20
|
+
uses: actions/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: 2.6.x
|
23
|
+
|
24
|
+
- name: Publish to GPR
|
25
|
+
run: |
|
26
|
+
mkdir -p $HOME/.gem
|
27
|
+
touch $HOME/.gem/credentials
|
28
|
+
chmod 0600 $HOME/.gem/credentials
|
29
|
+
printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
30
|
+
gem build *.gemspec
|
31
|
+
gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
|
32
|
+
env:
|
33
|
+
GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
|
34
|
+
OWNER: ${{ github.repository_owner }}
|
35
|
+
|
36
|
+
- name: Publish to RubyGems
|
37
|
+
run: |
|
38
|
+
mkdir -p $HOME/.gem
|
39
|
+
touch $HOME/.gem/credentials
|
40
|
+
chmod 0600 $HOME/.gem/credentials
|
41
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
42
|
+
gem build *.gemspec
|
43
|
+
gem push *.gem
|
44
|
+
env:
|
45
|
+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,109 +1,102 @@
|
|
1
|
-
require: rubocop-rspec
|
2
|
-
|
3
1
|
AllCops:
|
2
|
+
NewCops: enable
|
3
|
+
TargetRubyVersion: 3.0
|
4
4
|
Include:
|
5
5
|
- 'lib/**/*'
|
6
|
-
|
7
|
-
- '
|
8
|
-
- '
|
9
|
-
- '
|
6
|
+
- 'spec/**/*_spec.rb'
|
7
|
+
- 'Gemfile'
|
8
|
+
- 'Rakefile'
|
9
|
+
- '*.gemspace'
|
10
10
|
DisplayCopNames: true
|
11
|
-
TargetRubyVersion: 2.1
|
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
|
-
###
|
30
|
+
### Metrics ------------------------------------------------------------
|
39
31
|
|
40
|
-
|
41
|
-
|
32
|
+
Metrics:
|
33
|
+
Enabled: false
|
42
34
|
|
43
|
-
|
35
|
+
### Naming -------------------------------------------------------------
|
36
|
+
|
37
|
+
Naming/MethodParameterName:
|
44
38
|
Enabled: false
|
45
39
|
|
46
|
-
|
40
|
+
Naming/PredicateName:
|
47
41
|
Enabled: false
|
48
42
|
|
49
|
-
|
50
|
-
|
43
|
+
### Styles -------------------------------------------------------------
|
44
|
+
|
45
|
+
Style/CombinableLoops:
|
46
|
+
Enabled: false # there is case that it can't combined loop.
|
51
47
|
|
52
|
-
Style/
|
53
|
-
|
48
|
+
Style/Documentation:
|
49
|
+
Enabled: false
|
54
50
|
|
55
|
-
Style/
|
51
|
+
Style/FrozenStringLiteralComment:
|
56
52
|
Enabled: false
|
57
53
|
|
58
|
-
Style/
|
59
|
-
|
54
|
+
Style/NumericPredicate:
|
55
|
+
Enabled: false # it is easier to read `size > 0` than `size.positive?`
|
56
|
+
|
57
|
+
Style/OptionalBooleanParameter:
|
58
|
+
Enabled: false # it is necessary to change distructively.
|
60
59
|
|
61
60
|
Style/ParallelAssignment:
|
62
|
-
Enabled: false
|
61
|
+
Enabled: false # one line style is compact.
|
63
62
|
|
64
|
-
Style/
|
63
|
+
Style/PreferredHashMethods:
|
65
64
|
Enabled: false
|
66
65
|
|
67
|
-
Style/
|
68
|
-
Enabled: false
|
66
|
+
Style/SymbolArray:
|
67
|
+
Enabled: false # general array literal is easy to read. no problem.
|
69
68
|
|
70
|
-
Style/
|
71
|
-
Enabled: false #
|
69
|
+
Style/ZeroLengthPredicate:
|
70
|
+
Enabled: false # it is so easy to read `a.size > 0` as `!a.empty?`
|
72
71
|
|
73
|
-
###
|
72
|
+
### RSpec --------------------------------------------------------------
|
74
73
|
|
75
|
-
|
76
|
-
|
74
|
+
RSpec/MessageSpies:
|
75
|
+
EnforcedStyle: receive
|
77
76
|
|
78
|
-
|
79
|
-
|
80
|
-
- 'spec/**/*'
|
77
|
+
RSpec/DescribedClass:
|
78
|
+
Enabled: false
|
81
79
|
|
82
|
-
|
83
|
-
Max:
|
80
|
+
RSpec/ExampleLength:
|
81
|
+
Max: 25
|
84
82
|
|
85
|
-
|
86
|
-
|
83
|
+
RSpec/FilePath:
|
84
|
+
Enabled: false # too many offense
|
87
85
|
|
88
|
-
|
89
|
-
|
86
|
+
RSpec/ImplicitSubject:
|
87
|
+
Enabled: false # too many offenses
|
90
88
|
|
91
|
-
|
89
|
+
RSpec/MultipleExpectations:
|
92
90
|
Max: 15
|
93
91
|
|
94
|
-
|
95
|
-
Max:
|
92
|
+
RSpec/NestedGroups:
|
93
|
+
Max: 5
|
96
94
|
|
97
|
-
|
95
|
+
RSpec/PredicateMatcher:
|
98
96
|
Enabled: false
|
99
97
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
### RSpec --------------------------------------------------------------
|
104
|
-
|
105
|
-
RSpec/MessageSpies:
|
106
|
-
EnforcedStyle: receive
|
98
|
+
RSpec/RepeatedExampleGroupBody:
|
99
|
+
Enabled: false
|
107
100
|
|
108
|
-
RSpec/
|
109
|
-
|
101
|
+
RSpec/RepeatedExampleGroupDescription:
|
102
|
+
Enabled: false # too many offenses
|
data/.yardopts
CHANGED
data/README.md
CHANGED
@@ -1,57 +1,57 @@
|
|
1
1
|
# NetworkX.rb
|
2
2
|
|
3
|
-
[NetworkX](https://networkx.github.io/) is a very popular Python library, that handles various use-cases of the Graph Data Structure.
|
3
|
+
[NetworkX](https://networkx.github.io/) is a very popular Python library, that handles various use-cases of the Graph Data Structure.
|
4
|
+
This project intends to provide a working alternative to the Ruby community, by closely mimicing as many features as possible.
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
### List of contents
|
6
|
+
## List of contents
|
8
7
|
|
9
8
|
- [Installing](#installing)
|
9
|
+
- [Document](#document)
|
10
10
|
- [Roadmap](#roadmap)
|
11
11
|
- [Contributing](#contributing)
|
12
12
|
- [License](#license)
|
13
13
|
|
14
|
-
|
14
|
+
## Installing
|
15
15
|
|
16
|
-
- Clone the repository
|
16
|
+
- Clone the repository or fork
|
17
|
+
- Clone this repository with `git clone https://github.com/SciRuby/networkx.rb.git`
|
18
|
+
- or You can fork and do clone it.
|
17
19
|
- Navigate to networkx with `cd networkx.rb`
|
18
20
|
- Install dependencies with `gem install bundler && bundle install`
|
19
|
-
- Install networkx gem with `rake install`
|
20
|
-
- Start checking out in PRY / IRB console :
|
21
21
|
|
22
22
|
```ruby
|
23
23
|
require 'networkx'
|
24
|
-
#=> true
|
25
24
|
|
26
|
-
|
27
|
-
g = NetworkX::Graph.new()
|
25
|
+
g = NetworkX::Graph.new
|
28
26
|
g.add_edge('start', 'stop')
|
29
27
|
```
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
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 :
|
29
|
+
## Document
|
34
30
|
|
35
|
-
|
31
|
+
You can read [Document](https://SciRuby.github.io/networkx.rb/) for this library.
|
36
32
|
|
37
|
-
|
33
|
+
## Roadmap
|
38
34
|
|
39
|
-
|
40
|
-
|
41
|
-
- `DirectedGraph` : Inherits from `Graph` class. Uses directions between `Edge`s.
|
35
|
+
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 :
|
42
36
|
|
43
|
-
|
37
|
+
- `Node` : This class should be capable of handling different types of nodes (not just `String` / `Integer`).
|
38
|
+
A possible complex use-case could be XML nodes.
|
44
39
|
|
45
|
-
|
40
|
+
- `Edge` : This class should be capable of handling different types of edges.
|
41
|
+
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.
|
46
42
|
|
47
|
-
|
43
|
+
- `Graph` : The simplest of graphs.
|
44
|
+
This class handles just connections between different `Node`s via `Edge`s.
|
48
45
|
|
49
|
-
|
46
|
+
- `DirectedGraph` : Inherits from `Graph` class.
|
47
|
+
Uses directions between `Edge`s.
|
50
48
|
|
51
|
-
|
49
|
+
## Contributing
|
52
50
|
|
53
|
-
|
51
|
+
Your contributions are always welcome!
|
52
|
+
Please have a look at the [contribution guidelines](CONTRIBUTING.md) first. :tada:
|
54
53
|
|
55
|
-
|
54
|
+
## License
|
56
55
|
|
57
|
-
The MIT License 2017 - [Athitya Kumar](https://github.com/athityakumar).
|
56
|
+
The MIT License 2017 - [Athitya Kumar](https://github.com/athityakumar).
|
57
|
+
Please have a look at the [LICENSE.md](LICENSE.md) for more details.
|
data/Rakefile
CHANGED
@@ -0,0 +1,62 @@
|
|
1
|
+
module NetworkX
|
2
|
+
# Returns all cliques in the graph
|
3
|
+
#
|
4
|
+
# @param graph [Graph, MultiGraph] a graph
|
5
|
+
#
|
6
|
+
# @return [Array<Array<Object>>] Arrays of nodes in the cliques
|
7
|
+
def self.find_cliques(graph)
|
8
|
+
return nil if graph.nodes.empty?
|
9
|
+
|
10
|
+
q = [nil]
|
11
|
+
adj = {}
|
12
|
+
graph.nodes.each_key { |u| adj[u] = [] }
|
13
|
+
graph.adj.each { |u, u_edges| u_edges.each_key { |v| adj[u] << v if u != v } }
|
14
|
+
|
15
|
+
subg = graph.nodes.keys
|
16
|
+
cand = graph.nodes.keys
|
17
|
+
u = subg.max { |n1, n2| (cand & adj[n1]).length <=> (cand & adj[n2]).length }
|
18
|
+
ext_u = cand - adj[u]
|
19
|
+
stack = []
|
20
|
+
cliques = []
|
21
|
+
begin
|
22
|
+
loop do
|
23
|
+
if ext_u.empty?
|
24
|
+
q.pop
|
25
|
+
subg, cand, ext_u = stack.pop
|
26
|
+
else
|
27
|
+
q_elem = ext_u.pop
|
28
|
+
cand.delete(q_elem)
|
29
|
+
q[-1] = q_elem
|
30
|
+
adj_q = adj[q_elem]
|
31
|
+
subg_q = subg & adj_q
|
32
|
+
if subg_q.empty?
|
33
|
+
cliques << q[0..(q.length - 1)]
|
34
|
+
else
|
35
|
+
cand_q = cand & adj_q
|
36
|
+
unless cand_q.empty?
|
37
|
+
stack << [subg, cand, ext_u]
|
38
|
+
q << nil
|
39
|
+
subg = subg_q
|
40
|
+
cand = cand_q
|
41
|
+
u = subg.max { |n1, n2| (cand & adj[n1]).length <=> (cand & adj[n2]).length }
|
42
|
+
ext_u = cand - adj[u]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
rescue NoMethodError
|
48
|
+
cliques
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the number of cliques in a graph containing a node
|
53
|
+
#
|
54
|
+
# @param graph [Graph, MultiGraph] a graph
|
55
|
+
# @param node [Object] a node
|
56
|
+
#
|
57
|
+
# @return [Numeric] Number of cliques containing the given node
|
58
|
+
def self.number_of_cliques(graph, node)
|
59
|
+
cliques = find_cliques(graph)
|
60
|
+
cliques.count { |c| c.include?(node) }
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module NetworkX
|
2
|
+
# Returns all basis cycles in graph
|
3
|
+
#
|
4
|
+
# @param graph [Graph] a graph
|
5
|
+
# @param root [Object, Nil] root for the graph cycles
|
6
|
+
#
|
7
|
+
# @return [Array<Array<Object>>] Arrays of nodes in the cycles
|
8
|
+
def self.cycle_basis(graph, root = nil)
|
9
|
+
gnodes = graph.nodes.keys
|
10
|
+
cycles = []
|
11
|
+
until gnodes.empty?
|
12
|
+
root = gnodes.shift if root.nil?
|
13
|
+
stack = [root]
|
14
|
+
pred = {root => root}
|
15
|
+
used = {root => []}
|
16
|
+
until stack.empty?
|
17
|
+
z = stack.shift
|
18
|
+
zused = used[z]
|
19
|
+
graph.adj[z].each_key do |u|
|
20
|
+
if !used.has_key?(u)
|
21
|
+
pred[u] = z
|
22
|
+
stack << u
|
23
|
+
used[u] = [z]
|
24
|
+
elsif u == z
|
25
|
+
cycles << [z]
|
26
|
+
elsif !zused.include?(u)
|
27
|
+
pn = used[u]
|
28
|
+
cycle = [u, z]
|
29
|
+
p = pred[z]
|
30
|
+
until pn.include?(p)
|
31
|
+
cycle << p
|
32
|
+
p = pred[p]
|
33
|
+
end
|
34
|
+
cycle << p
|
35
|
+
cycles << cycle
|
36
|
+
used[u] << z
|
37
|
+
used[u] = used[u].uniq
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
gnodes -= pred.keys
|
42
|
+
root = nil
|
43
|
+
end
|
44
|
+
cycles
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the cycle containing the given node
|
48
|
+
#
|
49
|
+
# @param graph [Graph, DiGraph] a graph
|
50
|
+
# @param node [Object] node to be included in the cycle
|
51
|
+
#
|
52
|
+
# @return [Array<Array<Object>>] Arrays of nodes in the cycle
|
53
|
+
def self.find_cycle(graph, node)
|
54
|
+
explored = Set.new
|
55
|
+
cycle = []
|
56
|
+
final_node = nil
|
57
|
+
unless explored.include?(node)
|
58
|
+
edges = []
|
59
|
+
seen = [node]
|
60
|
+
active_nodes = [node]
|
61
|
+
previous_head = nil
|
62
|
+
|
63
|
+
edge_dfs(graph, node).each do |edge|
|
64
|
+
tail, head = edge
|
65
|
+
next if explored.include?(head)
|
66
|
+
|
67
|
+
if !previous_head.nil? && tail != previous_head
|
68
|
+
loop do
|
69
|
+
popped_edge = edges.pop
|
70
|
+
if popped_edge.nil?
|
71
|
+
edges = []
|
72
|
+
active_nodes = [tail]
|
73
|
+
break
|
74
|
+
else
|
75
|
+
popped_head = popped_edge[1]
|
76
|
+
active_nodes.delete(popped_head)
|
77
|
+
end
|
78
|
+
|
79
|
+
unless edges.empty?
|
80
|
+
last_head = edges[-1][1]
|
81
|
+
break if tail == last_head
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
edges << edge
|
86
|
+
|
87
|
+
if active_nodes.include?(head)
|
88
|
+
cycle += edges
|
89
|
+
final_node = head
|
90
|
+
break
|
91
|
+
else
|
92
|
+
seen << head
|
93
|
+
active_nodes << head
|
94
|
+
previous_head = head
|
95
|
+
end
|
96
|
+
end
|
97
|
+
cycle.each_with_index { |edge, i| return cycle[i..(cycle.length - 1)] if final_node == edge[0] }
|
98
|
+
end
|
99
|
+
raise ArgumentError, 'No cycle found!' if cycle.empty?
|
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
|
114
|
+
end
|