graphunk 0.2.0 → 0.2.1
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.
- checksums.yaml +4 -4
- data/lib/directed_graph.rb +32 -0
- data/lib/undirected_graph.rb +145 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3484b513a6924db90db6cef1e4d1a3a0c998e888
|
4
|
+
data.tar.gz: ced748e00283f8199d5b63ae25d7239232e46439
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ec2a5140951c25f4d21bc1b12e03c304870151a29651c0b3e1ebc2a77657ccd9132acf93085e53d1e94c4dffc93d12be91fd34e68291ecfaa7f34847e805f1b
|
7
|
+
data.tar.gz: 4aed0d585553025fe18facdfb860683ded5344803539aaded60056e4309038f5047021af6f12e38a44df82394ae0a17a64cede86aa8fe36ec98142aa22c6f114
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'graph'
|
2
|
+
class DirectedGraph < Graph
|
3
|
+
def add_edge(first_vertex, second_vertex)
|
4
|
+
if edge_exists?(first_vertex, second_vertex)
|
5
|
+
raise ArgumentError, "This edge already exists"
|
6
|
+
elsif vertex_exists?(first_vertex) && vertex_exists?(second_vertex)
|
7
|
+
self[first_vertex] << second_vertex
|
8
|
+
else
|
9
|
+
raise ArgumentError, "One of the vertices referenced does not exist in the graph"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def remove_edge(first_vertex, second_vertex)
|
14
|
+
if edge_exists?(first_vertex, second_vertex)
|
15
|
+
self[first_vertex].delete(second_vertex)
|
16
|
+
else
|
17
|
+
raise ArgumentError, "That edge does not exist in the graph"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def neighbors_of_vertex(name)
|
22
|
+
if vertex_exists?(name)
|
23
|
+
self[name]
|
24
|
+
else
|
25
|
+
raise ArgumentError, "That vertex does not exist in the graph"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def edge_exists?(first_vertex, second_vertex)
|
30
|
+
edges.include?([first_vertex, second_vertex])
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'graph'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
class UndirectedGraph < Graph
|
5
|
+
def add_edge(first_vertex, second_vertex)
|
6
|
+
if edge_exists?(first_vertex, second_vertex)
|
7
|
+
raise ArgumentError, "This edge already exists"
|
8
|
+
elsif vertex_exists?(first_vertex) && vertex_exists?(second_vertex)
|
9
|
+
ordered_vertices = order_vertices(first_vertex, second_vertex)
|
10
|
+
self[ordered_vertices.first] << ordered_vertices.last
|
11
|
+
else
|
12
|
+
raise ArgumentError, "One of the vertices referenced does not exist in the graph"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def remove_edge(first_vertex, second_vertex)
|
17
|
+
if edge_exists?(first_vertex, second_vertex)
|
18
|
+
ordered_vertices = order_vertices(first_vertex, second_vertex)
|
19
|
+
self[ordered_vertices.first].delete(ordered_vertices.last)
|
20
|
+
else
|
21
|
+
raise ArgumentError, "That edge does not exist in the graph"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def neighbors_of_vertex(name)
|
26
|
+
if vertex_exists?(name)
|
27
|
+
edges.select { |edge| edge.include? name }.map do |edge|
|
28
|
+
if edge.first == name
|
29
|
+
edge.last
|
30
|
+
else
|
31
|
+
edge.first
|
32
|
+
end
|
33
|
+
end
|
34
|
+
else
|
35
|
+
raise ArgumentError, "That vertex does not exist in the graph"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def edge_exists?(first_vertex, second_vertex)
|
40
|
+
edges.include?(order_vertices(first_vertex, second_vertex))
|
41
|
+
end
|
42
|
+
|
43
|
+
def lexicographic_bfs
|
44
|
+
sets = [vertices]
|
45
|
+
output_vertices = []
|
46
|
+
|
47
|
+
until sets.empty?
|
48
|
+
v = sets.first.delete_at(0)
|
49
|
+
sets.delete_at(0) if sets.first.empty?
|
50
|
+
output_vertices << v
|
51
|
+
replaced = []
|
52
|
+
neighbors_of_vertex(v).each do |neighbor|
|
53
|
+
s = sets.select{ |set| set.include?(neighbor) }.first
|
54
|
+
if s
|
55
|
+
if replaced.include?(s)
|
56
|
+
t = sets[sets.find_index(s)-1]
|
57
|
+
else
|
58
|
+
t = []
|
59
|
+
sets.insert(sets.find_index(s), t)
|
60
|
+
replaced << s
|
61
|
+
end
|
62
|
+
s.delete(neighbor)
|
63
|
+
t << neighbor
|
64
|
+
sets.delete(s) if s.empty?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
output_vertices
|
70
|
+
end
|
71
|
+
|
72
|
+
def clique?(vertex_list)
|
73
|
+
clique = true
|
74
|
+
vertex_list.each do |vertex|
|
75
|
+
unless (neighbors_of_vertex(vertex) & vertex_list).to_set == (vertex_list - [vertex]).to_set
|
76
|
+
clique = false
|
77
|
+
break
|
78
|
+
end
|
79
|
+
end
|
80
|
+
clique
|
81
|
+
end
|
82
|
+
|
83
|
+
def chordal?
|
84
|
+
chordal = true
|
85
|
+
(lexicographic_ordering = lexicographic_bfs.reverse).each_with_index do |v, i|
|
86
|
+
successors_of_v = lexicographic_ordering[i, lexicographic_ordering.size]
|
87
|
+
unless clique?([v] | (neighbors_of_vertex(v) & successors_of_v))
|
88
|
+
chordal = false
|
89
|
+
break
|
90
|
+
end
|
91
|
+
end
|
92
|
+
chordal
|
93
|
+
end
|
94
|
+
alias_method :triangulated?, :chordal?
|
95
|
+
|
96
|
+
def complete?
|
97
|
+
n = vertices.count
|
98
|
+
edges.count == (n * (n-1) / 2)
|
99
|
+
end
|
100
|
+
|
101
|
+
def bipartite?
|
102
|
+
colors = Hash.new
|
103
|
+
d = Hash.new
|
104
|
+
partition = Hash.new
|
105
|
+
vertices.each do |vertex|
|
106
|
+
colors[vertex] = "white"
|
107
|
+
d[vertex] = Float::INFINITY
|
108
|
+
partition[vertex] = 0
|
109
|
+
end
|
110
|
+
|
111
|
+
start = vertices.first
|
112
|
+
colors[start] = "gray"
|
113
|
+
partition[start] = 1
|
114
|
+
d[start] = 0
|
115
|
+
|
116
|
+
stack = []
|
117
|
+
stack.push(start)
|
118
|
+
|
119
|
+
until stack.empty?
|
120
|
+
vertex = stack.pop
|
121
|
+
neighbors_of_vertex(vertex).each do |neighbor|
|
122
|
+
if partition[neighbor] == partition[vertex]
|
123
|
+
return false
|
124
|
+
else
|
125
|
+
if colors[neighbor] == "white"
|
126
|
+
colors[neighbor] == "gray"
|
127
|
+
d[neighbor] = d[vertex] + 1
|
128
|
+
partition[neighbor] = 3 - partition[vertex]
|
129
|
+
stack.push(neighbor)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
stack.pop
|
134
|
+
colors[vertex] = "black"
|
135
|
+
end
|
136
|
+
|
137
|
+
true
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def order_vertices(first_vertex, second_vertex)
|
143
|
+
[first_vertex, second_vertex].sort
|
144
|
+
end
|
145
|
+
end
|
metadata
CHANGED
@@ -1,25 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphunk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Hemsley
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: This gem defines
|
13
|
+
description: This gem defines graph classes which are useful in various mathematical
|
14
14
|
applications.
|
15
15
|
email: evan.hemsley@gmail.com
|
16
16
|
executables: []
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
+
- lib/directed_graph.rb
|
20
21
|
- lib/graph.rb
|
21
22
|
- lib/graphunk.rb
|
22
|
-
|
23
|
+
- lib/undirected_graph.rb
|
24
|
+
homepage: https://github.com/ehemsley/graphunk
|
23
25
|
licenses:
|
24
26
|
- MIT
|
25
27
|
metadata: {}
|