tangle 0.8.2 → 0.11.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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +37 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +15 -4
- data/CHANGELOG.md +45 -0
- data/Gemfile +4 -10
- data/README.md +8 -3
- data/Rakefile +3 -1
- data/bin/console +5 -4
- data/bin/setup +0 -1
- data/lib/tangle.rb +7 -4
- data/lib/tangle/base_graph.rb +154 -0
- data/lib/tangle/{graph_vertices.rb → base_graph_private.rb} +12 -35
- data/lib/tangle/base_graph_protected.rb +50 -0
- data/lib/tangle/currify.rb +58 -0
- data/lib/tangle/directed/acyclic/graph.rb +3 -0
- data/lib/tangle/directed/acyclic/partial_order.rb +3 -0
- data/lib/tangle/directed/edge.rb +4 -2
- data/lib/tangle/directed/graph.rb +28 -6
- data/lib/tangle/edge.rb +5 -14
- data/lib/tangle/errors.rb +2 -0
- data/lib/tangle/mixin.rb +2 -1
- data/lib/tangle/mixin/directory.rb +48 -13
- data/lib/tangle/undirected/edge.rb +30 -0
- data/lib/tangle/undirected/graph.rb +73 -0
- data/lib/tangle/undirected/simple/graph.rb +22 -0
- data/lib/tangle/version.rb +8 -4
- data/ruby-tangle.sublime-project +8 -0
- data/tangle.gemspec +19 -7
- metadata +103 -27
- data/.travis.yml +0 -5
- data/lib/tangle/graph.rb +0 -81
- data/lib/tangle/graph_edges.rb +0 -49
- data/lib/tangle/mixin/connectedness.rb +0 -68
- data/lib/tangle/simple/graph.rb +0 -17
data/.travis.yml
DELETED
data/lib/tangle/graph.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
require 'tangle/mixin'
|
2
|
-
require 'tangle/mixin/connectedness'
|
3
|
-
require 'tangle/edge'
|
4
|
-
require 'tangle/graph_vertices'
|
5
|
-
require 'tangle/graph_edges'
|
6
|
-
|
7
|
-
module Tangle
|
8
|
-
#
|
9
|
-
# Base class for all kinds of graphs
|
10
|
-
#
|
11
|
-
class Graph
|
12
|
-
include Tangle::GraphVertices
|
13
|
-
include Tangle::GraphEdges
|
14
|
-
include Tangle::Mixin::Initialize
|
15
|
-
Edge = Tangle::Edge
|
16
|
-
DEFAULT_MIXINS = Tangle::Mixin::Connectedness::MIXINS
|
17
|
-
|
18
|
-
# Initialize a new graph, preloading it with vertices and edges
|
19
|
-
#
|
20
|
-
# Graph[+vertices+] => Graph
|
21
|
-
# Graph[+vertices+, +edges+) => Graph
|
22
|
-
#
|
23
|
-
# When +vertices+ is a hash, it contains initialization kwargs as
|
24
|
-
# values and vertex names as keys. When +vertices+ is an array of
|
25
|
-
# initialization kwargs, the vertices will be be anonymous.
|
26
|
-
#
|
27
|
-
# +edges+ can contain an array of exactly two, either names of vertices
|
28
|
-
# or vertices.
|
29
|
-
#
|
30
|
-
# Any kwarg supported by Graph.new is also allowed.
|
31
|
-
#
|
32
|
-
def self.[](vertices, edges = {}, **kwargs)
|
33
|
-
graph = new(**kwargs)
|
34
|
-
vertices.each { |vertex| graph.add_vertex(vertex) }
|
35
|
-
edges.each { |from, to| graph.add_edge(from, to) }
|
36
|
-
graph
|
37
|
-
end
|
38
|
-
|
39
|
-
# Initialize a new graph, optionally preloading it with vertices and edges
|
40
|
-
#
|
41
|
-
# Graph.new() => Graph
|
42
|
-
# Graph.new(mixins: [MixinModule, ...], ...) => Graph
|
43
|
-
#
|
44
|
-
# +mixins+ is an array of modules that can be mixed into the various
|
45
|
-
# classes that makes up a graph. Initialization of a Graph, Vertex or Edge
|
46
|
-
# looks for submodules in each mixin, with the same name and extends
|
47
|
-
# any created object. Defaults to [Tangle::Mixin::Connectedness].
|
48
|
-
#
|
49
|
-
# Any subclass of Graph should also subclass Edge to manage its unique
|
50
|
-
# constraints.
|
51
|
-
#
|
52
|
-
def initialize(mixins: self.class::DEFAULT_MIXINS, **kwargs)
|
53
|
-
initialize_vertices
|
54
|
-
initialize_edges
|
55
|
-
initialize_mixins(mixins: mixins, **kwargs)
|
56
|
-
end
|
57
|
-
|
58
|
-
# Return a subgraph, optionally filtered by a vertex selector block
|
59
|
-
#
|
60
|
-
# subgraph => Graph
|
61
|
-
# subgraph { |vertex| ... } => Graph
|
62
|
-
#
|
63
|
-
# Unless a selector is provided, the subgraph contains the entire graph.
|
64
|
-
#
|
65
|
-
def subgraph(included = nil)
|
66
|
-
included ||= vertices
|
67
|
-
result = clone
|
68
|
-
vertices.each do |vertex|
|
69
|
-
result.remove_vertex(vertex) unless included.include?(vertex)
|
70
|
-
next unless block_given?
|
71
|
-
result.remove_vertex(vertex) unless yield(vertex)
|
72
|
-
end
|
73
|
-
result
|
74
|
-
end
|
75
|
-
|
76
|
-
def to_s
|
77
|
-
"#<#{self.class}: #{vertices.count} vertices, #{edges.count} edges>"
|
78
|
-
end
|
79
|
-
alias inspect to_s
|
80
|
-
end
|
81
|
-
end
|
data/lib/tangle/graph_edges.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
|
-
module Tangle
|
4
|
-
# Edge related methods in a graph
|
5
|
-
module GraphEdges
|
6
|
-
# Get all edges.
|
7
|
-
#
|
8
|
-
# edges => Array
|
9
|
-
#
|
10
|
-
def edges(vertex = nil)
|
11
|
-
return @edges if vertex.nil?
|
12
|
-
@vertices.fetch(vertex)
|
13
|
-
end
|
14
|
-
|
15
|
-
# Add a new edge to the graph
|
16
|
-
#
|
17
|
-
# add_edge(vtx1, vtx2, ...) => Edge
|
18
|
-
#
|
19
|
-
def add_edge(*vertices, **kvargs)
|
20
|
-
insert_edge(self.class::Edge.new(*vertices, mixins: @mixins, **kvargs))
|
21
|
-
end
|
22
|
-
|
23
|
-
# Remove an edge from the graph
|
24
|
-
def remove_edge(edge)
|
25
|
-
edge.each_vertex do |vertex|
|
26
|
-
@vertices.fetch(vertex).delete(edge)
|
27
|
-
end
|
28
|
-
@edges.delete(edge)
|
29
|
-
end
|
30
|
-
|
31
|
-
protected
|
32
|
-
|
33
|
-
# Insert a prepared edge into the graph
|
34
|
-
#
|
35
|
-
def insert_edge(edge)
|
36
|
-
@edges << edge
|
37
|
-
edge.each_vertex do |vertex|
|
38
|
-
@vertices.fetch(vertex) << edge
|
39
|
-
end
|
40
|
-
edge
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def initialize_edges
|
46
|
-
@edges = Set[]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
module Tangle
|
2
|
-
module Mixin
|
3
|
-
#
|
4
|
-
# Mixins for adding connectedness features
|
5
|
-
#
|
6
|
-
module Connectedness
|
7
|
-
MIXINS = [Tangle::Mixin::Connectedness].freeze
|
8
|
-
#
|
9
|
-
# Mixin for adding connectedness to a graph
|
10
|
-
#
|
11
|
-
module Graph
|
12
|
-
# Two vertices are adjacent if there is an edge between them
|
13
|
-
def adjacent?(vertex, other)
|
14
|
-
edges(vertex).any? { |edge| edge[vertex] == other }
|
15
|
-
end
|
16
|
-
|
17
|
-
# Return the set of adjacent vertices
|
18
|
-
def adjacent(vertex)
|
19
|
-
Set.new(edges(vertex).map { |edge| edge.walk(vertex) })
|
20
|
-
end
|
21
|
-
|
22
|
-
# Get the largest connected subgraph for a vertex.
|
23
|
-
# Also aliased as :component and :connected_component
|
24
|
-
#
|
25
|
-
# connected_subgraph(vertex) => Graph
|
26
|
-
#
|
27
|
-
def connected_subgraph(vertex)
|
28
|
-
subgraph { |other| connected_vertices?(vertex, other) }
|
29
|
-
end
|
30
|
-
alias component connected_subgraph
|
31
|
-
alias connected_component connected_subgraph
|
32
|
-
|
33
|
-
# Get the largest subgraph that is not connected to a vertex, or what's
|
34
|
-
# left after removing the connected subgraph.
|
35
|
-
#
|
36
|
-
def disconnected_subgraph(vertex)
|
37
|
-
subgraph { |other| !connected_vertices?(vertex, other) }
|
38
|
-
end
|
39
|
-
|
40
|
-
# A graph is connected if all vertices are connected to all vertices
|
41
|
-
# An empty graph is disconnected.
|
42
|
-
#
|
43
|
-
def connected?(*tested_vertices)
|
44
|
-
tested_vertices = vertices if tested_vertices.empty?
|
45
|
-
return false if tested_vertices.empty?
|
46
|
-
|
47
|
-
tested_vertices.combination(2).all? do |pair|
|
48
|
-
this, that = pair.to_a
|
49
|
-
reachable(this).any? { |other| other == that }
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# A graph is disconnected if any vertex is not connected to all other.
|
54
|
-
# An empty graph is disconnected.
|
55
|
-
#
|
56
|
-
def disconnected?(*tested_vertices)
|
57
|
-
!connected?(*tested_vertices)
|
58
|
-
end
|
59
|
-
|
60
|
-
# Return a breadth-first Enumerator for all reachable vertices,
|
61
|
-
# by transitive adjacency.
|
62
|
-
def reachable(start_vertex)
|
63
|
-
vertex_enumerator(start_vertex, :adjacent)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
data/lib/tangle/simple/graph.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'tangle/graph'
|
2
|
-
|
3
|
-
module Tangle
|
4
|
-
module Simple
|
5
|
-
#
|
6
|
-
# A simple graph, without loops and multiple edges
|
7
|
-
class Graph < Tangle::Graph
|
8
|
-
protected
|
9
|
-
|
10
|
-
def insert_edge(edge)
|
11
|
-
raise LoopError if edge.loop?
|
12
|
-
raise MultiEdgeError if adjacent?(*edge.each_vertex)
|
13
|
-
super
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|