networkx 0.2.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -2
- data/README.md +20 -22
- data/lib/networkx/auxillary_functions/cliques.rb +4 -4
- data/lib/networkx/auxillary_functions/cycles.rb +1 -1
- data/lib/networkx/auxillary_functions/dag.rb +3 -3
- data/lib/networkx/auxillary_functions/eccentricity.rb +2 -2
- data/lib/networkx/auxillary_functions/mis.rb +4 -2
- data/lib/networkx/auxillary_functions/mst.rb +2 -2
- data/lib/networkx/auxillary_functions/vitality.rb +1 -1
- data/lib/networkx/converters/to_csv.rb +1 -1
- data/lib/networkx/flow/capacityscaling.rb +14 -12
- data/lib/networkx/flow/edmondskarp.rb +2 -2
- data/lib/networkx/flow/preflowpush.rb +3 -3
- data/lib/networkx/flow/shortestaugmentingpath.rb +3 -3
- data/lib/networkx/flow/utils.rb +1 -1
- data/lib/networkx/graph.rb +2 -3
- data/lib/networkx/link_analysis/hits.rb +1 -1
- data/lib/networkx/link_analysis/pagerank.rb +3 -47
- data/lib/networkx/operators/binary.rb +24 -13
- data/lib/networkx/operators/product.rb +8 -8
- data/lib/networkx/operators/unary.rb +2 -2
- data/lib/networkx/shortest_path/dense.rb +1 -1
- data/lib/networkx/shortest_path/unweighted.rb +3 -3
- data/lib/networkx/shortest_path/weighted.rb +10 -10
- data/lib/networkx/to_matrix.rb +2 -2
- data/lib/networkx/traversals/dfs.rb +1 -1
- data/lib/networkx/version.rb +1 -1
- data/networkx.gemspec +5 -1
- metadata +6 -6
- data/.github/workflows/gem-push.yml +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bce7e05d9da7dd9774ad976cb82c8de0bd5847be9fb0dfc07af1042568446a9
|
4
|
+
data.tar.gz: '085683454ca374c50f594509e13da7c3114131e54936a11f6daf4dd3f4924b29'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91cdd246c4692b87a90405676f58a330257ecc02d6cdc9e55c79428afc4d22a9d621fd175d6408e0a7f6aafec50deaa8cd2eb9a0d5ef49360befd5ae8e88dd30
|
7
|
+
data.tar.gz: 79bade11b9709a78102bb83d13d77a3abe661fbaf75bdc18dbc5f822e71d6c5ecd53c8b7c46324cf9d6eda1df570f299c77191e8079426c50e4fd5b3f87e7ffd
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -1,23 +1,37 @@
|
|
1
1
|
# NetworkX.rb
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/networkx.svg)](https://badge.fury.io/rb/networkx)
|
4
|
+
|
3
5
|
[NetworkX](https://networkx.github.io/) is a very popular Python library, that handles various use-cases of the Graph Data Structure.
|
4
6
|
This project intends to provide a working alternative to the Ruby community, by closely mimicing as many features as possible.
|
5
7
|
|
6
8
|
## List of contents
|
7
9
|
|
8
10
|
- [Installing](#installing)
|
11
|
+
- [Usage](#Usage)
|
9
12
|
- [Document](#document)
|
10
|
-
- [Roadmap](#roadmap)
|
11
13
|
- [Contributing](#contributing)
|
12
14
|
- [License](#license)
|
13
15
|
|
14
16
|
## Installing
|
15
17
|
|
16
|
-
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
- install it yourself as:
|
19
|
+
```console
|
20
|
+
$ gem install networkx
|
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
|
21
35
|
|
22
36
|
```ruby
|
23
37
|
require 'networkx'
|
@@ -30,22 +44,6 @@ g.add_edge('start', 'stop')
|
|
30
44
|
|
31
45
|
You can read [Document](https://SciRuby.github.io/networkx.rb/) for this library.
|
32
46
|
|
33
|
-
## Roadmap
|
34
|
-
|
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 :
|
36
|
-
|
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.
|
39
|
-
|
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.
|
42
|
-
|
43
|
-
- `Graph` : The simplest of graphs.
|
44
|
-
This class handles just connections between different `Node`s via `Edge`s.
|
45
|
-
|
46
|
-
- `DirectedGraph` : Inherits from `Graph` class.
|
47
|
-
Uses directions between `Edge`s.
|
48
|
-
|
49
47
|
## Contributing
|
50
48
|
|
51
49
|
Your contributions are always welcome!
|
@@ -5,15 +5,15 @@ module NetworkX
|
|
5
5
|
#
|
6
6
|
# @return [Array<Array<Object>>] Arrays of nodes in the cliques
|
7
7
|
def self.find_cliques(graph)
|
8
|
-
return nil if graph.nodes.empty?
|
8
|
+
return nil if graph.nodes(data: true).empty?
|
9
9
|
|
10
10
|
q = [nil]
|
11
11
|
adj = {}
|
12
|
-
graph.nodes.each_key { |u| adj[u] = [] }
|
12
|
+
graph.nodes(data: true).each_key { |u| adj[u] = [] }
|
13
13
|
graph.adj.each { |u, u_edges| u_edges.each_key { |v| adj[u] << v if u != v } }
|
14
14
|
|
15
|
-
subg = graph.nodes.keys
|
16
|
-
cand = graph.nodes.keys
|
15
|
+
subg = graph.nodes(data: true).keys
|
16
|
+
cand = graph.nodes(data: true).keys
|
17
17
|
u = subg.max { |n1, n2| (cand & adj[n1]).length <=> (cand & adj[n2]).length }
|
18
18
|
ext_u = cand - adj[u]
|
19
19
|
stack = []
|
@@ -6,7 +6,7 @@ module NetworkX
|
|
6
6
|
#
|
7
7
|
# @return [Array<Array<Object>>] Arrays of nodes in the cycles
|
8
8
|
def self.cycle_basis(graph, root = nil)
|
9
|
-
gnodes = graph.nodes.keys
|
9
|
+
gnodes = graph.nodes(data: true).keys
|
10
10
|
cycles = []
|
11
11
|
until gnodes.empty?
|
12
12
|
root = gnodes.shift if root.nil?
|
@@ -34,14 +34,14 @@ module NetworkX
|
|
34
34
|
raise ArgumentError, 'Topological Sort not defined on undirected graphs!' unless graph.directed?
|
35
35
|
|
36
36
|
nodes = []
|
37
|
-
indegree_map = graph.nodes.each_key.map do |u|
|
37
|
+
indegree_map = graph.nodes(data: true).each_key.map do |u|
|
38
38
|
[u, graph.in_degree(u)] if graph.in_degree(u).positive?
|
39
39
|
end.compact.to_h
|
40
|
-
zero_indegree = graph.nodes.each_key.select { |u| graph.in_degree(u).zero? }
|
40
|
+
zero_indegree = graph.nodes(data: true).each_key.select { |u| graph.in_degree(u).zero? }
|
41
41
|
|
42
42
|
until zero_indegree.empty?
|
43
43
|
node = zero_indegree.shift
|
44
|
-
raise ArgumentError, 'Graph changed during iteration!' unless graph.nodes.has_key?(node)
|
44
|
+
raise ArgumentError, 'Graph changed during iteration!' unless graph.nodes(data: true).has_key?(node)
|
45
45
|
|
46
46
|
graph.adj[node].each_key do |child|
|
47
47
|
indegree_map[child] -= 1
|
@@ -7,10 +7,10 @@ module NetworkX
|
|
7
7
|
# @return [Array<Numeric>, Numeric] eccentricity/eccentricites of all nodes
|
8
8
|
def self.eccentricity(graph, node = nil)
|
9
9
|
e = {}
|
10
|
-
graph.nodes.each do |u, _|
|
10
|
+
graph.nodes(data: true).each do |u, _|
|
11
11
|
length = single_source_shortest_path_length(graph, u)
|
12
12
|
l = length.length
|
13
|
-
raise ArgumentError, 'Found infinite path length!' unless l == graph.nodes.length
|
13
|
+
raise ArgumentError, 'Found infinite path length!' unless l == graph.nodes(data: true).length
|
14
14
|
|
15
15
|
e[u] = length.max_by { |a| a[1] }[1]
|
16
16
|
end
|
@@ -6,13 +6,15 @@ module NetworkX
|
|
6
6
|
#
|
7
7
|
# @return [Numeric] radius of the graph
|
8
8
|
def self.maximal_independent_set(graph, nodes)
|
9
|
-
|
9
|
+
if (graph.nodes(data: true).keys - nodes).empty?
|
10
|
+
raise 'The array containing the nodes should be a subset of the graph!'
|
11
|
+
end
|
10
12
|
|
11
13
|
neighbours = []
|
12
14
|
nodes.each { |u| graph.adj[u].each { |v, _| neighbours |= [v] } }
|
13
15
|
raise 'Nodes is not an independent set of graph!' if (neighbours - nodes).empty?
|
14
16
|
|
15
|
-
available_nodes = graph.nodes.keys - (neighbours | nodes)
|
17
|
+
available_nodes = graph.nodes(data: true).keys - (neighbours | nodes)
|
16
18
|
until available_nodes.empty?
|
17
19
|
node = available_nodes.sample
|
18
20
|
nodes << node
|
@@ -20,8 +20,8 @@ module NetworkX
|
|
20
20
|
mst = Marshal.load(Marshal.dump(graph))
|
21
21
|
mst.clear
|
22
22
|
edges = get_edges_weights(graph).sort_by { |a| a[1] }
|
23
|
-
union_find = UnionFind.new(graph.nodes.keys)
|
24
|
-
while edges.any? && mst.nodes.length <= graph.nodes.length
|
23
|
+
union_find = UnionFind.new(graph.nodes(data: true).keys)
|
24
|
+
while edges.any? && mst.nodes(data: true).length <= graph.nodes(data: true).length
|
25
25
|
edge = edges.shift
|
26
26
|
unless union_find.connected?(edge[0][0], edge[0][1])
|
27
27
|
union_find.union(edge[0][0], edge[0][1])
|
@@ -7,7 +7,7 @@ module NetworkX
|
|
7
7
|
# @return [Numeric] closeness vitality of the given node
|
8
8
|
def self.closeness_vitality(graph, node)
|
9
9
|
before = wiener_index(graph)
|
10
|
-
after = wiener_index(graph.subgraph(graph.nodes.keys - [node]))
|
10
|
+
after = wiener_index(graph.subgraph(graph.nodes(data: true).keys - [node]))
|
11
11
|
before - after
|
12
12
|
end
|
13
13
|
end
|
@@ -11,7 +11,7 @@ module NetworkX
|
|
11
11
|
# @return [Boolean] whether there exists a negative cycle in graph
|
12
12
|
def self.negative_edge_cycle(graph)
|
13
13
|
newnode = generate_unique_node
|
14
|
-
graph.add_edges(graph.nodes.keys.map { |n| [newnode, n] })
|
14
|
+
graph.add_edges(graph.nodes(data: true).keys.map { |n| [newnode, n] })
|
15
15
|
begin
|
16
16
|
bellmanford_predecesor_distance(graph, newnode)
|
17
17
|
rescue ArgumentError
|
@@ -25,10 +25,10 @@ module NetworkX
|
|
25
25
|
# Detects the unboundedness in the residual graph
|
26
26
|
def self._detect_unboundedness(residual)
|
27
27
|
g = NetworkX::DiGraph.new
|
28
|
-
g.add_nodes(residual.nodes.keys.zip(residual.nodes.values))
|
28
|
+
g.add_nodes(residual.nodes(data: true).keys.zip(residual.nodes(data: true).values))
|
29
29
|
inf = residual.graph[:inf]
|
30
30
|
|
31
|
-
residual.nodes.each do |u, _attr|
|
31
|
+
residual.nodes(data: true).each do |u, _attr|
|
32
32
|
residual.adj[u].each do |v, uv_attrs|
|
33
33
|
w = inf
|
34
34
|
uv_attrs.each { |_key, edge_attrs| w = [w, edge_attrs[:weight]].min if edge_attrs[:capacity] == inf }
|
@@ -41,10 +41,10 @@ module NetworkX
|
|
41
41
|
# Returns the residual graph of the given graph
|
42
42
|
def self._build_residual_network(graph)
|
43
43
|
raise ArgumentError, 'Sum of demands should be 0!' unless \
|
44
|
-
graph.nodes.values.map { |attr| attr[:demand] || 0 }.inject(0, :+).zero?
|
44
|
+
graph.nodes(data: true).values.map { |attr| attr[:demand] || 0 }.inject(0, :+).zero?
|
45
45
|
|
46
46
|
residual = NetworkX::MultiDiGraph.new(inf: 0)
|
47
|
-
residual.add_nodes(graph.nodes.map { |u, attr| [u, {excess: (attr[:demand] || 0) * -1, potential: 0}] })
|
47
|
+
residual.add_nodes(graph.nodes(data: true).map { |u, attr| [u, {excess: (attr[:demand] || 0) * -1, potential: 0}] })
|
48
48
|
inf = Float::INFINITY
|
49
49
|
edge_list = []
|
50
50
|
|
@@ -66,9 +66,11 @@ module NetworkX
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
temp_inf = [residual.nodes
|
70
|
-
|
71
|
-
|
69
|
+
temp_inf = [residual.nodes(data: true).map do |_u, attrs|
|
70
|
+
attrs[:excess].abs
|
71
|
+
end.inject(0, :+), edge_list.map do |_, _, _, e|
|
72
|
+
(e.has_key?(:capacity) && e[:capacity] != inf ? e[:capacity] : 0)
|
73
|
+
end.inject(0, :+) * 2].max
|
72
74
|
inf = temp_inf.zero? ? 1 : temp_inf
|
73
75
|
|
74
76
|
edge_list.each do |u, v, k, e|
|
@@ -88,7 +90,7 @@ module NetworkX
|
|
88
90
|
inf = Float::INFINITY
|
89
91
|
|
90
92
|
if graph.multigraph?
|
91
|
-
graph.nodes.each_key do |u|
|
93
|
+
graph.nodes(data: true).each_key do |u|
|
92
94
|
flow_dict[u] = {}
|
93
95
|
graph.adj[u].each do |v, uv_edges|
|
94
96
|
flow_dict[u][v] = uv_edges.transform_values do |e|
|
@@ -102,7 +104,7 @@ module NetworkX
|
|
102
104
|
end
|
103
105
|
end
|
104
106
|
else
|
105
|
-
graph.nodes.each_key do |u|
|
107
|
+
graph.nodes(data: true).each_key do |u|
|
106
108
|
flow_dict[u] = graph.adj[u].to_h do |v, e|
|
107
109
|
[v, u != v || (e[:capacity] || inf) <= 0 || (e[:weight] || 0) >= 0 ? 0 : e[:capacity]]
|
108
110
|
end
|
@@ -163,7 +165,7 @@ module NetworkX
|
|
163
165
|
s_set = Set.new
|
164
166
|
t_set = Set.new
|
165
167
|
|
166
|
-
residual.nodes.each do |u, _attrs|
|
168
|
+
residual.nodes(data: true).each do |u, _attrs|
|
167
169
|
excess = r_nodes[u][:excess]
|
168
170
|
if excess >= delta
|
169
171
|
s_set.add(u)
|
@@ -236,7 +238,7 @@ module NetworkX
|
|
236
238
|
|
237
239
|
r_nodes.each_value { |attrs| raise ArgumentError, 'No flow satisfying all demands!' if attrs[:excess] != 0 }
|
238
240
|
|
239
|
-
residual.nodes.each_key do |node|
|
241
|
+
residual.nodes(data: true).each_key do |node|
|
240
242
|
residual.adj[node].each_value do |uv_edges|
|
241
243
|
uv_edges.each_value do |k_attrs|
|
242
244
|
flow = k_attrs[:flow]
|
@@ -84,8 +84,8 @@ module NetworkX
|
|
84
84
|
|
85
85
|
# Helper function for the edmondskarp function
|
86
86
|
def self.edmondskarp_impl(graph, source, target, residual, cutoff)
|
87
|
-
raise ArgumentError, 'Source not in graph!' unless graph.nodes.has_key?(source)
|
88
|
-
raise ArgumentError, 'Target not in graph!' unless graph.nodes.has_key?(target)
|
87
|
+
raise ArgumentError, 'Source not in graph!' unless graph.nodes(data: true).has_key?(source)
|
88
|
+
raise ArgumentError, 'Target not in graph!' unless graph.nodes(data: true).has_key?(target)
|
89
89
|
raise ArgumentError, 'Source and target are same node!' if source == target
|
90
90
|
|
91
91
|
res_graph = residual.nil? ? build_residual_network(graph) : residual.clone
|
@@ -12,8 +12,8 @@ module NetworkX
|
|
12
12
|
|
13
13
|
# Helper function to apply the preflow push algorithm
|
14
14
|
def self.preflowpush_impl(graph, source, target, residual, globalrelabel_freq, value_only)
|
15
|
-
raise ArgumentError, 'Source not in graph!' unless graph.nodes.has_key?(source)
|
16
|
-
raise ArgumentError, 'Target not in graph!' unless graph.nodes.has_key?(target)
|
15
|
+
raise ArgumentError, 'Source not in graph!' unless graph.nodes(data: true).has_key?(source)
|
16
|
+
raise ArgumentError, 'Target not in graph!' unless graph.nodes(data: true).has_key?(target)
|
17
17
|
raise ArgumentError, 'Source and Target are same!' if source == target
|
18
18
|
|
19
19
|
globalrelabel_freq = 0 if globalrelabel_freq.nil?
|
@@ -38,7 +38,7 @@ module NetworkX
|
|
38
38
|
return r_network
|
39
39
|
end
|
40
40
|
|
41
|
-
n = r_network.nodes.length
|
41
|
+
n = r_network.nodes(data: true).length
|
42
42
|
max_height = heights.map { |u, h| u == source ? -1 : h }.max
|
43
43
|
heights[source] = n
|
44
44
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module NetworkX
|
2
2
|
# Helper function for running the shortest augmenting path algorithm
|
3
3
|
def self.shortest_augmenting_path_impl(graph, source, target, residual, two_phase, cutoff)
|
4
|
-
raise ArgumentError, 'Source is not in the graph!' unless graph.nodes.has_key?(source)
|
5
|
-
raise ArgumentError, 'Target is not in the graph!' unless graph.nodes.has_key?(target)
|
4
|
+
raise ArgumentError, 'Source is not in the graph!' unless graph.nodes(data: true).has_key?(source)
|
5
|
+
raise ArgumentError, 'Target is not in the graph!' unless graph.nodes(data: true).has_key?(target)
|
6
6
|
raise ArgumentError, 'Source and Target are the same!' if source == target
|
7
7
|
|
8
8
|
residual = residual.nil? ? build_residual_network(graph) : residual
|
@@ -35,7 +35,7 @@ module NetworkX
|
|
35
35
|
return residual
|
36
36
|
end
|
37
37
|
|
38
|
-
n = graph.nodes.length
|
38
|
+
n = graph.nodes(data: true).length
|
39
39
|
m = residual.size / 2
|
40
40
|
|
41
41
|
r_nodes.each do |node, attrs|
|
data/lib/networkx/flow/utils.rb
CHANGED
@@ -62,7 +62,7 @@ module NetworkX
|
|
62
62
|
raise NotImplementedError, 'MultiGraph and MultiDiGraph not supported!' if graph.multigraph?
|
63
63
|
|
64
64
|
r_network = NetworkX::DiGraph.new(inf: 0, flow_value: 0)
|
65
|
-
r_network.add_nodes(graph.nodes.keys)
|
65
|
+
r_network.add_nodes(graph.nodes(data: true).keys)
|
66
66
|
inf = Float::INFINITY
|
67
67
|
edge_list = []
|
68
68
|
|
data/lib/networkx/graph.rb
CHANGED
@@ -213,14 +213,13 @@ module NetworkX
|
|
213
213
|
end
|
214
214
|
end
|
215
215
|
|
216
|
-
#
|
217
|
-
# [Alert] Change the default in the futher. Please specify the `data`.
|
216
|
+
# Return nodes of graph
|
218
217
|
#
|
219
218
|
# @param data [bool] true if you want data of each edge
|
220
219
|
#
|
221
220
|
# @return [Hash | Array] if data is true, it returns hash including data.
|
222
221
|
# otherwise, simple nodes array.
|
223
|
-
def nodes(data:
|
222
|
+
def nodes(data: false)
|
224
223
|
if data
|
225
224
|
@nodes
|
226
225
|
else
|
@@ -8,7 +8,7 @@ module NetworkX
|
|
8
8
|
#
|
9
9
|
# @return [Array<Numeric, Numeric>] hits and authority scores
|
10
10
|
def self.hits(graph, max_iter = 100, tol = 1e-8, nstart)
|
11
|
-
return [{}, {}] if graph.nodes.empty?
|
11
|
+
return [{}, {}] if graph.nodes(data: true).empty?
|
12
12
|
|
13
13
|
h = nstart
|
14
14
|
sum = h.values.sum
|
@@ -2,61 +2,16 @@ module NetworkX
|
|
2
2
|
# Computes pagerank values for the graph
|
3
3
|
#
|
4
4
|
# @param graph [Graph] a graph
|
5
|
-
# @param init [Array<Numeric>] initial pagerank values for the nodes
|
6
5
|
# @param alpha [Numeric] the alpha value to compute the pagerank
|
7
6
|
# @param eps [Numeric] tolerence to check for convergence
|
8
7
|
# @param max_iter [Integer] max iterations for the pagerank algorithm to run
|
9
8
|
#
|
10
|
-
# @return [
|
11
|
-
def self.pagerank(graph,
|
12
|
-
dim = graph.nodes.length
|
13
|
-
if init.nil?
|
14
|
-
init = graph.nodes(data: false).to_h{ |i| [i, 1.0 / dim] }
|
15
|
-
else
|
16
|
-
s = init.values.sum.to_f
|
17
|
-
init = init.transform_values { |v| v / s }
|
18
|
-
end
|
19
|
-
raise ArgumentError, 'Init array needs to have same length as number of graph nodes!' \
|
20
|
-
unless dim == init.length
|
21
|
-
|
22
|
-
matrix = []
|
23
|
-
elem_ind = {}
|
24
|
-
p = []
|
25
|
-
curr = init.values
|
26
|
-
init.keys.each_with_index { |n, i| elem_ind[n] = i }
|
27
|
-
graph.adj.each do |_u, u_edges|
|
28
|
-
adj_arr = Array.new(dim, 0)
|
29
|
-
u_edges.each do |v, _|
|
30
|
-
adj_arr[elem_ind[v]] = 1
|
31
|
-
end
|
32
|
-
matrix << adj_arr
|
33
|
-
end
|
34
|
-
(0..(dim - 1)).each do |i|
|
35
|
-
p[i] = []
|
36
|
-
(0..(dim - 1)).each { |j| p[i][j] = matrix[i][j] / (matrix[i].sum * 1.0) }
|
37
|
-
end
|
38
|
-
|
39
|
-
max_iter.times do |_|
|
40
|
-
prev = curr.clone
|
41
|
-
dim.times do |i|
|
42
|
-
ip = 0
|
43
|
-
dim.times { |j| ip += p.transpose[i][j] * prev[j] }
|
44
|
-
curr[i] = (alpha * ip) + ((1 - alpha) / (dim * 1.0))
|
45
|
-
end
|
46
|
-
err = 0
|
47
|
-
dim.times { |i| err += (prev[i] - curr[i]).abs }
|
48
|
-
return curr if err < eps
|
49
|
-
end
|
50
|
-
raise ArgumentError, 'PageRank failed to converge!'
|
51
|
-
end
|
52
|
-
|
53
|
-
def self.pagerank2(graph, alpha: 0.85, personalization: nil, eps: 1e-6, max_iter: 100)
|
9
|
+
# @return [Hash of Object => Float] pagerank values of the graph
|
10
|
+
def self.pagerank(graph, alpha: 0.85, personalization: nil, eps: 1e-6, max_iter: 100)
|
54
11
|
n = graph.number_of_nodes
|
55
12
|
|
56
13
|
matrix, index_to_node = NetworkX.to_matrix(graph, 0)
|
57
14
|
|
58
|
-
# index_to_node = {0=>0, 1=>1, 2=>2, 3=>3}
|
59
|
-
|
60
15
|
index_from_node = index_to_node.invert
|
61
16
|
|
62
17
|
probabilities = Array.new(n) do |i|
|
@@ -84,6 +39,7 @@ module NetworkX
|
|
84
39
|
err = (0...n).map{|i| (prev[i] - curr[i]).abs }.sum
|
85
40
|
return (0...n).map{|i| [index_to_node[i], curr[i]] }.sort.to_h if err < eps
|
86
41
|
end
|
42
|
+
warn "pagerank() failed within #{max_iter} iterations. Please inclease max_iter: or loosen eps:"
|
87
43
|
(0...n).map{|i| [index_to_node[i], curr[i]] }.sort.to_h
|
88
44
|
end
|
89
45
|
end
|
@@ -27,12 +27,12 @@ module NetworkX
|
|
27
27
|
def self.convert_to_distinct_labels(graph, starting_int = -1)
|
28
28
|
new_graph = graph.class.new
|
29
29
|
|
30
|
-
idx_dict = graph.nodes.keys.to_h do |v|
|
30
|
+
idx_dict = graph.nodes(data: true).keys.to_h do |v|
|
31
31
|
starting_int += 1
|
32
32
|
[v, starting_int]
|
33
33
|
end
|
34
34
|
|
35
|
-
graph.nodes.each do |u, attrs|
|
35
|
+
graph.nodes(data: true).each do |u, attrs|
|
36
36
|
new_graph.add_node(u.to_s + idx_dict[u].to_s, **attrs)
|
37
37
|
end
|
38
38
|
|
@@ -60,9 +60,12 @@ module NetworkX
|
|
60
60
|
result = g1.class.new
|
61
61
|
|
62
62
|
raise ArgumentError, 'Arguments must be both Graphs or MultiGraphs!' unless g1.multigraph? == g2.multigraph?
|
63
|
-
raise ArgumentError, 'Node sets must be equal!' unless (g1.nodes.keys - g2.nodes.keys).empty?
|
64
63
|
|
65
|
-
g1.nodes.
|
64
|
+
unless (g1.nodes(data: true).keys - g2.nodes(data: true).keys).empty?
|
65
|
+
raise ArgumentError, 'Node sets must be equal!'
|
66
|
+
end
|
67
|
+
|
68
|
+
g1.nodes(data: true).each { |u, attrs| result.add_node(u, **attrs) }
|
66
69
|
|
67
70
|
g1, g2 = g2, g1 if g1.number_of_edges > g2.number_of_edges
|
68
71
|
g1.adj.each do |u, u_edges|
|
@@ -91,9 +94,12 @@ module NetworkX
|
|
91
94
|
result = g1.class.new
|
92
95
|
|
93
96
|
raise ArgumentError, 'Arguments must be both Graphs or MultiGraphs!' unless g1.multigraph? == g2.multigraph?
|
94
|
-
raise ArgumentError, 'Node sets must be equal!' unless (g1.nodes.keys - g2.nodes.keys).empty?
|
95
97
|
|
96
|
-
g1.nodes.
|
98
|
+
unless (g1.nodes(data: true).keys - g2.nodes(data: true).keys).empty?
|
99
|
+
raise ArgumentError, 'Node sets must be equal!'
|
100
|
+
end
|
101
|
+
|
102
|
+
g1.nodes(data: true).each { |u, attrs| result.add_node(u, **attrs) }
|
97
103
|
|
98
104
|
g1.adj.each do |u, u_edges|
|
99
105
|
u_edges.each do |v, uv_attrs|
|
@@ -121,9 +127,12 @@ module NetworkX
|
|
121
127
|
result = g1.class.new
|
122
128
|
|
123
129
|
raise ArgumentError, 'Arguments must be both Graphs or MultiGraphs!' unless g1.multigraph? == g2.multigraph?
|
124
|
-
raise ArgumentError, 'Node sets must be equal!' unless (g1.nodes.keys - g2.nodes.keys).empty?
|
125
130
|
|
126
|
-
g1.nodes.
|
131
|
+
unless (g1.nodes(data: true).keys - g2.nodes(data: true).keys).empty?
|
132
|
+
raise ArgumentError, 'Node sets must be equal!'
|
133
|
+
end
|
134
|
+
|
135
|
+
g1.nodes(data: true).each { |u, attrs| result.add_node(u, **attrs) }
|
127
136
|
|
128
137
|
g1.adj.each do |u, u_edges|
|
129
138
|
u_edges.each do |v, uv_attrs|
|
@@ -166,8 +175,8 @@ module NetworkX
|
|
166
175
|
|
167
176
|
raise ArgumentError, 'Arguments must be both Graphs or MultiGraphs!' unless g1.multigraph? == g2.multigraph?
|
168
177
|
|
169
|
-
result.add_nodes(g1.nodes.map { |u, attrs| [u, attrs] })
|
170
|
-
result.add_nodes(g2.nodes.map { |u, attrs| [u, attrs] })
|
178
|
+
result.add_nodes(g1.nodes(data: true).map { |u, attrs| [u, attrs] })
|
179
|
+
result.add_nodes(g2.nodes(data: true).map { |u, attrs| [u, attrs] })
|
171
180
|
|
172
181
|
if g1.multigraph?
|
173
182
|
g1.adj.each { |u, e| e.each { |v, uv_edges| uv_edges.each_value { |attrs| result.add_edge(u, v, **attrs) } } }
|
@@ -192,14 +201,16 @@ module NetworkX
|
|
192
201
|
new_graph.graph.merge!(g1.graph)
|
193
202
|
new_graph.graph.merge!(g2.graph)
|
194
203
|
|
195
|
-
|
204
|
+
unless (g1.nodes(data: true).keys & g2.nodes(data: true).keys).empty?
|
205
|
+
raise ArgumentError, 'Graphs must be disjoint!'
|
206
|
+
end
|
196
207
|
|
197
208
|
g1_edges = get_edges(g1)
|
198
209
|
g2_edges = get_edges(g2)
|
199
210
|
|
200
|
-
new_graph.add_nodes(g1.nodes.keys)
|
211
|
+
new_graph.add_nodes(g1.nodes(data: true).keys)
|
201
212
|
new_graph.add_edges(g1_edges)
|
202
|
-
new_graph.add_nodes(g2.nodes.keys)
|
213
|
+
new_graph.add_nodes(g2.nodes(data: true).keys)
|
203
214
|
new_graph.add_edges(g2_edges)
|
204
215
|
|
205
216
|
new_graph
|
@@ -28,8 +28,8 @@ module NetworkX
|
|
28
28
|
# Returns the node product of nodes of two graphs
|
29
29
|
def self.node_product(g1, g2)
|
30
30
|
n_product = []
|
31
|
-
g1.nodes.each do |k1, attrs1|
|
32
|
-
g2.nodes.each do |k2, attrs2|
|
31
|
+
g1.nodes(data: true).each do |k1, attrs1|
|
32
|
+
g2.nodes(data: true).each do |k2, attrs2|
|
33
33
|
n_product << [[k1, k2], hash_product(attrs1, attrs2)]
|
34
34
|
end
|
35
35
|
end
|
@@ -62,7 +62,7 @@ module NetworkX
|
|
62
62
|
def self.edges_cross_nodes(g1, g2)
|
63
63
|
result = []
|
64
64
|
edges_in_array(g1).each do |u, v, d|
|
65
|
-
g2.nodes.each_key do |x|
|
65
|
+
g2.nodes(data: true).each_key do |x|
|
66
66
|
result << [[u, x], [v, x], d]
|
67
67
|
end
|
68
68
|
end
|
@@ -72,7 +72,7 @@ module NetworkX
|
|
72
72
|
# Returns the product of directed nodes with edges
|
73
73
|
def self.nodes_cross_edges(g1, g2)
|
74
74
|
result = []
|
75
|
-
g1.nodes.each_key do |x|
|
75
|
+
g1.nodes(data: true).each_key do |x|
|
76
76
|
edges_in_array(g2).each do |u, v, d|
|
77
77
|
result << [[x, u], [x, v], d]
|
78
78
|
end
|
@@ -84,8 +84,8 @@ module NetworkX
|
|
84
84
|
def self.edges_cross_nodes_and_nodes(g1, g2)
|
85
85
|
result = []
|
86
86
|
edges_in_array(g1).each do |u, v, d|
|
87
|
-
g2.nodes.each_key do |x|
|
88
|
-
g2.nodes.each_key do |y|
|
87
|
+
g2.nodes(data: true).each_key do |x|
|
88
|
+
g2.nodes(data: true).each_key do |y|
|
89
89
|
result << [[u, x], [v, y], d]
|
90
90
|
end
|
91
91
|
end
|
@@ -174,8 +174,8 @@ module NetworkX
|
|
174
174
|
raise ArgumentError, 'Power must be a positive quantity!' if pow <= 0
|
175
175
|
|
176
176
|
result = NetworkX::Graph.new
|
177
|
-
result.add_nodes(graph.nodes.map { |n, attrs| [n, attrs] })
|
178
|
-
graph.nodes.each do |n, _attrs|
|
177
|
+
result.add_nodes(graph.nodes(data: true).map { |n, attrs| [n, attrs] })
|
178
|
+
graph.nodes(data: true).each do |n, _attrs|
|
179
179
|
seen = {}
|
180
180
|
level = 1
|
181
181
|
next_level = graph.adj[n]
|
@@ -8,9 +8,9 @@ module NetworkX
|
|
8
8
|
result = Marshal.load(Marshal.dump(graph))
|
9
9
|
result.clear
|
10
10
|
|
11
|
-
result.add_nodes(graph.nodes.map { |u, attrs| [u, attrs] })
|
11
|
+
result.add_nodes(graph.nodes(data: true).map { |u, attrs| [u, attrs] })
|
12
12
|
graph.adj.each do |u, u_edges|
|
13
|
-
graph.nodes.each { |v, attrs| result.add_edge(u, v, **attrs) if !u_edges.has_key?(v) && u != v }
|
13
|
+
graph.nodes(data: true).each { |v, attrs| result.add_edge(u, v, **attrs) if !u_edges.has_key?(v) && u != v }
|
14
14
|
end
|
15
15
|
result
|
16
16
|
end
|
@@ -7,7 +7,7 @@ module NetworkX
|
|
7
7
|
# b/w all pairs of nodes
|
8
8
|
def self.floyd_warshall(graph)
|
9
9
|
a, index = to_matrix(graph, Float::INFINITY, 'min')
|
10
|
-
nodelen = graph.nodes.length
|
10
|
+
nodelen = graph.nodes(data: true).length
|
11
11
|
(0..(nodelen - 1)).each { |i| a[i, i] = 0 }
|
12
12
|
(0..(nodelen - 1)).each do |k|
|
13
13
|
(0..(nodelen - 1)).each do |i|
|
@@ -34,7 +34,7 @@ module NetworkX
|
|
34
34
|
|
35
35
|
cutoff = Float::INFINITY if cutoff.nil?
|
36
36
|
nextlevel = {source => 1}
|
37
|
-
help_single_shortest_path_length(graph.adj, nextlevel, cutoff).take(graph.nodes.length)
|
37
|
+
help_single_shortest_path_length(graph.adj, nextlevel, cutoff).take(graph.nodes(data: true).length)
|
38
38
|
end
|
39
39
|
|
40
40
|
# Computes shortest path values to all nodes from all nodes
|
@@ -45,7 +45,7 @@ module NetworkX
|
|
45
45
|
# @return [Array<Object, Array<Object, Numeric>>] path lengths for all nodes from all nodes
|
46
46
|
def self.all_pairs_shortest_path_length(graph, cutoff = nil)
|
47
47
|
shortest_paths = []
|
48
|
-
graph.nodes.each_key { |n| shortest_paths << [n, single_source_shortest_path_length(graph, n, cutoff)] }
|
48
|
+
graph.nodes(data: true).each_key { |n| shortest_paths << [n, single_source_shortest_path_length(graph, n, cutoff)] }
|
49
49
|
shortest_paths
|
50
50
|
end
|
51
51
|
|
@@ -93,7 +93,7 @@ module NetworkX
|
|
93
93
|
# @return [Array<Object, Hash {Object => Array<Object> }>] paths for all nodes from all nodes
|
94
94
|
def self.all_pairs_shortest_path(graph, cutoff = nil)
|
95
95
|
shortest_paths = []
|
96
|
-
graph.nodes.each_key { |n| shortest_paths << [n, single_source_shortest_path(graph, n, cutoff)] }
|
96
|
+
graph.nodes(data: true).each_key { |n| shortest_paths << [n, single_source_shortest_path(graph, n, cutoff)] }
|
97
97
|
shortest_paths
|
98
98
|
end
|
99
99
|
|
@@ -188,7 +188,7 @@ module NetworkX
|
|
188
188
|
# paths and path lengths between all nodes
|
189
189
|
def self.all_pairs_dijkstra(graph, cutoff = nil)
|
190
190
|
path = []
|
191
|
-
graph.nodes.each_key { |n| path << [n, singlesource_dijkstra(graph, n, nil, cutoff)] }
|
191
|
+
graph.nodes(data: true).each_key { |n| path << [n, singlesource_dijkstra(graph, n, nil, cutoff)] }
|
192
192
|
path
|
193
193
|
end
|
194
194
|
|
@@ -200,7 +200,7 @@ module NetworkX
|
|
200
200
|
# @return [Array<Object, Hash{ Object => Numeric }>] path lengths between all nodes
|
201
201
|
def self.all_pairs_dijkstra_path_length(graph, cutoff = nil)
|
202
202
|
path_lengths = []
|
203
|
-
graph.nodes.each_key { |n| path_lengths << [n, singlesource_dijkstra_path_length(graph, n, cutoff)] }
|
203
|
+
graph.nodes(data: true).each_key { |n| path_lengths << [n, singlesource_dijkstra_path_length(graph, n, cutoff)] }
|
204
204
|
path_lengths
|
205
205
|
end
|
206
206
|
|
@@ -212,7 +212,7 @@ module NetworkX
|
|
212
212
|
# @return [Array<Object, Hash{ Object => Array<Object> }>] path lengths between all nodes
|
213
213
|
def self.all_pairs_dijkstra_path(graph, cutoff = nil)
|
214
214
|
paths = []
|
215
|
-
graph.nodes.each_key { |n| paths << singlesource_dijkstra_path(graph, n, cutoff) }
|
215
|
+
graph.nodes(data: true).each_key { |n| paths << singlesource_dijkstra_path(graph, n, cutoff) }
|
216
216
|
paths
|
217
217
|
end
|
218
218
|
|
@@ -221,7 +221,7 @@ module NetworkX
|
|
221
221
|
pred = sources.product([[]]).to_h if pred.nil?
|
222
222
|
dist = sources.product([0]).to_h if dist.nil?
|
223
223
|
|
224
|
-
inf, n, count, q, in_q = Float::INFINITY, graph.nodes.length, {}, sources.clone, Set.new(sources)
|
224
|
+
inf, n, count, q, in_q = Float::INFINITY, graph.nodes(data: true).length, {}, sources.clone, Set.new(sources)
|
225
225
|
until q.empty?
|
226
226
|
u = q.shift
|
227
227
|
in_q.delete(u)
|
@@ -281,7 +281,7 @@ module NetworkX
|
|
281
281
|
# TODO: Detection of selfloop edges
|
282
282
|
dist = {source => 0}
|
283
283
|
pred = {source => []}
|
284
|
-
return [pred, dist] if graph.nodes.length == 1
|
284
|
+
return [pred, dist] if graph.nodes(data: true).length == 1
|
285
285
|
|
286
286
|
dist = help_bellman_ford(graph, [source], weight, pred, nil, dist, cutoff, target)
|
287
287
|
[pred, dist]
|
@@ -360,7 +360,7 @@ module NetworkX
|
|
360
360
|
# @return [Array<Object, Hash{ Object => Numeric }>] path lengths from source to all nodes
|
361
361
|
def self.allpairs_bellmanford_path_length(graph, cutoff = nil)
|
362
362
|
path_lengths = []
|
363
|
-
graph.nodes.each_key { |n| path_lengths << [n, singlesource_bellmanford_path_length(graph, n, cutoff)] }
|
363
|
+
graph.nodes(data: true).each_key { |n| path_lengths << [n, singlesource_bellmanford_path_length(graph, n, cutoff)] }
|
364
364
|
path_lengths
|
365
365
|
end
|
366
366
|
|
@@ -372,13 +372,13 @@ module NetworkX
|
|
372
372
|
# @return [Array<Object, Hash{ Object => Array<Object> }>] path lengths from source to all nodes
|
373
373
|
def self.allpairs_bellmanford_path(graph, cutoff = nil)
|
374
374
|
paths = []
|
375
|
-
graph.nodes.each_key { |n| paths << [n, singlesource_bellmanford_path(graph, n, cutoff)] }
|
375
|
+
graph.nodes(data: true).each_key { |n| paths << [n, singlesource_bellmanford_path(graph, n, cutoff)] }
|
376
376
|
paths
|
377
377
|
end
|
378
378
|
|
379
379
|
# Helper function to get sources
|
380
380
|
def self.get_sources(graph)
|
381
|
-
graph.nodes.collect { |k, _v| k }
|
381
|
+
graph.nodes(data: true).collect { |k, _v| k }
|
382
382
|
end
|
383
383
|
|
384
384
|
# Helper function to get distances
|
@@ -393,7 +393,7 @@ module NetworkX
|
|
393
393
|
# Helper function to set path lengths for Johnson algorithm
|
394
394
|
def self.set_path_lengths_johnson(graph, dist_path, new_weight)
|
395
395
|
path_lengths = []
|
396
|
-
graph.nodes.each_key { |n| path_lengths << [n, dist_path.call(graph, n, new_weight)] }
|
396
|
+
graph.nodes(data: true).each_key { |n| path_lengths << [n, dist_path.call(graph, n, new_weight)] }
|
397
397
|
path_lengths
|
398
398
|
end
|
399
399
|
|
@@ -405,7 +405,7 @@ module NetworkX
|
|
405
405
|
def self.johnson(graph)
|
406
406
|
dist, pred = {}, {}
|
407
407
|
sources = get_sources(graph)
|
408
|
-
graph.nodes.each_key do |n|
|
408
|
+
graph.nodes(data: true).each_key do |n|
|
409
409
|
dist[n], pred[n] = 0, []
|
410
410
|
end
|
411
411
|
weight = get_weight(graph)
|
data/lib/networkx/to_matrix.rb
CHANGED
@@ -2,14 +2,14 @@ module NetworkX
|
|
2
2
|
def self.to_matrix(graph, val, multigraph_weight = 'sum')
|
3
3
|
is_undirected = !graph.directed?
|
4
4
|
is_multigraph = graph.multigraph?
|
5
|
-
nodelen = graph.nodes.length
|
5
|
+
nodelen = graph.nodes(data: true).length
|
6
6
|
|
7
7
|
m = Matrix.build(nodelen) { val }
|
8
8
|
index = {}
|
9
9
|
inv_index = {}
|
10
10
|
ind = 0
|
11
11
|
|
12
|
-
graph.nodes.each do |u, _|
|
12
|
+
graph.nodes(data: true).each do |u, _|
|
13
13
|
index[u] = ind
|
14
14
|
inv_index[ind] = u
|
15
15
|
ind += 1
|
@@ -11,7 +11,7 @@ module NetworkX
|
|
11
11
|
raise KeyError, "There exists no node names #{source} in the given graph." unless graph.node?(source)
|
12
12
|
|
13
13
|
depth_limit += 1 if depth_limit
|
14
|
-
depth_limit = graph.nodes.length if depth_limit.nil?
|
14
|
+
depth_limit = graph.nodes(data: true).length if depth_limit.nil?
|
15
15
|
dfs_edges = []
|
16
16
|
visited = [source]
|
17
17
|
stack = [[-1, source, depth_limit, graph.neighbours(source)]]
|
data/lib/networkx/version.rb
CHANGED
data/networkx.gemspec
CHANGED
@@ -13,13 +13,15 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.email = ['athityakumar@gmail.com']
|
14
14
|
spec.summary = 'A Ruby implemenation of the well-known graph library called networkx.'
|
15
15
|
spec.description = NetworkX::DESCRIPTION
|
16
|
-
spec.homepage = 'https://github.com/
|
16
|
+
spec.homepage = 'https://github.com/SciRuby/networkx.rb'
|
17
17
|
spec.license = 'MIT'
|
18
18
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
19
|
spec.bindir = 'bin'
|
20
20
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ['lib']
|
22
22
|
|
23
|
+
spec.required_ruby_version = '>= 2.7'
|
24
|
+
|
23
25
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
24
26
|
spec.add_development_dependency 'rake', '~> 13.0'
|
25
27
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
@@ -34,4 +36,6 @@ Gem::Specification.new do |spec|
|
|
34
36
|
|
35
37
|
spec.add_runtime_dependency 'matrix', '~> 0.4'
|
36
38
|
spec.add_runtime_dependency 'rb_heap', '~> 1.0'
|
39
|
+
|
40
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
37
41
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: networkx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Athitya Kumar
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-11-
|
11
|
+
date: 2022-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -207,7 +207,6 @@ files:
|
|
207
207
|
- ".github/PULL_REQUEST_TEMPLATE.md"
|
208
208
|
- ".github/workflows/ci.yml"
|
209
209
|
- ".github/workflows/doc.yml"
|
210
|
-
- ".github/workflows/gem-push.yml"
|
211
210
|
- ".gitignore"
|
212
211
|
- ".rspec"
|
213
212
|
- ".rubocop.yml"
|
@@ -259,10 +258,11 @@ files:
|
|
259
258
|
- lib/networkx/traversals/edge_dfs.rb
|
260
259
|
- lib/networkx/version.rb
|
261
260
|
- networkx.gemspec
|
262
|
-
homepage: https://github.com/
|
261
|
+
homepage: https://github.com/SciRuby/networkx.rb
|
263
262
|
licenses:
|
264
263
|
- MIT
|
265
|
-
metadata:
|
264
|
+
metadata:
|
265
|
+
rubygems_mfa_required: 'true'
|
266
266
|
post_install_message:
|
267
267
|
rdoc_options: []
|
268
268
|
require_paths:
|
@@ -271,7 +271,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
271
271
|
requirements:
|
272
272
|
- - ">="
|
273
273
|
- !ruby/object:Gem::Version
|
274
|
-
version: '
|
274
|
+
version: '2.7'
|
275
275
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
276
276
|
requirements:
|
277
277
|
- - ">="
|
@@ -1,45 +0,0 @@
|
|
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}}"
|