petri 0.0.0 → 0.0.1
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/README.md +1 -0
- data/lib/petri/arc.rb +32 -3
- data/lib/petri/element.rb +17 -1
- data/lib/petri/message.rb +31 -0
- data/lib/petri/net.rb +85 -20
- data/lib/petri/net_loader.rb +104 -14
- data/lib/petri/node.rb +32 -2
- data/lib/petri/place.rb +30 -4
- data/lib/petri/subprocess.rb +25 -0
- data/lib/petri/task_transition.rb +60 -0
- data/lib/petri/token.rb +25 -2
- data/lib/petri/transition.rb +17 -37
- data/lib/version.rb +3 -0
- data/petri.gemspec +22 -0
- metadata +15 -29
- data/lib/petri.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2e16e5fcbb59acc715a976e7aa7d4413fc82cca
|
4
|
+
data.tar.gz: 2079de4b12c5e40cf2acd911d11d2f5333671fa9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23a78414f842e70b17926cbaaa9e78f421cc29897a09392b3da99711c183e14aba1033c88a1fbb02b26e08a3da227a84dcc6d37264b7b8494f14776262de356f
|
7
|
+
data.tar.gz: 547dd41631abe1893d187dc7de37a0c36bb0212cbe0e95587b61e6a15b3b058ac3ea9b8d54f5a30bcbc723f5fc2239304ab2d51205e64dc1d32fb19bf8e733f4
|
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# IT ROCKS
|
data/lib/petri/arc.rb
CHANGED
@@ -2,11 +2,40 @@ module Petri
|
|
2
2
|
class Arc < Element
|
3
3
|
attr_reader :from_node, :to_node, :type
|
4
4
|
|
5
|
-
def initialize(net, from: nil, to: nil, type: nil, guid: nil)
|
6
|
-
super(net, {guid: guid})
|
5
|
+
def initialize(net, from: nil, to: nil, type: nil, guid: nil, production_rule: nil, guard: nil)
|
6
|
+
super(net, {guid: guid, production_rule: production_rule, guard: guard})
|
7
7
|
@from_node = from
|
8
8
|
@to_node = to
|
9
|
-
@type = type || :regular
|
9
|
+
@type = type.try(:to_sym) || :regular
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset?
|
13
|
+
@type == :reset
|
14
|
+
end
|
15
|
+
|
16
|
+
def regular?
|
17
|
+
@type == :regular
|
18
|
+
end
|
19
|
+
|
20
|
+
def inhibitor?
|
21
|
+
@type == :inhibitor
|
22
|
+
end
|
23
|
+
|
24
|
+
def production_rule
|
25
|
+
data[:production_rule]
|
26
|
+
end
|
27
|
+
|
28
|
+
def guard
|
29
|
+
data[:guard]
|
30
|
+
end
|
31
|
+
|
32
|
+
def normalized_guard
|
33
|
+
self.class.normalize_guard(guard)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.normalize_guard(guard)
|
37
|
+
return unless guard
|
38
|
+
guard.to_s.gsub(/\s+/, ' ').strip
|
10
39
|
end
|
11
40
|
end
|
12
41
|
end
|
data/lib/petri/element.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
1
3
|
module Petri
|
2
4
|
class Element
|
3
5
|
attr_reader :net, :data, :guid
|
@@ -7,7 +9,21 @@ module Petri
|
|
7
9
|
def initialize(net, data = {})
|
8
10
|
@net = net
|
9
11
|
@data = data.symbolize_keys || {}
|
10
|
-
@guid ||= data[:guid]
|
12
|
+
@guid ||= (data[:guid] ||= generate_guid)
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](key)
|
16
|
+
@data[key]
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(k, v)
|
20
|
+
@data[k] = v
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def generate_guid
|
26
|
+
SecureRandom.uuid
|
11
27
|
end
|
12
28
|
end
|
13
29
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Petri
|
2
|
+
class Message < Transition
|
3
|
+
|
4
|
+
# @return [String, nil]
|
5
|
+
def action
|
6
|
+
nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def automated?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def input_places
|
14
|
+
input_nodes
|
15
|
+
end
|
16
|
+
|
17
|
+
def output_places
|
18
|
+
output_nodes
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Array<Place>]
|
22
|
+
def places_to_reset
|
23
|
+
reset_arcs.map(&:to_node)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Array<Arc>]
|
27
|
+
def reset_arcs
|
28
|
+
net.arcs.select { |arc| arc.from_node == self && arc.reset? }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/petri/net.rb
CHANGED
@@ -2,49 +2,114 @@ module Petri
|
|
2
2
|
class Net
|
3
3
|
include NetLoader
|
4
4
|
|
5
|
-
attr_reader :places, :transitions, :arcs
|
5
|
+
attr_reader :places, :transitions, :arcs
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
@transitions = []
|
9
9
|
@places = []
|
10
10
|
@arcs = []
|
11
|
-
@
|
11
|
+
@data = {}
|
12
12
|
end
|
13
13
|
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
# @return [Array<Transition>]
|
15
|
+
def automated_transitions
|
16
|
+
transitions.select(&:automated?)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Array<Message>]
|
20
|
+
def messages
|
21
|
+
transitions.select { |transition| transition.is_a?(Petri::Message) }
|
20
22
|
end
|
21
23
|
|
22
|
-
# @
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
# @return [Place]
|
25
|
+
def start_place
|
26
|
+
start_places = @places.select(&:start?).select do |place|
|
27
|
+
place.identifier.blank? ||
|
28
|
+
places_by_identifier(place.identifier).select(&:finish?).empty?
|
27
29
|
end
|
30
|
+
|
31
|
+
raise ArgumentError, 'There are more than one start places' if start_places.many?
|
32
|
+
raise ArgumentError, 'There is no start place' if start_places.empty?
|
33
|
+
|
34
|
+
start_places.first
|
28
35
|
end
|
29
36
|
|
30
|
-
# @param
|
31
|
-
# @return [
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
+
# @param identifier [String]
|
38
|
+
# @return [Place, nil]
|
39
|
+
def place_by_identifier(identifier)
|
40
|
+
identifier = identifier.to_s
|
41
|
+
@places.each { |node| return node if node.identifier == identifier }
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param identifier [String]
|
46
|
+
# @return [Transition, nil]
|
47
|
+
def transition_by_identifier(identifier, automated: nil)
|
48
|
+
identifier = identifier.to_s
|
49
|
+
transitions = @transitions.select do |transition|
|
50
|
+
if automated
|
51
|
+
transition.automated?
|
52
|
+
elsif automated == false
|
53
|
+
!transition.automated?
|
54
|
+
else
|
55
|
+
true
|
37
56
|
end
|
38
57
|
end
|
58
|
+
|
59
|
+
transitions.each { |node| return node if node.identifier == identifier }
|
60
|
+
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param identifier [String]
|
65
|
+
# @return [Array<Transition>]
|
66
|
+
def transitions_by_identifier(identifier)
|
67
|
+
@transitions.select { |node| node.identifier == identifier }
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param guard [String]
|
71
|
+
# @return [Arc, nil]
|
72
|
+
def arc_by_guard(guard)
|
73
|
+
return if guard.blank?
|
74
|
+
|
75
|
+
guard = Arc.normalize_guard(guard)
|
76
|
+
@arcs.each { |arc| return arc if arc.normalized_guard == guard }
|
39
77
|
nil
|
40
78
|
end
|
41
79
|
|
80
|
+
# @param identifier [String]
|
81
|
+
# @return [Node, nil]
|
82
|
+
def node_by_identifier(identifier)
|
83
|
+
place_by_identifier(identifier) || transition_by_identifier(identifier)
|
84
|
+
end
|
85
|
+
|
86
|
+
def [](key)
|
87
|
+
@data[key]
|
88
|
+
end
|
89
|
+
|
90
|
+
def []=(k, v)
|
91
|
+
@data[k] = v
|
92
|
+
end
|
93
|
+
|
94
|
+
def inspect
|
95
|
+
"Petri::Net#{hash}"
|
96
|
+
end
|
97
|
+
|
42
98
|
protected
|
43
99
|
|
100
|
+
# @param guid [String]
|
101
|
+
# @return [Node, nil]
|
44
102
|
def node_by_guid(guid)
|
45
103
|
@places.each { |node| return node if node.guid == guid }
|
46
104
|
@transitions.each { |node| return node if node.guid == guid }
|
47
105
|
nil
|
48
106
|
end
|
107
|
+
|
108
|
+
# @param identifier [String]
|
109
|
+
# @return [Array<Place>]
|
110
|
+
def places_by_identifier(identifier)
|
111
|
+
identifier = identifier.to_s
|
112
|
+
@places.select { |node| node.identifier == identifier }
|
113
|
+
end
|
49
114
|
end
|
50
115
|
end
|
data/lib/petri/net_loader.rb
CHANGED
@@ -1,33 +1,110 @@
|
|
1
1
|
module Petri
|
2
2
|
module NetLoader
|
3
|
-
|
3
|
+
# @param val [String, Class]
|
4
|
+
def tasks_process_class=(val)
|
5
|
+
@tasks_process_class = val
|
6
|
+
end
|
7
|
+
|
8
|
+
# @return [String, Class]
|
9
|
+
def tasks_process_class
|
10
|
+
@tasks_process_class || 'TasksProcess'
|
11
|
+
end
|
4
12
|
|
5
13
|
# @param guid [String]
|
6
|
-
# @param
|
14
|
+
# @param identifier [String]
|
7
15
|
# @param start [true, false]
|
8
|
-
def add_place(guid: ,
|
9
|
-
|
16
|
+
def add_place(guid: nil, identifier: , start: false, finish: false)
|
17
|
+
Place.new(self, {guid: guid, identifier: identifier, start: start, finish: finish}).tap do |place|
|
18
|
+
@places << place
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param guid [String]
|
23
|
+
# @param identifier [String]
|
24
|
+
# @param action [String]
|
25
|
+
def add_transition(guid: nil, identifier: , action: nil, automated: )
|
26
|
+
Transition.new(self, {guid: guid, identifier: identifier, action: action, automated: automated}).tap do |transition|
|
27
|
+
@transitions << transition
|
28
|
+
end
|
10
29
|
end
|
11
30
|
|
12
31
|
# @param guid [String]
|
13
|
-
# @param
|
32
|
+
# @param identifier [String]
|
14
33
|
# @param action [String]
|
15
|
-
def
|
16
|
-
|
34
|
+
def add_message(guid: nil, identifier:)
|
35
|
+
Message.new(self, {guid: guid, identifier: identifier}).tap do |message|
|
36
|
+
@transitions << message
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param task_identifier [String]
|
41
|
+
# @param pin [String]
|
42
|
+
# @param automated [true, false]
|
43
|
+
def add_task_transition(task_identifier:, pin:, automated:)
|
44
|
+
TaskTransition.new(self, {task_identifier: task_identifier, pin: pin, automated: automated, process_class: tasks_process_class}).tap do |transition|
|
45
|
+
@transitions << transition
|
46
|
+
end
|
17
47
|
end
|
18
48
|
|
19
49
|
# @param guid [String]
|
20
|
-
# @param
|
50
|
+
# @param identifier [String]
|
21
51
|
# @param from_guid [String]
|
22
52
|
# @param to_guid [String]
|
23
53
|
# @param type [String]
|
24
|
-
|
54
|
+
# @param production_rule [String, nil]
|
55
|
+
def add_arc(guid: nil, from_guid: , to_guid: , type: , production_rule: nil, guard: nil)
|
25
56
|
from_node = node_by_guid(from_guid)
|
26
57
|
to_node = node_by_guid(to_guid)
|
27
|
-
|
58
|
+
|
59
|
+
if type == 'test'
|
60
|
+
@arcs << Arc.new(self, from: from_node, to: to_node, type: :regular, guid: guid, guard: guard)
|
61
|
+
@arcs << Arc.new(self, from: to_node, to: from_node, type: :regular, guid: guid)
|
62
|
+
else
|
63
|
+
@arcs << Arc.new(self, from: from_node, to: to_node, type: type.try(:to_sym), guid: guid, production_rule: production_rule, guard: guard)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param task_data [Hash]
|
68
|
+
# @param net_data [Hash] full bpf
|
69
|
+
def add_task(task_data, net_data)
|
70
|
+
identifier = task_data['identifier']
|
71
|
+
|
72
|
+
add_task_transition(task_identifier: identifier, pin: 'Finish', automated: false) if task_data['manual_finish_enabled']
|
73
|
+
add_task_transition(task_identifier: identifier, pin: 'Cancel', automated: false) # Manual cancel is always enabled?
|
74
|
+
|
75
|
+
task_arcs = net_data['arcs'].select { |arc| arc['to_guid'] == task_data['guid'] }.group_by { |arc| arc['pin'] }
|
76
|
+
task_arcs.each { |pin, arcs| connect_task_arcs(identifier, pin, arcs) }
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param task_identifier [String]
|
80
|
+
# @param pin [String] Create, Pause, Finish, Cancel
|
81
|
+
# @param arcs [Array<Petri::Arc>]
|
82
|
+
def connect_task_arcs(task_identifier, pin, arcs)
|
83
|
+
return if arcs.empty?
|
84
|
+
|
85
|
+
transition = add_task_transition(task_identifier: task_identifier, pin: pin, automated: true)
|
86
|
+
|
87
|
+
# (p*) <?-> [(T) task pin]
|
88
|
+
arcs.each_with_index do |arc, index|
|
89
|
+
front_arc_type = arc['type'] == 'test' ? 'regular' : arc['type']
|
90
|
+
|
91
|
+
add_arc(from_guid: arc['from_guid'],
|
92
|
+
to_guid: transition.guid,
|
93
|
+
type: front_arc_type,
|
94
|
+
guard: arc['guard'])
|
95
|
+
|
96
|
+
add_arc(from_guid: transition.guid,
|
97
|
+
to_guid: arc['from_guid'],
|
98
|
+
type: 'regular') if arc['type'] == 'test'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.included(base_class)
|
103
|
+
base_class.extend(ClassMethods)
|
28
104
|
end
|
29
105
|
|
30
106
|
module ClassMethods
|
107
|
+
|
31
108
|
# @param path [String]
|
32
109
|
# @return [Net]
|
33
110
|
def from_file(path)
|
@@ -52,21 +129,34 @@ module Petri
|
|
52
129
|
self.new.tap do |net|
|
53
130
|
hash['places'].each do |data|
|
54
131
|
net.add_place(guid: data['guid'],
|
55
|
-
|
56
|
-
start: data['start']
|
132
|
+
identifier: data['identifier'],
|
133
|
+
start: data['start'],
|
134
|
+
finish: data['finish'])
|
57
135
|
end
|
58
136
|
|
59
137
|
hash['transitions'].each do |data|
|
60
138
|
net.add_transition(guid: data['guid'],
|
61
|
-
|
139
|
+
identifier: data['identifier'],
|
140
|
+
automated: data['automated'],
|
62
141
|
action: data['action'])
|
63
142
|
end
|
64
143
|
|
144
|
+
hash['messages'].each do |data|
|
145
|
+
net.add_message(guid: data['guid'],
|
146
|
+
identifier: data['identifier'])
|
147
|
+
end if hash['messages']
|
148
|
+
|
149
|
+
hash['tasks'].each do |data|
|
150
|
+
net.add_task(data, hash)
|
151
|
+
end if hash['tasks']
|
152
|
+
|
65
153
|
hash['arcs'].each do |data|
|
66
154
|
net.add_arc(guid: data['guid'],
|
67
155
|
from_guid: data['from_guid'],
|
68
156
|
to_guid: data['to_guid'],
|
69
|
-
type: data['type']
|
157
|
+
type: data['type'],
|
158
|
+
production_rule: data['production_rule'],
|
159
|
+
guard: data['guard'])
|
70
160
|
end
|
71
161
|
end
|
72
162
|
end
|
data/lib/petri/node.rb
CHANGED
@@ -2,8 +2,38 @@ module Petri
|
|
2
2
|
class Node < Element
|
3
3
|
|
4
4
|
# @return [String, nil]
|
5
|
-
def
|
6
|
-
@data[:
|
5
|
+
def identifier
|
6
|
+
@data[:identifier]
|
7
|
+
end
|
8
|
+
|
9
|
+
# @return [Array<Arc>]
|
10
|
+
def input_arcs
|
11
|
+
net.arcs.select { |arc| arc.to_node == self && arc.regular? }
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Array<Node>]
|
15
|
+
def input_nodes
|
16
|
+
input_arcs.map(&:from_node)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Array<Arc>]
|
20
|
+
def output_arcs
|
21
|
+
net.arcs.select { |arc| arc.from_node == self && arc.regular? }
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Array<Node>]
|
25
|
+
def output_nodes
|
26
|
+
output_arcs.map(&:to_node)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Array<Arc>]
|
30
|
+
def outgoing_arcs
|
31
|
+
net.arcs.select { |arc| arc.from_node == self }
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Array<Arc>]
|
35
|
+
def ingoing_arcs
|
36
|
+
net.arcs.select { |arc| arc.to_node == self }
|
7
37
|
end
|
8
38
|
end
|
9
39
|
end
|
data/lib/petri/place.rb
CHANGED
@@ -1,12 +1,38 @@
|
|
1
1
|
module Petri
|
2
2
|
class Place < Node
|
3
3
|
|
4
|
-
def has_token?
|
5
|
-
net.tokens.any? { |token| token.place == self }
|
6
|
-
end
|
7
|
-
|
8
4
|
def start?
|
9
5
|
!!@data[:start]
|
10
6
|
end
|
7
|
+
|
8
|
+
def finish?
|
9
|
+
!!@data[:finish]
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Array<Arc>]
|
13
|
+
def reset_arcs
|
14
|
+
net.arcs.select { |arc| arc.to_node == self && arc.reset? }
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Array<Transition>]
|
18
|
+
def reset_transitions
|
19
|
+
reset_arcs.map(&:from_node)
|
20
|
+
end
|
21
|
+
|
22
|
+
# For a finish place returns start places with the same identifier.
|
23
|
+
# For nets where a finish place may be connected with start places
|
24
|
+
# in order to initialize one flow as a result of another.
|
25
|
+
# @return [Array<Place>]
|
26
|
+
def links
|
27
|
+
if finish?
|
28
|
+
@net.places.select { |place| place.start? && place.identifier == identifier }
|
29
|
+
else
|
30
|
+
[]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def inspect
|
35
|
+
"Petri::Place<#{identifier}>"
|
36
|
+
end
|
11
37
|
end
|
12
38
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Petri
|
2
|
+
module Subprocess
|
3
|
+
|
4
|
+
# Used as a key for caching
|
5
|
+
# @return [String]
|
6
|
+
def subprocess_identifier
|
7
|
+
fail NotImplementedError
|
8
|
+
end
|
9
|
+
|
10
|
+
# @return [Class]
|
11
|
+
def process_class
|
12
|
+
@process_class ||= begin
|
13
|
+
klass = @data[:process_class]
|
14
|
+
case klass
|
15
|
+
when String
|
16
|
+
klass.constantize
|
17
|
+
when Class
|
18
|
+
klass
|
19
|
+
else
|
20
|
+
fail ArgumentError, "Expected Class, String, got #{klass.class.name}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Petri
|
2
|
+
class TaskTransition < Transition
|
3
|
+
include Petri::Subprocess
|
4
|
+
|
5
|
+
attr_reader :task_identifier
|
6
|
+
|
7
|
+
# @param net [Net]
|
8
|
+
# @param data [Hash<Symbol>]
|
9
|
+
def initialize(net, data = {})
|
10
|
+
super
|
11
|
+
@task_identifier = @data[:task_identifier]
|
12
|
+
@data[:identifier] = generate_identifier
|
13
|
+
end
|
14
|
+
|
15
|
+
def create?
|
16
|
+
pin == 'Create'
|
17
|
+
end
|
18
|
+
|
19
|
+
def finish?
|
20
|
+
pin == 'Finish'
|
21
|
+
end
|
22
|
+
|
23
|
+
def pause?
|
24
|
+
pin == 'Pause'
|
25
|
+
end
|
26
|
+
|
27
|
+
def resume?
|
28
|
+
pin == 'Resume'
|
29
|
+
end
|
30
|
+
|
31
|
+
def cancel?
|
32
|
+
pin == 'Cancel'
|
33
|
+
end
|
34
|
+
|
35
|
+
def pin
|
36
|
+
@data[:pin]
|
37
|
+
end
|
38
|
+
|
39
|
+
# [Petri::Subprocess]
|
40
|
+
def subprocess_identifier
|
41
|
+
task_identifier
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def generate_identifier
|
47
|
+
if create?
|
48
|
+
"Create \"#{@task_identifier}\" task"
|
49
|
+
elsif finish?
|
50
|
+
"Finish \"#{@task_identifier}\" task"
|
51
|
+
elsif pause?
|
52
|
+
"Pause \"#{@task_identifier}\" task"
|
53
|
+
elsif resume?
|
54
|
+
"Resume \"#{@task_identifier}\" task"
|
55
|
+
elsif cancel?
|
56
|
+
"Cancel \"#{@task_identifier}\" task"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/petri/token.rb
CHANGED
@@ -1,10 +1,33 @@
|
|
1
1
|
module Petri
|
2
2
|
class Token
|
3
|
-
attr_reader :place
|
3
|
+
attr_reader :place, :source_transition, :data
|
4
4
|
|
5
5
|
# @param place [Place]
|
6
|
-
|
6
|
+
# @param source_transition [Transition, nil]
|
7
|
+
def initialize(place, source_transition = nil)
|
7
8
|
@place = place
|
9
|
+
@source_transition = source_transition
|
10
|
+
@data = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [String, nil]
|
14
|
+
def production_rule
|
15
|
+
source_arc && source_arc.production_rule
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Arc, nil]
|
19
|
+
def source_arc
|
20
|
+
if source_transition
|
21
|
+
place.input_arcs.find { |arc| arc.from_node == source_transition }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def []=(k, v)
|
26
|
+
@data[k] = v
|
27
|
+
end
|
28
|
+
|
29
|
+
def [](k)
|
30
|
+
@data[k]
|
8
31
|
end
|
9
32
|
end
|
10
33
|
end
|
data/lib/petri/transition.rb
CHANGED
@@ -6,59 +6,39 @@ module Petri
|
|
6
6
|
@data[:action].presence
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
10
|
-
|
9
|
+
def automated?
|
10
|
+
@data[:automated].present?
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
|
15
|
-
consume_tokens
|
16
|
-
callback.try(:call)
|
17
|
-
produce_tokens
|
13
|
+
def inhibitor_places
|
14
|
+
ingoing_arcs.select(&:inhibitor?).map(&:from_node)
|
18
15
|
end
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
@callback = block
|
23
|
-
end
|
24
|
-
|
25
|
-
# @return [Proc, nil]
|
26
|
-
def callback
|
27
|
-
@callback
|
17
|
+
def input_places
|
18
|
+
input_nodes
|
28
19
|
end
|
29
20
|
|
30
|
-
|
31
|
-
|
32
|
-
def consume_tokens
|
33
|
-
input_places.each do |place|
|
34
|
-
net.remove_token(place)
|
35
|
-
end
|
21
|
+
def output_places
|
22
|
+
output_nodes
|
36
23
|
end
|
37
24
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
25
|
+
# @return [Array<Place>]
|
26
|
+
def places_to_reset
|
27
|
+
reset_arcs.map(&:to_node)
|
42
28
|
end
|
43
29
|
|
44
30
|
# @return [Array<Arc>]
|
45
|
-
def
|
46
|
-
net.arcs.select { |arc| arc.
|
47
|
-
end
|
48
|
-
|
49
|
-
# @return [Array<Place>]
|
50
|
-
def input_places
|
51
|
-
input_arcs.map(&:from_node)
|
31
|
+
def reset_arcs
|
32
|
+
net.arcs.select { |arc| arc.from_node == self && arc.reset? }
|
52
33
|
end
|
53
34
|
|
54
35
|
# @return [Array<Arc>]
|
55
|
-
def
|
56
|
-
|
36
|
+
def guard_arcs
|
37
|
+
ingoing_arcs.select { |arc| arc.guard.present? }
|
57
38
|
end
|
58
39
|
|
59
|
-
|
60
|
-
|
61
|
-
output_arcs.map(&:to_node)
|
40
|
+
def inspect
|
41
|
+
"Petri::Transition<#{identifier}>"
|
62
42
|
end
|
63
43
|
end
|
64
44
|
end
|
data/lib/version.rb
ADDED
data/petri.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = %q{petri}
|
6
|
+
s.version = Petri::VERSION
|
7
|
+
|
8
|
+
s.date = %q{2016-03-01}
|
9
|
+
s.authors = ["Sergei Zinin (einzige)"]
|
10
|
+
s.email = %q{szinin@gmail.com}
|
11
|
+
s.homepage = %q{http://github.com/einzige/petri}
|
12
|
+
|
13
|
+
s.licenses = ["MIT"]
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.extra_rdoc_files = ["README.md"]
|
18
|
+
|
19
|
+
s.description = %q{A petri nets framework}
|
20
|
+
s.summary = %q{Moves tokens around}
|
21
|
+
end
|
22
|
+
|
metadata
CHANGED
@@ -1,50 +1,36 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: petri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Sergei Zinin
|
7
|
+
- Sergei Zinin (einzige)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '3.2'
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 3.2.16
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '3.2'
|
30
|
-
- - ">="
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 3.2.16
|
33
|
-
description: A simple petri nets structure
|
11
|
+
date: 2016-03-01 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A petri nets framework
|
34
14
|
email: szinin@gmail.com
|
35
15
|
executables: []
|
36
16
|
extensions: []
|
37
|
-
extra_rdoc_files:
|
17
|
+
extra_rdoc_files:
|
18
|
+
- README.md
|
38
19
|
files:
|
39
|
-
-
|
20
|
+
- README.md
|
40
21
|
- lib/petri/arc.rb
|
41
22
|
- lib/petri/element.rb
|
23
|
+
- lib/petri/message.rb
|
42
24
|
- lib/petri/net.rb
|
43
25
|
- lib/petri/net_loader.rb
|
44
26
|
- lib/petri/node.rb
|
45
27
|
- lib/petri/place.rb
|
28
|
+
- lib/petri/subprocess.rb
|
29
|
+
- lib/petri/task_transition.rb
|
46
30
|
- lib/petri/token.rb
|
47
31
|
- lib/petri/transition.rb
|
32
|
+
- lib/version.rb
|
33
|
+
- petri.gemspec
|
48
34
|
homepage: http://github.com/einzige/petri
|
49
35
|
licenses:
|
50
36
|
- MIT
|
@@ -65,8 +51,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
51
|
version: '0'
|
66
52
|
requirements: []
|
67
53
|
rubyforge_project:
|
68
|
-
rubygems_version: 2.
|
54
|
+
rubygems_version: 2.5.1
|
69
55
|
signing_key:
|
70
56
|
specification_version: 4
|
71
|
-
summary:
|
57
|
+
summary: Moves tokens around
|
72
58
|
test_files: []
|