networkx 0.1.0 → 0.2.0

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