petri_net_2020 1.0.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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +12 -0
  5. data/CHANGELOG +8 -0
  6. data/Gemfile +9 -0
  7. data/LICENSE +21 -0
  8. data/README.rdoc +97 -0
  9. data/Rakefile +32 -0
  10. data/lib/petri_net/arc.rb +143 -0
  11. data/lib/petri_net/base.rb +30 -0
  12. data/lib/petri_net/coverability_graph/edge.rb +14 -0
  13. data/lib/petri_net/coverability_graph/graph.rb +52 -0
  14. data/lib/petri_net/coverability_graph/node.rb +123 -0
  15. data/lib/petri_net/coverability_graph.rb +8 -0
  16. data/lib/petri_net/graph/edge.rb +64 -0
  17. data/lib/petri_net/graph/graph.rb +324 -0
  18. data/lib/petri_net/graph/node.rb +141 -0
  19. data/lib/petri_net/graph.rb +7 -0
  20. data/lib/petri_net/marking.rb +27 -0
  21. data/lib/petri_net/net.rb +457 -0
  22. data/lib/petri_net/place.rb +131 -0
  23. data/lib/petri_net/reachability_graph/edge.rb +14 -0
  24. data/lib/petri_net/reachability_graph/graph.rb +24 -0
  25. data/lib/petri_net/reachability_graph/node.rb +14 -0
  26. data/lib/petri_net/reachability_graph.rb +8 -0
  27. data/lib/petri_net/transition.rb +135 -0
  28. data/lib/petri_net/version.rb +8 -0
  29. data/lib/petri_net.rb +36 -0
  30. data/petri_net.gemspec +23 -0
  31. data/test/create.rb +64 -0
  32. data/test/reachability_graph/tc_edge.rb +0 -0
  33. data/test/reachability_graph/tc_graph.rb +201 -0
  34. data/test/reachability_graph/tc_node.rb +65 -0
  35. data/test/tc_arc.rb +0 -0
  36. data/test/tc_petri_net.rb +371 -0
  37. data/test/tc_place.rb +0 -0
  38. data/test/tc_transition.rb +7 -0
  39. data/test/ts_all.rb +4 -0
  40. data/test/ts_petri_net.rb +6 -0
  41. data/test/ts_reachability_graph.rb +5 -0
  42. metadata +137 -0
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PetriNet
4
+ # Transition
5
+ class Transition < PetriNet::Base
6
+ # Unique ID
7
+ attr_accessor :id
8
+ # Huan readable name
9
+ attr_accessor :name
10
+ # Description
11
+ attr_accessor :description
12
+ # Probability of firing (this moment)
13
+ attr_accessor :probability
14
+ # List of input-arcs
15
+ attr_reader :inputs
16
+ # List of output-arcs
17
+ attr_reader :outputs
18
+ # The net this transition belongs to
19
+ attr_writer :net
20
+
21
+ # Create a new transition.
22
+ def initialize(options = {}, &block)
23
+ @id = next_object_id
24
+ @name = (options[:name] || "Transition#{@id}")
25
+ @description = (options[:description] || "Transition #{@id}")
26
+ @inputs = []
27
+ @outputs = []
28
+ @probability = options[:probability]
29
+
30
+ yield self unless block.nil?
31
+ end
32
+
33
+ # Add an input arc
34
+ def add_input(arc)
35
+ @inputs << arc.id unless arc.nil? || !validate_input(arc)
36
+ end
37
+
38
+ # Add an output arc
39
+ def add_output(arc)
40
+ @outputs << arc.id unless arc.nil? || !validate_output(arc)
41
+ end
42
+
43
+ # GraphViz ID
44
+ def gv_id
45
+ "T#{@id}"
46
+ end
47
+
48
+ # Validate this transition.
49
+ def validate
50
+ return false if @id < 1
51
+ return false if @name.nil? || @name.empty?
52
+
53
+ true
54
+ end
55
+
56
+ # Stringify this transition.
57
+ def to_s
58
+ "#{@id}: #{@name}"
59
+ end
60
+
61
+ # GraphViz definition
62
+ def to_gv
63
+ "\t#{gv_id} [ label = \"#{@name}#{@probability ? ' ' + @probability.to_s : ''}\" ];\n"
64
+ end
65
+
66
+ def ==(object)
67
+ name == object.name && description = object.description
68
+ end
69
+
70
+ def preplaces
71
+ raise 'Not part of a net' if @net.nil?
72
+
73
+ places = []
74
+ places << @inputs.map { |i| @net.objects[i].source }
75
+ end
76
+
77
+ def postplaces
78
+ raise 'Not part of a net' if @net.nil?
79
+
80
+ @outputs.map { |o| @net.objects[o].source }
81
+ end
82
+
83
+ def activated?
84
+ raise 'Not part of a net' if @net.nil?
85
+
86
+ @inputs.each do |i|
87
+ return false if @net.get_object(i).source.markings.size < @net.get_object(i).weight
88
+ end
89
+
90
+ @outputs.each do |o|
91
+ return false if @net.get_object(o).destination.markings.size + @net.get_object(o).weight > @net.get_object(o).destination.capacity
92
+ end
93
+ end
94
+ alias firable? activated?
95
+
96
+ def activate!
97
+ @inputs.each do |i|
98
+ source = @net.get_object(i).source
99
+ source.add_marking(@net.get_object(i).weight - source.markings.size)
100
+ end
101
+
102
+ # what to do with outputs, if they have a capacity
103
+ end
104
+
105
+ def fire
106
+ raise 'Not part of a net' if @net.nil?
107
+ return false unless activated?
108
+
109
+ @inputs.each do |i|
110
+ @net.get_object(i).source.remove_marking @net.get_object(i).weight
111
+ end
112
+
113
+ @outputs.each do |o|
114
+ @net.get_object(o).destination.add_marking @net.get_object(o).weight
115
+ end
116
+ true
117
+ end
118
+
119
+ private
120
+
121
+ def validate_input(arc)
122
+ inputs.each do |a|
123
+ return false if (@net.get_objects[a] <=> arc) == 0
124
+ end
125
+ true
126
+ end
127
+
128
+ def validate_output(arc)
129
+ outputs.each do |a|
130
+ return false if (@net.get_objects[a] <=> arc) == 0
131
+ end
132
+ true
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PetriNet
4
+ # Current Version
5
+ VERSION = '1.0.0'
6
+ # True if this is a debug-version and should not be used in productive systems
7
+ DEBUG = false
8
+ end
data/lib/petri_net.rb ADDED
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # Copyright (c) 2009, Brian D. Nelson (bdnelson@wildcoder.com)
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #++
24
+
25
+ # This library provides a way to represent petri nets in ruby and do some algorithms on them as generating the Reachability Graph.
26
+
27
+ # Holds the path of the base-file petri_net.rb
28
+ PETRI_NET_LIB_FILE_PATH = File.dirname(__FILE__)
29
+ require "#{PETRI_NET_LIB_FILE_PATH}/petri_net/base"
30
+ require "#{PETRI_NET_LIB_FILE_PATH}/petri_net/net"
31
+ require "#{PETRI_NET_LIB_FILE_PATH}/petri_net/place"
32
+ require "#{PETRI_NET_LIB_FILE_PATH}/petri_net/transition"
33
+ require "#{PETRI_NET_LIB_FILE_PATH}/petri_net/arc"
34
+ require "#{PETRI_NET_LIB_FILE_PATH}/petri_net/marking"
35
+ require "#{PETRI_NET_LIB_FILE_PATH}/petri_net/reachability_graph"
36
+ require "#{PETRI_NET_LIB_FILE_PATH}/petri_net/coverability_graph"
data/petri_net.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('lib/petri_net/version', __dir__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.authors = ['cclausen']
7
+ gem.email = ['"cclausen@tzi.de"']
8
+ gem.description = 'A Petri net modeling gem'
9
+ gem.summary = 'You can create Petri Nets and do some calculations with them like generating the Reachability Graph'
10
+ gem.homepage = 'https://github.com/cclausen/petri_net'
11
+
12
+ gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = 'petri_net_2020'
16
+ gem.require_paths = ['lib']
17
+ gem.version = PetriNet::VERSION
18
+
19
+ gem.license = 'MIT'
20
+ gem.add_dependency 'ruby-graphviz'
21
+ gem.add_dependency "rgl"
22
+ gem.add_development_dependency 'net-sftp'
23
+ end
data/test/create.rb ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'rubygems'
5
+ require 'logger'
6
+ require "#{`pwd`.strip}/../lib/petri_net"
7
+
8
+ puts '((Create PetriNet [Water]))'
9
+ net = PetriNet::Net.new(name: 'Water',
10
+ description: 'Creation of water from base elements')
11
+ net.logger = Logger.new(STDOUT)
12
+
13
+ puts '((Create Place 1 [Hydrogen]))'
14
+ place = PetriNet::Place.new(name: 'Hydrogen')
15
+
16
+ puts '((Add Place 1 [Hydrogen] to PetriNet))'
17
+ net.add_place(place)
18
+
19
+ puts '((Add Place 2 [Oxygen] to PetriNet))'
20
+ net.add_place(PetriNet::Place.new(name: 'Oxygen'))
21
+
22
+ puts '((Add Place 3 [Water] to PetriNet))'
23
+ net << PetriNet::Place.new do |p|
24
+ p.name = 'Water'
25
+ end
26
+
27
+ puts '((Add Transition 1 [Join] to PetriNet))'
28
+ net.add_transition(PetriNet::Transition.new(name: 'Join'))
29
+
30
+ puts '((Add Arc 1 [Hydrogen.Join] to PetriNet))'
31
+ net << PetriNet::Arc.new do |a|
32
+ a.name = 'Hydrogen.Join'
33
+ a.weight = 2
34
+ a.add_source(net.objects[net.places['Hydrogen']])
35
+ a.add_destination(net.objects[net.transitions['Join']])
36
+ end
37
+
38
+ puts '((Add Arc 2 [Oxygen.Join] to PetriNet))'
39
+ arc = PetriNet::Arc.new do |a|
40
+ a.name = 'Oxygen.Join'
41
+ a.add_source(net.objects[net.places['Oxygen']])
42
+ a.add_destination(net.objects[net.transitions['Join']])
43
+ end
44
+ net.add_arc(arc)
45
+
46
+ puts '((Add Arc 3 [Join.Water] to PetriNet))'
47
+ net.add_arc(PetriNet::Arc.new(
48
+ name: 'Join.Water',
49
+ description: 'Join to Water',
50
+ source: net.objects[net.transitions['Join']],
51
+ destination: net.objects[net.places['Water']],
52
+ weight: 1
53
+ ))
54
+
55
+ puts
56
+ puts
57
+ puts net.inspect
58
+ puts
59
+ puts
60
+ puts net.to_s
61
+ puts
62
+ puts
63
+ puts net.to_gv
64
+ puts
File without changes
@@ -0,0 +1,201 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'logger'
5
+ require 'test/unit'
6
+
7
+ class TestPetriNetReachabilityGraph < Test::Unit::TestCase
8
+ def setup
9
+ @net = PetriNet::Net.new(name: 'Water', description: 'Creation of water from base elements.')
10
+ @net.logger = Logger.new(STDOUT)
11
+ end
12
+
13
+ def fill_net
14
+ @net << PetriNet::Place.new(name: 'testplace')
15
+ @net << PetriNet::Transition.new(name: 'testtrans')
16
+ arc = PetriNet::Arc.new do |a|
17
+ a.name = 'testarc'
18
+ a.weight = 2
19
+ a.add_source(@net.get_place('testplace'))
20
+ a.add_destination(@net.get_transition('testtrans'))
21
+ end
22
+ @net << arc
23
+ end
24
+
25
+ def teardown
26
+ @net.reset
27
+ end
28
+
29
+ def test_trivial_generate_reachability_graph
30
+ assert_equal "Reachability Graph [Water]
31
+ ----------------------------
32
+ Description:
33
+ Filename:
34
+
35
+ Nodes
36
+ ----------------------------
37
+ 1: Node1 ([])
38
+
39
+ Edges
40
+ ----------------------------
41
+
42
+ ", @net.generate_reachability_graph.to_s, 'Simple Reachability Graph with only one reachable state'
43
+ end
44
+
45
+ def test_generate_reachability_graph
46
+ fill_net
47
+ assert_equal "Reachability Graph [Water]
48
+ ----------------------------
49
+ Description:
50
+ Filename:
51
+
52
+ Nodes
53
+ ----------------------------
54
+ 4: Node4 ([0])
55
+
56
+ Edges
57
+ ----------------------------
58
+
59
+ ", @net.generate_reachability_graph.to_s, 'Reachability Graph of sample net'
60
+ end
61
+
62
+ def test_to_gv
63
+ fill_net
64
+ # @net.generate_reachability_graph().to_gv
65
+ end
66
+
67
+ def test_simple_net_1
68
+ @net = PetriNet::Net.new(name: 'SimpleNet1', description: 'PTP')
69
+ @net << PetriNet::Place.new(name: 'A')
70
+ @net << PetriNet::Place.new(name: 'B')
71
+ @net << PetriNet::Transition.new(name: 'T')
72
+ @net << PetriNet::Arc.new(source: @net.get_place('A'), destination: @net.get_transition('T'))
73
+ @net << PetriNet::Arc.new(source: @net.get_transition('T'), destination: @net.get_place('B'))
74
+ @net.get_place('A').add_marking
75
+ rn = @net.generate_reachability_graph
76
+ 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
77
+ end
78
+
79
+ def test_simple_net_2
80
+ @net = PetriNet::Net.new(name: 'SimpleNet2', description: 'PTTPP')
81
+ @net << PetriNet::Place.new(name: 'A')
82
+ @net << PetriNet::Place.new(name: 'B')
83
+ @net << PetriNet::Place.new(name: 'C')
84
+ @net << PetriNet::Transition.new(name: 'T1')
85
+ @net << PetriNet::Transition.new(name: 'T2')
86
+ @net << PetriNet::Arc.new(source: @net.get_place('A'), destination: @net.get_transition('T1'))
87
+ @net << PetriNet::Arc.new(source: @net.get_transition('T1'), destination: @net.get_place('B'))
88
+ @net << PetriNet::Arc.new(source: @net.get_place('A'), destination: @net.get_transition('T2'))
89
+ @net << PetriNet::Arc.new(source: @net.get_transition('T2'), destination: @net.get_place('C'))
90
+ @net.get_place('A').add_marking
91
+ rn = @net.generate_reachability_graph
92
+ 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
93
+ end
94
+
95
+ def test_simple_net_3
96
+ @net = PetriNet::Net.new(name: 'SimpleNet3', description: 'PTPPinf')
97
+ @net << PetriNet::Place.new(name: 'A')
98
+ @net << PetriNet::Place.new(name: 'B')
99
+ @net << PetriNet::Transition.new(name: 'T')
100
+ @net << PetriNet::Arc.new(source: @net.get_place('A'), destination: @net.get_transition('T'))
101
+ @net << PetriNet::Arc.new(source: @net.get_transition('T'), destination: @net.get_place('B'))
102
+ @net << PetriNet::Arc.new(source: @net.get_transition('T'), destination: @net.get_place('A'))
103
+ @net.get_place('A').add_marking
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: Node7 ([1, 0]) -> 8: Node8 ([1, 1]) )\n11: Edge11 8: Node8 ([1, 1]) -> 10: Node10 ([Infinity]) )\n\n", rn.to_s
106
+ end
107
+
108
+ def test_simple_net_4
109
+ @net = PetriNet::Net.new(name: 'SimpleNet4', description: 'PTPPinf')
110
+ @net << PetriNet::Place.new(name: 'A')
111
+ @net << PetriNet::Place.new(name: 'B')
112
+ @net << PetriNet::Transition.new(name: 'T1')
113
+ @net << PetriNet::Transition.new(name: 'T2')
114
+ @net << PetriNet::Arc.new(source: @net.get_place('A'), destination: @net.get_transition('T1'))
115
+ @net << PetriNet::Arc.new(source: @net.get_transition('T1'), destination: @net.get_place('B'))
116
+ @net << PetriNet::Arc.new(source: @net.get_transition('T1'), destination: @net.get_place('A'))
117
+ @net << PetriNet::Arc.new(source: @net.get_place('B'), destination: @net.get_transition('T2'))
118
+ @net << PetriNet::Arc.new(source: @net.get_transition('T2'), destination: @net.get_place('A'))
119
+ @net.get_place('A').add_marking
120
+ rn = @net.generate_reachability_graph
121
+ 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
122
+ end
123
+
124
+ def test_simple_net_5
125
+ @net = PetriNet::Net.new(name: 'SimpleNet5', description: 'PTPTP')
126
+ @net << PetriNet::Place.new(name: 'A')
127
+ @net << PetriNet::Place.new(name: 'B')
128
+ @net << PetriNet::Transition.new(name: 'T1')
129
+ @net << PetriNet::Transition.new(name: 'T2')
130
+ @net << PetriNet::Arc.new(source: @net.get_place('A'), destination: @net.get_transition('T1'))
131
+ @net << PetriNet::Arc.new(source: @net.get_transition('T1'), destination: @net.get_place('B'))
132
+ @net << PetriNet::Arc.new(source: @net.get_place('B'), destination: @net.get_transition('T2'))
133
+ @net << PetriNet::Arc.new(source: @net.get_transition('T2'), destination: @net.get_place('A'))
134
+ @net.get_place('A').add_marking
135
+ @net.to_gv
136
+ rn = @net.generate_reachability_graph
137
+ 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
138
+
139
+ rn.to_gv
140
+ end
141
+
142
+ def test_real_net_1
143
+ @net = PetriNet::Net.new(name: 'RealNet1', description: 'Failed in real situation')
144
+ @net << PetriNet::Place.new(name: 'A')
145
+ @net << PetriNet::Place.new(name: 'B')
146
+ @net << PetriNet::Place.new(name: 'C')
147
+ @net << PetriNet::Place.new(name: 'D')
148
+ @net << PetriNet::Transition.new(name: 'T1')
149
+ @net << PetriNet::Transition.new(name: 'T2')
150
+ @net << PetriNet::Transition.new(name: 'T3')
151
+ @net << PetriNet::Arc.new(source: @net.get_place('A'), destination: @net.get_transition('T1'))
152
+ @net << PetriNet::Arc.new(source: @net.get_transition('T1'), destination: @net.get_place('B'))
153
+ @net << PetriNet::Arc.new(source: @net.get_transition('T1'), destination: @net.get_place('D'))
154
+ @net << PetriNet::Arc.new(source: @net.get_place('B'), destination: @net.get_transition('T2'))
155
+ @net << PetriNet::Arc.new(source: @net.get_transition('T2'), destination: @net.get_place('C'))
156
+ @net << PetriNet::Arc.new(source: @net.get_transition('T2'), destination: @net.get_place('D'))
157
+ @net << PetriNet::Arc.new(source: @net.get_place('D'), destination: @net.get_transition('T3'))
158
+ @net << PetriNet::Arc.new(source: @net.get_transition('T3'), destination: @net.get_place('A'))
159
+ @net.get_place('A').add_marking
160
+ @net.to_gv
161
+ rg = @net.generate_reachability_graph
162
+
163
+ rg.to_gv
164
+ # TODO: assert_equal "", rg.to_s
165
+ end
166
+
167
+ def test_empty_net1
168
+ @net = PetriNet::Net.new(name: 'EmptyNet1', description: 'Should be boring')
169
+ @net.generate_reachability_graph # Don't know what to test here, bit this crashed with an Error before...
170
+ end
171
+
172
+ def test_empty_net2
173
+ @net = PetriNet::Net.new(name: 'EmptyNet2', description: 'Should be boring')
174
+ @net << PetriNet::Place.new(name: 'A')
175
+ @net.generate_reachability_graph # Don't know what to test here, bit this crashed with an Error before...
176
+ end
177
+
178
+ def test_empty_net3
179
+ @net = PetriNet::Net.new(name: 'EmptyNet3', description: 'Should be boring')
180
+ @net << PetriNet::Place.new(name: 'A')
181
+ @net << PetriNet::Transition.new(name: 'T1')
182
+ @net.generate_reachability_graph # Don't know what to test here, bit this crashed with an Error before...
183
+ end
184
+
185
+ def test_looped_net1
186
+ @net = PetriNet::Net.new(name: 'LoopedNet1', description: 'Should be looped')
187
+ @net << PetriNet::Place.new(name: 'A')
188
+ @net << PetriNet::Place.new(name: 'B')
189
+ @net << PetriNet::Transition.new(name: 'T1')
190
+ @net << PetriNet::Transition.new(name: 'T2')
191
+ @net << PetriNet::Arc.new(source: @net.get_place('A'), destination: @net.get_transition('T1'))
192
+ @net << PetriNet::Arc.new(source: @net.get_place('B'), destination: @net.get_transition('T2'))
193
+ @net << PetriNet::Arc.new(source: @net.get_transition('T1'), destination: @net.get_place('B'))
194
+ @net << PetriNet::Arc.new(source: @net.get_transition('T2'), destination: @net.get_place('A'))
195
+ @net.get_place('A').add_marking
196
+ @net.to_gv
197
+ rg = @net.generate_reachability_graph
198
+ rg.to_gv
199
+ 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
200
+ end
201
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'logger'
5
+ require 'test/unit'
6
+ require "#{File.dirname(__FILE__)}/../../lib/petri_net"
7
+
8
+ class TestReachabilityGraphNode < Test::Unit::TestCase
9
+ def setup
10
+ @net = PetriNet::Net.new(name: 'Water', description: 'Creation of water from base elements.')
11
+ @graph = PetriNet::ReachabilityGraph.new(@net)
12
+ @node = PetriNet::ReachabilityGraph::Node.new(@graph, markings: [1, 3, 5, 4, 0])
13
+ end
14
+
15
+ def teardown
16
+ @net.reset
17
+ end
18
+
19
+ def test_create_node
20
+ node = PetriNet::ReachabilityGraph::Node.new(@graph, markings: [1, 3, 5, 4, 0])
21
+ assert_not_nil node
22
+ assert_equal 'Node2', node.name
23
+ assert_equal [], node.inputs
24
+ assert_equal [], node.outputs
25
+ assert_equal node.name, node.label
26
+ assert_equal [1, 3, 5, 4, 0], node.markings
27
+ assert !node.omega_marked, 'should not be omega_marked as there is no omega-marking'
28
+ end
29
+
30
+ def test_omega_marking
31
+ node = PetriNet::ReachabilityGraph::Node.new(@graph, markings: [1, 3, 5, Float::INFINITY, 0])
32
+ assert node.omega_marked, 'should be omega_marked as there is an omega marking'
33
+ end
34
+
35
+ def test_adding_omega_marking
36
+ assert !@node.omega_marked
37
+ @node.add_omega 3
38
+ assert_equal [1, 3, 5, Float::INFINITY, 0], @node.markings
39
+ assert @node.omega_marked
40
+ end
41
+
42
+ def test_compare
43
+ node1 = PetriNet::ReachabilityGraph::Node.new(@graph, markings: [0, 1, 0, 0, 1])
44
+ node2 = PetriNet::ReachabilityGraph::Node.new(@graph, markings: [0, 1, 0, 0, 1])
45
+ node3 = PetriNet::ReachabilityGraph::Node.new(@graph, markings: [0, 0, 1, 0, 1])
46
+ node4 = PetriNet::ReachabilityGraph::Node.new(@graph, markings: [0, 2, 0, 0, 1])
47
+ node5 = PetriNet::ReachabilityGraph::Node.new(@graph, markings: [1, 1, 0, 0, 1])
48
+ node6 = PetriNet::ReachabilityGraph::Node.new(@graph, markings: [1, 1, 0, 0, 0])
49
+
50
+ assert node1 == node1
51
+ assert node2 == node2
52
+ assert node1 == node2
53
+ assert node1 >= node2
54
+ assert node1 <= node2
55
+ assert node3 != node1
56
+ assert_raise ArgumentError do node3 > node1 end
57
+ assert_raise ArgumentError do node3 < node1 end
58
+ assert node4 > node1
59
+ assert node1 < node4
60
+ assert node5 > node1
61
+ assert node4 != node5
62
+ assert_raise ArgumentError do node4 > node5 end
63
+ assert_raise ArgumentError do node6 > node1 end
64
+ end
65
+ end
data/test/tc_arc.rb ADDED
File without changes