petri_net 0.8.0 → 0.9.4
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/.travis.yml +3 -2
- data/Gemfile +3 -0
- data/lib/petri_net/graph/edge.rb +2 -1
- data/lib/petri_net/graph/graph.rb +152 -4
- data/lib/petri_net/graph/node.rb +4 -0
- data/lib/petri_net/net.rb +67 -3
- data/lib/petri_net/version.rb +1 -1
- data/petri_net.gemspec +1 -1
- data/test/reachability_graph/tc_graph.rb +22 -5
- data/test/tc_petri_net.rb +5 -0
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 785d6ed616e72a8f4229c584b3625bd182dcc354
|
4
|
+
data.tar.gz: 7ae508f907786e328f3148ab86c5653bdc6e03c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71ec4878553ee6f33000bf9901d2ba1b9707ad3ddb0e793812ec19bbc027ce2ea1a77ee2669f1f625210f82f13744ecd304614379c2348d76fa33288d4600ff0
|
7
|
+
data.tar.gz: 2eba62b83d60d28a62d14a67d07bb1981a2026a3f693b959f264bd7bd0c9e7f24fe6f556a7415c4db82edb9fd675aff38b8e5d28dee7a8e5634445d8691b4afa
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/lib/petri_net/graph/edge.rb
CHANGED
@@ -31,6 +31,7 @@ class PetriNet::Graph::Edge < PetriNet::Base
|
|
31
31
|
|
32
32
|
# Validates the data holded by this edge, this will be used while adding the edge to the graph
|
33
33
|
def validate
|
34
|
+
return false unless ( @graph.nodes.has_key? @source.name and @graph.nodes.has_key? @destination.name )
|
34
35
|
true
|
35
36
|
end
|
36
37
|
|
@@ -43,7 +44,7 @@ class PetriNet::Graph::Edge < PetriNet::Base
|
|
43
44
|
(@source == object.yource && @destination == oject.destination)
|
44
45
|
end
|
45
46
|
def to_s
|
46
|
-
"#{@id}: #{@name} #{@source
|
47
|
+
"#{@id}: #{@name} #{@source} -> #{@destination} )"
|
47
48
|
end
|
48
49
|
|
49
50
|
private
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'graphviz'
|
2
|
-
|
2
|
+
require 'graphviz/theory'
|
3
|
+
require 'rgl/adjacency'
|
4
|
+
require 'rgl/dijkstra'
|
3
5
|
class PetriNet::InfiniteReachabilityGraphError < RuntimeError
|
4
6
|
end
|
5
7
|
|
@@ -7,6 +9,10 @@ class PetriNet::Graph < PetriNet::Base
|
|
7
9
|
|
8
10
|
# The PetriNet this graph belongs to
|
9
11
|
attr_reader :net
|
12
|
+
# all nodes from this graph
|
13
|
+
attr_reader :nodes
|
14
|
+
# all edges of this graph
|
15
|
+
attr_reader :edges
|
10
16
|
|
11
17
|
def initialize(net, options = Hash.new)
|
12
18
|
@net = net
|
@@ -29,6 +35,10 @@ class PetriNet::Graph < PetriNet::Base
|
|
29
35
|
node.graph = self
|
30
36
|
return node.id
|
31
37
|
end
|
38
|
+
if @objects.include? node
|
39
|
+
res = (@objects.index node) * -1
|
40
|
+
return res
|
41
|
+
end
|
32
42
|
return false
|
33
43
|
end
|
34
44
|
alias_method :add_node!, :add_node
|
@@ -38,12 +48,24 @@ class PetriNet::Graph < PetriNet::Base
|
|
38
48
|
@objects[edge.id] = edge
|
39
49
|
@edges[edge.name] = edge.id
|
40
50
|
edge.graph = self
|
51
|
+
edge.source.outputs << edge.id
|
52
|
+
edge.destination.inputs << edge.id
|
41
53
|
return edge.id
|
42
54
|
end
|
43
55
|
return false
|
44
56
|
end
|
45
57
|
|
46
|
-
|
58
|
+
def get_edge(source, dest)
|
59
|
+
res = nil
|
60
|
+
@edges.each_value do |edge|
|
61
|
+
if @objects[edge].source == source && @objects[edge].destination == dest
|
62
|
+
res = @objects[edge]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
res
|
66
|
+
end
|
67
|
+
|
68
|
+
# Add an object to the Graph.
|
47
69
|
def <<(object)
|
48
70
|
case object.class.to_s
|
49
71
|
when "Array"
|
@@ -59,7 +81,16 @@ class PetriNet::Graph < PetriNet::Base
|
|
59
81
|
end
|
60
82
|
alias_method :add_object, :<<
|
61
83
|
|
62
|
-
def get_node(
|
84
|
+
def get_node(node)
|
85
|
+
if node.class.to_s == "Fixnum"
|
86
|
+
return @objects[node]
|
87
|
+
end
|
88
|
+
if node.class.to_s == "Array"
|
89
|
+
return @objects.select{|o| o.class.to_s == "PetriNet::ReachabilityGraph::Node" && o.markings == node}.first
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_object(id)
|
63
94
|
@objects[id]
|
64
95
|
end
|
65
96
|
|
@@ -71,6 +102,13 @@ class PetriNet::Graph < PetriNet::Base
|
|
71
102
|
res
|
72
103
|
end
|
73
104
|
|
105
|
+
def infinite?
|
106
|
+
@nodes.each_value do |node|
|
107
|
+
return true if @objects[node].infinite?
|
108
|
+
end
|
109
|
+
false
|
110
|
+
end
|
111
|
+
|
74
112
|
def to_gv(output = 'png', filename = '')
|
75
113
|
g = generate_gv
|
76
114
|
if filename.empty?
|
@@ -95,7 +133,18 @@ class PetriNet::Graph < PetriNet::Base
|
|
95
133
|
e.label = @objects[edge].transition
|
96
134
|
end
|
97
135
|
end
|
98
|
-
g
|
136
|
+
@gv = g
|
137
|
+
end
|
138
|
+
|
139
|
+
def generate_rgl
|
140
|
+
g = RGL::DirectedAdjacencyGraph.new
|
141
|
+
@nodes.each_value do |node|
|
142
|
+
g.add_vertex @objects[node].markings.to_s
|
143
|
+
end
|
144
|
+
@edges.each_value do |edge|
|
145
|
+
g.add_edge @objects[edge].source.markings.to_s, @objects[edge].destination.markings.to_s
|
146
|
+
end
|
147
|
+
@rgl = g
|
99
148
|
end
|
100
149
|
|
101
150
|
def to_s
|
@@ -118,4 +167,103 @@ class PetriNet::Graph < PetriNet::Base
|
|
118
167
|
return str
|
119
168
|
end
|
120
169
|
|
170
|
+
def get_rgl
|
171
|
+
if @rgl.nil?
|
172
|
+
generate_rgl
|
173
|
+
end
|
174
|
+
@rgl
|
175
|
+
end
|
176
|
+
|
177
|
+
def cycles
|
178
|
+
get_rgl.cycles
|
179
|
+
end
|
180
|
+
|
181
|
+
def shortest_path(start, destination)
|
182
|
+
g = get_rgl
|
183
|
+
weights = lambda { |edge| 1 }
|
184
|
+
g.dijkstra_shortest_path(weights, start.to_s, destination.to_s)
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def path_probability(path)
|
189
|
+
sanitize_probabilities
|
190
|
+
prob = 1
|
191
|
+
counter = 0
|
192
|
+
path.each do |node|
|
193
|
+
edge = get_edge(path[counter+1], node)
|
194
|
+
prob = prob * edge.probability unless edge.nil? # last node has no pre-edge
|
195
|
+
counter = counter += 1
|
196
|
+
end
|
197
|
+
prob
|
198
|
+
end
|
199
|
+
|
200
|
+
def node_probability(start, node)
|
201
|
+
paths = get_paths_without_loops(start, node)
|
202
|
+
prob = 0
|
203
|
+
paths.each do |path|
|
204
|
+
prob = prob + (path_probability path)
|
205
|
+
end
|
206
|
+
prob
|
207
|
+
end
|
208
|
+
|
209
|
+
def best_path(start, node)
|
210
|
+
paths = get_paths_without_loops(start, node)
|
211
|
+
prob = 0
|
212
|
+
res_path = nil
|
213
|
+
paths.each do |path|
|
214
|
+
if (path_probability path) >= prob
|
215
|
+
prob = (path_probability path)
|
216
|
+
res_path = path
|
217
|
+
end
|
218
|
+
end
|
219
|
+
[res_path,prob]
|
220
|
+
end
|
221
|
+
|
222
|
+
def worst_path(start, node)
|
223
|
+
paths = get_paths_without_loops(start, node)
|
224
|
+
prob = 1
|
225
|
+
res_path = nil
|
226
|
+
paths.each do |path|
|
227
|
+
if (path_probability path) <= prob
|
228
|
+
prob = (path_probability path)
|
229
|
+
res_path = path
|
230
|
+
end
|
231
|
+
end
|
232
|
+
[res_path,prob]
|
233
|
+
end
|
234
|
+
|
235
|
+
def get_paths_without_loops(start, goal)
|
236
|
+
get_paths_without_loops_helper(get_node(start), get_node(goal))
|
237
|
+
end
|
238
|
+
|
239
|
+
def sanitize_probabilities
|
240
|
+
@nodes.each_value do |node|
|
241
|
+
prob = 1.0
|
242
|
+
@objects[node].outputs.each do |edge|
|
243
|
+
prob = prob + @objects[edge].probability unless @objects[edge].probability.nil?
|
244
|
+
end
|
245
|
+
@objects[node].outputs.each do |edge|
|
246
|
+
@objects[edge].probability = prob/@objects[node].outputs.size if @objects[edge].probability.nil?
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
|
252
|
+
private
|
253
|
+
def get_paths_without_loops_helper(start, goal, reverse_paths = Array.new, reverse_path = Array.new)
|
254
|
+
if goal == start
|
255
|
+
reverse_path << goal
|
256
|
+
reverse_paths << reverse_path
|
257
|
+
return nil
|
258
|
+
end
|
259
|
+
if reverse_path.include? goal
|
260
|
+
return nil
|
261
|
+
end
|
262
|
+
path = Array.new
|
263
|
+
goal.inputs.each do |input|
|
264
|
+
get_paths_without_loops_helper(start, @objects[input].source, reverse_paths, reverse_path.clone << goal)
|
265
|
+
end
|
266
|
+
reverse_paths
|
267
|
+
end
|
268
|
+
|
121
269
|
end
|
data/lib/petri_net/graph/node.rb
CHANGED
data/lib/petri_net/net.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'yaml'
|
2
|
+
require 'graphviz'
|
3
|
+
require 'matrix'
|
4
|
+
require 'bigdecimal/ludcmp'
|
2
5
|
|
3
6
|
class PetriNet::Net < PetriNet::Base
|
7
|
+
include LUSolve
|
4
8
|
# Human readable name
|
5
9
|
attr_accessor :name
|
6
10
|
# Storage filename
|
@@ -240,6 +244,9 @@ Arcs
|
|
240
244
|
end
|
241
245
|
|
242
246
|
def reachability_graph
|
247
|
+
if !@up_to_date
|
248
|
+
update
|
249
|
+
end
|
243
250
|
generate_reachability_graph unless (@graph && @up_to_date)
|
244
251
|
@graph
|
245
252
|
end
|
@@ -300,6 +307,18 @@ Arcs
|
|
300
307
|
@places.map{|key,pid| @objects[pid].markings.size}
|
301
308
|
end
|
302
309
|
|
310
|
+
def get_marking(places)
|
311
|
+
unless places.class.to_s == "Array"
|
312
|
+
places = [places]
|
313
|
+
end
|
314
|
+
if places.first.class.to_s == "Fixnum"
|
315
|
+
places.map!{|p| get_place p}
|
316
|
+
end
|
317
|
+
res = Array.new
|
318
|
+
get_place_list.map{|place| if places.include? place.name then res << 1 else res << 0 end}
|
319
|
+
res
|
320
|
+
end
|
321
|
+
|
303
322
|
def set_markings(markings)
|
304
323
|
i = 0
|
305
324
|
@places.each_value do |pid|
|
@@ -313,6 +332,11 @@ Arcs
|
|
313
332
|
@places.map{|key,pid| @objects[pid]}
|
314
333
|
end
|
315
334
|
|
335
|
+
def get_place_from_marking(marking)
|
336
|
+
return marking if marking.count(1) != 1
|
337
|
+
get_place_list[marking.index(1)].name
|
338
|
+
end
|
339
|
+
|
316
340
|
|
317
341
|
def objects_size
|
318
342
|
@objects.count{|o| !o.nil?}
|
@@ -346,8 +370,46 @@ Arcs
|
|
346
370
|
get_transition(transition).fire
|
347
371
|
end
|
348
372
|
|
373
|
+
def delta
|
374
|
+
if @delta.nil?
|
375
|
+
generate_delta
|
376
|
+
end
|
377
|
+
@delta
|
378
|
+
end
|
379
|
+
|
380
|
+
def t_invariants
|
381
|
+
delta = self.delta
|
382
|
+
zero_vector = Array.new
|
383
|
+
delta.row_count.times { zero_vector << 0 }
|
384
|
+
zero = BigDecimal("0.0")
|
385
|
+
one = BigDecimal("1.0")
|
386
|
+
|
387
|
+
ps = ludecomp(delta.t.to_a.flatten.map{|i|BigDecimal(i,16)},delta.row_count, zero, one)
|
388
|
+
x = lusolve(delta.t.to_a.flatten.map{|i|BigDecimal(i,16)},zero_vector.map{|i|BigDecimal(i,16)},ps, zero)
|
389
|
+
|
390
|
+
x
|
391
|
+
end
|
392
|
+
|
393
|
+
def s_invariant
|
394
|
+
raise "Not jet implemented"
|
395
|
+
end
|
396
|
+
|
349
397
|
private
|
350
398
|
|
399
|
+
def generate_delta
|
400
|
+
d = Array.new(@places.size){Array.new(@transitions.size)}
|
401
|
+
i = 0
|
402
|
+
@places.each do |p_key,p_value|
|
403
|
+
j = 0
|
404
|
+
@transitions.each do |t_key,t_value|
|
405
|
+
d[i][j] = w0(t_value, p_value) - w0(p_value,t_value)
|
406
|
+
j += 1
|
407
|
+
end
|
408
|
+
i += 1
|
409
|
+
end
|
410
|
+
@delta = Matrix[d]
|
411
|
+
end
|
412
|
+
|
351
413
|
def changed_structure
|
352
414
|
@w_up_to_date = false
|
353
415
|
@up_to_date = false
|
@@ -356,7 +418,6 @@ Arcs
|
|
356
418
|
def changed_state
|
357
419
|
@up_to_date = false
|
358
420
|
end
|
359
|
-
|
360
421
|
def reachability_helper(markings, source)
|
361
422
|
@transitions.each_value do |tid|
|
362
423
|
raise PetriNet::ReachabilityGraph::InfinityGraphError if @objects[tid].inputs.empty? && !@objects[tid].outputs.empty?
|
@@ -373,8 +434,11 @@ Arcs
|
|
373
434
|
@graph.add_edge PetriNet::ReachabilityGraph::Edge.new(@graph, source: current_node, destination: infinity_node)
|
374
435
|
next
|
375
436
|
end
|
376
|
-
|
377
|
-
|
437
|
+
if node_id < 0
|
438
|
+
current_node = @graph.get_node node_id.abs
|
439
|
+
end
|
440
|
+
@graph.add_edge PetriNet::ReachabilityGraph::Edge.new(@graph, source: source, destination: current_node, probability: @objects[tid].probability)# if node_id
|
441
|
+
reachability_helper get_markings, current_node if node_id >= 0
|
378
442
|
end
|
379
443
|
set_markings markings
|
380
444
|
end
|
data/lib/petri_net/version.rb
CHANGED
data/petri_net.gemspec
CHANGED
@@ -71,7 +71,7 @@ Edges
|
|
71
71
|
@net << PetriNet::Arc.new(source:@net.get_transition('T'), destination:@net.get_place('B'))
|
72
72
|
@net.get_place('A').add_marking
|
73
73
|
rn = @net.generate_reachability_graph
|
74
|
-
assert_equal "Reachability Graph [SimpleNet1]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n6: Node6 ([1, 0])\n7: Node7 ([0, 1])\n\nEdges\n----------------------------\n8: Edge8 6 -> 7: Node7 ([0, 1]) )\n\n", rn.to_s
|
74
|
+
assert_equal "Reachability Graph [SimpleNet1]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n6: Node6 ([1, 0])\n7: Node7 ([0, 1])\n\nEdges\n----------------------------\n8: Edge8 6: Node6 ([1, 0]) -> 7: Node7 ([0, 1]) )\n\n", rn.to_s
|
75
75
|
|
76
76
|
end
|
77
77
|
|
@@ -88,7 +88,7 @@ Edges
|
|
88
88
|
@net << PetriNet::Arc.new(source:@net.get_transition('T2'), destination:@net.get_place('C'))
|
89
89
|
@net.get_place('A').add_marking
|
90
90
|
rn = @net.generate_reachability_graph
|
91
|
-
assert_equal "Reachability Graph [SimpleNet2]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n10: Node10 ([1, 0, 0])\n11: Node11 ([0, 1, 0])\n13: Node13 ([0, 0, 1])\n\nEdges\n----------------------------\n12: Edge12 10 -> 11: Node11 ([0, 1, 0]) )\n14: Edge14 10 -> 13: Node13 ([0, 0, 1]) )\n\n", rn.to_s
|
91
|
+
assert_equal "Reachability Graph [SimpleNet2]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n10: Node10 ([1, 0, 0])\n11: Node11 ([0, 1, 0])\n13: Node13 ([0, 0, 1])\n\nEdges\n----------------------------\n12: Edge12 10: Node10 ([1, 0, 0]) -> 11: Node11 ([0, 1, 0]) )\n14: Edge14 10: Node10 ([1, 0, 0]) -> 13: Node13 ([0, 0, 1]) )\n\n", rn.to_s
|
92
92
|
|
93
93
|
end
|
94
94
|
|
@@ -102,7 +102,7 @@ Edges
|
|
102
102
|
@net << PetriNet::Arc.new(source:@net.get_transition('T'), destination:@net.get_place('A'))
|
103
103
|
@net.get_place('A').add_marking
|
104
104
|
rn = @net.generate_reachability_graph
|
105
|
-
assert_equal "Reachability Graph [SimpleNet3]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n7: Node7 ([1, 0])\n8: Node8 ([1, 1])\n10: Node10 ([Infinity])\n\nEdges\n----------------------------\n9: Edge9 7 -> 8: Node8 ([1, 1]) )\n11: Edge11 8 -> 10: Node10 ([Infinity]) )\n\n", rn.to_s
|
105
|
+
assert_equal "Reachability Graph [SimpleNet3]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n7: Node7 ([1, 0])\n8: Node8 ([1, 1])\n10: Node10 ([Infinity])\n\nEdges\n----------------------------\n9: Edge9 7: Node7 ([1, 0]) -> 8: Node8 ([1, 1]) )\n11: Edge11 8: Node8 ([1, 1]) -> 10: Node10 ([Infinity]) )\n\n", rn.to_s
|
106
106
|
|
107
107
|
end
|
108
108
|
|
@@ -119,7 +119,7 @@ Edges
|
|
119
119
|
@net << PetriNet::Arc.new(source:@net.get_transition('T2'), destination:@net.get_place('A'))
|
120
120
|
@net.get_place('A').add_marking
|
121
121
|
rn = @net.generate_reachability_graph
|
122
|
-
assert_equal "Reachability Graph [SimpleNet4]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n10: Node10 ([1, 0])\n11: Node11 ([1, 1])\n13: Node13 ([Infinity])\n15: Node15 ([2, 0])\n17: Node17 ([Infinity])\n\nEdges\n----------------------------\n12: Edge12 10 -> 11: Node11 ([1, 1]) )\n14: Edge14 11 -> 13: Node13 ([Infinity]) )\n16: Edge16 10 -> 15: Node15 ([2, 0]) )\n18: Edge18 15 -> 17: Node17 ([Infinity]) )\n\n", rn.to_s
|
122
|
+
assert_equal "Reachability Graph [SimpleNet4]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n10: Node10 ([1, 0])\n11: Node11 ([1, 1])\n13: Node13 ([Infinity])\n15: Node15 ([2, 0])\n17: Node17 ([Infinity])\n\nEdges\n----------------------------\n12: Edge12 10: Node10 ([1, 0]) -> 11: Node11 ([1, 1]) )\n14: Edge14 11: Node11 ([1, 1]) -> 13: Node13 ([Infinity]) )\n16: Edge16 10: Node10 ([1, 0]) -> 15: Node15 ([2, 0]) )\n18: Edge18 15: Node15 ([2, 0]) -> 17: Node17 ([Infinity]) )\n\n", rn.to_s
|
123
123
|
|
124
124
|
end
|
125
125
|
|
@@ -136,7 +136,7 @@ Edges
|
|
136
136
|
@net.get_place('A').add_marking
|
137
137
|
@net.to_gv_new
|
138
138
|
rn = @net.generate_reachability_graph
|
139
|
-
assert_equal "Reachability Graph [SimpleNet5]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n9: Node9 ([1, 0])\n10: Node10 ([0, 1])\n\nEdges\n----------------------------\n11: Edge11 9 -> 10: Node10 ([0, 1]) )\n\n", rn.to_s
|
139
|
+
assert_equal "Reachability Graph [SimpleNet5]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n9: Node9 ([1, 0])\n10: Node10 ([0, 1])\n\nEdges\n----------------------------\n11: Edge11 9: Node9 ([1, 0]) -> 10: Node10 ([0, 1]) )\n13: Edge13 10: Node10 ([0, 1]) -> 9: Node9 ([1, 0]) )\n\n", rn.to_s
|
140
140
|
|
141
141
|
rn.to_gv
|
142
142
|
end
|
@@ -182,4 +182,21 @@ Edges
|
|
182
182
|
@net << PetriNet::Transition.new(name:'T1')
|
183
183
|
@net.generate_reachability_graph # Don't know what to test here, bit this crashed with an Error before...
|
184
184
|
end
|
185
|
+
|
186
|
+
def test_looped_net1
|
187
|
+
@net = PetriNet::Net.new(:name => 'LoopedNet1', :description => 'Should be looped')
|
188
|
+
@net << PetriNet::Place.new(name: 'A')
|
189
|
+
@net << PetriNet::Place.new(name: 'B')
|
190
|
+
@net << PetriNet::Transition.new(name:'T1')
|
191
|
+
@net << PetriNet::Transition.new(name:'T2')
|
192
|
+
@net << PetriNet::Arc.new(source:@net.get_place('A'), destination:@net.get_transition('T1'))
|
193
|
+
@net << PetriNet::Arc.new(source:@net.get_place('B'), destination:@net.get_transition('T2'))
|
194
|
+
@net << PetriNet::Arc.new(source:@net.get_transition('T1'), destination:@net.get_place('B'))
|
195
|
+
@net << PetriNet::Arc.new(source:@net.get_transition('T2'), destination:@net.get_place('A'))
|
196
|
+
@net.get_place('A').add_marking
|
197
|
+
@net.to_gv_new
|
198
|
+
rg = @net.generate_reachability_graph
|
199
|
+
rg.to_gv
|
200
|
+
assert_equal "Reachability Graph [LoopedNet1]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n9: Node9 ([1, 0])\n10: Node10 ([0, 1])\n\nEdges\n----------------------------\n11: Edge11 9: Node9 ([1, 0]) -> 10: Node10 ([0, 1]) )\n13: Edge13 10: Node10 ([0, 1]) -> 9: Node9 ([1, 0]) )\n\n", rg.to_s
|
201
|
+
end
|
185
202
|
end
|
data/test/tc_petri_net.rb
CHANGED
@@ -279,6 +279,11 @@ Edges
|
|
279
279
|
assert_equal weight, @net.generate_weight_function
|
280
280
|
end
|
281
281
|
|
282
|
+
def test_t_invariants
|
283
|
+
fill_net
|
284
|
+
assert BigDecimal("0.0") == @net.t_invariants.first
|
285
|
+
end
|
286
|
+
|
282
287
|
def test_get_markings
|
283
288
|
fill_net
|
284
289
|
@net << PetriNet::Place.new(name: 'place2')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: petri_net
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- cclausen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-graphviz
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: graphviz
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - '>='
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - '>='
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: net-sftp
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|