petri_net 0.6.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.rdoc +3 -3
- data/Rakefile +13 -8
- data/lib/petri_net/net.rb +29 -21
- data/lib/petri_net/{edge.rb → reachability_graph/edge.rb} +0 -0
- data/lib/petri_net/reachability_graph/graph.rb +118 -0
- data/lib/petri_net/reachability_graph/node.rb +119 -0
- data/lib/petri_net/reachability_graph.rb +5 -1
- data/lib/petri_net/version.rb +3 -1
- data/lib/petri_net.rb +0 -2
- data/test/{tc_edge.rb → reachability_graph/tc_edge.rb} +0 -0
- data/test/reachability_graph/tc_graph.rb +61 -0
- data/test/reachability_graph/tc_node.rb +67 -0
- data/test/tc_petri_net.rb +6 -1
- data/test/ts_all.rb +2 -0
- data/test/ts_petri_net.rb +4 -0
- data/test/ts_reachability_graph.rb +3 -0
- metadata +17 -12
- data/lib/petri_net/node.rb +0 -44
- data/test/tc_graph.rb +0 -0
- data/test/tc_node.rb +0 -0
- data/test/ts_test_all.rb +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ac9fa5977f53b289d5fc97d42c14a2847b80c9c
|
4
|
+
data.tar.gz: d66436746d5f190ef3bf3c8361242ecb71dd5d6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1e585661a11b0ab1789454a4f401d85de55fecbafdf913663083f06c23d2686cbb9ba6e98e7db810358f78514aa998af8ad6be448ffae2480cb81c2aab6ba8a
|
7
|
+
data.tar.gz: 3fbcf881036c7f18f87f14b0b21d226bfcc81b14e33ea772c9d716cda5b5dcdd805949e2c54f825d57f3ca04f8e03b487208e21f4a6fbbd4ea420f5f2fc9aa79
|
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
{<img src="https://travis-ci.org/cclausen/
|
1
|
+
{<img src="https://travis-ci.org/cclausen/petri_net.png" />}[https://travis-ci.org/cclausen/petri_net]
|
2
2
|
|
3
|
-
{<img src="https://codeclimate.com/github/cclausen/
|
3
|
+
{<img src="https://codeclimate.com/github/cclausen/petri_net.png" />}[https://codeclimate.com/github/cclausen/petri_net]
|
4
4
|
|
5
5
|
= PTNet: Petri-net Simulation in Ruby
|
6
6
|
===== based on the code by Brian D Nelson <bdnelson@wildcoder.com>
|
7
|
-
===== Christian Clausen cclausen@tzi.de
|
7
|
+
===== Christian Clausen <cclausen@tzi.de>
|
8
8
|
|
9
9
|
== Version 0.6
|
10
10
|
I implemented most of the basics you need for playing with PetriNets but there are a lot things to add.
|
data/Rakefile
CHANGED
@@ -1,24 +1,29 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'rake'
|
2
3
|
require 'rake/testtask'
|
3
|
-
|
4
|
+
require 'rake/tasklib'
|
5
|
+
require 'rdoc/rdoc'
|
6
|
+
require 'rdoc/task'
|
7
|
+
|
4
8
|
require 'net/sftp'
|
5
9
|
require 'fileutils'
|
6
10
|
|
7
11
|
desc 'Default task'
|
8
|
-
task :default => [:test, :rdoc, :
|
12
|
+
task :default => [:test, :rdoc, :clean]
|
9
13
|
|
10
14
|
task(:test) { puts "==> Running main test suite" }
|
11
15
|
Rake::TestTask.new(:test) do |t|
|
12
|
-
t.test_files = FileList['test/
|
16
|
+
t.test_files = FileList['test/ts_all']
|
13
17
|
t.ruby_opts = ['-rubygems'] if defined? Gem
|
14
18
|
end
|
15
19
|
|
16
|
-
|
17
|
-
|
18
|
-
|
20
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
21
|
+
rdoc.main = "README"
|
22
|
+
rdoc.rdoc_files.include('LICENSE', 'CHANGELOG','lib/')
|
23
|
+
rdoc.title = "PetriNet Documentation"
|
19
24
|
# rdoc.options << '--webcvs=http://svn.wildcoder.com/svn/petri/trunk/'
|
20
|
-
|
21
|
-
|
25
|
+
rdoc.rdoc_dir = 'doc' # rdoc output folder
|
26
|
+
end
|
22
27
|
|
23
28
|
desc 'Clean up unused files.'
|
24
29
|
task :clean => :clobber_rdoc do
|
data/lib/petri_net/net.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
1
3
|
class PetriNet::Net < PetriNet::Base
|
2
4
|
# Human readable name
|
3
5
|
attr_accessor :name
|
@@ -152,27 +154,22 @@ class PetriNet::Net < PetriNet::Base
|
|
152
154
|
|
153
155
|
# Stringify this Petri Net.
|
154
156
|
def to_s
|
155
|
-
str =
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
str += "Arcs\n"
|
172
|
-
str += "----------------------------\n"
|
173
|
-
@arcs.each_value {|a| str += @objects[a].to_s + "\n"}
|
174
|
-
str += "\n"
|
175
|
-
|
157
|
+
str =
|
158
|
+
%{Petri Net [#{@name}]
|
159
|
+
----------------------------
|
160
|
+
Description: #{@description}
|
161
|
+
Filename: #{@filename}
|
162
|
+
|
163
|
+
Places
|
164
|
+
----------------------------
|
165
|
+
#{str = ''; @places.each_value {|p| str += @objects[p].to_s + "\n"}; str }
|
166
|
+
Transitions
|
167
|
+
----------------------------
|
168
|
+
#{str = ''; @transitions.each_value {|t| str += @objects[t].to_s + "\n" }; str }
|
169
|
+
Arcs
|
170
|
+
----------------------------
|
171
|
+
#{str = ''; @arcs.each_value {|a| str += @objects[a].to_s + "\n" }; str}
|
172
|
+
}
|
176
173
|
return str
|
177
174
|
end
|
178
175
|
|
@@ -289,6 +286,14 @@ class PetriNet::Net < PetriNet::Base
|
|
289
286
|
@objects.find_index object
|
290
287
|
end
|
291
288
|
|
289
|
+
def save filename
|
290
|
+
File.open(filename, 'w') {|f| @net.to_yaml}
|
291
|
+
end
|
292
|
+
|
293
|
+
def load filename
|
294
|
+
@net = YAML.load(File.read(filename))
|
295
|
+
end
|
296
|
+
|
292
297
|
private
|
293
298
|
|
294
299
|
def changed_structure
|
@@ -306,6 +311,9 @@ class PetriNet::Net < PetriNet::Base
|
|
306
311
|
current_node = PetriNet::ReachabilityGraph::Node.new(markings: get_markings)
|
307
312
|
current_node_id = @graph.add_node current_node
|
308
313
|
@graph.add_edge PetriNet::ReachabilityGraph::Edge.new(source: source, destination: current_node, probability: @objects[tid].probability) unless current_node_id < 0
|
314
|
+
if current_node_id < 0 && @graph.get_node(current_node_id * -1) < current_node
|
315
|
+
@graph.getNode(current_node_id * -1).add_omega current_node
|
316
|
+
end
|
309
317
|
reachability_helper get_markings, current_node unless (current_node_id < 0)
|
310
318
|
end
|
311
319
|
set_markings markings
|
File without changes
|
@@ -0,0 +1,118 @@
|
|
1
|
+
class PetriNet::InfiniteReachabilityGraphError < RuntimeError
|
2
|
+
end
|
3
|
+
|
4
|
+
class PetriNet::ReachabilityGraph < PetriNet::Base
|
5
|
+
def initialize(net, options = Hash.new)
|
6
|
+
@objects = Array.new
|
7
|
+
@nodes = Hash.new
|
8
|
+
@edges = Hash.new
|
9
|
+
@name = net.name
|
10
|
+
if options['unlimited'].nil?
|
11
|
+
@unlimited = true
|
12
|
+
else
|
13
|
+
@unlimited = options['unlimited']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_node(node)
|
18
|
+
@nodes.each_value do |n|
|
19
|
+
begin
|
20
|
+
if node > @objects[n]
|
21
|
+
if @unlimited
|
22
|
+
return @objects[n].id *-1
|
23
|
+
else
|
24
|
+
raise PetriNet::ReachabilityGraph::InfiniteReachabilityGraphError
|
25
|
+
end
|
26
|
+
end
|
27
|
+
rescue ArgumentError
|
28
|
+
#just two different markings, completly ok
|
29
|
+
end
|
30
|
+
end
|
31
|
+
node_index = @objects.index node
|
32
|
+
if (!node_index.nil?)
|
33
|
+
return @objects[node_index].id * -1
|
34
|
+
end
|
35
|
+
|
36
|
+
if (node.validate && (!@nodes.include? node.name))
|
37
|
+
@objects[node.id] = node
|
38
|
+
@nodes[node.name] = node.id
|
39
|
+
node.graph = self
|
40
|
+
return node.id
|
41
|
+
end
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_edge(edge)
|
46
|
+
if (edge.validate && (!@edges.include? edge.name))
|
47
|
+
@objects[edge.id] = edge
|
48
|
+
@edges[edge.name] = edge.id
|
49
|
+
edge.graph = self
|
50
|
+
return edge.id
|
51
|
+
end
|
52
|
+
return false
|
53
|
+
end
|
54
|
+
|
55
|
+
# Add an object to the Petri Net.
|
56
|
+
def <<(object)
|
57
|
+
case object.class.to_s
|
58
|
+
when "Array"
|
59
|
+
object.each {|o| self << o}
|
60
|
+
when "PetriNet::ReachabilityGraph::Edge"
|
61
|
+
add_edge(object)
|
62
|
+
when "PetriNet::ReachabilityGraph::Node"
|
63
|
+
add_node(object)
|
64
|
+
else
|
65
|
+
raise "(PetriNet::ReachabilityGraph) Unknown object #{object.class}."
|
66
|
+
end
|
67
|
+
self
|
68
|
+
end
|
69
|
+
alias_method :add_object, :<<
|
70
|
+
|
71
|
+
def get_node(id)
|
72
|
+
return @objects[id]
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_gv
|
76
|
+
# General graph options
|
77
|
+
str = "digraph #{@name} {\n"
|
78
|
+
str += "\t// General graph options\n"
|
79
|
+
str += "\trankdir = LR;\n"
|
80
|
+
str += "\tsize = \"10.5,7.5\";\n"
|
81
|
+
str += "\tnode [ style = filled, fillcolor = white, fontsize = 8.0 ]\n"
|
82
|
+
str += "\tedge [ arrowhead = vee, arrowsize = 0.5, fontsize = 8.0 ]\n"
|
83
|
+
str += "\n"
|
84
|
+
|
85
|
+
str += "\t// Nodes\n"
|
86
|
+
str += "\tnode [ shape = circle ];\n"
|
87
|
+
@nodes.each_value {|id| str += @objects[id].to_gv }
|
88
|
+
str += "\n"
|
89
|
+
|
90
|
+
str += "\t// Edges\n"
|
91
|
+
@edges.each_value {|id| str += @objects[id].to_gv }
|
92
|
+
str += "}\n" # Graph closure
|
93
|
+
|
94
|
+
return str
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_s
|
99
|
+
str = "Reachability Graph [#{@name}]\n"
|
100
|
+
str += "----------------------------\n"
|
101
|
+
str += "Description: #{@description}\n"
|
102
|
+
str += "Filename: #{@filename}\n"
|
103
|
+
str += "\n"
|
104
|
+
|
105
|
+
str += "Nodes\n"
|
106
|
+
str += "----------------------------\n"
|
107
|
+
@nodes.each_value {|p| str += @objects[p].to_s + "\n" }
|
108
|
+
str += "\n"
|
109
|
+
|
110
|
+
str += "Edges\n"
|
111
|
+
str += "----------------------------\n"
|
112
|
+
@edges.each_value {|t| str += @objects[t].to_s + "\n" }
|
113
|
+
str += "\n"
|
114
|
+
|
115
|
+
return str
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
class PetriNet::ReachabilityGraph::Node < PetriNet::Base
|
2
|
+
include Comparable
|
3
|
+
|
4
|
+
# human readable name
|
5
|
+
attr_reader :name
|
6
|
+
# unique ID
|
7
|
+
attr_reader :id
|
8
|
+
# Makking this node represents
|
9
|
+
attr_reader :markings
|
10
|
+
# The graph this node belongs to
|
11
|
+
attr_accessor :graph
|
12
|
+
# Omega-marked node (unlimited Petrinet -> coverabilitygraph)
|
13
|
+
attr_reader :omega_marked
|
14
|
+
# Incoming edges
|
15
|
+
attr_reader :inputs
|
16
|
+
# Outgoing edges
|
17
|
+
attr_reader :outputs
|
18
|
+
# Label of the node
|
19
|
+
attr_reader :label
|
20
|
+
|
21
|
+
def initialize(options = {}, &block)
|
22
|
+
@id = next_object_id
|
23
|
+
@name = (options[:name] or "Node#{@id}")
|
24
|
+
@description = (options[:description] or "Node #{@id}")
|
25
|
+
@inputs = Array.new
|
26
|
+
@outputs = Array.new
|
27
|
+
@label = (options[:label] or @name)
|
28
|
+
@markings = options[:markings]
|
29
|
+
if @markings.nil?
|
30
|
+
raise ArgumentError.new "Every Node needs markings"
|
31
|
+
end
|
32
|
+
if @markings.include? Float::INFINITY
|
33
|
+
@omega_marked = true
|
34
|
+
else
|
35
|
+
@omega_marked = false
|
36
|
+
end
|
37
|
+
|
38
|
+
yield self unless block.nil?
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add an omega-marking to a specified place
|
42
|
+
def add_omega object
|
43
|
+
if object.class.to_s == "PetriNet::ReachabilityGraph::Node"
|
44
|
+
if self > object
|
45
|
+
counter = 0
|
46
|
+
object.markings.each do |marking|
|
47
|
+
if @markings[counter] < marking
|
48
|
+
@markings[counter] = Fload::INFINITY
|
49
|
+
end
|
50
|
+
counter += 1
|
51
|
+
end
|
52
|
+
else
|
53
|
+
return false
|
54
|
+
end
|
55
|
+
elsif object.class.to_s == "Array"
|
56
|
+
object.each do |place|
|
57
|
+
markings[place] = Float::INFINITY
|
58
|
+
end
|
59
|
+
elsif object.class.to_s == "Fixnum"
|
60
|
+
markings[object] = Float::INFINITY
|
61
|
+
end
|
62
|
+
@omega_marked = true
|
63
|
+
end
|
64
|
+
|
65
|
+
def validate
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
def gv_id
|
70
|
+
"N#{@id}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_gv
|
74
|
+
"\t#{self.gv_id} [ label = \"#{@markings}\" ];\n"
|
75
|
+
end
|
76
|
+
|
77
|
+
# Compare-operator, other Operators are available through comparable-mixin
|
78
|
+
def <=>(object)
|
79
|
+
return nil unless object.class.to_s == "PetriNet::ReachabilityGraph::Node"
|
80
|
+
if @markings == object.markings
|
81
|
+
return 0
|
82
|
+
end
|
83
|
+
|
84
|
+
counter = 0
|
85
|
+
less = true
|
86
|
+
self.markings.each do |marking|
|
87
|
+
if marking <= object.markings[counter] && less
|
88
|
+
less = true
|
89
|
+
else
|
90
|
+
less = false
|
91
|
+
break
|
92
|
+
end
|
93
|
+
counter += 1
|
94
|
+
end
|
95
|
+
if less
|
96
|
+
return -1
|
97
|
+
end
|
98
|
+
counter = 0
|
99
|
+
more = true
|
100
|
+
self.markings.each do |marking|
|
101
|
+
if marking >= object.markings[counter] && more
|
102
|
+
more = true
|
103
|
+
else
|
104
|
+
more = false
|
105
|
+
break
|
106
|
+
end
|
107
|
+
counter += 1
|
108
|
+
end
|
109
|
+
if more
|
110
|
+
return 1
|
111
|
+
end
|
112
|
+
return nil
|
113
|
+
end
|
114
|
+
|
115
|
+
def to_s
|
116
|
+
"#{@id}: #{@name} (#{@markings})"
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -1,4 +1,8 @@
|
|
1
|
+
require_relative 'reachability_graph/graph'
|
2
|
+
require_relative 'reachability_graph/node'
|
3
|
+
require_relative 'reachability_graph/edge'
|
1
4
|
class PetriNet::ReachabilityGraph < PetriNet::Base
|
5
|
+
=begin
|
2
6
|
def initialize(net)
|
3
7
|
@objects = Array.new
|
4
8
|
@nodes = Hash.new
|
@@ -89,5 +93,5 @@ class PetriNet::ReachabilityGraph < PetriNet::Base
|
|
89
93
|
|
90
94
|
return str
|
91
95
|
end
|
92
|
-
|
96
|
+
=end
|
93
97
|
end
|
data/lib/petri_net/version.rb
CHANGED
data/lib/petri_net.rb
CHANGED
@@ -31,5 +31,3 @@ require "#{PETRI_LIB_FILE_PATH}/petri_net/transition"
|
|
31
31
|
require "#{PETRI_LIB_FILE_PATH}/petri_net/arc"
|
32
32
|
require "#{PETRI_LIB_FILE_PATH}/petri_net/marking"
|
33
33
|
require "#{PETRI_LIB_FILE_PATH}/petri_net/reachability_graph"
|
34
|
-
require "#{PETRI_LIB_FILE_PATH}/petri_net/node"
|
35
|
-
require "#{PETRI_LIB_FILE_PATH}/petri_net/edge"
|
File without changes
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'logger'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class TestPetriNetReachabilityGraph < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@net = PetriNet::Net.new(:name => 'Water', :description => 'Creation of water from base elements.')
|
8
|
+
@net.logger = Logger.new(STDOUT)
|
9
|
+
end
|
10
|
+
|
11
|
+
def fill_net
|
12
|
+
@net << PetriNet::Place.new(:name => "testplace")
|
13
|
+
@net << PetriNet::Transition.new(:name => "testtrans")
|
14
|
+
arc = PetriNet::Arc.new do |a|
|
15
|
+
a.name = 'testarc'
|
16
|
+
a.weight = 2
|
17
|
+
a.add_source(@net.get_place 'testplace')
|
18
|
+
a.add_destination(@net.get_transition 'testtrans')
|
19
|
+
end
|
20
|
+
@net << arc
|
21
|
+
end
|
22
|
+
|
23
|
+
def teardown
|
24
|
+
@net.reset
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_trivial_generate_reachability_graph
|
28
|
+
assert_equal "Reachability Graph [Water]
|
29
|
+
----------------------------
|
30
|
+
Description:
|
31
|
+
Filename:
|
32
|
+
|
33
|
+
Nodes
|
34
|
+
----------------------------
|
35
|
+
1: Node1 ([])
|
36
|
+
|
37
|
+
Edges
|
38
|
+
----------------------------
|
39
|
+
|
40
|
+
", @net.generate_reachability_graph().to_s, "Simple Reachability Graph with only one reachable state"
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_generate_reachability_graph
|
44
|
+
fill_net
|
45
|
+
assert_equal "Reachability Graph [Water]
|
46
|
+
----------------------------
|
47
|
+
Description:
|
48
|
+
Filename:
|
49
|
+
|
50
|
+
Nodes
|
51
|
+
----------------------------
|
52
|
+
4: Node4 ([0])
|
53
|
+
|
54
|
+
Edges
|
55
|
+
----------------------------
|
56
|
+
|
57
|
+
", @net.generate_reachability_graph().to_s, "Reachability Graph of sample net"
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'logger'
|
5
|
+
require 'test/unit'
|
6
|
+
require "#{File.dirname(__FILE__)}/../../lib/petri_net"
|
7
|
+
|
8
|
+
#require 'pry'
|
9
|
+
|
10
|
+
class TestReachabilityGraphNode < Test::Unit::TestCase
|
11
|
+
def setup
|
12
|
+
@net = PetriNet::Net.new(:name => 'Water', :description => 'Creation of water from base elements.')
|
13
|
+
@node = PetriNet::ReachabilityGraph::Node.new(markings: [1,3,5,4,0])
|
14
|
+
end
|
15
|
+
|
16
|
+
def teardown
|
17
|
+
@net.reset
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_create_node
|
21
|
+
node = PetriNet::ReachabilityGraph::Node.new(markings: [1,3,5,4,0])
|
22
|
+
assert_not_nil node
|
23
|
+
assert_equal "Node2", node.name
|
24
|
+
assert_equal [], node.inputs
|
25
|
+
assert_equal [], node.outputs
|
26
|
+
assert_equal node.name, node.label
|
27
|
+
assert_equal [1,3,5,4,0], node.markings
|
28
|
+
assert !node.omega_marked, "should not be omega_marked as there is no omega-marking"
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_omega_marking
|
32
|
+
node = PetriNet::ReachabilityGraph::Node.new(markings: [1,3,5,Float::INFINITY,0])
|
33
|
+
assert node.omega_marked, "should be omega_marked as there is an omega marking"
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_adding_omega_marking
|
37
|
+
assert !@node.omega_marked
|
38
|
+
@node.add_omega 3
|
39
|
+
assert_equal [1,3,5,Float::INFINITY,0], @node.markings
|
40
|
+
assert @node.omega_marked
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_compare
|
44
|
+
node1 = PetriNet::ReachabilityGraph::Node.new(markings: [0,1,0,0,1])
|
45
|
+
node2 = PetriNet::ReachabilityGraph::Node.new(markings: [0,1,0,0,1])
|
46
|
+
node3 = PetriNet::ReachabilityGraph::Node.new(markings: [0,0,1,0,1])
|
47
|
+
node4 = PetriNet::ReachabilityGraph::Node.new(markings: [0,2,0,0,1])
|
48
|
+
node5 = PetriNet::ReachabilityGraph::Node.new(markings: [1,1,0,0,1])
|
49
|
+
node6 = PetriNet::ReachabilityGraph::Node.new(markings: [1,1,0,0,0])
|
50
|
+
|
51
|
+
assert node1 == node1
|
52
|
+
assert node2 == node2
|
53
|
+
assert node1 == node2
|
54
|
+
assert !(node1 < node2)
|
55
|
+
assert !(node1 > node2)
|
56
|
+
assert !(node3 == node1)
|
57
|
+
assert_raise ArgumentError do node3 > node1 end
|
58
|
+
assert_raise ArgumentError do node3 < node1 end
|
59
|
+
assert node4 > node1
|
60
|
+
assert node1 < node4
|
61
|
+
assert node5 > node1
|
62
|
+
assert !(node4 == node5)
|
63
|
+
assert_raise ArgumentError do node4 > node5 end
|
64
|
+
assert_raise ArgumentError do node6 > node1 end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
data/test/tc_petri_net.rb
CHANGED
@@ -5,7 +5,6 @@ require 'logger'
|
|
5
5
|
require 'test/unit'
|
6
6
|
require "#{File.dirname(__FILE__)}/../lib/petri_net"
|
7
7
|
|
8
|
-
#require 'pry'
|
9
8
|
|
10
9
|
class TestPetriNet < Test::Unit::TestCase
|
11
10
|
def setup
|
@@ -255,6 +254,12 @@ Edges
|
|
255
254
|
assert_equal 3, @net.objects_size
|
256
255
|
end
|
257
256
|
|
257
|
+
def test_save_and_load
|
258
|
+
fill_net
|
259
|
+
@net.save("/tmp/petrinet")
|
260
|
+
net = YAML.load(File.read("/tmp/petrinet"))
|
261
|
+
assert_not_nil net
|
262
|
+
end
|
258
263
|
|
259
264
|
# def test_create_marking
|
260
265
|
# place = PetriNet::Place.new(:name => 'Hydrogen')
|
data/test/ts_all.rb
ADDED
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.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- cclausen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-sftp
|
@@ -42,24 +42,27 @@ files:
|
|
42
42
|
- lib/petri_net.rb
|
43
43
|
- lib/petri_net/arc.rb
|
44
44
|
- lib/petri_net/base.rb
|
45
|
-
- lib/petri_net/edge.rb
|
46
45
|
- lib/petri_net/marking.rb
|
47
46
|
- lib/petri_net/net.rb
|
48
|
-
- lib/petri_net/node.rb
|
49
47
|
- lib/petri_net/place.rb
|
50
48
|
- lib/petri_net/reachability_graph.rb
|
49
|
+
- lib/petri_net/reachability_graph/edge.rb
|
50
|
+
- lib/petri_net/reachability_graph/graph.rb
|
51
|
+
- lib/petri_net/reachability_graph/node.rb
|
51
52
|
- lib/petri_net/transition.rb
|
52
53
|
- lib/petri_net/version.rb
|
53
54
|
- petri_net.gemspec
|
54
55
|
- test/create.rb
|
56
|
+
- test/reachability_graph/tc_edge.rb
|
57
|
+
- test/reachability_graph/tc_graph.rb
|
58
|
+
- test/reachability_graph/tc_node.rb
|
55
59
|
- test/tc_arc.rb
|
56
|
-
- test/tc_edge.rb
|
57
|
-
- test/tc_graph.rb
|
58
|
-
- test/tc_node.rb
|
59
60
|
- test/tc_petri_net.rb
|
60
61
|
- test/tc_place.rb
|
61
62
|
- test/tc_transition.rb
|
62
|
-
- test/
|
63
|
+
- test/ts_all.rb
|
64
|
+
- test/ts_petri_net.rb
|
65
|
+
- test/ts_reachability_graph.rb
|
63
66
|
homepage: https://github.com/cclausen/petri
|
64
67
|
licenses:
|
65
68
|
- MIT
|
@@ -87,11 +90,13 @@ summary: You can create Petri Nets and do some calculations with them like gener
|
|
87
90
|
the Reachability Graph
|
88
91
|
test_files:
|
89
92
|
- test/create.rb
|
93
|
+
- test/reachability_graph/tc_edge.rb
|
94
|
+
- test/reachability_graph/tc_graph.rb
|
95
|
+
- test/reachability_graph/tc_node.rb
|
90
96
|
- test/tc_arc.rb
|
91
|
-
- test/tc_edge.rb
|
92
|
-
- test/tc_graph.rb
|
93
|
-
- test/tc_node.rb
|
94
97
|
- test/tc_petri_net.rb
|
95
98
|
- test/tc_place.rb
|
96
99
|
- test/tc_transition.rb
|
97
|
-
- test/
|
100
|
+
- test/ts_all.rb
|
101
|
+
- test/ts_petri_net.rb
|
102
|
+
- test/ts_reachability_graph.rb
|
data/lib/petri_net/node.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
class PetriNet::ReachabilityGraph::Node < PetriNet::Base
|
2
|
-
# human readable name
|
3
|
-
attr_reader :name
|
4
|
-
# unique ID
|
5
|
-
attr_reader :id
|
6
|
-
# Makking this node represents
|
7
|
-
attr_reader :markings
|
8
|
-
# The graph this node belongs to
|
9
|
-
attr_accessor :graph
|
10
|
-
|
11
|
-
def initialize(options = {}, &block)
|
12
|
-
@id = next_object_id
|
13
|
-
@name = (options[:name] or "Node#{@id}")
|
14
|
-
@description = (options[:description] or "Node #{@id}")
|
15
|
-
@inputs = Array.new
|
16
|
-
@outputs = Array.new
|
17
|
-
@label = (options[:label] or @name)
|
18
|
-
@markings = options[:markings]
|
19
|
-
|
20
|
-
yield self unless block.nil?
|
21
|
-
end
|
22
|
-
|
23
|
-
def validate
|
24
|
-
true
|
25
|
-
end
|
26
|
-
|
27
|
-
def gv_id
|
28
|
-
"N#{@id}"
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_gv
|
32
|
-
"\t#{self.gv_id} [ label = \"#{@markings}\" ];\n"
|
33
|
-
end
|
34
|
-
|
35
|
-
def ==(object)
|
36
|
-
return false unless object.class.to_s == "PetriNet::ReachabilityGraph::Node"
|
37
|
-
@markings == object.markings
|
38
|
-
end
|
39
|
-
|
40
|
-
def to_s
|
41
|
-
"#{@id}: #{@name} (#{@markings})"
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
data/test/tc_graph.rb
DELETED
File without changes
|
data/test/tc_node.rb
DELETED
File without changes
|
data/test/ts_test_all.rb
DELETED