petri 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|