mementus 0.5.5 → 0.5.6
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/mementus/depth_first_search.rb +1 -1
- data/lib/mementus/edge_proxy.rb +32 -0
- data/lib/mementus/graph.rb +12 -8
- data/lib/mementus/node_proxy.rb +13 -5
- data/lib/mementus/pipeline/step.rb +11 -26
- data/lib/mementus/structure/adjacency_list.rb +3 -11
- data/lib/mementus/structure/incidence_list.rb +53 -11
- data/lib/mementus/version.rb +1 -1
- data/lib/mementus.rb +1 -0
- data/spec/edge_proxy_spec.rb +20 -0
- data/spec/pipeline_spec.rb +95 -35
- data/spec/structure/adjacency_list_spec.rb +9 -0
- data/spec/structure/directed_graph_example.rb +31 -0
- data/spec/structure/incidence_list_spec.rb +13 -0
- data/spec/structure/indexed_graph_example.rb +68 -0
- data/spec/structure/property_graph_example.rb +64 -0
- metadata +16 -5
- data/spec/structure_spec.rb +0 -145
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d0e0ff3ecc407016774cd2c78afd992296f7a4a
|
4
|
+
data.tar.gz: 0a9d6fcedc13f06dbec244662182cfa0a319fcab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c8c9a6a494b072019580ad80edf5ddcdf15781b0269e747bf615e9c8eb90235c59d7453daf4b90323ae0bd588565d09b7bbfa742459952f6c8f47a7e8c8ce7a
|
7
|
+
data.tar.gz: 93e7943eca3b04fb38eb957a0cc6c453e6065fefc7137c895279117ff1d8f66920ff18de51582cd920392424895852a0aa017a9007d74efa0917450370b37588
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Mementus
|
2
|
+
class EdgeProxy
|
3
|
+
def initialize(edge, graph)
|
4
|
+
@edge = edge
|
5
|
+
@graph = graph
|
6
|
+
end
|
7
|
+
|
8
|
+
def id
|
9
|
+
@edge.id
|
10
|
+
end
|
11
|
+
|
12
|
+
def label
|
13
|
+
@edge.label
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](prop)
|
17
|
+
@edge[prop]
|
18
|
+
end
|
19
|
+
|
20
|
+
def props
|
21
|
+
@edge.props
|
22
|
+
end
|
23
|
+
|
24
|
+
def from
|
25
|
+
@graph.node(@edge.from.id)
|
26
|
+
end
|
27
|
+
|
28
|
+
def to
|
29
|
+
@graph.node(@edge.to.id)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/mementus/graph.rb
CHANGED
@@ -52,20 +52,24 @@ module Mementus
|
|
52
52
|
@structure.nodes(match)
|
53
53
|
end
|
54
54
|
|
55
|
-
def adjacent(id)
|
56
|
-
@structure.adjacent(id)
|
55
|
+
def adjacent(id, match=nil)
|
56
|
+
@structure.adjacent(id, match)
|
57
57
|
end
|
58
58
|
|
59
|
-
def
|
60
|
-
@structure.
|
59
|
+
def incoming(id, match=nil)
|
60
|
+
@structure.incoming(id, match)
|
61
61
|
end
|
62
62
|
|
63
|
-
def
|
64
|
-
@structure.
|
63
|
+
def adjacent_edges(id, match=nil)
|
64
|
+
@structure.adjacent_edges(id, match)
|
65
|
+
end
|
66
|
+
|
67
|
+
def incoming_edges(id, match=nil)
|
68
|
+
@structure.incoming_edges(id, match)
|
65
69
|
end
|
66
70
|
|
67
|
-
def
|
68
|
-
@structure.
|
71
|
+
def each_node(&blk)
|
72
|
+
@structure.each_node(&blk)
|
69
73
|
end
|
70
74
|
|
71
75
|
def each_edge(&blk)
|
data/lib/mementus/node_proxy.rb
CHANGED
@@ -21,20 +21,28 @@ module Mementus
|
|
21
21
|
@node.props
|
22
22
|
end
|
23
23
|
|
24
|
+
def out
|
25
|
+
Pipeline::Step.new([self], Pipeline::Pipe.new(@graph), @graph).out_e
|
26
|
+
end
|
27
|
+
|
24
28
|
def out_e
|
25
|
-
Pipeline::Step.new(
|
29
|
+
Pipeline::Step.new([self], Pipeline::Pipe.new(@graph), @graph).out_e
|
26
30
|
end
|
27
31
|
|
28
32
|
def each_adjacent(&block)
|
29
33
|
@graph.each_adjacent(@node.id, &block)
|
30
34
|
end
|
31
35
|
|
32
|
-
def adjacent
|
33
|
-
@graph.adjacent(@node.id)
|
36
|
+
def adjacent(match=nil)
|
37
|
+
@graph.adjacent(@node.id, match)
|
38
|
+
end
|
39
|
+
|
40
|
+
def incoming(match=nil)
|
41
|
+
@graph.incoming(@node.id, match)
|
34
42
|
end
|
35
43
|
|
36
|
-
def adjacent_edges
|
37
|
-
@graph.adjacent_edges(@node.id)
|
44
|
+
def adjacent_edges(match=nil)
|
45
|
+
@graph.adjacent_edges(@node.id, match)
|
38
46
|
end
|
39
47
|
end
|
40
48
|
end
|
@@ -58,51 +58,36 @@ module Mementus
|
|
58
58
|
end
|
59
59
|
|
60
60
|
# Traverse to the outgoing nodes adjacent to the source elements.
|
61
|
-
def out
|
61
|
+
def out(match=nil)
|
62
62
|
outgoing_nodes = source.inject([]) do |result, node|
|
63
|
-
result.concat(node.adjacent)
|
63
|
+
result.concat(node.adjacent(match))
|
64
64
|
end
|
65
65
|
|
66
66
|
Step.new(outgoing_nodes)
|
67
67
|
end
|
68
68
|
|
69
69
|
# Traverse to the incoming nodes pointing to the source elements.
|
70
|
-
def in
|
71
|
-
incoming_nodes = []
|
72
|
-
|
73
|
-
source.each do |node|
|
74
|
-
graph.each_node do |graph_node|
|
75
|
-
graph.each_adjacent(graph_node.id) do |adj_node|
|
76
|
-
incoming_nodes << graph_node if adj_node.id == node.id
|
77
|
-
end
|
78
|
-
end
|
70
|
+
def in(match=nil)
|
71
|
+
incoming_nodes = source.inject([]) do |result, node|
|
72
|
+
result.concat(node.incoming(match))
|
79
73
|
end
|
80
74
|
|
81
75
|
Step.new(incoming_nodes)
|
82
76
|
end
|
83
77
|
|
84
78
|
# Traverse to the outgoing edges from the source elements.
|
85
|
-
def out_e
|
86
|
-
outgoing_edges = []
|
87
|
-
|
88
|
-
source.each do |node|
|
89
|
-
outgoing_edges = graph.each_adjacent(node.id).map do |id|
|
90
|
-
Mementus::Edge.new(from: node, to: id)
|
91
|
-
end
|
79
|
+
def out_e(match=nil)
|
80
|
+
outgoing_edges = source.inject([]) do |result, node|
|
81
|
+
result.concat(graph.adjacent_edges(node.id, match))
|
92
82
|
end
|
93
83
|
|
94
84
|
Step.new(outgoing_edges)
|
95
85
|
end
|
96
86
|
|
97
87
|
# Traverse to the incoming edges pointing to the source elements.
|
98
|
-
def in_e
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
graph.each_node do |graph_node|
|
103
|
-
graph.each_adjacent(graph_node.id) do |adj_node|
|
104
|
-
incoming_edges << Mementus::Edge.new(from: graph_node, to: adj_node) if ids.include?(adj_node.id)
|
105
|
-
end
|
88
|
+
def in_e(match=nil)
|
89
|
+
incoming_edges = source.inject([]) do |result, node|
|
90
|
+
result.concat(graph.incoming_edges(node.id, match))
|
106
91
|
end
|
107
92
|
|
108
93
|
Step.new(incoming_edges)
|
@@ -52,19 +52,11 @@ module Mementus
|
|
52
52
|
@index[id].to_a
|
53
53
|
end
|
54
54
|
|
55
|
-
def each_node(&blk)
|
56
|
-
nodes.each(&blk)
|
57
|
-
end
|
58
|
-
|
59
|
-
def each_adjacent(id, &blk)
|
60
|
-
@index[id].each(&blk)
|
61
|
-
end
|
62
|
-
|
63
55
|
def each_edge(&blk)
|
64
56
|
if directed?
|
65
|
-
|
66
|
-
|
67
|
-
yield Edge.new(from: from, to: to)
|
57
|
+
nodes.each do |from|
|
58
|
+
adjacent(from.id).each do |to|
|
59
|
+
yield EdgeProxy.new(Edge.new(from: from, to: to), self)
|
68
60
|
end
|
69
61
|
end
|
70
62
|
else
|
@@ -43,7 +43,7 @@ module Mementus
|
|
43
43
|
set_node(edge.from) unless has_node?(edge.from)
|
44
44
|
set_node(edge.to) unless has_node?(edge.to)
|
45
45
|
|
46
|
-
@edges[edge.id] = edge
|
46
|
+
@edges[edge.id] = EdgeProxy.new(edge, self)
|
47
47
|
@outgoing[edge.from.id] << edge.to.id
|
48
48
|
@incoming[edge.to.id] << edge.from.id
|
49
49
|
@outgoing_e[edge.from.id] << edge.id
|
@@ -58,10 +58,6 @@ module Mementus
|
|
58
58
|
@nodes[id]
|
59
59
|
end
|
60
60
|
|
61
|
-
def each_node(&block)
|
62
|
-
@nodes.values.each(&block)
|
63
|
-
end
|
64
|
-
|
65
61
|
def nodes(match=nil)
|
66
62
|
return @nodes.values unless match
|
67
63
|
|
@@ -94,16 +90,62 @@ module Mementus
|
|
94
90
|
end
|
95
91
|
end
|
96
92
|
|
97
|
-
def adjacent(id)
|
98
|
-
|
93
|
+
def adjacent(id, match=nil, direction=:out)
|
94
|
+
directional_index = case direction
|
95
|
+
when :out then @outgoing
|
96
|
+
when :in then @incoming
|
97
|
+
end
|
98
|
+
|
99
|
+
return @nodes.values_at(*directional_index[id]) unless match
|
100
|
+
|
101
|
+
if match.is_a?(Hash)
|
102
|
+
@nodes.values_at(*directional_index[id]).select do |node|
|
103
|
+
key = match.first.first
|
104
|
+
val = match.first.last
|
105
|
+
node[key] == val
|
106
|
+
end
|
107
|
+
elsif match.is_a?(Symbol)
|
108
|
+
@nodes.values_at(*directional_index[id]).select do |node|
|
109
|
+
node.label == match
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def outgoing(id, match=nil)
|
115
|
+
adjacent(id, match, :out)
|
116
|
+
end
|
117
|
+
|
118
|
+
def incoming(id, match=nil)
|
119
|
+
adjacent(id, match, :in)
|
120
|
+
end
|
121
|
+
|
122
|
+
def adjacent_edges(id, match=nil, direction=:out)
|
123
|
+
directional_index = case direction
|
124
|
+
when :out then @outgoing_e
|
125
|
+
when :in then @incoming_e
|
126
|
+
end
|
127
|
+
|
128
|
+
return @edges.values_at(*directional_index[id]) unless match
|
129
|
+
|
130
|
+
if match.is_a?(Hash)
|
131
|
+
@edges.values_at(*directional_index[id]).select do |edge|
|
132
|
+
key = match.first.first
|
133
|
+
val = match.first.last
|
134
|
+
edge[key] == val
|
135
|
+
end
|
136
|
+
elsif match.is_a?(Symbol)
|
137
|
+
@edges.values_at(*directional_index[id]).select do |edge|
|
138
|
+
edge.label == match
|
139
|
+
end
|
140
|
+
end
|
99
141
|
end
|
100
142
|
|
101
|
-
def
|
102
|
-
|
143
|
+
def outgoing_edges(id, match=nil)
|
144
|
+
adjacent_edges(id, match, :out)
|
103
145
|
end
|
104
146
|
|
105
|
-
def
|
106
|
-
|
147
|
+
def incoming_edges(id, match=nil)
|
148
|
+
adjacent_edges(id, match, :in)
|
107
149
|
end
|
108
150
|
end
|
109
151
|
end
|
data/lib/mementus/version.rb
CHANGED
data/lib/mementus.rb
CHANGED
@@ -5,6 +5,7 @@ require 'mementus/structure/incidence_list'
|
|
5
5
|
require 'mementus/node'
|
6
6
|
require 'mementus/edge'
|
7
7
|
require 'mementus/node_proxy'
|
8
|
+
require 'mementus/edge_proxy'
|
8
9
|
require 'mementus/pipeline/pipe'
|
9
10
|
require 'mementus/pipeline/filter'
|
10
11
|
require 'mementus/pipeline/transform'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mementus::EdgeProxy do
|
4
|
+
let(:graph) do
|
5
|
+
Mementus::Graph.new do
|
6
|
+
set_edge(edge_1_2)
|
7
|
+
set_edge(edge_1_3)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
specify '#from' do
|
12
|
+
edge_proxy = Mementus::EdgeProxy.new(edge_1_2, graph)
|
13
|
+
expect(edge_proxy.from.id).to eq(node_1.id)
|
14
|
+
end
|
15
|
+
|
16
|
+
specify '#to' do
|
17
|
+
edge_proxy = Mementus::EdgeProxy.new(edge_1_2, graph)
|
18
|
+
expect(edge_proxy.to.id).to eq(node_2.id)
|
19
|
+
end
|
20
|
+
end
|
data/spec/pipeline_spec.rb
CHANGED
@@ -26,6 +26,7 @@ describe 'pipeline api' do
|
|
26
26
|
edge.from = 1
|
27
27
|
edge.to = 2
|
28
28
|
edge.label = :choice
|
29
|
+
edge.props[:name] = 'e3'
|
29
30
|
end
|
30
31
|
|
31
32
|
create_edge do |edge|
|
@@ -33,55 +34,114 @@ describe 'pipeline api' do
|
|
33
34
|
edge.from = 2
|
34
35
|
edge.to = 4
|
35
36
|
edge.label = :choice
|
37
|
+
edge.props[:name] = 'e5'
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
describe '#n' do
|
43
|
+
it 'traverses from the given node id' do
|
44
|
+
pipeline = graph.n(1)
|
45
|
+
expect(pipeline.id).to eq(1)
|
46
|
+
expect(pipeline.first.id).to eq(1)
|
47
|
+
end
|
45
48
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
49
|
+
it 'traverses from the given label match' do
|
50
|
+
pipeline = graph.n(:passage)
|
51
|
+
expect(pipeline.id).to eq([1, 2, 4])
|
52
|
+
expect(pipeline.first.id).to eq(1)
|
53
|
+
end
|
51
54
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
it 'traverses from the given prop match' do
|
56
|
+
pipeline = graph.n(name: 'one')
|
57
|
+
expect(pipeline.id).to eq(1)
|
58
|
+
expect(pipeline.first.id).to eq(1)
|
59
|
+
end
|
56
60
|
end
|
57
61
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
62
|
+
describe '#out' do
|
63
|
+
it 'traverses to outgoing nodes' do
|
64
|
+
pipeline = graph.n(1).out
|
65
|
+
expect(pipeline.all.count).to eq(1)
|
66
|
+
expect(pipeline.all.first.id).to eq(2)
|
67
|
+
end
|
63
68
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
69
|
+
it 'traverses to outgoing nodes matching label' do
|
70
|
+
pipeline = graph.n(1).out(:passage)
|
71
|
+
expect(pipeline.all.count).to eq(1)
|
72
|
+
expect(pipeline.all.first.id).to eq(2)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'traverses to outgoing nodes matching filter' do
|
76
|
+
pipeline = graph.n(1).out(name: 'two')
|
77
|
+
expect(pipeline.all.count).to eq(1)
|
78
|
+
expect(pipeline.all.first.id).to eq(2)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'traverses to second-degree outgoing nodes' do
|
82
|
+
pipeline = graph.n(1).out.out
|
83
|
+
expect(pipeline.all.count).to eq(1)
|
84
|
+
expect(pipeline.all.first.id).to eq(4)
|
85
|
+
end
|
68
86
|
end
|
69
87
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
88
|
+
describe '#out_e' do
|
89
|
+
it 'traverses to outgoing edges' do
|
90
|
+
pipeline = graph.n(1).out_e
|
91
|
+
expect(pipeline.all.count).to eq(1)
|
92
|
+
expect(pipeline.all.first.to.id).to eq(2)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'traverses to outgoing edges matching label' do
|
96
|
+
pipeline = graph.n(1).out_e(:choice)
|
97
|
+
expect(pipeline.all.count).to eq(1)
|
98
|
+
expect(pipeline.all.first.to.id).to eq(2)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'traverses to outgoing edges matching filter' do
|
102
|
+
pipeline = graph.n(1).out_e(name: 'e3')
|
103
|
+
expect(pipeline.all.count).to eq(1)
|
104
|
+
expect(pipeline.all.first.to.id).to eq(2)
|
105
|
+
end
|
74
106
|
end
|
75
107
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
108
|
+
describe '#in' do
|
109
|
+
it 'traverses to incoming nodes' do
|
110
|
+
pipeline = graph.n(2).in
|
111
|
+
expect(pipeline.all.count).to eq(1)
|
112
|
+
expect(pipeline.all.first.id).to eq(1)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'traverses to incoming nodes matching label' do
|
116
|
+
pipeline = graph.n(2).in(:passage)
|
117
|
+
expect(pipeline.all.count).to eq(1)
|
118
|
+
expect(pipeline.all.first.id).to eq(1)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'traverses to incoming nodes matching filter' do
|
122
|
+
pipeline = graph.n(2).in(name: 'one')
|
123
|
+
expect(pipeline.all.count).to eq(1)
|
124
|
+
expect(pipeline.all.first.id).to eq(1)
|
125
|
+
end
|
80
126
|
end
|
81
127
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
128
|
+
describe '#in_e' do
|
129
|
+
it 'traverses to incoming edges' do
|
130
|
+
pipeline = graph.n(2).in_e
|
131
|
+
expect(pipeline.all.count).to eq(1)
|
132
|
+
expect(pipeline.all.first.from.id).to eq(1)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'traverses to incoming edges matching label' do
|
136
|
+
pipeline = graph.n(2).in_e(:choice)
|
137
|
+
expect(pipeline.all.count).to eq(1)
|
138
|
+
expect(pipeline.all.first.from.id).to eq(1)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'traverses to incoming edges matching filter' do
|
142
|
+
pipeline = graph.n(2).in_e(name: 'e3')
|
143
|
+
expect(pipeline.all.count).to eq(1)
|
144
|
+
expect(pipeline.all.first.from.id).to eq(1)
|
145
|
+
end
|
86
146
|
end
|
87
147
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for 'a directed graph data structure' do
|
4
|
+
it 'enumerates outgoing nodes from the given node' do
|
5
|
+
edge = Mementus::Edge.new(from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
6
|
+
structure.set_edge(edge)
|
7
|
+
|
8
|
+
expect(structure.outgoing(1).first.id).to eq(2)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'enumerates outgoing edges from the given node' do
|
12
|
+
edge = Mementus::Edge.new(id: 3, from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
13
|
+
structure.set_edge(edge)
|
14
|
+
|
15
|
+
expect(structure.outgoing_edges(1).first.id).to eq(3)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'enumerates incoming nodes from the given node' do
|
19
|
+
edge = Mementus::Edge.new(from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
20
|
+
structure.set_edge(edge)
|
21
|
+
|
22
|
+
expect(structure.incoming(2).first.id).to eq(1)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'enumerates incoming edges from the given node' do
|
26
|
+
edge = Mementus::Edge.new(id: 3, from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
27
|
+
structure.set_edge(edge)
|
28
|
+
|
29
|
+
expect(structure.incoming_edges(2).first.id).to eq(3)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'indexed_graph_example'
|
2
|
+
require_relative 'directed_graph_example'
|
3
|
+
require_relative 'property_graph_example'
|
4
|
+
|
5
|
+
describe Mementus::Structure::IncidenceList do
|
6
|
+
let(:structure) do
|
7
|
+
Mementus::Structure::IncidenceList.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it_behaves_like 'an indexed graph data structure'
|
11
|
+
it_behaves_like 'a directed graph data structure'
|
12
|
+
it_behaves_like 'a property graph data structure'
|
13
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for "an indexed graph data structure" do
|
4
|
+
describe '#new' do
|
5
|
+
it 'starts with empty node list' do
|
6
|
+
expect(structure.nodes_count).to eq(0)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'starts with empty edge list' do
|
10
|
+
expect(structure.edges_count).to eq(0)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#set_node' do
|
15
|
+
it 'assigns a node object to the graph' do
|
16
|
+
structure.set_node(Mementus::Node.new(id: 1))
|
17
|
+
|
18
|
+
expect(structure.nodes_count).to eq(1)
|
19
|
+
expect(structure.edges_count).to eq(0)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#set_edge' do
|
24
|
+
it 'adds an edge object to the graph' do
|
25
|
+
structure.set_edge(Mementus::Edge.new(from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2)))
|
26
|
+
|
27
|
+
expect(structure.nodes_count).to eq(2)
|
28
|
+
expect(structure.edges_count).to eq(1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#has_node?' do
|
33
|
+
it 'tests for the presence of a given node' do
|
34
|
+
node = Mementus::Node.new(id: 1)
|
35
|
+
structure.set_node(node)
|
36
|
+
|
37
|
+
expect(structure.has_node?(node)).to be true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#has_edge?' do
|
42
|
+
it 'tests for the presence of a given edge' do
|
43
|
+
edge = Mementus::Edge.new(from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
44
|
+
structure.set_edge(edge)
|
45
|
+
|
46
|
+
expect(structure.has_edge?(edge)).to be true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#node(id)' do
|
51
|
+
it 'finds a node by id' do
|
52
|
+
edge = Mementus::Edge.new(from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
53
|
+
structure.set_edge(edge)
|
54
|
+
|
55
|
+
expect(structure.node(1).id).to eq(edge.from.id)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#nodes' do
|
60
|
+
it 'lists all nodes in the graph' do
|
61
|
+
edge = Mementus::Edge.new(from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
62
|
+
structure.set_edge(edge)
|
63
|
+
|
64
|
+
expect(structure.nodes.first.id).to eq(edge.from.id)
|
65
|
+
expect(structure.nodes.last.id).to eq(edge.to.id)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for 'a property graph data structure' do
|
4
|
+
describe '#nodes(match)' do
|
5
|
+
it 'matches all nodes with the given prop' do
|
6
|
+
structure.set_node(Mementus::Node.new(id: 1, props: { tag: 'point'}))
|
7
|
+
structure.set_node(Mementus::Node.new(id: 2, props: { tag: 'point'}))
|
8
|
+
structure.set_node(Mementus::Node.new(id: 3))
|
9
|
+
|
10
|
+
structure.nodes(tag: 'point').tap do |matched|
|
11
|
+
expect(matched.first.id).to eq(1)
|
12
|
+
expect(matched.last.id).to eq(2)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'matches all nodes with the given label' do
|
17
|
+
structure.set_node(Mementus::Node.new(id: 1, label: :point))
|
18
|
+
structure.set_node(Mementus::Node.new(id: 2, label: :point))
|
19
|
+
structure.set_node(Mementus::Node.new(id: 3))
|
20
|
+
|
21
|
+
structure.nodes(:point).tap do |matched|
|
22
|
+
expect(matched.first.id).to eq(1)
|
23
|
+
expect(matched.last.id).to eq(2)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#edges' do
|
29
|
+
it 'lists all edges in the graph' do
|
30
|
+
edge = Mementus::Edge.new(id: 3, from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
31
|
+
structure.set_edge(edge)
|
32
|
+
|
33
|
+
structure.edges.tap do |matched|
|
34
|
+
expect(matched.first.id).to eq(edge.id)
|
35
|
+
expect(matched.first.from.id).to eq(edge.from.id)
|
36
|
+
expect(matched.first.to.id).to eq(edge.to.id)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#edges(match)' do
|
42
|
+
it 'matches all edges with the given prop' do
|
43
|
+
edge = Mementus::Edge.new(props: { tag: 'link' }, from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
44
|
+
structure.set_edge(edge)
|
45
|
+
|
46
|
+
structure.edges(tag: 'link').tap do |matched|
|
47
|
+
expect(matched.first.id).to eq(edge.id)
|
48
|
+
expect(matched.first.from.id).to eq(edge.from.id)
|
49
|
+
expect(matched.first.to.id).to eq(edge.to.id)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'matches all edges with the given label' do
|
54
|
+
edge = Mementus::Edge.new(label: :link, from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
55
|
+
structure.set_edge(edge)
|
56
|
+
|
57
|
+
structure.edges(:link).tap do |matched|
|
58
|
+
expect(matched.first.id).to eq(edge.id)
|
59
|
+
expect(matched.first.from.id).to eq(edge.from.id)
|
60
|
+
expect(matched.first.to.id).to eq(edge.to.id)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mementus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- maetl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- lib/mementus/direction.rb
|
71
71
|
- lib/mementus/edge.rb
|
72
72
|
- lib/mementus/edge_builder.rb
|
73
|
+
- lib/mementus/edge_proxy.rb
|
73
74
|
- lib/mementus/element_builder.rb
|
74
75
|
- lib/mementus/graph.rb
|
75
76
|
- lib/mementus/graph_builder.rb
|
@@ -94,6 +95,7 @@ files:
|
|
94
95
|
- lib/mementus/version.rb
|
95
96
|
- mementus.gemspec
|
96
97
|
- spec/direction_spec.rb
|
98
|
+
- spec/edge_proxy_spec.rb
|
97
99
|
- spec/edge_spec.rb
|
98
100
|
- spec/graph_spec.rb
|
99
101
|
- spec/herschel_spec.rb
|
@@ -103,7 +105,11 @@ files:
|
|
103
105
|
- spec/pipeline/step_spec.rb
|
104
106
|
- spec/pipeline_spec.rb
|
105
107
|
- spec/spec_helper.rb
|
106
|
-
- spec/
|
108
|
+
- spec/structure/adjacency_list_spec.rb
|
109
|
+
- spec/structure/directed_graph_example.rb
|
110
|
+
- spec/structure/incidence_list_spec.rb
|
111
|
+
- spec/structure/indexed_graph_example.rb
|
112
|
+
- spec/structure/property_graph_example.rb
|
107
113
|
- spec/traversal_spec.rb
|
108
114
|
homepage: https://github.com/maetl/mementus
|
109
115
|
licenses:
|
@@ -125,12 +131,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
131
|
version: '0'
|
126
132
|
requirements: []
|
127
133
|
rubyforge_project:
|
128
|
-
rubygems_version: 2.
|
134
|
+
rubygems_version: 2.5.1
|
129
135
|
signing_key:
|
130
136
|
specification_version: 4
|
131
137
|
summary: Graph data structure toolkit for Ruby applications.
|
132
138
|
test_files:
|
133
139
|
- spec/direction_spec.rb
|
140
|
+
- spec/edge_proxy_spec.rb
|
134
141
|
- spec/edge_spec.rb
|
135
142
|
- spec/graph_spec.rb
|
136
143
|
- spec/herschel_spec.rb
|
@@ -140,5 +147,9 @@ test_files:
|
|
140
147
|
- spec/pipeline/step_spec.rb
|
141
148
|
- spec/pipeline_spec.rb
|
142
149
|
- spec/spec_helper.rb
|
143
|
-
- spec/
|
150
|
+
- spec/structure/adjacency_list_spec.rb
|
151
|
+
- spec/structure/directed_graph_example.rb
|
152
|
+
- spec/structure/incidence_list_spec.rb
|
153
|
+
- spec/structure/indexed_graph_example.rb
|
154
|
+
- spec/structure/property_graph_example.rb
|
144
155
|
- spec/traversal_spec.rb
|
data/spec/structure_spec.rb
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
shared_examples_for "a mutable graph data structure" do
|
4
|
-
describe '#new' do
|
5
|
-
it 'starts with empty node list' do
|
6
|
-
expect(structure.nodes_count).to eq(0)
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'starts with empty edge list' do
|
10
|
-
expect(structure.edges_count).to eq(0)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe '#set_node' do
|
15
|
-
it 'assigns a node object to the graph' do
|
16
|
-
structure.set_node(Mementus::Node.new(id: 1))
|
17
|
-
|
18
|
-
expect(structure.nodes_count).to eq(1)
|
19
|
-
expect(structure.edges_count).to eq(0)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe '#set_edge' do
|
24
|
-
it 'adds an edge object to the graph' do
|
25
|
-
structure.set_edge(Mementus::Edge.new(from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2)))
|
26
|
-
|
27
|
-
expect(structure.nodes_count).to eq(2)
|
28
|
-
expect(structure.edges_count).to eq(1)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe '#has_node?' do
|
33
|
-
it 'tests for the presence of a given node' do
|
34
|
-
node = Mementus::Node.new(id: 1)
|
35
|
-
structure.set_node(node)
|
36
|
-
|
37
|
-
expect(structure.has_node?(node)).to be true
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe '#has_edge?' do
|
42
|
-
it 'tests for the presence of a given edge' do
|
43
|
-
edge = Mementus::Edge.new(from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
44
|
-
structure.set_edge(edge)
|
45
|
-
|
46
|
-
expect(structure.has_edge?(edge)).to be true
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe '#node(id)' do
|
51
|
-
it 'finds a node by id' do
|
52
|
-
edge = Mementus::Edge.new(from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
53
|
-
structure.set_edge(edge)
|
54
|
-
|
55
|
-
expect(structure.node(1).id).to eq(edge.from.id)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe '#nodes' do
|
60
|
-
it 'lists all nodes in the graph' do
|
61
|
-
edge = Mementus::Edge.new(from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
62
|
-
structure.set_edge(edge)
|
63
|
-
|
64
|
-
expect(structure.nodes.first.id).to eq(edge.from.id)
|
65
|
-
expect(structure.nodes.last.id).to eq(edge.to.id)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe Mementus::Structure::AdjacencyList do
|
71
|
-
let(:structure) do
|
72
|
-
Mementus::Structure::AdjacencyList.new
|
73
|
-
end
|
74
|
-
|
75
|
-
it_behaves_like "a mutable graph data structure"
|
76
|
-
end
|
77
|
-
|
78
|
-
describe Mementus::Structure::IncidenceList do
|
79
|
-
let(:structure) do
|
80
|
-
Mementus::Structure::IncidenceList.new
|
81
|
-
end
|
82
|
-
|
83
|
-
it_behaves_like "a mutable graph data structure"
|
84
|
-
|
85
|
-
describe '#nodes(match)' do
|
86
|
-
it 'matches all nodes with the given prop' do
|
87
|
-
structure.set_node(Mementus::Node.new(id: 1, props: { tag: 'point'}))
|
88
|
-
structure.set_node(Mementus::Node.new(id: 2, props: { tag: 'point'}))
|
89
|
-
structure.set_node(Mementus::Node.new(id: 3))
|
90
|
-
|
91
|
-
structure.nodes(tag: 'point').tap do |matched|
|
92
|
-
expect(matched.first.id).to eq(1)
|
93
|
-
expect(matched.last.id).to eq(2)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'matches all nodes with the given label' do
|
98
|
-
structure.set_node(Mementus::Node.new(id: 1, label: :point))
|
99
|
-
structure.set_node(Mementus::Node.new(id: 2, label: :point))
|
100
|
-
structure.set_node(Mementus::Node.new(id: 3))
|
101
|
-
|
102
|
-
structure.nodes(:point).tap do |matched|
|
103
|
-
expect(matched.first.id).to eq(1)
|
104
|
-
expect(matched.last.id).to eq(2)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
describe '#edges' do
|
110
|
-
it 'lists all edges in the graph' do
|
111
|
-
edge = Mementus::Edge.new(id: 3, from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
112
|
-
structure.set_edge(edge)
|
113
|
-
|
114
|
-
structure.edges.tap do |matched|
|
115
|
-
expect(matched.first.id).to eq(edge.id)
|
116
|
-
expect(matched.first.from.id).to eq(edge.from.id)
|
117
|
-
expect(matched.first.to.id).to eq(edge.to.id)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
describe '#edges(match)' do
|
123
|
-
it 'matches all edges with the given prop' do
|
124
|
-
edge = Mementus::Edge.new(props: { tag: 'link' }, from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
125
|
-
structure.set_edge(edge)
|
126
|
-
|
127
|
-
structure.edges(tag: 'link').tap do |matched|
|
128
|
-
expect(matched.first.id).to eq(edge.id)
|
129
|
-
expect(matched.first.from.id).to eq(edge.from.id)
|
130
|
-
expect(matched.first.to.id).to eq(edge.to.id)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'matches all edges with the given label' do
|
135
|
-
edge = Mementus::Edge.new(label: :link, from: Mementus::Node.new(id: 1), to: Mementus::Node.new(id: 2))
|
136
|
-
structure.set_edge(edge)
|
137
|
-
|
138
|
-
structure.edges(:link).tap do |matched|
|
139
|
-
expect(matched.first.id).to eq(edge.id)
|
140
|
-
expect(matched.first.from.id).to eq(edge.from.id)
|
141
|
-
expect(matched.first.to.id).to eq(edge.to.id)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|