networkx 0.1.0 → 0.2.0

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 (60) hide show
  1. checksums.yaml +5 -5
  2. data/{CODE_OF_CONDUCT.md → .github/CODE_OF_CONDUCT.md} +0 -0
  3. data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +21 -11
  4. data/.github/ISSUE_TEMPLATE.md +15 -0
  5. data/.github/PULL_REQUEST_TEMPLATE.md +10 -0
  6. data/.github/workflows/ci.yml +17 -0
  7. data/.github/workflows/doc.yml +23 -0
  8. data/.github/workflows/gem-push.yml +45 -0
  9. data/.rspec +0 -1
  10. data/.rubocop.yml +56 -63
  11. data/.yardopts +0 -1
  12. data/README.md +27 -27
  13. data/Rakefile +2 -3
  14. data/lib/networkx/auxillary_functions/cliques.rb +62 -0
  15. data/lib/networkx/auxillary_functions/cycles.rb +114 -0
  16. data/lib/networkx/auxillary_functions/dag.rb +59 -0
  17. data/lib/networkx/auxillary_functions/eccentricity.rb +37 -0
  18. data/lib/networkx/auxillary_functions/mis.rb +23 -0
  19. data/lib/networkx/auxillary_functions/mst.rb +33 -0
  20. data/lib/networkx/auxillary_functions/union_find.rb +104 -0
  21. data/lib/networkx/auxillary_functions/vitality.rb +13 -0
  22. data/lib/networkx/auxillary_functions/wiener.rb +13 -0
  23. data/lib/networkx/converters/to_csv.rb +45 -0
  24. data/lib/networkx/converters/to_json.rb +37 -0
  25. data/lib/networkx/digraph.rb +234 -0
  26. data/lib/networkx/flow/capacityscaling.rb +249 -0
  27. data/lib/networkx/flow/edmondskarp.rb +115 -0
  28. data/lib/networkx/flow/preflowpush.rb +249 -0
  29. data/lib/networkx/flow/shortestaugmentingpath.rb +154 -0
  30. data/lib/networkx/flow/utils.rb +139 -0
  31. data/lib/networkx/graph.rb +448 -0
  32. data/lib/networkx/link_analysis/hits.rb +59 -0
  33. data/lib/networkx/link_analysis/pagerank.rb +89 -0
  34. data/lib/networkx/multidigraph.rb +249 -0
  35. data/lib/networkx/multigraph.rb +199 -0
  36. data/lib/networkx/operators/all.rb +65 -0
  37. data/lib/networkx/operators/binary.rb +222 -0
  38. data/lib/networkx/operators/product.rb +201 -0
  39. data/lib/networkx/operators/unary.rb +17 -0
  40. data/lib/networkx/others/bridges.rb +30 -0
  41. data/lib/networkx/others/generators.rb +237 -0
  42. data/lib/networkx/others/grid_2d_graph.rb +38 -0
  43. data/lib/networkx/others/info.rb +11 -0
  44. data/lib/networkx/others/number_connected_components.rb +17 -0
  45. data/lib/networkx/others/reads.rb +52 -0
  46. data/lib/networkx/shortest_path/astar.rb +73 -0
  47. data/lib/networkx/shortest_path/dense.rb +29 -0
  48. data/lib/networkx/shortest_path/unweighted.rb +136 -0
  49. data/lib/networkx/shortest_path/weighted.rb +417 -0
  50. data/lib/networkx/to_matrix.rb +51 -0
  51. data/lib/networkx/traversals/bfs.rb +110 -0
  52. data/lib/networkx/traversals/dfs.rb +135 -0
  53. data/lib/networkx/traversals/edge_dfs.rb +114 -0
  54. data/lib/networkx/version.rb +1 -1
  55. data/lib/networkx.rb +43 -1
  56. data/networkx.gemspec +14 -12
  57. metadata +118 -62
  58. data/.rspec_formatter.rb +0 -24
  59. data/.travis.yml +0 -18
  60. data/Guardfile +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3f43ce74dd6bd8fbe91d6b5f29f3b7af355881e9
4
- data.tar.gz: 0275c9f6161b6bcf973af9f18a989969ce757bd0
2
+ SHA256:
3
+ metadata.gz: 4e86cfdb083751f6aa9d45d894dd4a83ec75623acd237c6cdc8e7cd356306409
4
+ data.tar.gz: 60ef78a9da3df8d7f61e297af48873795b21d9675138e953dd160597d9bfdc09
5
5
  SHA512:
6
- metadata.gz: 17623a41e26fceebed54169c423dbe95a3ee59456a3cc4d3d888e74b70d8e2a58b7329d1565026babdc5196ae37b19422432eaa6e74cce03bbcef21c883c5312
7
- data.tar.gz: 8727b100efab027667eb7c8f3aa13bb3396b56e28a21437b3e21eda904bb99e7ebc9fc35a31451e3661f909faba8c6e57a14c2be1c832100526c1dcfedda4c1e
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. Clone this repository and install all the required gem dependencies.
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/athityakumar/daru-io.git
18
- cd daru-io
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 any gem dependencies required, appropriately to the gemspec file or Gemfile.
25
+ 3. Add code (, test, and YARD documentation).
26
26
 
27
- 4. Add code and YARD documentation.
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
- 7. Run the rubocop for static code quality comments.
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
- 8. Send a Pull Request back to this repository. :tada:
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
@@ -1,2 +1 @@
1
- --color
2
1
  --require spec_helper
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
- Exclude:
7
- - 'vendor/**/*'
8
- - 'benchmarks/*'
9
- - 'profile/*'
6
+ - 'spec/**/*_spec.rb'
7
+ - 'Gemfile'
8
+ - 'Rakefile'
9
+ - '*.gemspace'
10
10
  DisplayCopNames: true
11
- TargetRubyVersion: 2.1
12
11
 
13
- # Preferred codebase style ---------------------------------------------
12
+ require:
13
+ - rubocop-rspec
14
+ - rubocop-rake
14
15
 
15
16
  ### Layouts ------------------------------------------------------------
16
17
 
17
- Layout/AlignParameters:
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/SpaceAroundEqualsInParameterDefault:
27
- EnforcedStyle: no_space
28
-
29
- Layout/SpaceAroundOperators:
21
+ Layout/SpaceBeforeBlockBraces:
30
22
  Enabled: false
31
23
 
32
24
  Layout/SpaceInsideBlockBraces:
33
- EnforcedStyle: space
25
+ Enabled: false
34
26
 
35
27
  Layout/SpaceInsideHashLiteralBraces:
36
28
  EnforcedStyle: no_space
37
29
 
38
- ### Styles -------------------------------------------------------------
30
+ ### Metrics ------------------------------------------------------------
39
31
 
40
- Style/AndOr:
41
- EnforcedStyle: conditionals
32
+ Metrics:
33
+ Enabled: false
42
34
 
43
- Style/DoubleNegation:
35
+ ### Naming -------------------------------------------------------------
36
+
37
+ Naming/MethodParameterName:
44
38
  Enabled: false
45
39
 
46
- Style/EmptyCaseCondition:
40
+ Naming/PredicateName:
47
41
  Enabled: false
48
42
 
49
- Style/EmptyElse:
50
- EnforcedStyle: empty
43
+ ### Styles -------------------------------------------------------------
44
+
45
+ Style/CombinableLoops:
46
+ Enabled: false # there is case that it can't combined loop.
51
47
 
52
- Style/EmptyMethod:
53
- EnforcedStyle: compact
48
+ Style/Documentation:
49
+ Enabled: false
54
50
 
55
- Style/FileName:
51
+ Style/FrozenStringLiteralComment:
56
52
  Enabled: false
57
53
 
58
- Style/FormatString:
59
- EnforcedStyle: percent
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/SingleLineBlockParams:
63
+ Style/PreferredHashMethods:
65
64
  Enabled: false
66
65
 
67
- Style/PerlBackrefs:
68
- Enabled: false
66
+ Style/SymbolArray:
67
+ Enabled: false # general array literal is easy to read. no problem.
69
68
 
70
- Style/Documentation:
71
- Enabled: false # TODO
69
+ Style/ZeroLengthPredicate:
70
+ Enabled: false # it is so easy to read `a.size > 0` as `!a.empty?`
72
71
 
73
- ### Metrics ------------------------------------------------------------
72
+ ### RSpec --------------------------------------------------------------
74
73
 
75
- Metrics/AbcSize:
76
- Max: 20
74
+ RSpec/MessageSpies:
75
+ EnforcedStyle: receive
77
76
 
78
- Metrics/BlockLength:
79
- Exclude:
80
- - 'spec/**/*'
77
+ RSpec/DescribedClass:
78
+ Enabled: false
81
79
 
82
- Metrics/ClassLength:
83
- Max: 200
80
+ RSpec/ExampleLength:
81
+ Max: 25
84
82
 
85
- Metrics/CyclomaticComplexity:
86
- Max: 7
83
+ RSpec/FilePath:
84
+ Enabled: false # too many offense
87
85
 
88
- Metrics/LineLength:
89
- Max: 120
86
+ RSpec/ImplicitSubject:
87
+ Enabled: false # too many offenses
90
88
 
91
- Metrics/MethodLength:
89
+ RSpec/MultipleExpectations:
92
90
  Max: 15
93
91
 
94
- Metrics/ModuleLength:
95
- Max: 200
92
+ RSpec/NestedGroups:
93
+ Max: 5
96
94
 
97
- Style/MultilineBlockChain:
95
+ RSpec/PredicateMatcher:
98
96
  Enabled: false
99
97
 
100
- Metrics/ParameterLists:
101
- Max: 10
102
-
103
- ### RSpec --------------------------------------------------------------
104
-
105
- RSpec/MessageSpies:
106
- EnforcedStyle: receive
98
+ RSpec/RepeatedExampleGroupBody:
99
+ Enabled: false
107
100
 
108
- RSpec/NestedGroups:
109
- Max: 5
101
+ RSpec/RepeatedExampleGroupDescription:
102
+ Enabled: false # too many offenses
data/.yardopts CHANGED
@@ -1,2 +1 @@
1
1
  --markup markdown
2
- --markup-provider redcarpet
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. This project intends to provide a working alternative to the Ruby community, by closely mimicing as many features as possible.
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
- *This project has begun just now, and a v0.1.0 release with basic Graph classes can be expected by January 2018.*
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
- ### Installing
14
+ ## Installing
15
15
 
16
- - Clone the repository with `git clone git@github.com:athityakumar/networkx.rb.git`
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
- # Yet to be implemented
27
- g = NetworkX::Graph.new()
25
+ g = NetworkX::Graph.new
28
26
  g.add_edge('start', 'stop')
29
27
  ```
30
28
 
31
- ### Roadmap
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
- - `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.
31
+ You can read [Document](https://SciRuby.github.io/networkx.rb/) for this library.
36
32
 
37
- - `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.
33
+ ## Roadmap
38
34
 
39
- - `Graph` : The simplest of graphs. This class handles just connections between different `Node`s via `Edge`s.
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
- [(Back to top)](#list-of-contents)
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
- 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.
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
- ### Contributing
43
+ - `Graph` : The simplest of graphs.
44
+ This class handles just connections between different `Node`s via `Edge`s.
48
45
 
49
- [(Back to top)](#list-of-contents)
46
+ - `DirectedGraph` : Inherits from `Graph` class.
47
+ Uses directions between `Edge`s.
50
48
 
51
- Your contributions are always welcome! Please have a look at the [contribution guidelines](CONTRIBUTING.md) first. :tada:
49
+ ## Contributing
52
50
 
53
- ### License
51
+ Your contributions are always welcome!
52
+ Please have a look at the [contribution guidelines](CONTRIBUTING.md) first. :tada:
54
53
 
55
- [(Back to top)](#list-of-contents)
54
+ ## License
56
55
 
57
- The MIT License 2017 - [Athitya Kumar](https://github.com/athityakumar). Please have a look at the [LICENSE.md](LICENSE.md) for more details.
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
@@ -1,7 +1,6 @@
1
- require 'bundler/setup'
1
+ require 'bundler/gem_tasks'
2
2
 
3
- require 'rubygems/tasks'
4
- Gem::Tasks.new
3
+ require 'bundler/setup'
5
4
 
6
5
  require 'rspec/core/rake_task'
7
6
  RSpec::Core::RakeTask.new
@@ -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